Emacs - 对shell-command-on-region的非交互式调用总是删除区域?

时间:2013-05-23 17:40:12

标签: emacs elisp

函数shell-command-on-region的Emacs帮助页面显示(省略空格):

(shell-command-on-region START END COMMAND &optional OUTPUT-BUFFER
REPLACE ERROR-BUFFER DISPLAY-ERROR-BUFFER)

...
The noninteractive arguments are START, END, COMMAND,
OUTPUT-BUFFER, REPLACE, ERROR-BUFFER, and DISPLAY-ERROR-BUFFER.
...

If the optional fourth argument OUTPUT-BUFFER is non-nil,
that says to put the output in some other buffer.
If OUTPUT-BUFFER is a buffer or buffer name, put the output there.
If OUTPUT-BUFFER is not a buffer and not nil,
insert output in the current buffer.
In either case, the output is inserted after point (leaving mark after it).

If REPLACE, the optional fifth argument, is non-nil, that means insert
the output in place of text from START to END, putting point and mark
around it.

这不是最清楚的,但刚才引用的最后几句话似乎说如果我想将shell命令的输出插入当前缓冲区的点,让缓冲区的其他内容保持不变,我应为nil传递非OUTPUT-BUFFER参数,nil传递REPLACE

但是,如果我在*scratch*缓冲区中执行此代码(不是我正在处理的实际代码,而是演示该问题的最小案例):

(shell-command-on-region
 (point-min) (point-max) "wc" t nil)

删除缓冲区的全部内容并替换为wc

的输出

非交互式使用时shell-command-on-region是否被破坏,或者我误读了文档?如果是后者,我怎么能改变上面的代码来插入wc的输出而不是替换缓冲区的内容?理想情况下,我想要一个通用的解决方案,不仅可以在最小的示例中运行整个缓冲区上的命令(例如,(point-min)(point-max)),还可以用于运行命令的情况将该区域作为输入,然后在不删除该区域的情况下插入结果。

3 个答案:

答案 0 :(得分:4)

你错了

在emacs lisp代码中使用shell-command-on-region之类的交互式命令并不是一个好主意。请改用call-process-region

Emacs错了

shell-command-on-region中存在错误:它未将replace参数传递给call-process-region;这是修复:

=== modified file 'lisp/simple.el'
--- lisp/simple.el  2013-05-16 03:41:52 +0000
+++ lisp/simple.el  2013-05-23 18:44:16 +0000
@@ -2923,7 +2923,7 @@ interactively, this is t."
      (goto-char start)
      (and replace (push-mark (point) 'nomsg))
      (setq exit-status
-       (call-process-region start end shell-file-name t
+       (call-process-region start end shell-file-name replace
                     (if error-file
                     (list t error-file)
                       t)

我很快就会答应。

答案 1 :(得分:2)

如果你点击功能源代码的链接,你会很快看到它的确:

(if (or replace
    (and output-buffer
     (not (or (bufferp output-buffer) (stringp output-buffer)))))

我不知道为什么会那样做,所以。在任何情况下,这主要是指一个命令而不是一个函数;来自Elisp我建议您改用call-process-region

答案 2 :(得分:1)

在我的情况下(emacs 24.3,不知道你正在使用什么版本),文档在可选参数中略有不同:

Optional fourth arg OUTPUT-BUFFER specifies where to put the
command's output.  If the value is a buffer or buffer name, put
the output there.  Any other value, including nil, means to
insert the output in the current buffer.  In either case, the
output is inserted after point (leaving mark after it).

检查是否删除输出(当前)缓冲区内容的代码如下:

(if (or replace
    (and output-buffer
     (not (or (bufferp output-buffer) (stringp output-buffer)))))

如此明确地将t放在你的情况下,它不是字符串或缓冲区,并且它不是nil,因此它将用输出替换当前缓冲区内容。但是,如果我尝试:

(shell-command-on-region
 (point-min) (point-max) "wc" nil nil)

然后不删除缓冲区,并将输出放入“ Shell命令输出”缓冲区。乍一看,我说这个功能没有正确实现。即使文档的两个版本似乎也不符合代码。