如何逐行执行 shell 脚本并将每行发送到终端?

如何逐行执行 shell 脚本并将每行发送到终端?

我有一个.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

与此最密切相关的帖子似乎是 但这些解决方案都不太好用。例如,使用tmuxinside Terminal.app,结合使用emamux不起作用,因为后者不允许发送完整的行(并且使用的解决方案tmux除了过度之外还有一些缺点)。得票最少的答案这里提出了 iTerm 的一个想法。最重要的功能是iterm-send-string,但我没有使用 Emacs Lisp 编程的经验,所以无法让它发挥作用。

我发现的另一个想法是eepitch,但我不想将我的 shell 脚本与其他输入混淆(同样,出于教学目的)。另一个想法是,但适用于 GNU/Linux。

这些问题的常见答案似乎是“为什么不使用 Mx (e)shell?”到目前为止,效果最好的确实是M-x ansi-term结合 这种方法. 问题是shelleshell和 都不ansi-term等同于Terminal.app,例如,上例中的最后两行 shell 脚本 ( less, htop) 在 中不起作用ansi-term。因此,我现在最好的解决方案是逐步执行 shell 脚本中的“大多数”行,ansi-term并偶尔Terminal.app执行在 中不起作用的命令ansi-term

答案1

我尝试使用 AppleScript 脚本向终端发送命令。这有效,但从 Emacs 与 AppleScript 对话却无效。经过长时间的搜索,我偶然发现了vterm 这里,这是一个与我预期不同的解决方案,但更好,因为它vterm可以在 Emacs 缓冲区中运行。所以我的解决方案是这样的:

  1. 安装vterm。对我来说,这是brew install cmake libvterm,然后M-x list-packages(=> 安装vterm)。

  2. .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)
    
  1. 这允许vterm通过启动C-c v,然后我可以通过重复 将当前行vterm从代码缓冲区(例如某个.sh文件)发送到C-RET。 重点是比或更vterm强大。shelleshellansi-term

如果您不想弄乱.emacs,那么只需执行M-x vterm-other-window,然后(从.sh文件中)执行M-x isend-associate + RET + *vterm* + RET,您就会获得相同的功能。

相关内容