*channel.txt* 	For Vim version 8.0.  最近更新: 2017年7月


		  VIM 参考手册    by Bram Moolenaar
				译者: Willis
				http://vimcdoc.sf.net


		      进 程 间 通 信				*channel*

Vim 使用通道 (channel) 和其他进程通信。
通道使用套接字 (socket) 或管道 pipe 机制。 		*socket-interface*
作业 (job) 用来启动进程并与之通信。
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. 带通道启动作业  			|job-start|
9. 不带通道启动作业			|job-start-nochannel|
10. 作业选项				|job-options|
11. 控制作业				|job-control|

{Vi 没有这些功能}
{仅当编译时带有 |+channel| 特性时才有通道功能}
	可以这样查看: `has('channel')`
{仅当编译时带有 |+job| 特性时才有作业功能}
	可以这样查看: `has('job')`

==============================================================================
1. 总览						*job-channel-overview*

有四种主要的作业类型:
1. 守护进程 (daemon)，服务于多个 Vim 实例。
   Vim 使用套接字连接。
2. 用于单个 Vim 实例的单个作业，异步操作。
   使用套接字或管道。
3. 用于短期若干工作的作业，异步操作。
   使用套接字或管道。
4. 作为过滤器，同步操作。
   使用管道。

使用套接字请见 |job-start|、|job-start-nochannel| 和 |channel-open|。2 和 3 类
中一个或多个作业若使用管道，可见 |job-start|。4 类即 ":{range}!cmd" 命令，参见
|filter|。

套接字和管道可用以下协议:
RAW	无规范，Vim 不知信息如何终止
NL	每条信息由 NL (换行) 字符终止
JSON	JSON 编码 |json_encode()|
JS	JavaScript 风格类 JSON 的编码 |js_encode()|

常用组合有:
- 使用 NL 模式的管道连接的作业。例如，运行风格检查器并接收错误与警告。
- 使用 JSON 模式的套接字连接的守护进程。例如，从数据库中查找交叉索引。

==============================================================================
2. 通道演示				*channel-demo* *demoserver.py*

需要 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 中可以看到该消息。要移动光标前进一个单词:
	["normal","w"] ~

要处理异步通信，需要提供回调函数: >
	func MyHandler(channel, msg)
	  echo "from the handler: " . a:msg
	endfunc
	call ch_sendexpr(channel, 'hello!', {'callback': "MyHandler"})
Vim 不会等待响应。这样，服务器就可以稍后发送响应，响应时会调用 MyHandler。

回调除了每次在发送时以外，也可以在打开通道时提供: >
	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. 打开通道						*channel-open*

要打开通道: >
    let channel = ch_open({address} [, {options}])
    if ch_status(channel) == "open"
      " use the channel

可用 |ch_status()| 看到通道是否已打开。

{address} 的格式为 "hostname:port"。例如 "localhost:8765"。

{options} 是可选项目的字典:				*channel-open-options*

"mode" 可以是:						*channel-mode*
	"json" - JSON，见下；最方便的方式。缺省。
	"js"   - JS (JavaScript) 编码，比 JSON 经济。
	"nl"   - Nl 字符结尾的消息
	"raw"  - 原始消息
						*channel-callback* *E921*
"callback"	消息收到时，如果还未被处理，调用本函数。接受两个参数: 通道和收
		到的消息。例如: >
	func Handle(channel, msg)
	  echo 'Received: ' . a:msg
	endfunc
	let channel = ch_open("localhost:8765", {"callback": "Handle"})
<
		"mode" 如果是 "json" 或 "js"，"msg" 参数是转换到 Vim 类型的收
		到消息的正文。
		"mode" 如果是 "nl"，"msg" 参数是单个消息，不包含 NL。
		"mode" 如果是 "raw"，"msg" 参数是作为字符串的整个消息。

		对所有的回调: 可用 |function()| 绑定它到参数和/或字典。也可用
		"dict.function" 形式来绑定到字典。

		只有在 "安全" 时才会调用回调函数，通常是 Vim 等待用户输入字符
		的时候。Vim 不支持多线程。

							*close_cb*
"close_cb"	通道关闭时，除非调用了 ch_close()，调用本函数。定义如下: >
	func MyCloseHandler(channel)
<		Vim 会调用回调函数先处理完所有数据，然后再调用 close_cb。当此
		函数调用时，不会再有更多数据传到回调函数。
							*channel-drop*
"drop"		指定如何丢弃消息:
		    "auto"	没有回调来处理消息时。"close_cb" 也考虑在内。
		    "never"	所有消息都会保存。

							*waittime*
"waittime"	等待连接完成的时间，以毫秒计。负数代表永久等待。

		缺省为零，不等待。用于本地服务器已经运行的情形。Unix 上 Vim 实
		际使用 1 毫秒等待时间，在很多系统上这是必要的。对于远程服务服
		务器，使定更高的值，例如，至少 10 毫秒。
							*channel-timeout*
"timeout"	等待请求处理完成的阻塞时间，例如 ch_evalexpr()。以毫秒计。缺省
		为 2000 (2 秒)。

"mode" 为 "json" 或 "js" 时，"callback" 是可选的。省略时只有在发送一条消息后才
能收到消息。

打开通道后要改变通道选项，用 |ch_setoptions()|。参数类似于 |ch_open()| 所用的
参数，但不能指定 "waittime"，因为它只在通道打开时有意义。

例如，可以新增或改变处理函数: >
    call ch_setoptions(channel, {'callback': callback})
"callback" 为空 (零或空字符串) 时删除该处理函数。

回调执行后 Vim 会刷新屏幕，并复原光标之前所在的位置。因而，回调无须执行
`:redraw`。

可以改变 timeout: >
    call ch_setoptions(channel, {'timeout': msec})
<
							  *channel-close* *E906*
用完通道后，这样可以关闭之: >
    call ch_close(channel)
使用套接字时，关闭双向的套接字。使用管道时 (stdin/stdout/stderr)，关闭所有的管
道。这可能不是你想要的！用 job_stop() 停止作业可能更好。
放弃所有预读取，不再调用回调。

注意 通道关闭分三个阶段:
  - I/O 结束，记录日志: "Closing channel"。队列中可能还有消息等待读取或回调。
  - 清理预读取，记录日志: "Clearing channel"。有些变量还可能引用该通道。
  - 释放通道，记录日志: "Freeing channel"。

通道如果不能打开，会报错。MS-Windows 和 Unix 有一点区别。Unix 上如果打不开端
口，会迅速失败。MS-Windows 上会等上 "waittime"。
*E898* *E901* *E902*

读写通道时如果有错，会关闭通道。
*E630* *E631*

==============================================================================
4. 使用 JSON 或 JS 通道						*channel-use*

JSON 模式可以以同步方式发送消息: >
    let response = ch_evalexpr(channel, {expr})
此时，等待对方回复响应。

JS 模式也是如此，但消息使用 JavasScript 编码。其中的区别，见 |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}]

这样 Vim 就会知道哪个发送的消息对应哪个收到的消息，并调用正确的处理函数。即使
消息接收的顺序打乱也不要紧。

JSON 文本以换行符结尾。可用于分隔读取的文本。例如，Python 中:
	splitidx = read_text.find('\n')
	message = read_text[:splitidx]
	rest = read_text[splitidx + 1:]

发送者必须发送合法的 JSON 给 Vim。Vim 会分析 JSON 来检查消息是否完整结尾。只
有完整结尾的消息才会被接受。消息结尾的换行符是可选的。

一个进程如果没有先收到消息，而要主动发送消息给 Vim 时，应使用数值零:
    [0,{response}]

此时通道处理函数会把 {response} 转换为 Vim 类型。如果通道没有处理函数，该消息
被丢弃。

JSON 或 JS 通道也可以用 ch_sendraw() 和 ch_evalraw()。调用者必须自行负责正确的
编码和解码。

==============================================================================
5. 通道命令						*channel-commands*

通过 JSON 通道，进程可以向 Vim 发送一些 Vim 内部可以处理，无需通道处理函数的命
令。

可能命令包括:					*E903* *E904* *E905*
    ["redraw", {forced}]
    ["ex",     {Ex 命令}]
    ["normal", {普通模式命令}]
    ["expr",   {expression}, {number}]
    ["expr",   {expression}]
    ["call",   {函数名}, {参数列表}, {number}]
    ["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'])"] ~
请求中没有第三个参数。


"call" 命令 ~

和 "expr" 类似，但不是把整个表达式作为一个字符串传递，而是分别传递函数名和一个
参数列表。这样有助于避免把参数经过转义、连接等步骤转换为字符串的过程。例如:
	["call", "line", ["$"], -2] ~

如果不需要响应，不用提供第四个参数:
	["call", "setline", ["$", ["one", "two", "three"]]] ~

==============================================================================
6. 使用 RAW 或 NL 通道					*channel-raw*

使用 RAW 或 NL 模式时，可以这样发送信息: >
    let response = ch_evalraw(channel, {string})

{string} 直接传送。响应也是通道读取的直接结果。既然 Vim 不知道如何识别信息怎样
结尾，你需要自己处理。超时只及于首个字节的读取，之后将不再等待。

模式为 "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. 更多通道函数						*channel-more*

要获知通道的状态: ch_status(channel)。可能的值为:
	"fail"		通道打开失败。
	"open"		通道可用。
	"buffered"	通道已关闭，但还有待读的数据。
	"closed"	通道已关闭。

要获知通道相关的作业: ch_getjob(channel)

要从通道读取一条信息: >
	let output = ch_read(channel)
这里使用通道的 timeout。要读取不带超时以获得所有所用的信息: >
	let output = ch_read(channel, {'timeout': 0})
如果无信息可读，结果在 JSON 或 JS 模式通道下为 v:none，RAW 或 NL 通道下为空字
符串。可以用 |ch_canread()| 检查是否有信息可读。

注意 如果没有回调，消息会被丢弃。要避免之，给通道加入一个关闭回调函数。

要读取 RAW 通道所有可用的输出: >
	let output = ch_readraw(channel)
可读取错误输出: >
	let output = ch_readraw(channel, {"part": "err"})

ch_read() 和 ch_readraw() 都适用通道 timeout。如果在该时间内没有任何消息可读，
返回空字符串。要指定其他的超时，使用以毫秒计的 "timeout" 选项:
	{"timeout": 123} ~
要读取错误输出，使用 "part" 选项:
	{"part": "err"} ~
要在 JS 或 JSON 通道上读取指定 ID 的信息:
	{"id": 99} ~
如果没有给出 ID 或 ID 为 -1，返回首个信息。这里的优先级高于等待该信息的回调。

RAW 通道这里返回任何可用的信息，因为 Vim 不知道信息如何终止。
NL 通道这里返回一条信息。
JS 或 JSON 通道这里返回一条解码的信息。
包含任何序列号。

==============================================================================
8. 带通道启动作业  					*job-start* *job*

要启动一个作业并打开对应 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|。

注意 如果作业在你读取输出结果之前结束，输出可能会丢失。这取决于系统 (Unix 上是
如此，因为管道的写入端的关闭使得读取端读到 EOF)。要避免之，作业退出之前可进行
短暂地休眠。

"out_cb" 定义的处理函数不会读 stderr。如果另外要处理错误，加入 "err_cb" 处理函
数: >
    let job = job_start(command, {"out_cb": "MyHandler",
	    \			  "err_cb": "ErrHandler"})

如果要用相同的处理函数同时处理 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


作业从缓冲区获得输入 ~
							*in_io-buffer*
要运行的作业从缓冲区中读取内容: >
	let job = job_start({command},
	    \ {'in_io': 'buffer', 'in_name': 'mybuffer'})
<
							*E915* *E918*
缓冲区是通过名字来查找的，类似于 |bufnr()|。该缓冲区必须存在并在 job_start()
调用时己载入。

缺省读入整个缓冲区。可通过 "in_top" 和 "in_bot" 选项改变。

一个特殊的模式是 "in_top" 设为零而 "in_bot" 不设置: 每次缓冲区加入一行新行时，
倒数第二行被发送到作业的 stdin。这样你可以编辑末行并在回车时将它发送。
							*channel-close-in*
如果不使用这种特殊模式，管道或套接字会在最后一行写入后关闭。这样就告诉了读入端
输入己经完成。也可用 |ch_close_in()| 在更早之前关闭。

文本中的 NUL 字节会被传给作业 (Vim 内部用 NL 字节保存)。


在关闭回调中读取作业输出 ~
							*read-in-close-cb*
如果作业运行需时而你不需要中间结果，可以加入关闭回调函数，在那里读取输出: >

	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" 有用些吧。

==============================================================================
9. 不带通道启动作业					*job-start-nochannel*

要启动别处的进程而不建立通道: >
    let job = job_start(command,
	\ {"in_io": "null", "out_io": "null", "err_io": "null"})

{command} 会在后台启动，Vim 不等待其运行结束。

如果 Vim 看到 stdin、stdout 或 stderr 没有一个被连接，则不会建立通道。一般，你
需要进行重定向以保证命令不会被卡住。

可用选项见 |job-options|。

							*job-start-if-needed*
要想在不能连接某个地址的时候才启动某个作业，可以这么做: >
	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

注意 这里 ch_open() 的 waittime 给作业一秒钟时间使端口可用。

==============================================================================
10. 作业选项						*job-options*

job_start() 的 {options} 参数是一个字典。所有的项目都是可选的。有些选项可以在
作业启动后通过 job_setoptions(job, {options}) 给出。许多选项可通过
ch_setoptions(channel, {options}) 对作业相关的通道给出。
见 |job_setoptions()| 和 |ch_setoptions()|。

						*in_mode* *out_mode* *err_mode*
"in_mode"		stdin 特定的模式，仅适用于管道情形
"out_mode"		stdout 特定的模式，仅适用于管道情形
"err_mode"		stderr 特定的模式，仅适用于管道情形
			可用值参见 |channel-mode|。

			注意: 设置 "mode" 时，覆盖部分特定的模式。因而，先设置
			"mode"，再设置部分特定的模式。

			备注: 写入文件或缓冲区和从缓冲区读取时，缺省使用 NL 模
			式。

						*job-callback*
"callback": handler	通道任何部分有读取内容时的回调。
						*job-out_cb* *out_cb*
"out_cb": handler	stdout 有读取内容时的回调。仅适用于通道使用管道时。如
			果不设 "out_cb"，使用通道本身的回调。
			两个参数是通道和信息。

						*job-err_cb* *err_cb*
"err_cb": handler	stderr 有读取内容时的回调。仅适用于通道使用管道时。如
			果不设 "err_cb"，使用通道本身的回调。
			两个参数是通道和信息。
						*job-close_cb*
"close_cb": handler	通道关闭时的回调。与 |ch_open()| 的 "close_cb" 相同，
			见 |close_cb|。
						*job-drop*
"drop"			指定何时丢弃消息。与 |ch_open()| 的 "drop" 相同，见
			|channel-drop|。如用 "auto"，不考虑 exit_cb。
						*job-exit_cb*
"exit_cb": handler	作业结束时的回调。参数是作业和退出状态。
			对退出的作业，Vim 作最多每秒十次的检查。也可以通过
			|job_status()| 调用触发检查，这样也会调用 exit_cb 处理
			函数。
			备注 数据可能会缓冲，进程结束后还可能调用回调。
							*job-timeout*
"timeout"		等待阻塞请求，如 ch_evalexpr() 等的时间，以毫秒计。缺
			省是 2000 (2 秒)。
						*out_timeout* *err_timeout*
"out_timeout"		stdout 所用的超时。仅适用于管道情形。
"err_timeout"		stderr 所用的超时。仅适用于管道情形。
			注意: 设置 "timeout" 时，覆盖部分特定的模式。因而，先
			设置 "timeout"，再设置部分特定的模式。

						*job-stoponexit*
"stoponexit": {signal}	Vim 结束时给作业发信号 {signal}。可取值参见
			|job_stop()|。
"stoponexit": ""	Vim 结束时不结束作业。
			缺省是 "term"。

						*job-term*
"term": "open"		启动终端并重定向作业的 stdin/stdout/stderr 到终端。
			注意: 尚未实现！

"channel": {channel}	使用己有的通道，而不重新创建。
			新作业所用的通道部分会从之前的使用者处断开。如果通道还
			在被其它的作业使用，这可能会导致 I/O 错误。
			已有的回调和其它设置不变。

				*job-in_io* *in_top* *in_bot* *in_name* *in_buf*
"in_io": "null"		不连接 stdin (从 /dev/null 读取)
"in_io": "pipe"		连接 stdin 到通道 (缺省)
"in_io": "file"		stdin 从文件读取
"in_io": "buffer"	stdin 从缓冲区读取
"in_top": number	用 "buffer" 时: 发送的首行 (缺省: 1)
"in_bot": number	用 "buffer" 时: 发送的末行 (缺省: 最后一行)
"in_name": "/path/file"	读取的文件或缓冲区名
"in_buf": number	读取的缓冲区号

				*job-out_io* *out_name* *out_buf*
"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
			error..."

				*job-err_io* *err_name* *err_buf*
"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 写入是阻塞写入


写入缓冲区 ~
							*out_io-buffer*
如果 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*
"out_modifiable" 和 "err_modifiable" 选项可用来关闭 'modifiable' 选项，或写入
关闭了 'modifiable' 的缓冲区。这意味着新行被附加到缓冲区后，但用户却不能轻易地
修改此缓冲区。
					*out_msg* *err_msg*
"out_msg" 选项可用来指定新缓冲区是否将首行设为 "Reading from channel
output..."。缺省是加入该信息。"err_msg" 则对错误通道同样办理。

如果要写入已有的缓冲区，但其 'modifiable' 已关闭并且 "out_modifiable" 或
"err_modifiable" 选项非零，报错并拒绝写入訪缓冲区。

如果写入的缓冲区在窗口显示并且光标在末行的首列，光标会被移动到新行上，有必要的
话滚动窗口以显示光标所在的位置。

所有新加的行都同步了撤销历史。接受 NUL 字节 (Vim 内部存为 NL 字节)。


写入文件 ~
							*E920*
文件建立的缺省权限为 600 (用户可读写，其它人不能访问)。可用 |setfperm()| 改
变。

如果文件已存在，文件内容被清空。

==============================================================================
11. 控制作业						*job-control*

要获知作业的状态: >
	echo job_status(job)

要停止作业的运行: >
	job_stop(job)

这是停止作业的正常方式，Unix 上会给作业发出 SIGTERM。也可以用其它方式来停止作
业，甚至可以发送任意的信号。例如，要强制终止作业，"杀了它": >
	job_stop(job, "kill")

更多选项，可见 |job_stop()|。


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