最近再次在macOS 上开始 vterm,发现性能很好,终于不用经常切换到 iterm2 使用终端了。
我用的是 zsh,只要在 ~/.zshrc
中加入以下配置,dired 就能和 term 同步目录了。
# vterm
if [[ "$INSIDE_EMACS" = 'vterm' ]] \
&& [[ -n ${EMACS_VTERM_PATH} ]] \
&& [[ -f ${EMACS_VTERM_PATH}/etc/emacs-vterm-zsh.sh ]]; then
source ${EMACS_VTERM_PATH}/etc/emacs-vterm-zsh.sh
fi
如果希望有更好的体验,强烈推荐安装 vterm-toggle ,方便随时调出 vterm。再订制一个 vterm-compile
函数,就可以不用 M-x compile 了。
不过官方README 中推荐的 vterm-compile
设置有点问题,如果 vterm 窗口正在显示时就没法工作,我稍加修改一下,就可以在任意的非 vterm buffer 中通过 vterm-compile
命令进行编译,分享给需要的朋友。
在 vterm-compile 中加入了compilation-shell-minor-mode
, 如果编译出错,就可以直接点击出错位置跳转到相应的行 ,非常方便。
(defvar vterm-compile-buffer nil)
(defun vterm-compile ()
"Compile the program including the current buffer in `vterm'."
(interactive)
(let* ((command (eval compile-command))
(w (vterm-toggle--get-window)))
(setq compile-command (compilation-read-command command))
(let ((vterm-toggle-use-dedicated-buffer t)
(vterm-toggle--vterm-dedicated-buffer (if w (vterm-toggle-hide)
vterm-compile-buffer)))
(with-current-buffer (vterm-toggle-cd)
(setq vterm-compile-buffer (current-buffer))
(rename-buffer "*vterm compilation*")
(compilation-shell-minor-mode 1)
(vterm-send-M-w)
(vterm-send-string compile-command t)
(vterm-send-return)))))
这是本人的 vterm 设置 :
12 个赞
cireu
2022 年4 月 11 日 14:22
4
vterm 是利用 libvterm
这个抽象终端实现,然后渲染进 Emacs buffer 里.
Alacritty 是用 OpenGL 渲染的, 终端实现是自己用 Rust 写的.
vterm 的优点是和 Emacs 结合紧密, 至于 OpenGL 渲染, 对于终端来说, 作用有限. 反正终端基本都是纯文本.
5 个赞
vterm 里面可以 Ctrl-x Ctrl-e
编辑大段内容吗?
刚刚试了下,C-x C-e
是可以用的,不知道你说的编辑大段内容是怎么样的应用?
dcy
2022 年4 月 11 日 14:51
7
并且在vterm中使用emacsclient很丝滑,宛如eshell 中使用 find-file
1 个赞
还有这样用啊,在emacs 里面怎么不直接 find-file?
我试过用在vterm 里跑 vim,也丝滑
刚刚试了 emacsclient 确实很快,
这是无限套娃的节奏!
1 个赞
dcy
2022 年4 月 11 日 15:06
9
就…我写python目录一般是这样的
.
├── poetry.lock
├── pyproject.toml
├── readme.org
├── src
│ ├── __init__.py
│ ├── __pycache__
│ ├── config.py
│ └── var_cov.py
└── tests
├── __init__.py
├── __pycache__
└── test_src.py
在子目录下 python xxx.py运行完,符合预期写到 org 文档里面,不符合就emacsclient打开
感谢分享工作流。
我个人还是比较习惯 C-x C-f
打开文件,会跟随当前 vterm 所在的目录,可能因为我主要用原生按键习惯了😄。
用 emacsclient 的话在 eglot 中会提示有些特性不支持,不过其他基础编辑功能都很好。
就是从命令行进入多行编辑状态。在 bash 里的快捷键是 Ctrl-x Ctrl-e
,在 fish 里是 Meta-e
:
edit-and-execute-command (C-xC-e)
Invoke an editor on the current command line, and execute the
result as shell commands. Bash attempts to invoke $VISUAL, $EDITOR,
and emacs as the editor, in that order.
你打开 iTmer2 试一下,看看跟 vterm 的是不是一回事。
原来是这个功能。vterm 默认没有定义 C-x C-e
,所以目前执行还是会执行 emacs 的 eval-last-sexp
.
这个需求得请教一下 @jixiuf 大佬了。我目前没找到相关的命令。
看来是不支持了。
虽然我还没用上 vterm,但是正在考虑让 separedit 支持 vterm。不过麻烦的是 vterm--get-prompt-point
函数不能返回正确的位置。例如,按 C-p
召回上一条命令:
$ echo '1
2
3'
M-: (vterm--get-prompt-point)
只能返回 3
的位置,正确应该是返回 $
的位置。这算不算是 bug?
如果手动 C-a
移动光标到 prompt 位置,那么目前已经可以通过 separedit
进行多行编辑了:
开 vterm copy mode,然后执行 vterm-previous-prompt
是可以移动到 $ 那里的。
你看看这个函数里面调用了什么
vterm-previous-prompt
调用的是 vterm--get-prompt-point
,而且要指定参数 N
,无法自动探测到期望的位置:
$ echo '1
2
3'
上边执行 (vterm-previous-prompt 1)
返回的是 2
的位置。
vterm--get-prompt-point
和 vterm-[previous,next]-prompt
都把是否携带 vterm-prompt
属性当作判断 prompt 的依据,可是默认配置下 prompt 根本不带这个属性。可能这就是 bug 的原因?
先前还试过不断 (vterm-send-left)
,直到光标位置不动为止,后来发现这些 send 函数都是异步的,执行之后立即获取到的 (point)
没有变化:
(let ((last-point (point)))
(vterm-send-left)
(list last-point (point)))
;; => (81 81)
我前面截图展示的功能里做过很多尝试。
而且,不开 copy mode 无法用 overlay 锁定编辑内容:
我想到一个更好的方案,就是把 C-x C-e 绑定到一个函数,这个函数接收 vterm 的 buffer name 用于等会儿定位到要发回去的地方。
然后函数里触发打开一个 shell mode 的空 buffer,在这个 buffer 里编辑完之后,然后按 C-c C-c 把 buffer 中的内容发送给函数参数中传来的 vterm 所在的 buffer。
在这个临时 buffer 里可以绑定两个快捷键,一个是只发送 buffer 内容但不执行,一个是发送并执行(就多 send 一个回车的动作给 vterm buffer)。
如果是新的编辑,也许可以这么做。
但如果是召回上一条命令,进行修改,然后发给 vterm。就会遇到我说的问题。
首先你要定位 prompt,获得还未提交执行的内容。然后保护现场不被修改,把内容放到另外一个地方编辑。编辑好了发回 vterm,覆盖旧的内容,解除保护。
1 个赞
vterm和evil的协作该如何避免冲突呢?官方的issue里好像有关于这个问题的讨论,建议似乎是在vterm中默认使用emacs-state,然后需要的话再开启zsh的vim-mode,这感觉就有点多此一举了……