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()|