Up: 目次   [Index]


ジョブ、チャネル、プロセス閒通信

*channel.txt*      For Vim バージョン 8.1.  Last change: 2019 Sep 11


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

プロセス閒通信

Vim は別のプロセスと通信するのにチャネルを用ゐます。

チャネルはソケットまたはパイプを用ゐます。

ジョブはプロセスを開始し、プロセスと通信するために使用できます。

Netbeans インターフェイスもチャネルを使つてゐます。|netbeans|

1. 槪要|job-channel-overview|
2. チャネルデモ|channel-demo|
3. チャネルを開く|channel-open|
4. JSON, JS チャネルを使ふ|channel-use|
5. チャネルコマンド|channel-commands|
6. RAW, NL チャネルを使ふ|channel-raw|
7. その他のチャネル機能|channel-more|
8. チャネル函數の詳細|channel-functions-details|
9. チャネルでジョブを開始する|job-start|
10. チャネルなしでジョブを開始する|job-start-nochannel|
11. ジョブ函數|job-functions-details|
12. ジョブオプション|job-options|
13. ジョブを制禦する|job-control|
14. プロンプトバッファを使ふ|prompt-buffer|

{Vim が |+channel| 機能付きでコンパイルされたときのみ有效}
has('channel')‘ でこれを確認できる

{Vim が |+job| 機能付きでコンパイルされたときのみ有效}
has('job')‘ でこれを確認できる

1. 槪要

主に 4 種類のジョブがあります:

  1. いくつかの Vim インスタンスを扱ふデーモン。Vim はソケットで接續します。
  2. 1 つの Vim インスタンスを 1 つのジョブが非同期に處理する。ソケットまたはパイプを使用します。
  3. 短時閒、非同期で仕事をするジョブ。ソケットまたはパイプを使用します。
  4. フィルタを同期して實行する。パイプを使用します。

ソケットを使用する場合 |job-start|, |job-start-nochannel| および |channel-open| 參照。2 と 3 の場合は、パイプを使用する 1 つ以上のジョブです (|job-start| 參照)。

4 の場合、":{range}!cmd" コマンドを使用します (|filter| 參照)。

ソケットとパイプ上でこれらのプロトコルを利用できます:

RAW何も知られてゐない、Vim はメッセージの終はりを知らせない。
NLすべてのメッセージは NL (改行) 文字で終はります。
JSONJSON エンコーディング |json_encode()|
JSJavaScript スタイルの JSON 風のエンコーディング |js_encode()|

共通の組み合はせ:

2. チャネルデモ

デモには Python が必要です。デモプログラムは次の場所にあります。

$VIMRUNTIME/tools/demoserver.py

それをあるターミナルで實行しませう。そのターミナルを T1 と呼びます。

次に別のターミナルで Vim を實行します。そして以下のコマンドでサーバーに接續します:

let channel = ch_open('localhost:8765')

T1 の中に次のやうに表示されます:

=== socket opened ===

つひにサーバーにメッセージを送信できます:

echo ch_evalexpr(channel, 'hello!')

このメッセージは T1 で受信され、Vim には應答が送り返されます。

T1 では Vim が送つた生のメッセージを確認できます:

[1,"hello!"]

そしてレスポンスはかうなります:

[1,"got it"]

この數値はメッセージを送るたびに增加していきます。

サーバーは Vim にコマンドを送信できます。T1 において、次のやうに正確に (引用符を含めて文字通りに) タイプしてください:

["ex","echo 'hi there'"]

するとそのメッセージが Vim に表示されます。カーソルを 1 單語先に移動することができます:

["normal","w"]

非同期通信を取り扱ふためにはコールバック (以下ハンドラー) が必要です:

func MyHandler(channel, msg)
  echo "from the handler: " . a:msg
endfunc
call ch_sendexpr(channel, 'hello!', {'callback': "MyHandler"})

Vim は應答を待つことはありません。これで、サーバーは應答を後で送信し、MyHandler が呼び出されます。

send を呼ぶたびに每囘コールバックを指定する代はりに、チャネルを開く際に指定することもできます:

call ch_close(channel)
let channel = ch_open('localhost:8765', {'callback': "MyHandler"})
call ch_sendexpr(channel, 'hello!')

チャネルを試してみると、何が起こつてゐるのかを知ることができます。あなたは Vim にログファイルに行を書くよう指示することができます:

call ch_logfile('channellog', 'w')

|ch_logfile()| 參照.

3. チャネルを開く

チャネルを開くには次のやうにします:

let channel = ch_open({address} [, {options}])
if ch_status(channel) == "open"
  " use the channel

|ch_status()| を使用して、チャネルを開くことができたかどうかを確認します。

{address} は "ホスト名:ポート番號" の形式です。例: "localhost:8765"

{options} はオプションのエントリを持つ辭書です:

"mode" でモード (通信フォーマット) を指定します:

"json"JSON を使ふ (詳しくは下記を參照。もつとも使ひやすい方法。既定)
"js"JS (JavaScript) エンコーディングを使用し、JSON よりも效率的。
"nl"NL 文字で終はるメッセージを使ふ
"raw"raw メッセージを使ふ
"callback"

メッセージ受信時に他のハンドラーで扱はれない時に呼ばれます。これはチャネルのハンドルと、受信したメッセージの 2 つの引數を取ります。例:

func Handle(channel, msg)
  echo '受信した: ' . a:msg
endfunc
let channel = ch_open("localhost:8765", {"callback": "Handle"})

"mode" が "json", "js" の時には、"msg" 引數は受信したメッセージの本文で、Vim の型に變換されてゐます。

"mode" が "nl" の時には、"msg" 引數は NL を除く 1 つのメッセージです。

"mode" が "raw" の時には、"msg" 引數はメッセージ全體を格納した文字列です。

すべてのコールバック: |function()| を使用して、引數および/または辭書にバインドします。または、"dict.function" といふ形式を使用して辭書をバインドします。

コールバックは、通常、Vim がユーザーが文字を入力するのを待つてゐるとき、「安全な」瞬閒にのみ呼び出されます。Vim はマルチスレッドを使用しません。

"close_cb"

|ch_close()| を呼び出す以外に、チャネルが閉ぢられたときに呼び出される函數。このやうに定義する必要があります:

func MyCloseHandler(channel)

Vim は close_cb を呼び出す前にデータを處理するコールバックを呼び出します。したがつて、この函數が呼び出されると、それ以上のデータはコールバックに渡されません。ただし、コールバックにより Vim のメッセージのチェックが發生するなら、コールバック中に close_cb が呼び出されることがあります。プラグインは何とかこれを處理する必要があり、これ以上データが來てゐないことを知つておくと便利です。

"drop"

メッセージをいつドロップするかを指定します:

"auto"メッセージを處理するコールバックがない場合。"close_cb" もこのために考慮されます。
"never"すべてのメッセージが保存されます。
"noblock"

|job-noblock| と同じ效果。書き込み時にのみ重要です。

"waittime"

接續がミリ秒單位で待機する時閒。負の數は永遠に待ちます。

デフォルトはゼロで、待機しません。これは、ローカルサーバーがすでに實行されてゐる場合に便利です。Unix Vim では實際には 1ms のタイムアウトが使はれます。多くのシステムではそれが必要なためです。リモートサーバーには大きな値を使用してください。例: 少なくとも 10msec。

"timeout"

ブロッキング時にリクエストを待つ時閒。例: |ch_evalexpr()| を使用するとき。ミリ秒單位。デフォルトは 2000 (2秒) です。

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

チャネルオプションを開いた後に變更するには、|ch_setoptions()| を使用します。引數は |ch_open()| に渡されるものと似てゐますが、"waittime" は與へられません。これはチャネルを開く場合にのみ適用されるためです。

例へば、ハンドラーは後から追加したり、變更したりできます:

call ch_setoptions(channel, {'callback': callback})

"callback" が空の場合 (一度も指定しないか、空文字列を指定した場合) ハンドラーは削除されます。

コールバックが呼び出された後、Vim は畫面を更新し、カーソルをそれが屬する場所に戾します。コールバックは ‘:redraw‘ を行ふ必要はありません。

タイムアウトは次のやうに變更できます:

call ch_setoptions(channel, {'timeout': msec})

チャネルを使ひ終はつたら、以下のやうに切斷してください:

call ch_close(channel)

ソケットが使用されてゐると、兩方向のソケットが閉ぢられます。パイプが使用されてゐると (stdin/stdout/stderr)、それらはすべて閉ぢられます。これはあなたが望むものではないかもしれません! |job_stop()| でジョブを停止する方が良いかもしれません。すべての先讀みは破毀され、コールバックは呼び出されなくなります。

Note:
チャネルは 3 つの段階で閉ぢられることに注意してください:

チャネルを開くことができない場合、エラーメッセージが表示されます。MS-Windows と Unix には違ひがあります: Unix では、ポートが存在しないとき、|ch_open()| はすぐに失敗します。MS-Windows では "waittime" が適用されます。

チャネルを讀み書きする際にエラーが發生した場合、チャネルは閉ぢられます。

4. JSON、JS チャネルを使ふ

"mode" が JSON の場合は、以下のやうにメッセージを同期的に送信できます:

let response = ch_evalexpr(channel, {expr})

これは通信相手から應答があるまで待ち合はせます。

mode が JS の場合は、メッセージが JavaScript エンコーディングを使用する點を除いて、これは同じです。その違ひについては、|js_encode()| 參照。

應答を處理せずにメッセージを送信する、またはチャネルコールバックに應答を處理させるには:

call ch_sendexpr(channel, {expr})

メッセージを送信し、應答を特別な函數で非同期的に處理する場合には、このやうにします:

call ch_sendexpr(channel, {expr}, {'callback': Handler})

Vim は、メッセージ ID を使用して要求との應答を照合します。應答が受信されると、コールバックが呼び出されます。同じ ID を持つさらなる應答は無視されます。あなたのサーバーが複數の應答を返信する場合、ID ゼロで送信する必要があります。それらはチャネルコールバックに渡されます。

{expr} は JSON に變換され、排列で包まれます。{expr} として文字列 "hello" を送信した場合に、通信相手が受け取るメッセージの例は次のやうになります:

[12,"hello"]

送信される JSON のフォーマットはこのやうになつてゐます:

[{number},{expr}]

{number} には每囘異なる値が入ります。これは應答があるならば、必ず使はれます:

[{number},{response}]

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

改行文字が JSON テキストを終了してゐます。これは、讀み込まれたテキストを區切るために使用できます。例へば Python では:

splitidx = read_text.find('\n')
message = read_text[:splitidx]
rest = read_text[splitidx + 1:]

送信側はかならず有效な JSON を Vim へ送らなければなりません。Vim は JSON として解釋することで、受信メッセージの終端をチェックします。終端を受信することが、メッセージを受理する唯一の方法です。メッセージ最後の改行はオプションです。

サーバープロセスが Vim からのメッセージを受信すること無く、メッセージを送信するには、數値に 0 を使ふ必要があります。

[0,{response}]

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

JSON または JS チャネルで |ch_sendraw()| および |ch_evalraw()| を使用することもできます。その場合呼び出し元は、正しくエンコードとデコードを行ふ完全な責任があります。

5. チャネルコマンド

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

實行可能なコマンドは以下のとほりです:

["redraw", {forced}]
["ex", {Ex コマンド}]
["normal", {ノーマルモードコマンド}]
["eval", {式}, {數値}]
["expr", {式}]
["call", {函數名}, {引數リスト}, {數値}]
["call", {函數名}, {引數リスト}]

これらを使ふときは、これらのコマンドが何をするかに十分氣をつけてください!ユーザーが何をしてゐるかによつては容易に干涉してしまひます。トラブルを避けるには |mode()| を使ひ、エディタが期待した狀態にあるかチェックしてください。例へば、コマンド實行ではなくテキストとして入力させたい文字列を送るには、以下のやうにします:

["ex","if mode() == 'i' | call feedkeys('ClassName') | endif"]

これらのコマンドのエラーは、表示が亂れないやうにするため、通常は報告されません。表示したい場合は、’verbose’ オプションを 3 以上に設定してください。

コマンド "redraw"

他のコマンドは明示的に畫面を更新しないので、カーソルを動かさずに一聯のコマンドを送ることができます。再描畫は他のコマンドの副作用として發生することがあります。變更されたテキストを表示し、それが屬する場所にカーソルを表示するには、"redraw" コマンドで終了する必要があります。

引數は通常は空の文字列です:

["redraw", ""]

最初に畫面をクリアするには "force" を渡してください:

["redraw", "force"]

コマンド "ex"

"ex" コマンドは Ex コマンドを實行します。完了やエラーの應答はありません。|autoload| スクリプトの中の函數を使へます:

["ex","call myscript#MyFunc(arg)"]

"call |feedkeys()|" を使用してキーシーケンスを插入することもできます。

エラーが發生すると、チャネルログにメッセージが書き込まれ、存在する場合は v:errmsg にエラーが設定されます。

コマンド "normal"

"normal" コマンドは ":normal!" のやうに實行され、コマンドはマップされません。カーソルの下の折疊を開く例:

["normal" "zO"]

コマンド "expr" (應答あり)

"expr" コマンドは、式の結果を得るために使ふことができます。たとへば、現在のバッファ內の行數を取得するには、次のやうにします:

["expr","line('$')", -2]

式の結果を返します:

[-2, "last line"]

形式は次のとほりです:

[{number}, {result}]

{number} は、リクエストに指定したのと同じものです。Vim が送信するメッセージとの混亂を避けるには、負の數を使用します。リクエストとレスポンスを一致させるには、リクエストごとに異なる番號を使用します。

{result} は評價の結果であり、JSON エンコードされてゐます。評價が失敗したり、結果を JSON でエンコードできない場合は、文字列 "ERROR" となります。

コマンド "expr" (應答なし)

このコマンドは上記の "expr" に近いのですが、應答を返信しません。例:

["expr","setline('$', ['one', 'two', 'three'])"]

リクエストに第 3 引數はありません。

コマンド "call"

これは "expr" に似てゐますが、式全體を文字列として渡す代はりに、函數の名前と引數のリストを渡します。これは、引數の文字列への變換を避け、エスケープして連結します。例:

["call", "line", ["$"], -2]

應答が送信されない場合は、第 4 引數を省いてください:

["call", "setline", ["$", ["one", "two", "three"]]]

6. RAW、NL チャネルを使ふ

モードが RAW か NL の場合には、以下のやうにしてメッセージを送信します:

let response = ch_evalraw(channel, {string})

{string} はそのまま送信されます。受信した應答メッセージは直ちにチャネルから讀み込み可能になります。この時、Vim にはメッセージの終了をどう判斷するかがわかりませんから、あなた自身が面倒を見る必要があります。タイムアウトは、最初のバイトを讀み取るために適用され、その後は何も待つことはありません。

mode が "nl" の場合、同樣の方法でメッセージを送信できます。あなたは各メッセージの後に NL に入れなければなりません。したがつて、一度に NL で終はる複數のメッセージを送信することもできます。應答は最初の NL までのテキストとなります。これは空のレスポンスの NL だけでもかまひません。チャネルタイムアウトの前に NL が讀み取られなかつた場合、空の文字列が返されます。

應答を必要としないメッセージを送信するには以下のやうにします:

call ch_sendraw(channel, {string})

プロセス {譯注: サーバーのこと} はレスポンスを返し、チャネルのハンドラーに渡されます。

メッセージを送信し、レスポンスを特定の函數で非同期的に取り扱ふには以下のやうにします:

call ch_sendraw(channel, {string}, {'callback': 'MyHandler'})

この {string} は JSON にもできます。その場合、|json_encode()| でそれを作成し |json_decode()| で受信した JSON メッセージを取り扱ひます。

生のチャネルで |ch_evalexpr()| または |ch_sendexpr()| を使用することはできません。

Vim の文字列に NUL バイトを含めることはできません。NUL バイトを送受信するには、バッファから讀み書きしてください。|in_io-buffer| と |out_io-buffer| 參照。

7. その他のチャネル機能

チャネルのステータスを取得するには、ch_status(channel) を使用します。ありうる結果は次のとほりです:

"fail"チャネルを開くことができませんでした。
"open"チャネルを使用することができます。
"buffered"チャネルは閉ぢられましたが讀み込むデータがあります。
"closed"チャネルが閉ぢられました。

チャネルに關聯付けられたジョブを取得するには: ch_getjob(channel)

チャネルから 1 つのメッセージを讀むには:

let output = ch_read(channel)

これは、チャネルのタイムアウトを使用します。タイムアウトなしで讀むには、利用可能なメッセージを取得するだけです:

let output = ch_read(channel, {'timeout': 0})

メッセージが利用できなかつた場合、結果は JSON またはJSモードのチャネルでは v:none, RAW または NL チャネルでは空の文字列です。|ch_canread()| を使用して、何かがあるかどうかを調べることができます。

Note:
コールバックメッセージがない場合、メッセージは破毀されます。これを囘避するには、チャネルにコールバックを追加します。

使用可能なRAWチャネルからすべての出力を讀み込むには:

let output = ch_readraw(channel)

エラー出力を讀むには:

let output = ch_readraw(channel, {"part": "err"})

ch_read() と ch_readraw() はチャネルタイムアウトを使用します。その時閒內に何も讀み込めない場合、空の文字列が返されます。別のタイムアウトをミリ秒で指定するには、"timeout" オプションを使用します:

{"timeout": 123}

エラー出力から讀み込むには、"part" オプションを使用します:

{"part": "err"}

特定の ID を持つメッセージを JS または JSON チャネルで讀み取るには:

{"id": 99}

ID が指定されてゐないか、または ID が -1 の場合、最初のメッセージが返されます。これは、このメッセージを待つてゐるコールバックをすべて無效にします。

RAW チャネルの場合、Vim はメッセージの終はりを知らないので、利用可能なものを返します。

NL チャネルの場合、これは 1 つのメッセージを返します。

JS または JSON チャネルの場合、これは 1 つのデコードされたメッセージを返します。

これには、任意のシーケンス番號が含まれます。

8. チャネル函數の詳細

ch_canread({handle})

{handle} から何か讀むものがあれば非ゼロを返します。{handle} はチャネルもしくはチャネルを持つジョブであつても良い。

これはチャネルから、都合のよいときに讀むのに便利です。例へば、タイマーから。

Note:
チャンルがコールバックを持つてゐない場合、メッセージはドロップされることに注意してください。それを防ぐには close コールバックを追加してください。

|method| としても使用できます:

GetChannel()->ch_canread()
ch_close({handle})

{handle} を閉ぢます。|channel-close| を參照してください。{handle} はチャネルもしくはチャネルを持つジョブであつても良い。閉ぢられたコールバックは呼び出されません。

|method| としても使用できます:

GetChannel()->ch_close()
ch_close_in({handle})

{handle} の "入力" を閉ぢる。|channel-close-in| を參照してください。{handle} はチャネルもしくはチャネルを持つジョブであつても良い。閉ぢられたコールバックは呼び出されません。

|method| としても使用できます:

GetChannel()->ch_close_in()

ch_evalexpr({handle}, {expr} [, {options}]) {handle} へ {expr} を送信します。{expr} はチャネル側と同じ型にエンコードされる。この函數は生のチャネルでは使用できません。|channel-use| を參照してください。{handle} はチャネルもしくはチャネルを持つジョブであつても良い。 {options} は辭書でなければなりません。また "callback" のエントリを持つてはなりません。また個別のリクエストに對して "timeout" を持つ事ができます。

ch_evalexpr() は應答を待ち、式をデコードした物が返されます。エラーもしくはタイムアウトの場合は空文字列を返します。

Note:
應答を待つてゐる閒、Vim は他のメッセージを處理することに注意してください。これがトラブルを引き起こさないことを確認する必要があります。

|method| としても使用できます:

GetChannel()->ch_evalexpr(expr)
ch_evalraw({handle}, {string} [, {options}])

{handle} へ {string} を送信します。{handle} はチャネルもしくはチャネルを持つジョブであつても良い。

|ch_evalexpr()| と同樣に動作します。しかしリクエストをエンコードしたり應答をデコードしたりはしません。呼び出しは正しいコンテンツである事が保證されます。また NL モードでは改行が行はれますが、ここでは改行が付與されません。NL は應答から削除されます。

Note:
Vim は Raw チャネル上で受け取るテキストがいつ完了するのか分からないことに注意してください。最初の部分だけを返す可能性もあり、殘りを取り出すために |ch_readraw()| を使ふ必要があります。|channel-use| を參照してください。

|method| としても使用できます:

GetChannel()->ch_evalraw(rawstring)
ch_getbufnr({handle}, {what})

l{what} に使用されてゐる {handle} のバッファ番號を得ます。{handle} はチャネルもしくはチャネルを持つジョブであつても良い。{what} は標準エラーのための "err"、標準出力のための "out"、もしくはソケット出力のための空文字列を指定できます。バッファが存在しない場合は -1 を返します。

|method| としても使用できます:

GetChannel()->ch_getbufnr(what)
ch_getjob({channel})

{channel} に關聯付けられた Job を得ます。もしジョブが無い場合、戾り値の Job で |job_status()| を呼び出すと "fail" が返されます。

|method| としても使用できます:

GetChannel()->ch_getjob()
ch_info({handle})

{handle} に關する情報を辭書で返します。アイテムは:

"id"チャネル番號
"status"ch_status() と同樣に "open", "buffered" または "closed"

ch_open() で開いた場合:

"hostname"アドレスのホスト名
"port"アドレスのポート
"sock_status""open" または "closed"
"sock_mode""NL", "RAW", "JSON" または "JS"
"sock_io""socket"
"sock_timeout"タイムアウト (ミリ秒)

job_start() で開いた場合:

"out_status""open", "buffered" または "closed"
"out_mode""NL", "RAW", "JSON" または "JS"
"out_io""null", "pipe", "file" または "buffer"
"out_timeout"タイムアウト (ミリ秒)
"err_status""open", "buffered" または "closed"
"err_mode""NL", "RAW", "JSON" または "JS"
"err_io""out", "null", "pipe", "file" または "buffer"
"err_timeout"タイムアウト (ミリ秒)
"in_status""open" または "closed"
"in_mode""NL", "RAW", "JSON" または "JS"
"in_io""null", "pipe", "file" または "buffer"
"in_timeout"タイムアウト (ミリ秒)

|method| としても使用できます:

GetChannel()->ch_info()
ch_log({msg} [, {handle}])

|ch_logfile()| によつてログファイルが開かれてゐる場合は、チャネルのログファイルに {msg} を書き込みます。{handle} が渡されてゐる場合はチャネル番號がメッセージの中で使はれます。{handle} はチャネルもしくはチャネルを持つジョブであつても良い。使用されるチャネル番號のチャネルは開いてゐなければなりません。

|method| としても使用できます:

'did something'->ch_log()
ch_logfile({fname} [, {mode}])

{fname} へチャネルの擧動ログ出力を開始します。{fname} が空の場合、ロギングは停止します。

{mode} が省略されるか "a" の場合、ファイルへの追加になります。{mode} が "w" の場合、空のファイルへで開始されます。

ログメッセージを書き込むには |ch_log()| を使用します。UNIX で "tail -f" にてリアルタイムで何が行はれてゐるかが見える樣に、ファイルはメッセージ每にフラッシュされます。

この函數は |sandbox| 內では無效です。

Note:
チャネルとの通信はファイルに格納されます。これには、あなたが端末ウィンドウ上でタイプしたパスワードのやうな、機密やプライバシーに關する情報を含むことがあることに注意してください。

|method| としても使用できます:

'logfile'->ch_logfile('w')
ch_open({address} [, {options}])

{address} へのチャネルを開きます。|channel| を參照してください。チャネルを返します。失敗をチェックするには |ch_status()| を使用します。

{address} は "localhost:8765" のやうに "ホスト名:ポート" の形式です。

{options} が與へられる場合は辭書でなければなりません。|channel-open-options| を參照してください。

|method| としても使用できます:

GetAddress()->ch_open()
ch_read({handle} [, {options}])

{handle} から讀み込みメッセージを受信します。{handle} はチャネルもしくはチャネルを持つジョブであつても良い。NL チャネルの場合、何も讀み込むものがない (チャネルが閉ぢられた) 場合を除いて NL を受信するまで待ちます。|channel-more| を參照してください。

|method| としても使用できます:

GetChannel()->ch_read()
ch_readblob({handle} [, {options}])

ch_read() と同樣に動作しますが、バイナリデータを讀み込んで |Blob| を返します。|channel-more| を參照してください。

|method| としても使用できます: GetChannel()->ch_readblob()

ch_readraw({handle} [, {options}])

ch_read() と同樣に動作しますが JS や JSON の場合でもメッセージはデコードされません。NL チャネルの場合、NL を受信するまで待つことはありませんが、それ以外は ch_read() と同樣に動作します。|channel-more| を參照してください。

|method| としても使用できます:

GetChannel()->ch_readraw()
ch_sendexpr({handle}, {expr} [, {options}])

{handle} へ {expr} を送信します。{expr} はチャネル側と同じ型にエンコードされます。この函數は生のチャネルでは使用できません。 |channel-use| を參照してください。 {handle} はチャネルもしくはチャネルを持つジョブであつても良い。

|method| としても使用できます:

GetChannel()->ch_sendexpr(expr)
ch_sendraw({handle}, {expr} [, {options}])

文字列 |String| または |Blob| {expr} を {handle} に送ります。|ch_sendexpr()| と同樣に動作しますが、リクエストをエンコードしたり應答をデコードしたりはしません。呼び出しは正しいコンテンツである事が保證されます。また NL モードでは改行が行はれますが、ここでは改行が付與されません。NL は應答から削除されます。|channel-use| を參照してください。

|method| としても使用できます:

GetChannel()->ch_sendraw(rawexpr)
ch_setoptions({handle}, {options})

{handle} にオプションを設定します:

"callback"チャネルのコールバック
"timeout"デフォルトの讀み込みタイムアウト (ミリ秒)
"mode"チャネル全體のモード

より詳しい說明は |ch_open()| を參照してください。{handle} はチャネルもしくはチャネルを持つジョブであつても良い。

Note:
モードの變更はキューイングされてゐるメッセージを失つてしまふかもしれないことに注意してください。

以下のオプションは變更できません:

"waittime"|ch_open()| のみに適用できる

|method| としても使用できます:

GetChannel()->ch_setoptions(options)
ch_status({handle} [, {options}])

{handle} の狀態を返します:

"fail"チャネルのオープンに失敗
"open"チャネルは利用可能
"buffered"チャネルは讀込可能、または書き込まれてゐない
"closed"チャネルは利用不可

{handle} はチャネルもしくはチャネルを持つジョブであつても良い。チャネルは閉ぢられてゐるが |ch_read()| を使つて殘つたデータをまだ讀み取る事ができる場合には "buffered" が利用できます。

{options} が指定された場合、"part" 要素でチャネルのどのパート ("out" または "err") の狀態を返すかを指定できます。例へば、エラーの狀態を得るには:

ch_status(job, {"part": "err"})

|method| としても使用できます:

GetChannel()->ch_status()

9. チャネルでジョブを開始する

ジョブを開始し、stdin/stdout/stderr のチャネルを開くには:

let job = job_start(command, {options})

チャネルを得るには:

let channel = job_getchannel(job)

チャネルは NL モードを使用します。別のモードが必要な場合は、{options} でこれを指定することをお勸めします。後でモードを變更すると、一部のテキストがすでに受信され、正しく解析されてゐない可能性があります。

コマンドが處理したい出力行を生成する場合は、stdout のハンドラを指定します:

let job = job_start(command, {"out_cb": "MyHandler"})

この函數は、チャネルとメッセージで呼び出されます。あなたはこれをこのやうに定義します:

func MyHandler(channel, msg)

ハンドラがなければ、|ch_read()| または |ch_readraw()| で出力を讀み取る必要があります。クローズコールバックでこれを行ふことができます。|read-in-close-cb| 參照。

Note:
出力を讀み取る前にジョブが終了すると、出力が失はれる可能性があることに注意してください。これはシステムによつて異なります (Unix 上では、パイプの書き込み終了を閉ぢると EOF が得られます)。これを避けるには、ジョブが終了する前にそれをしばらくスリープさせること。

"out_cb" に定義されたハンドラは stderr を受け取りません。もし個別に扱ひたい場合は、"err_cb" ハンドラを追加します:

let job = job_start(command, {"out_cb": "MyHandler",
        \			  "err_cb": "ErrHandler"})

1 つのハンドラで stderr と stdout の兩方を處理する場合は、"callback" オプションを使用します:

let job = job_start(command, {"callback": "MyHandler"})

システムによつては、ジョブを開始するとVimをバックグラウンドに移動することがあり、開始されたジョブはフォーカスを取得します。これを避けるには ‘foreground()‘ 函數を使用してください。これは、早く呼び出されたとき、コールバックハンドラ內に置いたとき、またはジョブが開始した後にタイマーを使用して呼び出すときは、必ずしも機能しない場合があります。

ch_evalraw() でコマンドにメッセージを送ることができます。チャネルが JSON または JS モードの場合、ch_evalexpr() を使用できます。

使用できるオプションがいくつかあります。|job-options| 參照。

例へば、ジョブを開始し、その出力をバッファ "dummy" に書き込むには:

let logjob = job_start("tail -f /tmp/log",
                     \ {'out_io': 'buffer', 'out_name': 'dummy'})
sbuf dummy

バッファからのジョブ入力

バッファから讀み取るジョブを實行するには:

let job = job_start({command},
    \ {'in_io': 'buffer', 'in_name': 'mybuffer'})

バッファは、|bufnr()| と同樣の名前で見つけられます。バッファは、job_start() が呼び出されたときに存在し、ロードされてゐなければなりません。

デフォルトでは、これはバッファ全體を讀み込みます。これは "in_top" と "in_bot" オプションで變更できます。

特殊モードは、"in_top" が 0 に設定され、"in_bot" が設定されてゐない場合です。バッファに行が追加されるたびに、最後の 1 行がジョブ stdin に送信されます。これにより、最後の行を編輯し、Enter を押したときに送信することができます。 特殊モードを使用しないときは、最後の行が書き込まれた後にパイプまたはソケットが閉ぢられます。これは、入力が終了した讀み取り終了を知らせます。|ch_close_in()| を使用すると、より早く終了することもできます。

テキストの NUL バイトはジョブに渡されます (內部では Vim はこれらを NL バイトとして格納します)。

クローズコールバックでジョブ出力を讀み込む

ジョブに時閒がかかり、中閒結果が必要ない場合は、クローズコールバックを追加してそこの出力を讀み取ることができます:

func! CloseHandler(channel)
  while ch_status(a:channel, {'part': 'out'}) == 'buffered'
    echomsg ch_read(a:channel)
  endwhile
endfunc
let job = job_start(command, {'close_cb': 'CloseHandler'})

あなたは "echomsg" よりも役に立つ何かをしたいでせう。

10. チャネルなしでジョブを開始する

チャネルを作成せずに別のプロセスを開始するには:

let job = job_start(command,
    \ {"in_io": "null", "out_io": "null", "err_io": "null"})

これはバックグラウンドで {command} を開始し、Vim はそれが完了するのを待ちません。

Vim が stdin、stdout、stderr のいづれも接續されてゐないと判斷すると、チャネルは作成されません。コマンドが停止するのを避けるために、リダイレクションをコマンドに含めることがよくあります。

使用できるオプションがいくつかあります。|job-options| 參照。

アドレスへの接續が動作しない時にのみジョブを開始するには、次のやうな操作を行ひます:

let channel = ch_open(address, {"waittime": 0})
if ch_status(channel) == "fail"
  let job = job_start(command)
  let channel = ch_open(address, {"waittime": 1000})
endif

Note:
ch_open() の待ち時閒は、ポートを利用可能にするためにジョブに 1 秒を與へることに注意してください。

11. Job 函數

job_getchannel({job})

{job} が使用してゐるチャネルハンドルを取得します。ジョブにチャネルがないかどうかを確認するには:

if string(job_getchannel()) == 'channel fail'

|method| としても使用できます:

GetJob()->job_getchannel()
job_info([{job}])

{job} に關する情報を持つ辭書を返します:

"status"|job_status()| が返すもの
"channel"|job_getchannel()| が返すもの
"cmd"ジョブを開始するのに使はれるコマンド引數のリスト
"process"プロセス ID
"tty_in"端末入力名、何もないときには空
"tty_out"端末出力名、何もないときには空
"exitval""status" が "dead" のときのみ有效
"exit_cb"終了時に呼び出される函數
"stoponexit"|job-stoponexit|

Unix のみ:

"termsig"プロセスを終了させたシグナル (値については |job_stop()| を參照してください)

"status"が "dead" の場合にのみ有效で

MS-Windows のみ:

"tty_type"使用してゐる假想コンソールのタイプ。値は "winpty" または "conpty"。

termwintype’ を參照してください。

引數なしの場合、すべてのジョブオブジェクトのリストを返します。

|method| としても使用できます:

GetJob()->job_info()
job_setoptions({job}, {options})

{job} のオプションを變更します。サポートされてゐるものは:

"stoponexit"|job-stoponexit|
"exit_cb"|job-exit_cb|

|method| としても使用できます:

GetJob()->job_setoptions(options)
job_start({command} [, {options}])

ジョブを開始し、ジョブオブジェクトを返します。|system()| と |:!cmd| とは異なり、これはジョブが終了するのを待つことはありません。端末ウィンドウ內でジョブを開始する方法については |term_start()| を參照してください。

ジョブが起動に失敗した場合、返されたジョブオブジェクトの |job_status()| は "fail" となり、どのコールバックも呼び出されません。

{command} は文字列にすることができます。これは MS-Windows 上で最も效果的です。Unix では、それは execvp() に渡すために空白で區切られたパーツに分割されます。二重引用符で圍まれた引數には空白を含めることができます。

{command} はリストにすることができ、最初の項目は實行可能ファイルで、殘りの項目は引數です。すべての項目は文字列に變換されます。これ は Unix で最も效果的です。

MS-Windows では、|job_start()| は GUI アプリケーションを隱します。それを表示したい場合は、|:!start| を代はりに使用してください。

コマンドはシェルではなく直接實行され、’shell’ オプションは使用されません。シェルを使用するには:

let job = job_start(["/bin/sh", "-c", "echo hello"])

または:

let job = job_start('/bin/sh -c "echo hello"')

Note:
これは 2 つのプロセス、シェルとそれが實行するコマンドを開始することに注意してください。これを望まない場合は、"exec" シェルコマンドを使用します。

Unix では $PATH は、コマンドにスラッシュが含まれてゐない場合にのみ、實行可能ファイルを檢索するために使用されます。

ジョブは Vim と同じ端末を使用します。ジョブが stdin を讀む場合、ジョブと Vim が入力を奪ひ合ふことになるのでうまく動作しません。問題を避けるために stdin と stdout をリダイレクトします:

let job = job_start(['sh', '-c', "myserver </dev/null >/dev/null"])

返されたジョブオブジェクトを使用して、|job_status()| でステータスを取得し、|job_stop()| でジョブを停止することができます。

Note:
ジョブオブジェクトは、それを參照するものがない場合削除されることに注意してください。これは stdin および stdout を閉ぢ、エラーによるジョブの失敗を引き起こします。これを囘避するにはジョブへの參照を維持します。 そのため、次の代はりに:

call job_start('my-command')

以下のやうにします:

let myjob = job_start('my-command')

さらに、ジョブが必要なくなつたとき、もしくは (開始時にメッセージが表示されたときのやうに) ジョブが失敗した後に、"myjob" を unlet します。函數のローカル變數は、函數が終了すると消滅することに注意してください。必要であればスクリプトローカルな變數を使用することができます:

let s:myjob = job_start('my-command')

{options} は辭書でなければなりません。多くのオプション項目を含めることができます。|job-options| を參照してください。

|method| としても使用できます:

BuildCommand()->job_start()
job_status({job})

{job} のステータスを String で返します:

"run"ジョブが實行中
"fail"ジョブを開始できなかつた
"dead"ジョブが死んだか實行後にジョブが停止した

Unix では存在しないコマンドは、失敗が檢出される前にフォークが發生するため、"fail" ではなく "dead" になります。

exit コールバックが "exit_cb" オプションで設定され、ジョブが "dead" と檢出された場合、コールバックが呼び出されます。

詳細は |job_info()| を參照してください。

|method| としても使用できます:

GetJob()->job_status()
job_stop({job} [, {how}])

{job} を停止します。これはジョブを通知するためにも使用できます。

{how} が省略されたり "term" の場合、ジョブは終了します。Unix では SIGTERM が送信されます。MS-Windows では、ジョブは强制的に終了します ("優しい"方法は存在しません)。これはプロセスグループに行くので、子プロセスにも影響を受けるかもしれません。

UNIX への影響:

"term"SIGTERM (既定)
"hup"SIGHUP
"quit"SIGQUIT
"int"SIGINT
"kill"SIGKILL (停止するための最も强い方法)
numberその番號の信號

MS-Windows への影響:

"term"プロセスを强制終了 (既定)
"hup"CTRL_BREAK
"quit"CTRL_BREAK
"int"CTRL_C
"kill"プロセスを强制終了
OthersCTRL_BREAK

Unix では、シグナルはプロセスグループに送られます。これは、ジョブが "sh -c command" であるときにシェルとコマンドの兩方に影響を與へることを意味します。

結果は數値で、操作が實行できる場合は 1、システムで "how" がサポートされてゐない場合は 0。

Note:
ジョブが實際に停止したかどうかは、操作が實行された場合でも、|job_status()| でチェックする必要があることに注意してください。

ジョブのステータスが "dead" の場合、シグナルは送られません。これは、(特にプロセス番號が再利用される Unix において) 閒違つたジョブを停止することを防ぐためです。

"kill" を使用したとき、Vim はジョブが死ぬと想定し、チャネルを閉ぢます。

|method| としても使用できます:

GetJob()->job_stop()

12. ジョブオプション

job_start() の {options} 引數は辭書です。すべての入力はオプションです。job_setoptions(job, {options}) を使用して、ジョブの開始後にいくつかのオプションを使用できます。ch_setoptions(channel, {options}) を使用して、ジョブに關聯するチャネルで多くのオプションを使用できます。|job_setoptions()| および |ch_setoptions()| 參照。

"in_mode"

stdin 用のモード、パイプを使用してゐる場合にのみ。

"out_mode"

stdout 用のモード、パイプを使用してゐる場合にのみ。

"err_mode"

stderr 用のモード、パイプを使用してゐる場合にのみ。

値については、|channel-mode| 參照。

Note:
"mode" を設定すると、パーツ固有のモードが上書きされます。したがつて、最初に "mode" を、後でパーツ固有のモードを設定します。

Note:
ファイルやバッファに書き込むときやバッファから讀み込むときは、NL モードがデフォルトで使用されます。

"noblock": 1

書き込み時にノンブロッキング書き込み呼び出しを使ふ。これは、もしも Vim が他のメッセージを扱ふべき場合に、スタックするのを囘避する。例へばジョブがバックデータを Vim の送る時など。まだすべてを書き込まれてゐないデータを ‘ch_sendraw()‘ が返す時を意味する。 このオプションはパッチ 8.1.0350 にて追加された。次でテストしよう:

if has("patch-8.1.350")
  let options['noblock'] = 1
endif
"callback": handler

チャネルの任意の部分で何かを讀むためのコールバック。

"out_cb": handler

stdout で讀み込むべきものがあるときのコールバック。チャネルがパイプを使用してゐる場合のみ。"out_cb" が設定されてゐない場合は、チャネルコールバックが使用されます。2 つの引數はチャネルとメッセージです。

"err_cb": handler

stderr で讀み込むべきものがあるときのコールバック。チャネルがパイプを使用してゐる場合のみ。"err_cb" が設定されてゐない場合は、チャネルコールバックが使用されます。2 つの引數はチャネルとメッセージです。

"close_cb": handler

チャネルが閉ぢられるときのコールバック。|ch_open()| の "close_cb" と同じです。|close_cb| 參照。

"drop": when

メッセージをいつドロップするかを指定します。|ch_open()| の "drop" と同樣 (|channel-drop| 參照)。"auto" の場合、exit_cb は考慮されません。

"exit_cb": handler

ジョブが終了したときのコールバック。引數はジョブと終了ステータスです。

Vim は、終了したジョブに對して最大 10 回/秒をチェックします。チェックは、|job_status()| を呼び出すことによつてトリガーすることもでき、exit_cb ハンドラを呼び出すことができます。

Note:
データがバッファリングされ、プロセスが終了した後もコールバックが呼び出されることに注意してください。

"timeout": time

ブロッキング時にリクエストを待つ時閒 (例: ch_evalexpr() を使用するとき。ミリ秒單位。デフォルトは 2000(2 秒) です。

"out_timeout": time

stdout のタイムアウト。パイプ使用時のみ。

"err_timeout": time

stderr のタイムアウト。パイプ使用時のみ。

Note:
"timeout" を設定すると、パーツ固有のモードが上書きされます。したがつて、最初に "timeout" を設定し、後でパーツ固有のモードを設定します。

"stoponexit": {signal}

Vim が終了すると {signal} をジョブに送ります。可能な値については、|job_stop()| 參照。

"stoponexit": ""

Vim が終了してもジョブを停止しません。デフォルトは "term" です。

"term": "open"

新しいウィンドウでターミナルを起動し、ジョブ stdin/stdout/stderr を接續します。‘:terminal‘ を使用することと同じです。

Note:
まだ實裝されてゐません!

"channel": {channel}

新しいチャネルを作成する代はりに、既存のチャネルを使用します。新しいジョブに使用されるチャネルの部分は、以前使用された部分から切り離されます。チャネルが別のジョブで引き續き使用されてゐた場合、I/O エラーが發生する可能性があります。

既存のコールバックやその他の設定が殘つてゐます。

"pty": 1

可能であれば、パイプのかはりに pty (pseudo-tty) を使ひます。これは端末ウィンドウとの組み合せで最も便利です。|terminal| を參照。

{Unix と Unix系 のシステムでのみ有效}

"in_io": "null"

stdin を切斷する (/dev/null から讀み込む)

"in_io": "pipe"

標準入力がチャネルに接續されてゐる (デフォルト)

"in_io": "file"

stdin はファイルから讀み込む

"in_io": "buffer"

stdin はバッファから讀み込む

"in_top": number

"buffer" を使用する場合: 送信する最初の行 (デフォルト: 1)

"in_bot": number

"buffer" を使用する場合: 送信する最後の行 (デフォルト:最後)

"in_name": "/path/file"

讀み込むファイルまたはバッファの名前

"in_buf": number

讀み込むバッファの番號

"out_io": "null"

stdout を切斷する (/dev/null に行く)

"out_io": "pipe"

stdout がチャネルに接續されてゐる (デフォルト)

"out_io": "file"

stdout がファイルに書き込む

"out_io": "buffer"

stdout はバッファに追加する (下記參照)

"out_name": "/path/file"

書き込むファイルまたはバッファの名前

"out_buf": number

書き込むバッファの番號

"out_modifiable": 0

バッファに書き込むときに、’modifiable’ はオフになる (下記參照)

"out_msg": 0

新しいバッファに書き込むとき、最初の行は "Reading from channel output..." に設定される

"err_io": "out"

stderr のメッセージは stdout に行く

"err_io": "null"

stderr を切斷する (/dev/null に行く)

"err_io": "pipe"

stderr がチャネルに接續されてゐる (デフォルト)

"err_io": "file"

stderr はファイルに書き込む

"err_io": "buffer"

stderr はバッファに追加する (下記參照)

"err_name": "/path/file"

書き込むファイルまたはバッファの名前

"err_buf": number

書き込むバッファの番號

"err_modifiable": 0

バッファに書き込むときに、’modifiable’ はオフになる (下記參照)

"err_msg": 0

新しいバッファに書き込むとき、最初の行は "Reading from channel error..." に設定される

"block_write": number

テストのためにのみ: stdin への他のすべての書き込みをブロックするふりをする

"env": dict

新しいプロセスのための環境變數

"cwd": "/path/to/dir"

新しいプロセスのためのカレント作業ディレクトリ。ディレクトリが存在しない場合は、エラーが發生します。

バッファへの書き込み

out_io または err_io モードが "buffer" で、コールバックがある場合、コールバックを呼び出す前にテキストがバッファに追加されます。

入力と出力の兩方にバッファが使用されてゐる場合、最後の行はチャネル入力に書き込まれたものなので、出力行は最後の行の上に置かれます。それ以外の場合は最後の行の下に行が追加されます。

"buffer" を指定して JS または JSON モードを使用すると、デコード + エンコーディング後に、ゼロまたは負の ID を持つメッセージのみがバッファに追加されます。正の數を持つメッセージはコールバックによつて處理され、コマンドは通常通り處理されます。

"out_name" または "err_name" のバッファ名は、現在のディレクトリの名前を擴張した後も、既存のバッファの完全名と比較されます。たとへば、":edit somename" でバッファが作成され、バッファ名が "somename" の場合、そのバッファが使用されます。

一致するバッファがない場合、新しいバッファが作成されます。新しいバッファを常に作成するには、空の名前を使用します。|ch_getbufnr()| を使用してバッファ番號を取得できます。

新しいバッファの場合、’buftype’ は "nofile" に設定され、’bufhidden’ は "hide" に設定されます。他の設定が必要な場合は、まづバッファを作成し、バッファ番號を渡します。 "out_modifiable" と "err_modifiable" オプションは、’modifiable’ オプションをオフにするか、’modifiable’ になつてゐるバッファに書き込むために使用できます。つまり、行がバッファに追加されますが、ユーザーはバッファを簡單に變更できません。 "out_msg" オプションは、新しいバッファが最初の行を "Reading from channel output..." に設定するかどうかを指定するために使用できます。デフォルトではメッセージを追加します。"err_msg" はチャネルエラーでも同じです。

既存のバッファに ’modifiable’ が指定されてをらず、"out_modifiable" または "err_modifiable" オプションがゼロでない場合、エラーが發生し、バッファに書き込まれません。

書き込まれたバッファがウィンドウに表示され、カーソルが最後の行の最初の列にある場合、カーソルは新しく追加された行に移動され、ウィンドウは必要に應じてカーソルを表示するために上にスクロールされます。

追加されたすべての行に對して、取り消しが同期されます。NUL バイトは受け入れられます (內部では Vim はこれらを NL バイトとして格納します)。

ファイルへの書き込み

ファイルはアクセス許可 600 (ユーザーに對しては讀み書き可能、他のユーザーはアクセス不可) で作成されます。これを變更するには、|setfperm()| を使用してください。

ファイルがすでに存在する場合は切り捨てられます。

13. ジョブを制禦する

ジョブの狀態を取得するには:

echo job_status(job)

ジョブの實行を停止するには:

job_stop(job)

これはジョブを終了させる通常の方法です。Unix では、ジョブに SIGTERM を送信します。他の方法でジョブを停止したり、任意の信號を送信したりすることもできます。例へば、ジョブを强制的に停止させるには、"kill it":

job_stop(job, "kill")

他のオプションについては、|job_stop()| 參照。

14. プロンプトバッファを使ふ

Vim のウィンドウでジョブのための入力をタイプしたい場合、いくつかのオプションがあります:

プロンプトバッファは ’buftype’ を "prompt" に設定することによつて作成されます。通常は新規作成バッファでのみおこなひます。

ユーザーは、バッファの最後の行に 1 行のテキストを編輯して入力することができます。プロンプト行で Enter キーを押すと、|prompt_setcallback()| で設定されたコールバックが呼び出されます。通常は、その行をジョブに送信します。別のコールバックは、ジョブからの出力を受け取り、バッファ內のプロンプトの下 (次のプロンプトの上) に表示します。

プロンプトの後の最後の行のテキストのみが編輯可能です。殘りのバッファはノーマルモードのコマンドでは變更できません。|append()| などの函數を呼び出すことで變更できます。他のコマンドを使用すると、バッファを壞す可能性があります。

buftype’ を "prompt" に設定した後、Vim は自動的に插入モードを開始しません。插入モードに入るには ‘:startinsert‘ を使ひます。これにより、ユーザーは行の入力を開始できます。

プロンプトのテキストは |prompt_setprompt()| 函數で設定することができます。

ユーザーはノーマルモードに移行し、バッファ內を移動できます。これは、古い出力の參照やテキストのコピーに便利です。

CTRL-W キーを使用して次のウィンドウに切り替へるための CTRL-W w などのウィンドウコマンドを開始できます。これは插入モードでも機能します (單語を削除するには Shift-CTRL-W を使用します)。ウィンドウを離れたとき插入モードは停止します。プロンプトウィンドウに戾ると、插入モードが復元されます。

"a", "i", "A" や "I" などの插入モードを開始するコマンドは、最終行にカーソルを移動します。"A" は 行末に移動し、"I" は行頭に移動します。


Up: 目次   [Index]