vterm + zsh 配置

功能:

  • 多个vterm
  • buffer name和当天目录自动同步
  • toggle命令,可以自动新建目录在当前目录的vterm进程 (vterm-toggle/C-u vterm-toggle)
  • vterm之间跳转 (switch-buffer-same-major-mode)
(require 'cl-lib)

;;; Package

(use-package vterm
  :load-path  "~/attic/emacs-libvterm"
  :config
  (setq vterm-shell "zsh")
  (add-hook 'vterm-set-title-functions 'vterm--rename-buffer-as-title))

;;; Functions

(defun vterm--rename-buffer-as-title (title)
  (rename-buffer (format "vterm @ %s" title) t))

(defvar vterm-toggle-prev-buffer nil
  "Used by ‘vterm-toggle’.")

(defun vterm-buffer-list ()
  "Return a list of vterm buffers."
  (cl-remove-if-not (lambda (buf)
                      (provided-mode-derived-p
                       (buffer-local-value 'major-mode buf)
                       'vterm-mode))
                    (buffer-list)))

(defun vterm-cd (dir)
  "cd to DIR."
  (when (derived-mode-p 'vterm-mode)
    (vterm-send-key "u" nil nil t)
    (execute-kbd-macro (format "cd %s
" dir))))

(defun vterm-toggle (&optional arg)
  "Toggle vterm.

ARG: C-u: open the vterm buffer with the same dir of current buffer
If there exists an Vterm buffer with current directory, use that,
otherwise create one.

C-u C-u: same as C-u, but reuse a existing vterm buffer instead of
creating one."
  (interactive "p")
  (if (derived-mode-p 'vterm-mode)
      ;; toggle off
      (if vterm-toggle-prev-buffer
          (switch-to-buffer vterm-toggle-prev-buffer)
        (user-error "No previous buffer to jump back to"))
    ;; toggle on
    (let ((buffer-list (vterm-buffer-list)))
      (cond
       ((or (eq arg 4) ; C-u
            (eq arg 16)) ; C-u C-u
        ;; open in current dir
        (let* ((dir default-directory)
               (buffer-with-same-dir
                (catch 'found
                  (dolist (buffer buffer-list nil)
                    (when (equal dir (buffer-local-value
                                      'default-directory
                                      buffer))
                      (throw 'found buffer))))))
          ;; found the buffer with the same dir
          (setq vterm-toggle-prev-buffer
                (current-buffer))
          (if buffer-with-same-dir
              (switch-to-buffer buffer-with-same-dir)
            ;; or not and maybe create a new one
            (switch-to-buffer
             (if (eq arg 16)
                 (progn (message "No valid vterm buffer found, reuse one.")
                        (car buffer-list))
               (message "No valid vterm buffer found, create a new one.")
               (vterm)))
            (vterm-cd dir))))
       ;; simply open
       (t (setq vterm-toggle-prev-buffer (current-buffer))
          (switch-to-buffer (or (car buffer-list)
                                (vterm))))))))

(defun switch-buffer-same-major-mode ()
  "Switch buffer among those who have the same major mode as the current one."
  (interactive)
  (switch-to-buffer
   (completing-read
    "Buffer: "
    (mapcar #'buffer-name
            (cl-remove-if-not (lambda (buf)
                                (provided-mode-derived-p
                                 (buffer-local-value 'major-mode buf)
                                 major-mode))
                              (buffer-list))))))

.zshrc:

# vterm dir tracking
vterm_prompt_end() {
    # or maybe only pwd?
    printf "\e]51;A$(whoami)@$(hostname):$(pwd)\e\\";
}
PROMPT=$PROMPT"%{$(vterm_prompt_end)%}"

# sync title
# https://github.com/ohmyzsh/ohmyzsh/issues/5700
function precmd () {
  window_title="\033]0;${PWD##*/}\007"
  echo -ne "$window_title"
}
4 个赞

补充一个

2 个赞

你提的这个bug ,还是没解决吗? zsh版本是多少。

还是不行,版本是

zsh 5.7.1 (x86_64-apple-darwin19.0)

很奇怪, 怀疑是你.zshrc内其他配置内容把上面的配置给冲掉了。 你echo $PROMPT 确认一下, 最好能把.zshrc内其他内容一点点去掉,看看到不能修复。

哦对,有道理,我没怀疑过自己的配置😁

验证完给个反馈。

还是不行,我用zsh -df启动,执行

printf "\e]51;A$(whoami)@$(hostname):$(pwd)\e\\";

没有效果,我怀疑是escape的问题,试了下

printf '\e]51;Ayuan@missSilver:/usr\e\\';

也不行。