【分享】vterm 才是Emacs中我最棒的终端模拟器

我这里试了 vterm--get-prompt-point 返回的是正确的位置
你那边有没有配 readme 里说的 prompt tracking 相关的配置呢?GitHub - akermu/emacs-libvterm: Emacs libvterm integration

多行情况下?

prompt 文本有携带者 vterm-prompt 属性?

多行情况下是正确的。

这句没理解

光标放在 e 上,执行 point,结果是 646 image image

光标放在 3‘ 上,执行 vterm–get-prompt-point,结果是 646 image image

光标放在 3’ 上,执行 point,结果是 658
image

看起来我这边应该是正常的

进入 copy mode 把光标移动到了prompt 符号上,describe-char。我这边看到的 face 是 default,可能就是探测不到正确位置的原因。

有可能,不过我之前都不知道可以有这个功能哈哈。明天蹲一波看看你有没有什么好的实现方案。
我明天也尝试写一个看看。我先休息啦,你也早点休息 :sleeping:

我很久没用 evil 了,不是很清楚。看看有没有大佬在 vterm 上用 evil 的。
官方 Readme 有说明,vterm 不支持 evil-mode,因为按键都是发送给 shell了,也许以后会在这方面进行改进。

用了一年多了,可惜有些 bug,一直忍着。

遇到什么bug了? 去给 vterm 报个 issue?

果然是我这边 PS1 设置问题,导致 prompt 没有渲染。

我的设置还是最早试用 vterm 留下的:

vterm_prompt_end(){
    printf "\e]51;A$(whoami)@$(hostname):$(pwd)\e\\"
}
PS1=$PS1'$(vterm_prompt_end)'

现在是:

vterm_prompt_end(){
    vterm_printf "51;A$(whoami)@$(hostname):$(pwd)"
}
PS1=$PS1'\[$(vterm_prompt_end)\]'

两者用了不同的 print 函数。

除了这个 promt 位置的问题,我这边其他工作早就完成了。

2 个赞

请教下是怎么获取 vterm 输入的记录,以及如何覆盖原来的输入么?

我是默认 insert-state,需要时按 ESC,用一些基本的操作没有问题

在normal-state下,移动光标之后,再次进入insert-state,光标的位置又会回到进入normal-state之前的位置,类似的问题还比较多的。

1 个赞

@twlz0ne 请问你是怎么拿到多行情况下最后一行末尾的位置的?

我是在 separedit 的基础上实现的。编辑的是当前可见(&可编辑)的内容。不是从直接从历史记录中获取,vterm 似乎没有提供相关接口。只有通过发送 C-n 按键,把旧的命令召回。

我现在全部自己用 (vterm-send-key ...) 来操作,不依赖 vterm 提供的高级函数。

原因如下:

prompt 正确之后,反而暴露了更多问题。例如 vterm-delete-region 无法删除合理范围内的内容:

bash-3.2$ echo '1
2
3'

光标位于以上内容的末尾,执行 (vterm-delete-region (vterm--get-prompt-point) (point)) 无效。

调试发现这个函数(以及相关的函数都)有点不正常:

(defun vterm-delete-region (start end)
  "Delete the text between START and END for vterm. "
  (when vterm--term
    (if (vterm-goto-char start) ;; 居然不成立?!
        (cl-loop repeat (- end start) do
                 (vterm-send-key "<delete>" nil nil nil t))
      (let ((inhibit-read-only nil)) ;; if 条件不成立,走到这里是必然。但这
                                     ;; 个删除之前的 read-only 就很让人不解了。
        (vterm--delete-region start end)))))

vterm-goto-char 为什么不成立呢?

(defun vterm-goto-char (pos)
  "Set point to POSITION for vterm.

The return value is `t' when point moved successfully.
It will reset to original position if it can't move there."
  (when (and vterm--term
             (vterm-cursor-in-command-buffer-p) ;; 问题出在这个函数
             (vterm-cursor-in-command-buffer-p pos))
...))

(defun vterm-cursor-in-command-buffer-p (&optional pt)
  "Check whether cursor in command buffer area."
  (save-excursion
    (vterm-reset-cursor-point)
    (let ((promp-pt (vterm--get-prompt-point))
          eol)
      (when promp-pt
        (goto-char promp-pt)
        (setq eol (vterm--get-end-of-line)) ;; 问题在这里。单行没问题,多行
                                            ;; 则下边语句不成立。
        (<= promp-pt (or pt (vterm--get-cursor-point)) eol)))))
 promtp-point     end-of-line
           |       |
.----------*-------*-.
| bash-3.2$ echo '1  |
| 2                  |   (<= prompt-point cursor-point end-of-line) ❌
| 3'                 |
'---*----------------'
    |
   cursor-point 

如果我不管上面这些问题,强制 (let ((inhibit-read-only t)) (vterm--delete-region start end)) 呢?表面上是可以删了,但是删除动作并没有提交给 c 模块。所以只要追加一点内容,原先删除掉的内容又现形了。可召回一条多行命令执行下列语句验证:

;; .--------------------.
;; | bash-3.2$ echo '1  |
;; | 2                  |
;; | 3'                 |
;; '---*----------------'
;;     cursor-point

(let ((inhibit-read-only t))
  (vterm--delete-region (vterm--get-prompt-point) (point))
  (vterm-insert "a"))
;; =>
;; .--------------------.
;; | bash-3.2$ echo '1  |
;; | 2                  |
;; | 3'a                |
;; '---*----------------'
1 个赞

那是怎么实现的删除一个范围呢?我们可以去另一个帖子里讨论 :pray:t2:

C-x C-e 是zsh 定义的命令 跟vterm/ iterm2 等terminial 无关,它的作用是用你默认Editor 编辑当前zsh buffer 不过vterm 对C-x 的按键 给拦截了 emacs-libvterm/vterm.el at master · akermu/emacs-libvterm · GitHub

1 个赞

vterm_prompt_end 相关的东西 你的zsh/bash 里有配置吗 (vterm--get-prompt-point) 计算prompt 的时候依赖shell 上报prompt 的结束位置来定位的。

evil-collection 对vterm 作了集成,理论上 移动光标之后,再次进入insert-state 不会回到原来的位置

我又验证了一遍 vterm-cursor-in-command-buffer-p确实如你所说的, 我研究下 看看有没有什么好办法解这个问题 @twlz0ne

EDIT: push 了一个commit, 再验证一下 make vterm-cursor-in-command-buffer-p work when shell buffer is multi… · akermu/emacs-libvterm@a2f2286 · GitHub

1 个赞

如何在启动vterm时自动进入zsh或fish?