3

The GNU Screen utility has the ability to log all shell output to a file, a useful feature to log the output of a long running build system, for instance.

  • The log file generated by GNU Screen contains the terminal escape sequences that were output during the session.
  • Although I could filter them out with some tool, I'd like to keep these escape sequences inside the log file as they color the output and help pin-point things like compiler warning and error messages.
  • But I want to be able to view the file inside Emacs to process it, search for things, etc...

I'd like to visit that log file in Emacs and get Emacs render the escape code the way the shell originally did. Now what is seen is the escape sequences. Is there an Emacs major or minor mode that can do that?

Something like term-mode that would only render the text but without launching a terminal process?

  • I was able to render the escape sequence by visiting the screen log file in fundamental-mode first, then launching the eshell-mode and then executing (term-mode). But that's not ideal as it gets in the way by starting an active shell in the buffer.
  • If something already exists that'd be great, otherwise maybe it would be possible to write a major mode that acts just as a text editing mode but renders the escape sequences like term-mode does. Any suggestions?

2 Answers 2

3

There's a function called ansi-color-apply-on-region that can almost do what you want. It's not interactive, but I was able to create an interactive wrapper and apply it to a region with escape characters in it.

(defun u/ansi-color-apply-on-region (begin end)
  (interactive "r")
  (ansi-color-apply-on-region begin end t))

Highlight a region with terminal escape sequences in it, and hit M-x u/ansi-color-apply-on-region to test it out. Maybe you can build something on top of this.

4
  • This is a very good start! That mostly works leaving some escape sequences left in the buffer and an empty line between each line and Emacs detecting a Mac-line ending style (each line terminated by CR only). I tried something else: open a shell in a buffer (M-x-shell) and execute a 'cat logfile' leaving the shell render the log file. The rendering is a little better (no extra line, for one) . I also noticed that in Emacs 27.2 ansi-color-apply-on-region takes only 2 arguments not 3. What Version of Emacs do you use?
    – PRouleau
    Dec 10, 2022 at 17:53
  • Also note that when executing the cat command from within the regular bash shell all rendering is like the original output, no remnant of any escape code or empty line remains. I'm trying to get to that point within Emacs.
    – PRouleau
    Dec 10, 2022 at 18:10
  • @PRouleau I'm using Emacs 28.1. That last t is optional in the version of ansi-color-apply-on-region that I'm using, and setting it asks the function to not mutate the underlying text. (Just color the visible parts and hide the escape sequences.)
    – g-gundam
    Dec 10, 2022 at 19:20
  • 1
    The use of that function fixes the rendering of the escape codes. The log file I got contains other artifacts related to the content of the PS1 prompt> I don't know why the GNU screen generated log file ends up having those, so the complete solution I need involves using the function you suggested and the execution of a couple of regexp replacements. I'll have to provide user-options to support those extra translations for the complete solution. But for the rendering your solution does the job, so I'll accept it as is.
    – PRouleau
    Dec 10, 2022 at 21:27
1

Perhaps what follows will be useful to you. I use a variant of this in my emacs setup. (I don't use screen but another program that logs screen output.)

As is, it instructs emacs, whenever you open a file which filename looks like screenlog.n with n a number, to enable rendering ANSI sequences in color. (It does not process cursor movement and the like, which I prefer anyway.)

(add-hook 'text-mode-hook
          (lambda ()
        (when (string-match "screenlog\.[0-9]*$" (buffer-name))
              (progn
        (format-decode-buffer 'backspace-overstrike)
        (format-decode-buffer 'ansi-colors)
        (hide-dos-eol)
        (face-remap-add-relative 'default '((:foreground "white" :background "black")))
        ))))

It has some drawbacks, e.g. you cannot save buffers (you get "Sorry, 'ansi-colors' format is read-only."), but it allows what you asked for, rendering shell escape codes.

1
  • Interesting; a different aspect of Emacs to explore. I'll try it out.
    – PRouleau
    Dec 13, 2022 at 22:07

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.