Skip to content

channel roughly translated #159

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jan 29, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
223 changes: 223 additions & 0 deletions doc/channel.jax
Original file line number Diff line number Diff line change
@@ -0,0 +1,223 @@
*channel.txt* For Vim バージョン 7.4. Last change: 2016 Jan 28


VIMリファレンスマニュアル by Bram Moolenaar


プロセス間通信 *channel*

ドラフト ドラフト ドラフト ドラフト ドラフト ドラフト ドラフト

Vimは別のプロセスと通信するのにチャンネルを用います。
チャンネルはソケットを用います。 *socket-interface*

現在のところVimは同時に10個までのチャンネルをサポートします。
Netbeansインターフェースもチャンネルを使っています。 |netbeans|

1. デモ |channel-demo|
2. チャンネルを開く |channel-open|
3. JSONチャンネルを使う |channel-use|
4. Vimコマンド |channel-commands|
5. rawチャンネルを使う |channel-use|
6. ジョブ制御 |job-control|

{Vi does not have any of these features}
{only available when compiled with the |+channel| feature}

==============================================================================
1. デモ *channel-demo*

デモにはPythonが必要です。でもプログラムは次の場所にあります。
$VIMRUNTIME/tools/demoserver.py
それをあるターミナルで実行しましょう。そのターミナルをT1と呼びます。

次に別のターミナルでVimを実行します。そして以下のコマンドででもサーバーに接続
します: >
let handle = connect('localhost:8765', 'json')
T1の中に次のようなに表示されます:
=== socket opened === ~

ついにサーバーにメッセージを送信できます: >
echo sendexpr(handle, 'hello!')
このメッセージはT1で受信され、Vimには応答が送り返されます。
T1ではVimが送った生のメッセージを確認できます:
[1,"hello!"] ~
そしてレスポンスはこうなります:
[1,"got it"] ~
この数値はメッセージを送るたびに増加していきます。

サーバーはVimにコマンドを送信できます。T1に於いて、次のように正確に(引用符を含
めて文字通りに)タイプしてください: >
ま だ 実 装 さ れ て い ま せ ん
["ex","echo 'hi there'"]
するとそのメッセージがVimに表示されます。

非同期通信を取り扱うためにはコールバック(以下ハンドラー)が必要です: >
func MyHandler(handle, msg)
echo "from the handler: " . a:msg
endfunc
call sendexpr(handle, 'hello!', "MyHandler")
sendを呼ぶたびに毎回コールバックを指定する代わりに、チャンネルを開く際に指定す
ることもできます: >
call disconnect(handle)
let handle = connect('localhost:8765', 'json', "MyHandler")
call sendexpr(handle, 'hello!', 0)
==============================================================================
2. チャンネルを開く *channel-open*

チャンネルを開くには次のようにします: >
let handle = connect({address}, {mode}, {callback})
{address} は "ホスト名:ポート番号" の形式です。 例:"localhost:8765"

{mode} でモード(通信フォーマット)を指定します: *channel-mode*
"json" - JSONを使う(詳しくは下記を参照。もっとも使いやすい方法)
"raw" - rawメッセージを使う

*channel-callback*
{callback} はメッセージ受信時に他のハンドラーで扱われない時に呼ばれます。
これはチャンネルのハンドルと、受信したメッセージの2つの引数を取ります。例: >
func Handle(handle, msg)
echo '受信した: ' . a:msg
endfunc
let handle = connect("localhost:8765", 'json', "Handle")
{mode} が "json" の時には、"msg" 引数は受信たメッセージの本文で、Vimの型に変換
されています。
一方 {mode} が "raw" の時には、 "msg" 引数はメッセージ全体を格納した文字列で
す。

{mode} が "json" の時には {callback} はオプションです。これを省略した場合、
メッセージを1つ受信するにはメッセージを1つ送信する必要があります。

ハンドラーは後から追加したり、変更したりできます: >
call sethandler(handle, {callback})
{callback} が空の場合 (一度も指定しないか、空文字列を指定した場合) ハンドラー
は削除されます。

チャンネルを使い終わったら、以下のように切断してください: >
call disconnect(handle)
==============================================================================
3. JSONチャンネルを使う *channel-use*

{mode} が "json" 場合は、以下のようにメッセージを同期的に送信できます: >
let response = sendexpr(handle, {expr})
これは通信相手から応答があるまで待ち合わせます。

応答を処理する必要が無いのであれば、以下のように送れます: >
call sendexpr(handle, {expr}, 0)
メッセージを送信し、応答を特別な関数で非同期的に処理する場合には、このようにし
ます: >
call sendexpr(handle, {expr}, {callback})
{expr} は JSON に変換され、配列で包まれます。{expr} として文字列 "hello" を送
信した場合に、通信相手が受け取るメッセージの例は次のようになります:
[12,"hello"] ~

送信されるJSONのフォーマットはこのようになっています:
[{number},{expr}]

{number} には毎回異なる値が入ります。これは応答(があるならば)、必ず使われま
す:

[{number},{response}]

このようにして、受信したメッセージがどの送信メッセージに対応するかを知ることが
でき、正しいハンドラーを呼び出すことができます。これによって応答メッセージの到
着順序を気にしなくても良くなります。

送信側はかならず有効なJSONをVimへ送らなければなりません。VimはJSONとして解釈す
ることで、受信メッセージの終端をチェックします。終端を受信することが、
メッセージを受理する唯一の方法です。

サーバープロセスがVimからのメッセージを受信すること無く、メッセージを送信する
には、数値に 0 を使う必要があります。
[0,{response}]

するとチャンネルのハンドラーが {response} をVimの方に変換したものを受け取るで
しょう。チャンネルにハンドラーが関連付けられていない場合には、メッセージは破棄
されます。

読み込みエラーが発生した場合や |disconnect()| した場合には、可能であるなら文字
列 "DETACH" が送られます。チャンネルはそれから非アクティブになります。

==============================================================================
4. Vimコマンド *channel-commands*

ま だ 実 装 さ れ て い ま せ ん

"json" チャンネルを使用すると、サーバープロセス側はVimへコマンドを送信できま
す。そのコマンドはチャンネルのハンドラーを介さずに、Vimの内部で実行されます。

実行可能なコマンドは以下のとおりです: >
["ex", {Ex コマンド}]
["normal", {ノーマルモードコマンド}]
["eval", {数値}, {式}]
["expr", {式}]
これらを使うときは、これらのコマンドが何をするかに十分気をつけてください!
ユーザーが何をしているかによっては容易に干渉してしまいます。トラブルを避けるに
|mode()| を使い、エディタが期待した状態にあるかチェックしてください。例え
ば、コマンド実行ではなくテキストとして入力させたい文字列を送るには、以下のよう
にします: >
["ex","if mode() == 'i' | call feedkeys('ClassName') | endif"]
"ex" コマンドは Ex コマンドを実行します。完了やエラーの応答はありませ
ん。|autoload| スクリプトの中の関数を使えます。何かを入力するのに |feedkeys()|
を実行することもできます。

"normal" コマンドは |:normal| のように実行されます。

"eval" コマンドは式の評価結果を以下の様に返信します: >
[{数値}, {result}]
{数値} は、リクエストに指定したのと同じものです。

"expr" コマンドはそれに近いのですが、応答を返信しません。例: >
["expr","setline('$', ['one', 'two', 'three'])"]
==============================================================================
5. rawチャンネルを使う *channel-raw*

{mode} が "raw" の場合には、以下のようにしてメッセージを送信します:
let response = sendraw(handle, {string})
{string} はそのまま送信されます。受信した応答メッセージは直ちにチャンネルから
読み込み可能になります。この時、Vimにはメッセージの終了をどう判断するかがわか
りませんから、あなた自身が面倒を見る必要があります。

応答を必要としないメッセージを送信するには以下のようにします: >
call sendraw(handle, {string}, 0)
プロセス(訳注:サーバーのこと)はレスポンスを返し、チャンネルのハンドラーに渡さ
れます。

メッセージを送信し、レスポンスを特定の関数で非同期的に取り扱うには以下のように
します: >
call sendraw(handle, {string}, {callback})
この {string} はJSONにもできます。その場合 |jsonencode()| それを作成し
|jsondecode()| で受信したJSONメッセージを取り扱います。

==============================================================================
6. ジョブ制御 *job-control*

ま だ 実 装 さ れ て い ま せ ん

別のプロセスを開始するには: >
call startjob({command})
これは {command} の終了を待ちません。

TODO:

let handle = startjob({command}, 's') # 標準入出力を使う
let handle = startjob({command}, '', {address}) # ソケットを使う
let handle = startjob({command}, 'd', {address}) # 接続に失敗したら開始


vim:tw=78:ts=8:ft=help:norl:
Loading