|
| 1 | +*channel.txt* For Vim バージョン 7.4. Last change: 2016 Jan 28 |
| 2 | + |
| 3 | + |
| 4 | + VIMリファレンスマニュアル by Bram Moolenaar |
| 5 | + |
| 6 | + |
| 7 | + プロセス間通信 *channel* |
| 8 | + |
| 9 | +ドラフト ドラフト ドラフト ドラフト ドラフト ドラフト ドラフト |
| 10 | + |
| 11 | +Vimは別のプロセスと通信するのにチャンネルを用います。 |
| 12 | +チャンネルはソケットを用います。 *socket-interface* |
| 13 | + |
| 14 | +現在のところVimは同時に10個までのチャンネルをサポートします。 |
| 15 | +Netbeansインターフェースもチャンネルを使っています。 |netbeans| |
| 16 | + |
| 17 | +1. デモ |channel-demo| |
| 18 | +2. チャンネルを開く |channel-open| |
| 19 | +3. JSONチャンネルを使う |channel-use| |
| 20 | +4. Vimコマンド |channel-commands| |
| 21 | +5. rawチャンネルを使う |channel-use| |
| 22 | +6. ジョブ制御 |job-control| |
| 23 | + |
| 24 | +{Vi does not have any of these features} |
| 25 | +{only available when compiled with the |+channel| feature} |
| 26 | + |
| 27 | +============================================================================== |
| 28 | +1. デモ *channel-demo* |
| 29 | + |
| 30 | +デモにはPythonが必要です。でもプログラムは次の場所にあります。 |
| 31 | +$VIMRUNTIME/tools/demoserver.py |
| 32 | +それをあるターミナルで実行しましょう。そのターミナルをT1と呼びます。 |
| 33 | + |
| 34 | +次に別のターミナルでVimを実行します。そして以下のコマンドででもサーバーに接続 |
| 35 | +します: > |
| 36 | + let handle = connect('localhost:8765', 'json') |
| 37 | +
|
| 38 | +T1の中に次のようなに表示されます: |
| 39 | + === socket opened === ~ |
| 40 | + |
| 41 | +ついにサーバーにメッセージを送信できます: > |
| 42 | + echo sendexpr(handle, 'hello!') |
| 43 | +
|
| 44 | +このメッセージはT1で受信され、Vimには応答が送り返されます。 |
| 45 | +T1ではVimが送った生のメッセージを確認できます: |
| 46 | + [1,"hello!"] ~ |
| 47 | +そしてレスポンスはこうなります: |
| 48 | + [1,"got it"] ~ |
| 49 | +この数値はメッセージを送るたびに増加していきます。 |
| 50 | + |
| 51 | +サーバーはVimにコマンドを送信できます。T1に於いて、次のように正確に(引用符を含 |
| 52 | +めて文字通りに)タイプしてください: > |
| 53 | + ま だ 実 装 さ れ て い ま せ ん |
| 54 | + ["ex","echo 'hi there'"] |
| 55 | +するとそのメッセージがVimに表示されます。 |
| 56 | + |
| 57 | +非同期通信を取り扱うためにはコールバック(以下ハンドラー)が必要です: > |
| 58 | + func MyHandler(handle, msg) |
| 59 | + echo "from the handler: " . a:msg |
| 60 | + endfunc |
| 61 | + call sendexpr(handle, 'hello!', "MyHandler") |
| 62 | +
|
| 63 | +sendを呼ぶたびに毎回コールバックを指定する代わりに、チャンネルを開く際に指定す |
| 64 | +ることもできます: > |
| 65 | + call disconnect(handle) |
| 66 | + let handle = connect('localhost:8765', 'json', "MyHandler") |
| 67 | + call sendexpr(handle, 'hello!', 0) |
| 68 | +
|
| 69 | +============================================================================== |
| 70 | +2. チャンネルを開く *channel-open* |
| 71 | + |
| 72 | +チャンネルを開くには次のようにします: > |
| 73 | + let handle = connect({address}, {mode}, {callback}) |
| 74 | +
|
| 75 | +{address} は "ホスト名:ポート番号" の形式です。 例:"localhost:8765" |
| 76 | + |
| 77 | +{mode} でモード(通信フォーマット)を指定します: *channel-mode* |
| 78 | + "json" - JSONを使う(詳しくは下記を参照。もっとも使いやすい方法) |
| 79 | + "raw" - rawメッセージを使う |
| 80 | + |
| 81 | + *channel-callback* |
| 82 | +{callback} はメッセージ受信時に他のハンドラーで扱われない時に呼ばれます。 |
| 83 | +これはチャンネルのハンドルと、受信したメッセージの2つの引数を取ります。例: > |
| 84 | + func Handle(handle, msg) |
| 85 | + echo '受信した: ' . a:msg |
| 86 | + endfunc |
| 87 | + let handle = connect("localhost:8765", 'json', "Handle") |
| 88 | +
|
| 89 | +
|
| 90 | +{mode} が "json" の時には、"msg" 引数は受信たメッセージの本文で、Vimの型に変換 |
| 91 | +されています。 |
| 92 | +一方 {mode} が "raw" の時には、 "msg" 引数はメッセージ全体を格納した文字列で |
| 93 | +す。 |
| 94 | + |
| 95 | +{mode} が "json" の時には {callback} はオプションです。これを省略した場合、 |
| 96 | +メッセージを1つ受信するにはメッセージを1つ送信する必要があります。 |
| 97 | + |
| 98 | +ハンドラーは後から追加したり、変更したりできます: > |
| 99 | + call sethandler(handle, {callback}) |
| 100 | +{callback} が空の場合 (一度も指定しないか、空文字列を指定した場合) ハンドラー |
| 101 | +は削除されます。 |
| 102 | + |
| 103 | +チャンネルを使い終わったら、以下のように切断してください: > |
| 104 | + call disconnect(handle) |
| 105 | +
|
| 106 | +============================================================================== |
| 107 | +3. JSONチャンネルを使う *channel-use* |
| 108 | + |
| 109 | +{mode} が "json" 場合は、以下のようにメッセージを同期的に送信できます: > |
| 110 | + let response = sendexpr(handle, {expr}) |
| 111 | +これは通信相手から応答があるまで待ち合わせます。 |
| 112 | + |
| 113 | +応答を処理する必要が無いのであれば、以下のように送れます: > |
| 114 | + call sendexpr(handle, {expr}, 0) |
| 115 | +
|
| 116 | +メッセージを送信し、応答を特別な関数で非同期的に処理する場合には、このようにし |
| 117 | +ます: > |
| 118 | + call sendexpr(handle, {expr}, {callback}) |
| 119 | +
|
| 120 | +{expr} は JSON に変換され、配列で包まれます。{expr} として文字列 "hello" を送 |
| 121 | +信した場合に、通信相手が受け取るメッセージの例は次のようになります: |
| 122 | + [12,"hello"] ~ |
| 123 | + |
| 124 | +送信されるJSONのフォーマットはこのようになっています: |
| 125 | + [{number},{expr}] |
| 126 | + |
| 127 | +{number} には毎回異なる値が入ります。これは応答(があるならば)、必ず使われま |
| 128 | +す: |
| 129 | + |
| 130 | + [{number},{response}] |
| 131 | + |
| 132 | +このようにして、受信したメッセージがどの送信メッセージに対応するかを知ることが |
| 133 | +でき、正しいハンドラーを呼び出すことができます。これによって応答メッセージの到 |
| 134 | +着順序を気にしなくても良くなります。 |
| 135 | + |
| 136 | +送信側はかならず有効なJSONをVimへ送らなければなりません。VimはJSONとして解釈す |
| 137 | +ることで、受信メッセージの終端をチェックします。終端を受信することが、 |
| 138 | +メッセージを受理する唯一の方法です。 |
| 139 | + |
| 140 | +サーバープロセスがVimからのメッセージを受信すること無く、メッセージを送信する |
| 141 | +には、数値に 0 を使う必要があります。 |
| 142 | + [0,{response}] |
| 143 | + |
| 144 | +するとチャンネルのハンドラーが {response} をVimの方に変換したものを受け取るで |
| 145 | +しょう。チャンネルにハンドラーが関連付けられていない場合には、メッセージは破棄 |
| 146 | +されます。 |
| 147 | + |
| 148 | +読み込みエラーが発生した場合や |disconnect()| した場合には、可能であるなら文字 |
| 149 | +列 "DETACH" が送られます。チャンネルはそれから非アクティブになります。 |
| 150 | + |
| 151 | +============================================================================== |
| 152 | +4. Vimコマンド *channel-commands* |
| 153 | + |
| 154 | +ま だ 実 装 さ れ て い ま せ ん |
| 155 | + |
| 156 | +"json" チャンネルを使用すると、サーバープロセス側はVimへコマンドを送信できま |
| 157 | +す。そのコマンドはチャンネルのハンドラーを介さずに、Vimの内部で実行されます。 |
| 158 | + |
| 159 | +実行可能なコマンドは以下のとおりです: > |
| 160 | + ["ex", {Ex コマンド}] |
| 161 | + ["normal", {ノーマルモードコマンド}] |
| 162 | + ["eval", {数値}, {式}] |
| 163 | + ["expr", {式}] |
| 164 | +
|
| 165 | +これらを使うときは、これらのコマンドが何をするかに十分気をつけてください! |
| 166 | +ユーザーが何をしているかによっては容易に干渉してしまいます。トラブルを避けるに |
| 167 | +は |mode()| を使い、エディタが期待した状態にあるかチェックしてください。例え |
| 168 | +ば、コマンド実行ではなくテキストとして入力させたい文字列を送るには、以下のよう |
| 169 | +にします: > |
| 170 | + ["ex","if mode() == 'i' | call feedkeys('ClassName') | endif"] |
| 171 | +
|
| 172 | +"ex" コマンドは Ex コマンドを実行します。完了やエラーの応答はありませ |
| 173 | +ん。|autoload| スクリプトの中の関数を使えます。何かを入力するのに |feedkeys()| |
| 174 | +を実行することもできます。 |
| 175 | + |
| 176 | +"normal" コマンドは |:normal| のように実行されます。 |
| 177 | + |
| 178 | +"eval" コマンドは式の評価結果を以下の様に返信します: > |
| 179 | + [{数値}, {result}] |
| 180 | +{数値} は、リクエストに指定したのと同じものです。 |
| 181 | + |
| 182 | +"expr" コマンドはそれに近いのですが、応答を返信しません。例: > |
| 183 | + ["expr","setline('$', ['one', 'two', 'three'])"] |
| 184 | +
|
| 185 | +============================================================================== |
| 186 | +5. rawチャンネルを使う *channel-raw* |
| 187 | + |
| 188 | +{mode} が "raw" の場合には、以下のようにしてメッセージを送信します: |
| 189 | + let response = sendraw(handle, {string}) |
| 190 | +{string} はそのまま送信されます。受信した応答メッセージは直ちにチャンネルから |
| 191 | +読み込み可能になります。この時、Vimにはメッセージの終了をどう判断するかがわか |
| 192 | +りませんから、あなた自身が面倒を見る必要があります。 |
| 193 | + |
| 194 | +応答を必要としないメッセージを送信するには以下のようにします: > |
| 195 | + call sendraw(handle, {string}, 0) |
| 196 | +プロセス(訳注:サーバーのこと)はレスポンスを返し、チャンネルのハンドラーに渡さ |
| 197 | +れます。 |
| 198 | + |
| 199 | +メッセージを送信し、レスポンスを特定の関数で非同期的に取り扱うには以下のように |
| 200 | +します: > |
| 201 | + call sendraw(handle, {string}, {callback}) |
| 202 | +
|
| 203 | +この {string} はJSONにもできます。その場合 |jsonencode()| それを作成し |
| 204 | +|jsondecode()| で受信したJSONメッセージを取り扱います。 |
| 205 | + |
| 206 | +============================================================================== |
| 207 | +6. ジョブ制御 *job-control* |
| 208 | + |
| 209 | +ま だ 実 装 さ れ て い ま せ ん |
| 210 | + |
| 211 | +別のプロセスを開始するには: > |
| 212 | + call startjob({command}) |
| 213 | +
|
| 214 | +これは {command} の終了を待ちません。 |
| 215 | + |
| 216 | +TODO: |
| 217 | + |
| 218 | + let handle = startjob({command}, 's') # 標準入出力を使う |
| 219 | + let handle = startjob({command}, '', {address}) # ソケットを使う |
| 220 | + let handle = startjob({command}, 'd', {address}) # 接続に失敗したら開始 |
| 221 | + |
| 222 | + |
| 223 | + vim:tw=78:ts=8:ft=help:norl: |
0 commit comments