Vim documentation: channel
*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()|。