4

In ansi-term's "char run" mode, I can use C-<left> and C-<right> to move around in steps of one word, but as soon as I start typing again, the point moves back to where it was. They work fine in "line run" mode (C-cC-j).

How to I get the point to stay where I moved it?

Similarly, C-w seems to use a different definition of "word" than backward-kill-word, which I have also bound to C-w for normal buffers. For Instance, hitting C-w on the end of ls /usr/local/bin gives me ls /usr/local/ in a scratch buffer, but in ansi-term it leaves me with ls.

Is there any way to configure these things more granularly?

1 Answer 1

6

In ansi-term's "char run mode", C-<left> & co are by default intercepted by emacs, which moves the point instead of telling the undelying terminal to do it. This leads to the situation you describe: the point moves in the emacs buffer, but the next insertion will use the real cursor position in the terminal, which hasn't changed.

You thus need to reassign C-<left> and C-<right> to commands that actually forward the correct keys to the terminal:

(defun term-send-Cright () (interactive) (term-send-raw-string "\e[1;5C"))
(defun term-send-Cleft  () (interactive) (term-send-raw-string "\e[1;5D"))
(define-key term-raw-map (kbd "C-<right>")      'term-send-Cright)
(define-key term-raw-map (kbd "C-<left>")       'term-send-Cleft)

FYI, I found the \e[1;5C and \e[1;5D codes using the following trick:

  1. run cat >/dev/null in a terminal
  2. type C-<left> and C-<right> and see what is echoed back in the terminal
  3. exit with C-d or C-c

Another way to find them would be to type in a terminal: C-vC-<left>


As for the C-w problem, it is of a different kind: as you said, emacs and bash do not have the same definition of what a word is. The only solution I would see would be to change one of them (either emacs or bash) to make it consistent with the other.

It looks like bash's default M-<backspace> binding is closer to the behaviour of Emacs' backward-kill-word. You could thus bind C-w to a command which forwards the M-<backspace> key sequence to the terminal:

(defun term-send-Mbackspace () (interactive)(term-send-raw-string "\e\d"))
(define-key term-raw-map (kbd "C-w") 'term-send-Mbackspace)
3
  • 1
    I had to put in "\eb" and "\ef" (which is ^[b for alt+left and ^[f for alt+right). It works perfectly now. Being able to use C-w is so nice. Thanks :) Commented Oct 21, 2014 at 8:23
  • Note: In Emacs 24.4, I had to do this inside (add-hook 'term-load-hook (lambda () ... ) because term-raw-map is not defined outside of this hook. Commented Oct 21, 2014 at 8:43
  • You're right: you need to delay evaluation until term is loaded. You could try wrapping everything in an (eval-after-load "term" ...) form: this should work for every emacs version. Commented Oct 21, 2014 at 12:20

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.