Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I display ANSI color codes in emacs for any mode?

Tags:

emacs

ansi

I have a log file that uses ANSI escape color codes to format the text. The mode is fundamental. There are other answered questions that address this issue but I'm not sure how to apply it to this mode or any other mode. I know the solution has something to do with configuring ansi-color in some way.

  • ANSI codes in shell mode
  • ANSI codes in gdb mode
like image 328
Avery Avatar asked Apr 30 '14 01:04

Avery


People also ask

How does ANSI color work?

In fact, any code we type into this prompt will also be colored red, as will any subsequent output! That is how Ansi colors work: once you print out the special code enabling a color, the color persists forever until someone else prints out the code for a different color, or prints out the Reset code to disable it.

How do ANSI escape codes work?

ANSI escape sequences are a standard for in-band signaling to control cursor location, color, font styling, and other options on video text terminals and terminal emulators. Certain sequences of bytes, most starting with an ASCII escape character and a bracket character, are embedded into text.


4 Answers

You could use code below

(require 'ansi-color)
(defun display-ansi-colors ()
  (interactive)
  (ansi-color-apply-on-region (point-min) (point-max)))

Then you can execute display-ansi-colors via M-x, via a key-binding of your choosing, or via some programmatic condition (maybe your log files have a extension or name that matches some regexp)

If you want to do this with read-only buffers (log files, grep results), you may use inhibit-read-only, so the function will be:

(defun display-ansi-colors ()
  (interactive)
  (let ((inhibit-read-only t))
    (ansi-color-apply-on-region (point-min) (point-max))))
like image 181
juanleon Avatar answered Oct 17 '22 07:10

juanleon


User defined function:

(defun my-ansi-color (&optional beg end)
  "Interpret ANSI color esacape sequence by colorifying cotent.
Operate on selected region on whole buffer."
  (interactive
   (if (use-region-p)
       (list (region-beginning) (region-end))
     (list (point-min) (point-max))))
  (ansi-color-apply-on-region beg end))

For buffers that uses comint/compilation use filter:

(ignore-errors
  (require 'ansi-color)
  (defun my-colorize-compilation-buffer ()
    (when (eq major-mode 'compilation-mode)
      (ansi-color-apply-on-region compilation-filter-start (point-max))))
  (add-hook 'compilation-filter-hook 'my-colorize-compilation-buffer))
like image 42
gavenkoa Avatar answered Oct 17 '22 09:10

gavenkoa


Gavenkoa's and Juanleon's solutions worked for me, but were not satisfying as they were modifying the contents of the file I was reading.

To colorize without modifying the contents of the file, download tty-format.el and add the following to your .emacs:

(add-to-list 'load-path "path/to/your/tty-format.el/")

(require 'tty-format)

;; M-x display-ansi-colors to explicitly decode ANSI color escape sequences                                                                                                                                        
(defun display-ansi-colors ()
  (interactive)
  (format-decode-buffer 'ansi-colors))

;; decode ANSI color escape sequences for *.txt or README files                                                                                                                                                    
(add-hook 'find-file-hooks 'tty-format-guess)

;; decode ANSI color escape sequences for .log files                                                                                                                                                               
(add-to-list 'auto-mode-alist '("\\.log\\'" . display-ansi-colors))

tty-format is based on ansi-color.el which is only shipped natively with recent versions of emacs.

like image 8
deb0ch Avatar answered Oct 17 '22 07:10

deb0ch


On large files, performance of ansi-color-apply-on-region is slow. Here's a solution that colors the current region and works with read-only buffers.

(require 'ansi-color)
(defun ansi-color-region ()
  "Color the ANSI escape sequences in the acitve region.
Sequences start with an escape \033 (typically shown as \"^[\")
and end with \"m\", e.g. this is two sequences
  ^[[46;1mTEXT^[[0m
where the first sequence says to diplay TEXT as bold with
a cyan background and the second sequence turns it off.

This strips the ANSI escape sequences and if the buffer is saved,
the sequences will be lost."
  (interactive)
  (if (not (region-active-p))
      (message "ansi-color-region: region is not active"))
  (if buffer-read-only
      ;; read-only buffers may be pointing a read-only file system, so don't mark the buffer as
      ;; modified. If the buffer where to become modified, a warning will be generated when emacs
      ;; tries to autosave.
      (let ((inhibit-read-only t)
            (modified (buffer-modified-p)))
        (ansi-color-apply-on-region (region-beginning) (region-end))
        (set-buffer-modified-p modified))
    (ansi-color-apply-on-region (region-beginning) (region-end))))

The one downside is that ansi-color-apply-on-region removes the ANSI escape sequence characters from the buffer, so when you save, they are lost. I wonder if there's a way to hide the characters instead of stripping them?

like image 1
John32ma Avatar answered Oct 17 '22 07:10

John32ma