自 Emacs 如何运行交换式的 shell 命令 继续讨论:
Emacs 自带终端模拟器 (M-x term
),不过对于需要用到终端的命令,比如 man
, less
, vim
等,我还是习惯用专门的终端程序,对于已经运行在终端中的 Emacs, suspend-emacs
能实现这一点:
(suspend-emacs "man ls ; fg")
这里的参数是一个 Shell 命令。为了方便使用,封装成一个用户命令:
(defun terminal-shell-command (command)
"Suspend Emacs, run COMMAND in the Terminal."
(interactive "sShell command: ")
(suspend-emacs command))
于是乎似乎可以实现跟 Vim 的 !
类似的效果(?):
M-x terminal-shell-command RET man ls ; fg RET
suspend-emacs
在 Lisp 和 Shell Command 间构造了一个桥梁,因此我们构造一个更高级 Lisp 函数,自动化这一过程:
(defun terminal-shell-command-to-string (command)
"Suspend Emacs, run COMMAND in the Terminal, then resume Emacs."
(suspend-emacs (concat command " > /tmp/shell-command.output ; fg"))
(shell-command-to-string "cat /tmp/shell-command.output"))
一个应用是,实现 peco1 + Emacs 的协作,效果应该和 peco + vim 差不多。
(defun peco-find-file (command)
"Run `find-file' on the output of 'COMMAND | peco'."
(interactive "sShell 'Command' | peco: ")
(let ((files (split-string
(terminal-shell-command-to-string (concat command " | peco"))
"\n" t)))
(mapc #'find-file files)))
1 peco 感觉像是终端版本的 Helm。