Emacs Lisp shell进程参数问题

4

我正在尝试从xemacs直接运行P4V命令。 在将p4.el导入到emacs后,我编写了以下内容:

(defun p4v-command (cmd)
  (get-buffer-create p4-output-buffer-name);; We do these two lines
  (kill-buffer p4-output-buffer-name)      ;; to ensure no duplicates
  (call-process "p4v" nil (get-buffer-create p4-output-buffer-name) nil
                "-p" (p4-get-p4-port)
                "-u" "UserName"
                "-c" (p4-current-client)
                "-cmd" (shell-quote-argument (concat cmd " " (buffer-name))))
  (display-buffer p4-output-buffer-name))

我正在尝试获取Shell命令的以下内容(当cmd等于prevdiff时):

p4v -p port -u user -c client -cmd "prevdiff file.txt"

然而,当我使用prevdiff执行上述功能时,我收到以下错误信息。
P4V: unrecognized argument '"prevdiff' for '-cmd' option.

看起来,call-process正在将带引号的字符串“prevdiff file.txt”拆分为单独的参数,并且P4V仅处理第一个参数。

我尝试了其他命令使用call-process并没有这种情况,所以我不确定是Lisp的问题还是与P4V有关。

有人知道如何解决吗?


我无法完全重现您所看到的情况,但您确定需要在其中使用(shell-quote-argument ...)吗?似乎call-process直接将参数传递给进程,而不使用shell。如果您不尝试引用参数会发生什么? - Mike Dinsdale
谢谢Mike。我想我确实需要它。它将引号插入字符串中,因此您会得到一个带有 ""prevdiff file.txt"" 的字符串。这意味着在传递给shell命令时,该字符串被包裹在引号中。 - sickgemini
1个回答

4

call-process绝对不会连接其参数; 它直接将它们传递给程序。 为了证明这一点,请键入M-:并评估以下表达式:

(call-process "/bin/ls" nil "*scratch*" nil "avg ba")

"avg"和"ba"是当前目录中的文件。我在scratch缓冲区中得到了以下消息:

/bin/ls: cannot access avg ba: No such file or directory

如果call-process重新解析参数,它会将"avg ba"分成两个独立的参数---但错误消息显示它没有这样做。
相反,问题出在shell-quote-argument上。当我在scratch缓冲区中评估你提到的调用时,我得到以下结果:
(shell-quote-argument "prevdiff file.txt")
"prevdiff\\ file.txt"

换句话说,p4v命令实际接收的是你在shell中输入的内容:
p4v -p port -u user -c client -cmd '"prevdiff file.txt"'

这就是为什么p4v会抱怨“prevdiff”的原因。
所以我认为你想要的是:
"-cmd" (concat cmd " " (shell-quote-argument (buffer-name))))

(但是当然要检查我的括号。)

这不太对:当你得到"prevdiff\\ file.text"并将其传递给call-process时,引号不会被发送到进程中(它们是elisp字符串语法的一部分,而不是字符串的一部分)。我认为发生的事情是@Jim Blandy和我在类Unix系统上,而@Jeremy Simon在Windows上,在那里shell-quote-argument将返回"\"prevdiff file.txt\""。这可以解释p4v错误。 - Mike Dinsdale
是的,Mike,你说得对。我误读了scratch缓冲区中的内容。Jeremy,我很高兴我的错误和操作系统的差异抵消了! - Jim Blandy
从Emacs Lisp手册中:;; 这个例子展示了在MS-DOS和MS-Windows上的行为。 (shell-quote-argument "foo > bar") => "\"foo > bar\""并且有额外的引号。 - Jim Blandy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接