Skip to content

Translate ANSI characters #16

@Ambrevar

Description

@Ambrevar

Many shell commands leverage the terminal processing of special characters like ^H (backspace) and ^M (newline) to perform some special formatting, like rewriting text in place.

This is often seen when a progress bar is displayed by the command. Try rsync, wget, curl, your package manager...

Running these commands in a Lisp REPL often makes for pages of garbage output, making them practically un-runnable.

An easy way around this is to ask uiop:launch-program to write the output to a stream, then to process the stream for special characters.

Here is an example that processes ^H and ^M:

(let ((process (uiop:launch-program "test.sh" :output :stream :error-output :output)))
  (labels ((decode-process-output-to-stream (process output-stream)
             (alex:when-let ((line (read-line (uiop:process-info-output process) nil nil)))
               (let ((lines (str:split "
" line)))
                 (write-string
                  (sera:ensure-suffix
                   (str:join
                    (string #\n ewline)
                    (mapcar (lambda (line)
                              (reduce (lambda (&optional string char)
                                        (if (eq char #\�)
                                            (subseq string 0 (max 0 (1- (length string))))
                                            (str:concat string (string char))))
                                      line
                                      :initial-value ""))
                            lines))
                   (string #\n ewline))
                  output-stream))
               (decode-process-output-to-stream process output-stream))))
    (decode-process-output-to-stream process t)))

with foo.sh:

#!/bin/sh

printf "backspace test: begin-ERR\b\b\bOR\b\bend\n\bline0"
echo
printf "newline test: line1\nline2"
echo
printf "CRLF newline test: line3\r\nline4"
echo

It would be super useful to integrate this to CMD. I suggest adding a dynamic variable where the user could specify the output translators. When NIL, no translation would happen.

Thoughts?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions