In term-mode I've configured the keybindings for term-line-mode
and term-char-mode
as follows:
(setq term-bind-key-alist
(list (cons "C-c C-j" '(lambda () (interactive)
(term-line-mode)
(evil-normal-state)))
(cons "C-c C-k" '(lambda () (interactive)
(term-char-mode)
(evil-emacs-state)
(end-of-buffer)))
This gives the expected behavior when I type "C-c C-j" but only term-char-mode
seems to be called when I type "C-c C-k". All of them are called if I type "C-c C-k" for a 2nd time. How can I get them to work on the first key press?
Edit 1
Here's the full configuration for term. Also, I mistakenly thought that this is a variable for term-mode, when it's actually a variable defined in multi-term. However, if I place this in the multi-term configuration it produces the same behavior
(use-package term
:after helm
:config
(defun expose-global-binding-in-term (binding)
(define-key term-raw-map binding
(lookup-key (current-global-map) binding)))
(expose-global-binding-in-term (kbd "C-x"))
(define-key term-raw-map (kbd "M-x") 'helm-M-x)
(setq term-scroll-to-bottom-on-output t)
(setq term-scroll-show-maximum-output t))
(use-package multi-term
:bind (("<C-next>" . multi-term-next)
("<C-prior>" . multi-term-prev)
("<f1>" . multi-term))
:config
(require 'multi-term-ext)
(setq multi-term-program "/bin/bash")
(setq term-bind-key-alist
(list (cons "C-c C-c" 'term-interrupt-subjob)
(cons "C-z" 'term-stop-subjob)
(cons "C-l" 'term-send-raw)
(cons "C-r" 'term-send-raw)
(cons "C-s" 'term-send-raw)
(cons "M-f" 'term-send-forward-word)
(cons "M-b" 'term-send-backward-word)
(cons "C-c C-j" '(lambda () (interactive)
(term-line-mode)
(evil-normal-state)))
(cons "C-c C-k" '(lambda () (interactive)
(evil-emacs-state)
(term-char-mode)
(end-of-buffer)))
(cons "M-DEL" 'term-send-backward-kill-word)
(cons "M-d" 'term-send-forward-kill-word)
(cons "<C-left>" 'term-send-backward-word)
(cons "<C-right>" 'term-send-forward-word)
(cons "C-y" 'term-paste))))
Edit 2
I've modified the multi-term configuration so that these keybindings are outside of term-bind-key-alist
but I'm still getting the same behavior.
(use-package multi-term
:bind (("<C-next>" . multi-term-next)
("<C-prior>" . multi-term-prev)
("<f1>" . multi-term)
("C-c C-j" . (lambda () (interactive)
(term-line-mode)
(evil-normal-state)))
("C-c C-k" . (lambda () (interactive)
(evil-emacs-state)
(term-char-mode)
(end-of-buffer))))
:config
(require 'multi-term-ext)
(setq multi-term-program "/bin/bash")
(setq term-bind-key-alist
(list (cons "C-c C-c" 'term-interrupt-subjob)
(cons "C-z" 'term-stop-subjob)
(cons "C-l" 'term-send-raw)
(cons "C-r" 'term-send-raw)
(cons "C-s" 'term-send-raw)
(cons "M-f" 'term-send-forward-word)
(cons "M-b" 'term-send-backward-word)
(cons "M-DEL" 'term-send-backward-kill-word)
(cons "M-d" 'term-send-forward-kill-word)
(cons "<C-left>" 'term-send-backward-word)
(cons "<C-right>" 'term-send-forward-word)
(cons "C-y" 'term-paste))))
Edit 3
The version below now works. The trick, as pointed out by Phil in his answer, is that
term-bind-key-alist
doesn't bind keys for term-mode-map
(used by term-line-mode
). I believe it only
binds keys for term-raw-map
, or some combination of that and term-raw-escape-map
. The reason that
term-char-mode
was still called (and the other two functions weren't) when using "C-c C-k" in term-line-mode was that it's the default
keybinding in term-line-mode
.
(use-package term
:after (helm evil)
:bind (:map term-mode-map
("C-c C-k" . (lambda () (interactive)
(evil-emacs-state)
(term-char-mode)
(goto-char (point-max)))))
:config
(defun expose-global-binding-in-term (binding)
(define-key term-raw-map binding
(lookup-key (current-global-map) binding)))
(expose-global-binding-in-term (kbd "C-x"))
(define-key term-raw-map (kbd "M-x") 'helm-M-x)
(setq term-scroll-to-bottom-on-output t)
(setq term-scroll-show-maximum-output t))
(use-package multi-term
:bind (("<C-next>" . multi-term-next)
("<C-prior>" . multi-term-prev)
("<f1>" . multi-term))
:config
(require 'multi-term-ext)
(setq multi-term-program "/bin/bash")
(setq term-bind-key-alist
(list (cons "C-c C-c" 'term-interrupt-subjob)
(cons "C-z" 'term-stop-subjob)
(cons "C-l" 'term-send-raw)
(cons "C-r" 'term-send-raw)
(cons "C-s" 'term-send-raw)
(cons "M-f" 'term-send-forward-word)
(cons "M-b" 'term-send-backward-word)
;; I've defined "C-c C-k" in term's configuration since it must be defined in
;; term-mode-map. It could be placed here as a define-key in config, but this way we
;; get to keep use-package's typical syntax.
(cons "C-c C-j" '(lambda () (interactive)
(term-line-mode)
(evil-normal-state)))
(cons "M-DEL" 'term-send-backward-kill-word)
(cons "M-d" 'term-send-forward-kill-word)
(cons "<C-left>" 'term-send-backward-word)
(cons "<C-right>" 'term-send-forward-word)
(cons "C-y" 'term-paste))))