如何在快捷键中绑定一个函数使 vterm 在下方创建新的实例或隐藏窗口?

通过绑定 Control + ` , 按键时在下方创建一个 vterm 实例的小窗口, 如果当前存在这个 vterm 的窗口, 则隐藏它.

由于个人 Elisp 水平有限(抄配置的程度), 恳请指点一二.

目前尝试的代码实现了在下方创建小窗的功能, 但感觉有点绕.

(defun vterm-split-window-below ()
       (interactive)
       (vterm)
       (split-window-below -12)
       (previous-buffer)
       (other-window 1))

(global-set-key (kbd "C-`") 'vterm-split-window-below)

先记录当前buffer

然后启动vterm 判断*new-vterm* buffer

如果buffer存在就直接(switch-to-buffer "new-vterm") 不存在就创建并(switch-to-buffer "new-vterm") 记录当前状态 如果为false 就back-to (switch-to-buffer "old-buffer")原来的buffer

2 个赞

可以抄aweshell的代码

你这种实现,窗口多的时候不一定会弄到底部,aweshell处理了最底部创建窗口,同时做了专注窗口处理,不会被kill other windows命令关闭

1 个赞

vterm-toggle?

2 个赞

感谢各位的帮助加深了我对 Emacs 和 Elisp 的认识, 拓宽了我学习写代码的思路. :smile:

shell-pop 完全满足楼主需求

2 个赞

https://github.com/alexluigit/emacs-grandview#vterm-vtermel 里面的 ale/vterm-toggle 就是你提到的功能。 也支持预设窗口位置,多开vterm。

1 个赞

今天撸了一个新功能,在child frame中显示vterm,临时用还是很方便的。效果如下:

代码参考 Centaur Emacs 的 init-shell.el。

5 个赞

感谢大家的热心帮助 :smiling_face_with_three_hearts:

参考抄袭了一下你的代码,加上检测 project root 的功能,做成了一个独立的包,

基于当前的 Projectile Project Root,新建 Posframe 的 VTerm 窗口。

这是我第一个尝试写的 Emacs 包,欢迎大家试用和多提意见

https://github.com/zwpaper/posframe-project-term

3 个赞

给力!终端挥之即来,临时执行一些命令真方便!

1 个赞

目前写了一个最小可行性版本 :smile:

(defun vterm-split-window-below ()
  (interactive)
  (vterm)
  (split-window-below -12)
  (previous-buffer)
  (other-window 1))

(defun vterm-toggle ()
  (interactive)
  (if (eq major-mode 'vterm-mode)
      (delete-window)
    (vterm-split-window-below)))

(global-set-key (kbd "C-`") 'vterm-toggle)

vterm-toggle

1 个赞

默认位置显示有问题,需要随意按个键才会到底部。

我也发现这个问题了,简单尝试加了 posframe 的 position 参数,没能修复,这几天我再看看修一下

没啥好解决办法,我用了clear,每次都显示干净的信息就好了。实际上需要看旧的 滚动向上翻就可以了。

(with-current-buffer buffer
                  (save-excursion
                   (vterm-clear))
                  (setq-local cursor-type 'bar))

之前试着修复了一下这个问题,才反应过来,似乎是可以自动跳到最下面了,可以试一下看看

我用的popwin 在右边显示vterm,C-g隐藏或者光标换到其它窗口的时候隐藏。https://github.com/emacsorphanage/popwin 我感觉这个包不少功能很好用,推荐一下

(push '("*vterm*" :width 0.5 :position right) popwin:special-display-config)

比如

(push '("^\\*eldoc.*\\*$" :regexp t :noselect t :width 0.5 :position right) popwin:special-display-config)

regexp匹配所有名字为eldoc xx的buffer,noselect打开的时候可以设置是否选中,width可以设置大小,position可以设置位置,默认C-g就可以隐藏

(defun shell-toggle ()
  "Toggle a persistent shell popup window.
If popup is visible but unselected, select it.
If popup is focused, kill it."
  (interactive)
  (if-let ((win (get-buffer-window "*shell-popup*")))
      (when (eq (selected-window) win)
        ;; If users attempt to delete the sole ordinary window, silence it.
        (ignore-errors (delete-window win)))
    (let ((display-comint-buffer-action '(display-buffer-at-bottom
                                          (inhibit-same-window . nil))))

      (shell "*shell-popup*"))))

我个人使用这个版本,主要做了2件事:

  1. 在发现有 *shell-popup* 这个窗口并且当前光标也在这个窗口,那么把这个窗口关掉。

  2. 如果没发现 *shell-popup* 这个窗口,这就意味着:

    • *shell-popup* buffer 不存在
    • *shell-popup* buffer 存在,但是没有在当前窗口上显示

    不过比较欣慰的是, shell 这个函数可以同时处理第 2 种情况。