Your problem was way more fun than expected to look into !
The function used in the solution described in your link,
(ansi-color-apply-on-region (point-min) (point-max))
is the one to go for in my opinion as it is the function used in comint-mode itself, so I guess pretty "low level" and well integrated in emacs.
One idea would be to apply it only on the visible region by replacing point-min
and point-max
by window-start
and window-end
and putting it into the window-scroll-functions
:
(require 'ansi-color)
(defun my-colorize-buffer-window (win)
(ansi-color-apply-on-region (window-start win) (window-end win t)))
(defun my-colorize-buffer (win _start)
(mapc #'my-colorize-buffer-window (get-buffer-window-list (window-buffer win) nil 'visible)))
(add-hook 'window-scroll-functions 'my-colorize-buffer)
(I copied the way linum-mode
updates line numbers)
Though using that on a 323Mo log file seems to have good performance (smooth and no freeze when it works), I am still facing some issues with that solution.
In particular:
- infinite loops that go away when resizing frame
- infinite loops that do not go away when resizing frame
- some ansi sequences do not decode right away but only on the second scroll showing them
ansi-color-apply-on-region
actually modifies the buffer's contents, whereas format-decode-buffer
with tty-format
doesnt. It might by worthy looking into that.
Have to go now, I might update later on !
seq 10000 | xargs -I{} cat sample.log >>verybig.log
– phils Jul 06 '16 at 06:11(buffer-string)
, but it would likely be even slower (the fact that it works on strings implies the author was only considering colorizing short texts, not whole files). – npostavs Jul 06 '16 at 11:11