我有一个.sh
包含 shell 命令的文件,例如:
echo "What shall are we running?"
if [ "$0" == "-bash" ]; then
echo "I'm running a bash"
else
echo "Not a bash"
fi
ls -al | less
htop
我想在 Emacs (27.2) 中一次一行地浏览这些文件(出于教学目的),并将每一行发送到 macOS (12.1) 终端应用程序Terminal.app
。
与此最密切相关的帖子似乎是
这但这些解决方案都不太好用。例如,使用tmux
inside Terminal.app
,结合使用emamux
不起作用,因为后者不允许发送完整的行(并且使用的解决方案tmux
除了过度之外还有一些缺点)。得票最少的答案这里提出了 iTerm 的一个想法。最重要的功能是iterm-send-string
,但我没有使用 Emacs Lisp 编程的经验,所以无法让它发挥作用。
我发现的另一个想法是eepitch
,但我不想将我的 shell 脚本与其他输入混淆(同样,出于教学目的)。另一个想法是这,但适用于 GNU/Linux。
这些问题的常见答案似乎是“为什么不使用 Mx (e)shell?”到目前为止,效果最好的确实是M-x ansi-term
结合
这种方法. 问题是shell
,eshell
和 都不ansi-term
等同于Terminal.app
,例如,上例中的最后两行 shell 脚本 ( less
, htop
) 在 中不起作用ansi-term
。因此,我现在最好的解决方案是逐步执行 shell 脚本中的“大多数”行,ansi-term
并偶尔Terminal.app
执行在 中不起作用的命令ansi-term
。
答案1
我尝试使用 AppleScript 脚本向终端发送命令。这有效,但从 Emacs 与 AppleScript 对话却无效。经过长时间的搜索,我偶然发现了vterm
这里,这是一个与我预期不同的解决方案,但更好,因为它vterm
可以在 Emacs 缓冲区中运行。所以我的解决方案是这样的:
安装
vterm
。对我来说,这是brew install cmake libvterm
,然后M-x list-packages
(=> 安装vterm
)。在
.emacs
我有(global-set-key (kbd "C-c v") #'vterm-other-window)
,然后以下(直接改编这篇文章的解决方案):(defun isend-with-vterm () (interactive) (let ((term-buf (get-buffer "*vterm*"))) (unless term-buf (display-buffer (save-window-excursion (save-current-buffer (setq term-buf (vterm (or explicit-shell-file-name (getenv "ESHELL") shell-file-name))))))) (isend-associate (buffer-name term-buf)))) (define-key global-map [C-return] 'isend-with-vterm) (defun isend-dissociate-on-kill (buffer-name) (let ((buf (get-buffer buffer-name)) (orig-buffer (current-buffer))) (with-current-buffer buf (add-hook 'kill-buffer-hook `(lambda () (with-current-buffer ,orig-buffer (isend-mode -1))) nil t)))) (advice-add 'isend-associate :after #'isend-dissociate-on-kill)
- 这允许
vterm
通过启动C-c v
,然后我可以通过重复 将当前行vterm
从代码缓冲区(例如某个.sh
文件)发送到C-RET
。 重点是比或更vterm
强大。shell
eshell
ansi-term
如果您不想弄乱.emacs
,那么只需执行M-x vterm-other-window
,然后(从.sh
文件中)执行M-x isend-associate + RET + *vterm* + RET
,您就会获得相同的功能。