From eab9bdf79f5b0e9cafe84b88f9fd44d607fff509 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Mattias=20Engdeg=C3=A5rd?= Date: Mon, 23 Oct 2023 19:09:01 +0200 Subject: [PATCH] More robust control sequence handling in LLDB output (bug#66604) * lisp/progmodes/gud.el (gud-lldb-marker-filter): Slightly more elaborate interpretation of CHA and ED sequences in LLDB output, allowing edits to previously emitted characters on the same line. --- lisp/progmodes/gud.el | 43 ++++++++++++++++++++++++++++++++++++------- 1 file changed, 36 insertions(+), 7 deletions(-) diff --git a/lisp/progmodes/gud.el b/lisp/progmodes/gud.el index d3064b6116c..1d3c2a72863 100644 --- a/lisp/progmodes/gud.el +++ b/lisp/progmodes/gud.el @@ -3886,13 +3886,42 @@ so they have been disabled.")) string) (setq gud-last-last-frame nil) (setq gud-overlay-arrow-position nil))) - ;; While being attached to a process, LLDB emits control sequences, - ;; even if TERM is "dumb". This is the case in at least LLDB - ;; version 14 to 17. The control sequences are filtered out by - ;; Emacs after this process filter runs, but LLDB also prints an - ;; extra space after the prompt, which we fix here. - (replace-regexp-in-string (rx "(lldb)" (group (1+ blank)) "\e[8") - " " string nil nil 1)) + + ;; LLDB sometimes emits certain ECMA-48 sequences even if TERM is "dumb": + ;; CHA (Character Horizontal Absolute) and ED (Erase in Display), + ;; seemingly to undo previous output on the same line. + ;; Filter out these sequences here while carrying out their edits. + (let ((bol (pos-bol))) + (when (> (point) bol) + ;; Move the current line to the string, so that control sequences + ;; can delete parts of it. + (setq string (concat (buffer-substring-no-properties bol (point)) + string)) + (delete-region bol (point)))) + (let ((ofs 0)) + (while (string-match (rx (group (* (not (in "\e\n")))) ; preceding chars + "\e[" ; CSI + (? (group (+ digit))) ; argument + (group (in "GJ"))) ; CHA or ED + string ofs) + (let* ((start (match-beginning 1)) + (prefix-end (match-end 1)) + (op (aref string (match-beginning 3))) + (end (match-end 0)) + (keep-end + (if (eq op ?G) + ;; Move to absolute column (CHA) + (min prefix-end + (+ start + (if (match-beginning 2) + (1- (string-to-number (match-string 2 string))) + 0))) + ;; Erase in display (ED): no further action. + prefix-end))) + (setq string (concat (substring string 0 keep-end) + (substring string end))) + (setq ofs start)))) + string) ;; According to SBCommanInterpreter.cpp, the return value of ;; HandleCompletions is as follows: -- 2.39.2