1- *channel.txt* For Vim バージョン 9.0. Last change: 2022 Feb 27
1+ *channel.txt* For Vim バージョン 9.0. Last change: 2022 Jun 23
22
33
44 VIMリファレンスマニュアル by Bram Moolenaar
@@ -25,7 +25,9 @@ Netbeans インターフェイスもチャネルを使っています。|netbean
252512. ジョブオプション | job-options |
262613. ジョブを制御する | job-control |
272714. プロンプトバッファを使う | prompt-buffer |
28+ 15. Language Server Protocol | language-server-protocol |
2829
30+ *E1277*
2931{Vim が | +channel | 機能付きでコンパイルされたときのみ有効}
3032 `has (' channel' )` でこれを確認できる
3133{Vim が | +job | 機能付きでコンパイルされたときのみ有効}
@@ -51,6 +53,7 @@ RAW 何も知られていない、Vim はメッセージの終わりを知らせ
5153NL すべてのメッセージは NL (改行) 文字で終わります。
5254JSON JSON エンコーディング | json_encode() |
5355JS JavaScript スタイルの JSON 風のエンコーディング | js_encode() |
56+ LSP Language Server Protocol のエンコーディング | language-server-protocol |
5457
5558共通の組み合わせ:
5659- NL モードでパイプを介して接続されたジョブを使用します。例えば、スタイルチェッ
@@ -118,18 +121,22 @@ send を呼ぶたびに毎回コールバックを指定する代わりに、チ
118121
119122| ch_status() | を使用して、チャネルを開くことができたかどうかを確認します。
120123
121- {address} は "ホスト名:ポート番号" の形式です。例:"localhost:8765"
122-
123- IPv6 アドレスを使う時、角カッコでくくった中に納めてください。
124- たとえば、"[2001:db8::1]:8765"。
124+ *channel-address*
125+ {address} はドメイン名か IP アドレスで、それにポート番号を続ける、あるいは
126+ "unix:" プリフィックスを付けて Unix ドメインソケットパス にできます。例 >
127+ www.example.com:80 " ドメイン + ポート
128+ 127.0.0.1:1234 " IPv4 + ポート
129+ [2001:db8::1]:8765 " IPv6 + ポート
130+ unix:/tmp/my-socket " Unix ドメインソケットパス
125131
126132{options} はオプションのエントリを持つ辞書です: *channel-open-options*
127133
128- "mode" でモード (通信フォーマット) を指定します: *channel-mode*
134+ "mode" は次のいずれかです: *channel-mode*
129135 "json" - JSONを使う (詳しくは下記を参照。もっとも使いやすい方法。既定)
130136 "js" - JS (JavaScript) エンコーディングを使用し、JSON よりも効率的。
131137 "nl" - NL 文字で終わるメッセージを使う
132138 "raw" - raw メッセージを使う
139+ "lsp" - language server protocol エンコーディングを使う
133140 *channel-callback* *E921*
134141"callback" メッセージ受信時に他のハンドラーで扱われない時に呼ばれます
135142 (例えば、ID が0の JSON メッセージ)。これはチャネルのハンドル
@@ -139,8 +146,8 @@ IPv6 アドレスを使う時、角カッコでくくった中に納めてくだ
139146 endfunc
140147 let channel = ch_open("localhost:8765", {"callback": "Handle"})
141148<
142- "mode" が "json", "js" の時には、"msg" 引数は受信したメッセー
143- ジの本文で 、Vim の型に変換されています。
149+ "mode" が "json", "js", "lsp" の時には、"msg" 引数は受信した
150+ メッセージの本文で 、Vim の型に変換されています。
144151 "mode" が "nl" の時には、"msg" 引数は NL を除く 1 つのメッセー
145152 ジです。
146153 "mode" が "raw" の時には、"msg" 引数はメッセージ全体を格納し
@@ -165,7 +172,19 @@ IPv6 アドレスを使う時、角カッコでくくった中に納めてくだ
165172 close_cb が呼び出されることがあります。プラグインは何とかこれ
166173 を処理する必要があり、これ以上データが来ていないことを知ってお
167174 くと便利です。
168- *channel-drop*
175+ 読み込むメッセージがあるか不明な場合は、try/catch ブロックを使
176+ います: >
177+ try
178+ let msg = ch_readraw(a:channel)
179+ catch
180+ let msg = 'no message'
181+ endtry
182+ try
183+ let err = ch_readraw(a:channel, #{part: 'err'})
184+ catch
185+ let err = 'no error'
186+ endtry
187+ < *channel-drop*
169188"drop" メッセージをいつドロップするかを指定します:
170189 "auto" メッセージを処理するコールバックがない場合。
171190 "close_cb" もこのために考慮されます。
@@ -407,6 +426,7 @@ mode が "nl" の場合、同様の方法でメッセージを送信できます
407426 プロセス {訳注:サーバーのこと} はレスポンスを返し、チャネルのハンドラーに渡さ
408427れます。
409428
429+ *channel-onetime-callback*
410430メッセージを送信し、レスポンスを特定の関数で非同期的に取り扱うには以下のように
411431します: >
412432 call ch_sendraw(channel, {string}, {'callback': 'MyHandler'})
@@ -444,10 +464,11 @@ v:none、RAW または NL チャネルでは空の文字列です。|ch_canread(
444464コールバックメッセージがない場合、メッセージは破棄されます。これを回避するに
445465は、チャネルにコールバックを追加します。
446466
447- 使用可能な RAW チャネルからすべての出力を読み込むには : >
467+ 使用可能な RAW チャネルからすべての通常出力を読み込むには : >
448468 let output = ch_readraw(channel)
449- エラー出力を読むには : >
469+ 使用可能な RAW チャネルからすべてのエラー出力を読み込むには : >
450470 let output = ch_readraw(channel, {"part": "err"})
471+ Note チャネルが NL モードの場合、ch_readraw() は各呼び出しで1行しか返しません。
451472
452473ch_read() と ch_readraw() はチャネルタイムアウトを使用します。その時間内に何も
453474読み込めない場合、空の文字列が返されます。別のタイムアウトをミリ秒で指定するに
@@ -505,13 +526,16 @@ ch_evalexpr({handle}, {expr} [, {options}]) *ch_evalexpr()*
505526 ンコードされる。この関数は生のチャネルでは使用できない。
506527 | channel-use | を参照。
507528 {handle} はチャネルもしくはチャネルを持つジョブであっても良い。
529+ "lsp" モードでチャネル使用時は、{expr} は | Dict | でなければな
530+ らない。
508531 *E917*
509532 {options} は辞書でなければならない。また "callback" のエントリ
510533 を持ってはならない。また個別のリクエストに対して "timeout" を
511534 持つ事ができる。
512535
513536 ch_evalexpr() は応答を待ち、式をデコードした物が返される。エ
514- ラーもしくはタイムアウトの場合は空文字列が返る。
537+ ラーもしくはタイムアウトの場合は空の | String | 、あるいは "lsp"
538+ モードでチャネル使用時は空の | Dict | が返る。
515539
516540 Note 応答を待っている間、Vimは他のメッセージを処理する。これが
517541 トラブルを引き起こさないことを確認する必要がある。
@@ -563,10 +587,15 @@ ch_info({handle}) *ch_info()*
563587 ch_open() で開いた場合:
564588 "hostname" アドレスのホスト名
565589 "port" アドレスのポート
590+ "path" Unix ドメインソケットのパス
566591 "sock_status" "open" または "closed"
567592 "sock_mode" "NL", "RAW", "JSON" または "JS"
568593 "sock_io" "socket"
569594 "sock_timeout" タイムアウト(ミリ秒)
595+
596+ Note "path" は Unix ドメインソケットの場合にのみ存在し、通常は
597+ "hostname" と "port" が代わりに存在する。
598+
570599 job_start() で開いた場合:
571600 "out_status" "open", "buffered" または "closed"
572601 "out_mode" "NL", "RAW", "JSON" または "JS"
@@ -577,7 +606,7 @@ ch_info({handle}) *ch_info()*
577606 "err_io" "out", "null", "pipe", "file" または "buffer"
578607 "err_timeout" タイムアウト(ミリ秒)
579608 "in_status" "open" または "closed"
580- "in_mode" "NL", "RAW", "JSON" または "JS "
609+ "in_mode" "NL", "RAW", "JSON", "JS" または "LSP "
581610 "in_io" "null", "pipe", "file" または "buffer"
582611 "in_timeout" タイムアウト(ミリ秒)
583612
@@ -601,16 +630,20 @@ ch_logfile({fname} [, {mode}]) *ch_logfile()*
601630 {fname} へチャネルの挙動ログ出力を開始する。
602631 {fname} が空の場合、ロギングは停止する。
603632
604- {mode} が省略されるか "a" の場合、ファイルへの追加になる。
605- {mode} が "w" の場合、空のファイルへで開始される。
633+ {mode} が省略されるか "a" を含むか "o" の場合、ファイルへの追
634+ 加になる。
635+ {mode} が "w" を含み "a" を含まない場合、空のファイルで開始さ
636+ れる。
637+ {mode} が "o" を含む場合、全ての端末出力が記録される。
638+ その他の場合は、興味深い端末出力のみがログに記録される。
606639
607640 ログメッセージを書き込むには | ch_log() | を使用する。UNIX で
608641 "tail -f" にてリアルタイムで何が行われているかが見える様に、
609642 ファイルはメッセージ毎にフラッシュされる。
610643
611644 最初期にログを有効にし、初期化中に端末から何を受信したのかを参
612- 照するには、| --cmd | を使う: >
613- vim --cmd "call ch_logfile(' logfile', 'w')"
645+ 照するには、| --log | ("ao" モードを使用) を使う: >
646+ vim --log logfile
614647<
615648 この関数は | sandbox | 内では無効である。
616649 Note: チャネルとの通信はファイルに格納される。これには、あなた
@@ -626,11 +659,8 @@ ch_open({address} [, {options}]) *ch_open()*
626659 チャネルを返す。失敗をチェックするには | ch_status() | を使用す
627660 る。
628661
629- {address} は文字列で "localhost:8765" のように "ホスト名:ポー
630- ト" の形式である。
631-
632- IPv6 アドレスを使う時、角カッコでくくった中に納めること。
633- たとえば、"[2001:db8::1]:8765"。
662+ {address} は文字列で、受け付け可能な形式は | channel-address |
663+ を参照のこと。
634664
635665 {options} が与えられる場合は辞書でなければならない。
636666 | channel-open-options | を参照。
@@ -675,6 +705,17 @@ ch_sendexpr({handle}, {expr} [, {options}]) *ch_sendexpr()*
675705 | channel-use | を参照。
676706 {handle} はチャネルもしくはチャネルを持つジョブであっても良い。
677707 チャネルは開いていなければならない。
708+ "lsp" モードでチャネル使用時は、{expr} は | Dict | でなければな
709+ らない。
710+
711+ チャネルのモードが "lsp" の場合、辞書を返す。それ以外は空の文
712+ 字列を返す。{options} に "callback" の項目が存在する場合、リク
713+ エストメッセージのIDを含む辞書を返す。IDはLSPサーバーへキャン
714+ セルのリクエスト(必要な場合)を送るのに使うことができる。エラー
715+ のときは空の辞書を返す。
716+
717+ {expr} に対して応答メッセージを受けないのであれば、{options}
718+ に "callback" 項目を指定しないこと。
678719
679720 | method | としても使用できる: >
680721 GetChannel()->ch_sendexpr(expr)
@@ -1365,5 +1406,155 @@ Shift-CTRL-W を使用します)。ウィンドウを離れるとき挿入モー
13651406 # シェルコマンドの受け付けを開始する。
13661407 startinsert
13671408
1409+ ==============================================================================
1410+ 15. Language Server Protocol *language-server-protocol*
1411+
1412+ language server protocol の仕様は以下にあります:
1413+
1414+ https://microsoft.github.io/language-server-protocol/specification
1415+
1416+ 各 LSP プロトコルメッセージは単純な HTTP ヘッダ で始まり JSON-RPC フォーマット
1417+ にエンコードされたペイロードが続きます。次で説明されています:
1418+
1419+ https://www.jsonrpc.org/specification
1420+
1421+ Vim | Dict | 内の LSP のリクエスト/通知メッセージをエンコードして LSP JSON-RPC
1422+ メッセージ に入れて送信をするのと LSP JSON-RPC 応答/通知メッセージの受信とデ
1423+ コードをして Vim | Dict | 内に収めるには、| channel-mode | を "lsp" に設定して LSP
1424+ サーバーに接続します。
1425+
1426+ | channel-mode | を "lsp" に設定したチャネルからメッセージを受信したたなら、Vim
1427+ は HTTP ヘッダを処理し、JSON-RPC ペイロードをデコードして Vim | Dict | 型に格納
1428+ し、| channel-callback | 関数もしくは指定された | channel-onetime-callback | 関数
1429+ を呼びます。| ch_evalexpr() | か | ch_sendexpr() | 関数を用いてチャネルからメッセー
1430+ ジを送信した時には、Vim は HTTP ヘッダを付与し Vim の式を JSON にエンコードし
1431+ ます。Vim が組み込み型を JSON へエンコードあるいはデコードする方法の詳細につい
1432+ ては、| json_encode() | と | json_decode() | を参照してください。
1433+
1434+ 'lsp' モードを使用してチャネルを開くには、| ch_open() | の引数 {options} の
1435+ 'mode' 項目を 'lsp' にします。例: >
1436+
1437+ let ch = ch_open(..., #{mode: 'lsp'})
1438+
1439+ 'lsp' モードを使用したチャネルをジョブで開くには、| job_start() | の引数
1440+ {options} の 'in_mode' と 'out_mode' 項目を 'lsp' にします。例: >
1441+
1442+ let cmd = ['clangd', '--background-index', '--clang-tidy']
1443+ let opts = {}
1444+ let opts.in_mode = 'lsp'
1445+ let opts.out_mode = 'lsp'
1446+ let opts.err_mode = 'nl'
1447+ let opts.out_cb = function('LspOutCallback')
1448+ let opts.err_cb = function('LspErrCallback')
1449+ let opts.exit_cb = function('LspExitCallback')
1450+ let job = job_start(cmd, opts)
1451+
1452+ Note ジョブが LSP メッセージを標準出力に、非LSPメッセージを標準エラーに出す場
1453+ 合、チャネルのコールバック関数は両方のメッセージフォーマットを適切に扱うか、上
1454+ 記にあるように "out_cb" と "err_cb" で個別のコールバック関数を使って扱わなくて
1455+ はなりません。
1456+
1457+ サーバーにむけて JSON-RPC リクエストの同期送信をするには、| ch_evalexpr() | 関数
1458+ を使います。この関数は応答を待ちサーバーからのレスポンスメッセージをデコードし
1459+ て返します。| channel-timeout | を使うかあるいは引数 {options} の 'timeout'
1460+ フィールドに値を設定することで応答の待ち時間の制御ができます。レスポンスがタイ
1461+ ムアウトした場合、空の | Dict | が返ります。例: >
1462+
1463+ let req = {}
1464+ let req.method = 'textDocument/definition'
1465+ let req.params = {}
1466+ let req.params.textDocument = #{uri: 'a.c'}
1467+ let req.params.position = #{line: 10, character: 3}
1468+ let defs = ch_evalexpr(ch, req, #{timeout: 100})
1469+ if defs->empty()
1470+ ... <handle failure>
1471+ endif
1472+
1473+ Note リクエストメッセージには 'id' フィールドを指定してはいけません。指定した
1474+ 場合、Vimは内部的に生成する識別子の値を上書きします。Vimは現在、'id' フィール
1475+ ドの種別として数値のみをサポートしています。RPC のリクエストの成功と失敗の両方
1476+ でコールバック関数が呼び出されます。
1477+
1478+ JSON-RPC リクエストをサーバーに送信して応答を非同期に処理するには、
1479+ | ch_sendexpr() | 関数を使ってコールバック関数を与えます。リクエストメッセージに
1480+ "id" フィールドが設定されている場合は、Vimは内部的に生成する識別子の値を上書き
1481+ します。この関数はメッセージに使用した識別子を含む Dict を返します。キャンセル
1482+ リクエストを LSP サーバーに送信する(必要な場合)にも使用できます。例: >
1483+
1484+ let req = {}
1485+ let req.method = 'textDocument/hover'
1486+ let req.id = 200
1487+ let req.params = {}
1488+ let req.params.textDocument = #{uri: 'a.c'}
1489+ let req.params.position = #{line: 10, character: 3}
1490+ let resp = ch_sendexpr(ch, req, #{callback: 'HoverFunc'})
1491+
1492+ | ch_sendexpr() | 関数を使用してサーバーに送信した非同期 LSP リクエストの未処理
1493+ のものをキャンセルするには、リクエスト時に返されたIDとともに | ch_sendexpr() |
1494+ 関数でキャンセル用メッセージをサーバーに送信します。例: >
1495+
1496+ " 補完リクエストを送信
1497+ let req = {}
1498+ let req.method = 'textDocument/completion'
1499+ let req.params = {}
1500+ let req.params.textDocument = #{uri: 'a.c'}
1501+ let req.params.position = #{line: 10, character: 3}
1502+ let reqstatus = ch_sendexpr(ch, req, #{callback: 'LspComplete'})
1503+ " キャンセル通知を送信
1504+ let notif = {}
1505+ let notif.method = '$/cancelRequest'
1506+ let notif.id = reqstatus.id
1507+ call ch_sendexpr(ch, notif)
1508+
1509+ JSON-RPC 通知メッセージをサーバーに送信するには、| ch_sendexpr() | 関数を使いま
1510+ す。サーバーは通知のレスポンスメッセージを送信しません。"callback" 項目は指定
1511+ をしてはいけません。例: >
1512+
1513+ call ch_sendexpr(ch, #{method: 'initialized'})
1514+
1515+ サーバーからの JSON-RPC リクエストメッセージへの返答には | ch_sendexpr() | 関数
1516+ を使用します。レスポンスメッセージの中の 'id' フィールドの値はサーバーへのリク
1517+ エストメッセージの応答メッセージからコピーします。例: >
1518+
1519+ let resp = {}
1520+ let resp.id = req.id
1521+ let resp.result = 1
1522+ call ch_sendexpr(ch, resp)
1523+
1524+ サーバーからの JSON-RPC 通知メッセージは | channel-callback | 関数を通じて伝達さ
1525+ れます。
1526+
1527+ ユースケースに依存しますが、ch_evalexpr(), ch_sendexpr(), ch_sendraw() 関数を
1528+ 同じチャネルで使うことができます。
1529+
1530+ LSP リクエストメッセージは以下のフォーマット(Vim Dict で表現)を持ちます。
1531+ "params" フィールドはオプションです: >
1532+
1533+ {
1534+ "jsonrpc": "2.0",
1535+ "id": <number>,
1536+ "method": <string>,
1537+ "params": <list|dict>
1538+ }
1539+
1540+ LSP レスポンスメッセージは以下のフォーマット(Vim Dict で表現)を持ちます。
1541+ "result" と "error" フィールドはオプションです: >
13681542
1543+ {
1544+ "jsonrpc": "2.0",
1545+ "id": <number>,
1546+ "result": <vim type>
1547+ "error": <dict>
1548+ }
1549+
1550+ LSP 通知メッセージは以下のフォーマット(Vim Dict で表現)を持ちます。"params"
1551+ フィールドはオプションです: >
1552+
1553+ {
1554+ "jsonrpc": "2.0",
1555+ "method": <string>,
1556+ "params": <list|dict>
1557+ }
1558+
1559+ <
13691560 vim:tw=78:ts=8:noet:ft=help:norl:
0 commit comments