Skip to content

Commit

Permalink
Improve handling of carriage return ("\r")
Browse files Browse the repository at this point in the history
A CARRIAGE RETURN character moves the head of the teletype printer (the
carriage) to the beginning of the line, without scrolling the paper (this is
done by the LINE FEED "\n")

In a contemporary terminal emulator this translates to moving the cursor to the
beginning of the current line. Any subsequent output then overwrites what was
already on that line. This is how terminal progress bars are implemented.

The existing implementation incorrectly treated "\r" as "\n", thus inserting a
newline, instead of moving to the beginning of the current line.

Instead iterate over the output and deal with "\r" and "\n" the way terminals
do, "\r" (ASCII 13) moves to the beginning of the line, "\n" (ASCII 10) moves to
the beginning of the next line. Any output overwrites output on the same line
after the cursor position.

Sample code:

```
(println "aaaa\rbb\ncccc\rdd")
;; Outputs:
;; bbaa
;; ddcc

(dotimes [i 20]
  (print "\r[" (inc i) "]")
  (flush)
  (Thread/sleep 500))
;; prints a counter in place
```

Feedback welcome as I'm not sure of the performance impact of dealing with each
character individually. Also not sure what the effect is of propertizing and
running cider-repl-preoutput-hook per character.

Fixes clojure-emacs#1677 (which was closed but not actually implemented, only worked around)
  • Loading branch information
plexus committed Jul 23, 2020
1 parent 3d8552a commit cc2ccb9
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 6 deletions.
23 changes: 18 additions & 5 deletions cider-repl.el
Original file line number Diff line number Diff line change
Expand Up @@ -745,11 +745,24 @@ Before inserting, run `cider-repl-preoutput-hook' on STRING."
(save-excursion
(cider-save-marker cider-repl-output-start
(goto-char cider-repl-output-end)
(setq string (propertize string
'font-lock-face face
'rear-nonsticky '(font-lock-face)))
(setq string (cider-run-chained-hook 'cider-repl-preoutput-hook string))
(insert-before-markers string)
(seq-map
(lambda (char)
(cond
((= 13 char)
(beginning-of-line))
((= 10 char)
(end-of-line)
(insert-before-markers "\n"))
(t
(when (< (point) (line-end-position))
(delete-char 1))
(setq char (char-to-string char))
(setq char (propertize char
'font-lock-face face
'rear-nonsticky '(font-lock-face)))
(setq char (cider-run-chained-hook 'cider-repl-preoutput-hook char))
(insert-before-markers char))))
string)
(cider-repl--flush-ansi-color-context))
(when (and (= (point) cider-repl-prompt-start-mark)
(not (bolp)))
Expand Down
2 changes: 1 addition & 1 deletion nrepl-client.el
Original file line number Diff line number Diff line change
Expand Up @@ -323,7 +323,7 @@ object is a root list or dict."
(goto-char end)
;; normalise any platform-specific newlines
(let* ((original (buffer-substring-no-properties beg end))
(result (replace-regexp-in-string "\r\n\\|\n\r\\|\r" "\n" original)))
(result (replace-regexp-in-string "\r\n\\|\n\r" "\n" original)))
(cons nil (nrepl--push result stack))))))
;; integer
((looking-at "i\\(-?[0-9]+\\)e")
Expand Down

0 comments on commit cc2ccb9

Please # to comment.