创建 同步进程(synchronous process) 之后,Emacs 会等待该进程终止才继续执行。在 GNU 或 Unix 系统中启动 Dired29 就是一例:它以同步进程运行 ls,之后略微修改输出。由于进程是同步的,整个目录列表会先全部进入缓冲区,Emacs 才会对其进行后续处理。
当 Emacs 等待同步子进程终止时,用户可以按 C-g 退出。第一次按下 C-g 会尝试以 SIGINT 信号终止子进程,但会等待子进程实际结束后再退出。如果在此期间用户再次按下 C-g,则会立即以 SIGKILL 杀死子进程并直接退出(MS-DOS 除外,该系统无法杀死其他进程)。See 退出.
同步子进程相关函数会返回进程的终止状态。
同步子进程的输出通常会使用编码系统解码,与从文件读取文本类似。由 call-process-region 发送给子进程的输入会使用编码系统编码,与写入文件的文本类似。See 编码系统.
该函数调用 program 并等待其运行结束。
子进程的当前工作目录会设为当前缓冲区的 default-directory 值(前提是本地目录,由 unhandled-file-name-directory 判断),否则设为 "~"。若需要在远程目录运行进程,请使用 process-file。
若 infile 不为 nil,新进程的标准输入来自文件 infile,否则来自空设备。参数 destination 指明进程输出的去向,可选值如下:
将输出插入该缓冲区中点之前,包含进程的标准输出流和标准错误流。
将输出插入对应名称的缓冲区中点之前。
t将输出插入当前缓冲区中点之前。
nil丢弃输出。
丢弃输出,并立即返回 nil,不等待子进程结束。
这种情况下进程并非真正同步,因为它可与 Emacs 并行运行;但可以视作同步,因为该函数返回后 Emacs 就不再处理该子进程。
MS-DOS 不支持异步子进程,因此该选项无效。
(:file file-name)将输出写入指定文件,文件已存在则覆盖。
(real-destination error-destination)将标准输出与标准错误流分开处理;按 real-destination 处理普通输出,按 error-destination 处理错误输出。若 error-destination 为 nil 表示丢弃错误输出,t 表示与普通输出混合,字符串则指定重定向错误输出的文件名。
不能直接指定缓冲区存放错误输出,实现难度较高。但可以先将错误输出写入临时文件,子进程结束后再读入缓冲区。
若 display 非 nil,call-process 会在插入输出时重新刷新缓冲区。(不过,若用于解码输出的编码系统为 undecided,即根据实际数据推断编码,遇到非 ASCII 字符时刷新有时会中断。此问题存在底层原因难以修复,参见 接收进程输出。)
否则 call-process 不会刷新,结果仅在 Emacs 正常刷新缓冲区时才显示在屏幕上。
剩余参数 args 为字符串,指定程序的命令行参数。每个字符串作为独立参数传递给 program。
call-process 的返回值(未设置不等待时)表示进程终止原因。数字为子进程退出状态码;0 表示成功,其他值表示失败。若进程因信号终止,返回描述该信号的字符串。若设置不等待,则返回 nil。
下面示例中,缓冲区 ‘foo’ 为当前缓冲区。
(call-process "pwd" nil t)
⇒ 0
---------- Buffer: foo ----------
/home/lewis/manual
---------- Buffer: foo ----------
(call-process "grep" nil "bar" nil "lewis" "/etc/passwd")
⇒ 0
---------- Buffer: bar ----------
lewis:x:1001:1001:Bil Lewis,,,,:/home/lewis:/bin/bash
---------- Buffer: bar ----------
以下是 call-process 的使用示例,曾用于 insert-directory 函数定义:
(call-process insert-directory-program nil t nil switches
(if full-directory-p
(concat (file-name-as-directory file) ".")
file))
该函数在独立进程中同步处理文件。用法与 call-process 类似,但会根据变量 default-directory(子进程当前工作目录)调用文件名处理器。
参数用法与 call-process 基本一致,区别如下:
部分文件名处理器可能不支持 infile、buffer、display 的所有组合与格式。例如,部分处理器可能无视传入值,将 display 当作 nil 处理;又如,部分处理器可能不支持通过 buffer 参数分离标准输出与错误输出。
若调用文件名处理器,它会根据第一个参数 program 决定要运行的程序。例如,若触发远程文件处理器,搜索程序的路径可能与 exec-path 不同。
第二个参数 infile 可能触发文件名处理器,该处理器可能与 process-file 自身所用处理器不同。(例如,default-directory 位于一台远程主机,而 infile 位于另一台;或 default-directory 为普通路径,而 infile 位于远程主机。)
若 buffer 为 (real-destination error-destination) 列表形式,且 error-destination 为文件名,则规则与 infile 相同。
剩余参数 args 会原样传递给进程。Emacs 不处理 args 中包含的文件名。为避免混淆,最好不要在 args 中使用绝对文件名,而应全部指定为相对于 default-directory 的路径。函数 file-relative-name 可用于构造此类相对路径。或者,也可以使用 file-local-name(see 实现“魔法”文件名机制)获取远程主机视角下的绝对路径。
该变量表示调用 process-file 是否会修改远程文件。
默认始终为 t,表示调用 process-file 可能修改远程主机上的任意文件。设为 nil 时,文件名处理器可针对远程文件属性缓存优化行为。
仅应通过 let 绑定修改该变量,不可使用 setq。
该用户选项表示 process-file 调用是否返回描述中断远程进程信号的字符串。
若进程退出码大于 128,会被解释为信号。process-file 需要返回描述该信号的字符串。
由于部分进程不遵循此规则,退出码大于 128 却不对应信号,因此 process-file 对远程进程始终以自然数返回退出码。将该选项设为非 nil 可强制其将此类退出码解释为信号,并返回对应字符串。
该函数将缓冲区中从 start 到 end 的文本作为标准输入发送给运行 program 的进程。若 delete 非 nil,则删除已发送文本;当 destination 为 t 时,可在当前缓冲区以输出替换输入。
参数 destination 与 display 控制子进程输出的处理方式及是否随输出刷新显示,详情参见上文 call-process。若 destination 为整数 0,call-process-region 会丢弃输出并立即返回 nil,不等待子进程结束(仅在支持异步子进程的系统有效,MS-DOS 除外)。
剩余参数 args 为字符串,指定程序的命令行参数。
call-process-region 返回值与 call-process 相同:设置不等待则返回 nil,否则为数字或字符串,表示子进程终止方式。
下例使用 call-process-region 运行工具 cat,标准输入为缓冲区 ‘foo’ 前五个字符(单词 ‘input’)。cat 将标准输入复制到标准输出。由于 destination 为 t,输出被插入当前缓冲区。
---------- Buffer: foo ---------- input∗ ---------- Buffer: foo ----------
(call-process-region 1 6 "cat" nil t)
⇒ 0
---------- Buffer: foo ----------
inputinput∗
---------- Buffer: foo ----------
例如,命令 shell-command-on-region 以类似方式使用 call-shell-region:
(call-shell-region
start end
command ; shell 命令
nil ; 不删除区域
buffer) ; 将输出发送至 buffer
该函数同步执行 Shell 命令 command。其余参数与 call-process 一致。旧调用约定允许在 display 后传入任意数量附加参数并拼接到 command,该用法仍兼容但强烈不推荐。
该函数与 call-process-shell-command 类似,但内部使用 process-file。根据 default-directory,command 也可在远程主机执行。旧调用约定允许在 display 后传入任意数量附加参数并拼接到 command,该用法仍兼容但强烈不推荐。
该函数将缓冲区中从 start 到 end 的文本作为标准输入,发送给运行 command 的子 Shell。功能与 call-process-region 类似,只是进程为 Shell。参数 delete、destination 及返回值均与 call-process-region 相同。
注意该函数不接受额外参数。
若 command 指定 Shell(例如通过 shell-file-name),需注意:当命令通过标准输入管道传递给 Shell 时,不同 Shell 的行为与系统相关,因此不具备可移植性。当区域包含多行内容(即管道传递带换行的 Shell 命令)时差异尤为明显。使用该方式的 Lisp 程序需要根据 Shell 预期对区域内文本做不同格式化。
该函数执行 Shell 命令 command(字符串),并以字符串形式返回命令输出。若 command 包含多条命令,行为取决于所调用的 Shell(本地命令由 shell-file-name 决定)。特别地,MS-Windows 系统中命令分隔符不能为换行符,应使用 ‘&&’。
该函数运行 program 并等待其结束,以字符串列表形式返回输出。列表中每个字符串为程序输出的一行文本,每行末尾换行符已去除。program 之后的参数 args 为字符串,指定运行程序的命令行参数。
若 program 以非零退出状态结束,该函数会抛出错误。
该函数通过调用 call-process 实现,因此程序输出的解码方式与 call-process 相同。
该函数与 process-lines 完全相同,但 program 以非零状态退出时不会抛出错误。