I have opened a terminal using M-x ansi-term. Everything else seems to work as expected. However, when I use the node.js repl, or the mongdb repl, or any other interactive node program, backspace rewrites the whole line like this: $ node

console> consol> conso> cons> con> co> c>

This also happens with interactive node js programs written with nodejs's 'readline' module.

I'm using the following versions on ubuntu:

$ node --version
$ emacs --version
GNU Emacs 24.5.1

All other REPLs seem to work as expected. (bash, python, irb)

Any ideas?

2 Answers 2


I've tested this in Emacs and found that when backspacing, M-x term has to handle the escapes G and H, but only handles H correctly. I've handed in a patch to handle G properly last year, therefore the misbehavior should not be present in Emacs 26 (which you can obtain by building from Git).


For those that don't want to have to build Emacs 26 to apply the fix, you can simply redefine term-handle-ansi-escape with wasamasa's patch in your .emacs. Just be sure to require term first, or your function will be overridden on the first launch of term-mode (you can also just cut and paste the snippet below). This way, if you're replicating your .emacs with dropbox or the like, you will only have to do this on one machine.

(require 'term)
(defun term-handle-ansi-escape (proc char)
   ((or (eq char ?H)  ;; cursor motion (terminfo: cup,home)
    ;; (eq char ?f) ;; xterm seems to handle this sequence too, not
    ;; needed for now
    (when (<= term-terminal-parameter 0)
      (setq term-terminal-parameter 1))
    (when (<= term-terminal-previous-parameter 0)
      (setq term-terminal-previous-parameter 1))
    (when (> term-terminal-previous-parameter term-height)
      (setq term-terminal-previous-parameter term-height))
    (when (> term-terminal-parameter term-width)
      (setq term-terminal-parameter term-width))
     (1- term-terminal-previous-parameter)
     (1- term-terminal-parameter)))
   ;; \E[A - cursor up (terminfo: cuu, cuu1)
   ((eq char ?A)
    (let ((tcr (term-current-row)))
       (if (< (- tcr term-terminal-parameter) term-scroll-start)
       ;; If the amount to move is before scroll start, move
       ;; to scroll start.
       (- term-scroll-start tcr)
     (if (>= term-terminal-parameter tcr)
         (- tcr)
       (- (max 1 term-terminal-parameter)))) t)))
   ;; \E[B - cursor down (terminfo: cud)
   ((eq char ?B)
    (let ((tcr (term-current-row)))
      (unless (= tcr (1- term-scroll-end))
     (if (> (+ tcr term-terminal-parameter) term-scroll-end)
         (- term-scroll-end 1 tcr)
       (max 1 term-terminal-parameter)) t))))
   ;; \E[C - cursor right (terminfo: cuf, cuf1)
   ((eq char ?C)
     (max 1
      (if (>= (+ term-terminal-parameter (term-current-column)) term-width)
          (- term-width (term-current-column)  1)
   ;; \E[D - cursor left (terminfo: cub)
   ((eq char ?D)
    (term-move-columns (- (max 1 term-terminal-parameter))))
   ((eq char ?G)
    (term-move-columns (- (max 0 (min term-width term-terminal-parameter))
   ;; \E[J - clear to end of screen (terminfo: ed, clear)
   ((eq char ?J)
    (term-erase-in-display term-terminal-parameter))
   ;; \E[K - clear to end of line (terminfo: el, el1)
   ((eq char ?K)
    (term-erase-in-line term-terminal-parameter))
   ;; \E[L - insert lines (terminfo: il, il1)
   ((eq char ?L)
    (term-insert-lines (max 1 term-terminal-parameter)))
   ;; \E[M - delete lines (terminfo: dl, dl1)
   ((eq char ?M)
    (term-delete-lines (max 1 term-terminal-parameter)))
   ;; \E[P - delete chars (terminfo: dch, dch1)
   ((eq char ?P)
    (term-delete-chars (max 1 term-terminal-parameter)))
   ;; \E[@ - insert spaces (terminfo: ich)
   ((eq char ?@)
    (term-insert-spaces (max 1 term-terminal-parameter)))
   ;; \E[?h - DEC Private Mode Set
   ((eq char ?h)
    (cond ((eq term-terminal-parameter 4)  ;; (terminfo: smir)
       (setq term-insert-mode t))
      ;; ((eq term-terminal-parameter 47) ;; (terminfo: smcup)
      ;; (term-switch-to-alternate-sub-buffer t))
   ;; \E[?l - DEC Private Mode Reset
   ((eq char ?l)
    (cond ((eq term-terminal-parameter 4)  ;; (terminfo: rmir)
       (setq term-insert-mode nil))
      ;; ((eq term-terminal-parameter 47) ;; (terminfo: rmcup)
      ;; (term-switch-to-alternate-sub-buffer nil))

   ;; Modified to allow ansi coloring -mm
   ;; \E[m - Set/reset modes, set bg/fg
   ;;(terminfo: smso,rmso,smul,rmul,rev,bold,sgr0,invis,op,setab,setaf)
   ((eq char ?m)
    (when (= term-terminal-more-parameters 1)
      (when (>= term-terminal-previous-parameter-4 0)
    (term-handle-colors-array term-terminal-previous-parameter-4))
      (when (>= term-terminal-previous-parameter-3 0)
    (term-handle-colors-array term-terminal-previous-parameter-3))
      (when (>= term-terminal-previous-parameter-2 0)
    (term-handle-colors-array term-terminal-previous-parameter-2))
      (term-handle-colors-array term-terminal-previous-parameter))
    (term-handle-colors-array term-terminal-parameter))

   ;; \E[6n - Report cursor position (terminfo: u7)
   ((eq char ?n)
    (process-send-string proc
             ;; (terminfo: u6)
             (format "\e[%s;%sR"
                 (1+ (term-current-row))
                 (1+ (term-horizontal-column)))))
   ;; \E[r - Set scrolling region (terminfo: csr)
   ((eq char ?r)
     (1- term-terminal-previous-parameter)
     (1- term-terminal-parameter)))

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.