求问term模式的keymap是啥

最近使用fzf.el插件,里面使用了term,想要映射ESC实现退出term的功能,发现C-g实现了该功能。所以想一下term-mode的keymap是啥,晚上搜到term-raw-keymap但是emacs 26.1说不存在这个符号,还有我该怎么查看C-g在term下对应的函数,C-h k不起作用啊

C-h l 能不能看到是什么命令?

可以看一下我的 multi-term.el 的代码

C-h b 可以看到当前的绑定键信息,也可以看下。

keymap 可以尝试看下他的源码,通过关键字应该比较快就能找到了(可以先查看他的某个函数信息,然后在 help buffer中点击跳转过去)

term 的按键是直接接到用户的事件, 直接把事件序列转换给 shell , 不像传统模式那样有很多 keymap 对应很多事件。

看我写的 https://www.emacswiki.org/emacs/multi-term.el

(defcustom term-bind-key-alist
  '(
    ("C-c C-c" . term-interrupt-subjob)
    ("C-c C-e" . term-send-esc)
    ("C-p" . previous-line)
    ("C-n" . next-line)
    ("C-s" . isearch-forward)
    ("C-r" . isearch-backward)
    ("C-m" . term-send-return)
    ("C-y" . term-paste)
    ("M-f" . term-send-forward-word)
    ("M-b" . term-send-backward-word)
    ("M-o" . term-send-backspace)
    ("M-p" . term-send-up)
    ("M-n" . term-send-down)
    ("M-M" . term-send-forward-kill-word)
    ("M-N" . term-send-backward-kill-word)
    ("<C-backspace>" . term-send-backward-kill-word)
    ("M-r" . term-send-reverse-search-history)
    ("M-d" . term-send-delete-word)
    ("M-," . term-send-raw)
    ("M-." . comint-dynamic-complete))
  "The key alist that will need to be bind.
If you do not like default setup, modify it, with (KEY . COMMAND) format."
  :type 'alist
  :group 'multi-term)

上面是 multi-term.el 定义按键的 keymap

(defun multi-term-keystroke-setup ()
  "Keystroke setup of `term-char-mode'.

By default, the key bindings of `term-char-mode' conflict with user's keystroke.
So this function unbinds some keys with `term-raw-map',
and binds some keystroke with `term-raw-map'."
  (let (bind-key bind-command)
    ;; Unbind base key that conflict with user's keys-tokes.
    (cl-dolist (unbind-key term-unbind-key-list)
      (cond
       ((stringp unbind-key) (setq unbind-key (read-kbd-macro unbind-key)))
       ((vectorp unbind-key) nil)
       (t (signal 'wrong-type-argument (list 'array unbind-key))))
      (define-key term-raw-map unbind-key nil))
    ;; Add some i use keys.
    ;; If you don't like my keystroke,
    ;; just modified `term-bind-key-alist'
    (cl-dolist (element term-bind-key-alist)
      (setq bind-key (car element))
      (setq bind-command (cdr element))
      (cond
       ((stringp bind-key) (setq bind-key (read-kbd-macro bind-key)))
       ((vectorp bind-key) nil)
       (t (signal 'wrong-type-argument (list 'array bind-key))))
      (define-key term-raw-map bind-key bind-command))))

这个函数是做按键绑定的, 要用 define-key 来 unbind 和 bind 按键到 term-raw-map 中, 关键是

(add-hook 'term-mode-hook 'multi-term-keystroke-setup)

你只能在 term-mode 运行的时候用 term-mode-hook 去挂在按键, 而不是像传统那样直接设置 term-raw-map , term 外面访问不到这个函数。

要自定义按键都需要像 mult-term.el 里面,

(defun term-send-M-x ()
  "Type M-x in term-mode."
  (interactive)
  (term-send-raw-string "\ex"))

用 term-send-raw-string 去发送按键序列, 你是不可能直接指定 term 执行什么代码的, term 只接受按键序列。

3 个赞

我建议你直接基于 multi-term.el 来改进, 用 term-send-raw-string 来发送 Ctrl + D, 然后直接自定义 multi-term.el 的 term-bind-key-alist 这个按键变量, 把发送 Ctrl + D的函数绑定到 Esc 按键上, 比你自己折腾 term.el 要快很多。

1 个赞