Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Translate ANSI characters #16

Open
Ambrevar opened this issue Jul 10, 2021 · 6 comments
Open

Translate ANSI characters #16

Ambrevar opened this issue Jul 10, 2021 · 6 comments

Comments

@Ambrevar
Copy link
Contributor

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?

@Ambrevar
Copy link
Contributor Author

Ambrevar commented Jul 10, 2021

Update with ^M handled as rubout when not followed by ^J:

(let ((process (uiop:launch-program "foo.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)))
               (setf line (string-right-trim '(#\return) line))
               (write-string
                (sera:ensure-suffix
                 (reduce (lambda (&optional string char)
                           (match char
                             (#\backspace
                                  (subseq string 0 (max 0 (1- (length string)))))
                             (#\return
                                  "")
                             (char (str:concat string (string char)))))
                         line
                         :initial-value "")
                 (string #\newline))
                output-stream)
               (decode-process-output-to-stream process output-stream))))
    (decode-process-output-to-stream process t)))

@ruricolist
Copy link
Owner

I think that stripping out special characters is a great idea.

Do you think it would be worth having a mode like less - R, that strips everything but color codes?

@Ambrevar
Copy link
Contributor Author

Ambrevar commented Jul 12, 2021 via email

@Ambrevar
Copy link
Contributor Author

Should I send a patch?

@ruricolist
Copy link
Owner

Please do.

@Ambrevar
Copy link
Contributor Author

Ambrevar commented Aug 10, 2021 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants