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 Answers1

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)
François Févotte
  • 5,917
  • 1
  • 24
  • 37
  • 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 :) – Stefano Palazzo Oct 21 '14 at 08: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. – Stefano Palazzo Oct 21 '14 at 08: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. – François Févotte Oct 21 '14 at 12:20