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:
- run
cat >/dev/null
in a terminal
- type C-<left> and C-<right> and see what is echoed back in the terminal
- 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)