xterm-color.el is an ANSI control sequence to text-property translator.
Translation takes place through state machine emulation which provides a far more accurate, comprehensive result than ansi-color.el that is built-into Emacs, without compromising on performance.
- Regular ANSI color support
- XTERM 256 color support
- Truecolor (24-bit) support
- AIXTERM bright foreground color
- AIXTERM bright background color (since 1.8)
- Use bold instead of bright (since 1.8)
- When colorizing entire buffers, optional overlay support (since 2.0)
- Optionally, filter out ANSI control sequences (since 2.0)
- Works with compilation-mode
- Works with eshell
Simple and most flexible method:
;; Clone this repository, ensure directory of xterm-color.el is in your
;; load-path and add the following to your init file:
(require 'xterm-color)
;; You should byte-compile xterm-color.el for maximum performance.
Alternatively, you can install through MELPA or some other Emacs package manager.
Interactively or from Emacs Lisp, call xterm-color-colorize-buffer
to
colorize an entire buffer.
You may customize xterm-color-debug
(default nil, if non-nil you will get warnings
in Messages when unsupported escape sequences are encountered),
xterm-color-use-bold-for-bright
(default nil), xterm-color-names
,
xterm-color-names-bright
. Additionally, you may set xterm-color-preserve-properties
to t (default nil, should be set to t only if using xterm-color with eshell, see below).
If you want to filter out all ANSI control sequences, without applying them to the text,
set xterm-color-render
to nil.
A buffer-local face attribute cache is used since 1.8 to improve performance.
This means that if changes are made to xterm-color-names
or xterm-color-names-bright
or
xterm-color-use-bold-for-bright
at runtime, xterm-color-clear-cache
should be called
in a buffer with activated xterm-color for changes to take effect in that buffer.
You can replace ansi-color.el with xterm-color for all comint buffers,
but you should take into account modes that propertize strings and pass them
through comint-preoutput-filter-functions
since xterm-color-filter
will
strip all text properties (this is done to get maximum performance). The
recommended configuration that avoids issues is to remove ansi-color-process-output
from comint-output-filter-functions
and add xterm-color-filter
as the first
hook in the buffer-local comint-preoutput-filter-functions
for any comint-based
mode that you would like it to affect (e.g. shell-mode).
Additionally, it is recommended to disable font-locking for shell-mode buffers since it interacts badly with comint and drastically affects performance. Font locking in shell-mode buffers is superfluous since xterm-color.el will handle faces fine by itself.
Example configuration for shell-mode (M-x shell):
(setq comint-output-filter-functions
(remove 'ansi-color-process-output comint-output-filter-functions))
(add-hook 'shell-mode-hook
(lambda ()
;; Disable font-locking in this buffer to improve performance
(font-lock-mode -1)
;; Prevent font-locking from being re-enabled in this buffer
(make-local-variable 'font-lock-function)
(setq font-lock-function (lambda (_) nil))
(add-hook 'comint-preoutput-filter-functions 'xterm-color-filter nil t)))
;; Also set TERM accordingly (xterm-256color) in the shell itself.
Using compilation-shell-minor-mode
(NOTE: not the same as compilation-mode)
with shell-mode buffers that have xterm-color enabled is NOT recommended,
as compilation-shell-minor-mode
depends on font-locking and causes severe
performance degradation. Omit the statements that disable font-locking in the
shell-mode example configuration if you need it.
An example configuration for eshell:
(require 'eshell) ; or use with-eval-after-load
(add-hook 'eshell-before-prompt-hook
(lambda ()
(setq xterm-color-preserve-properties t)))
(add-to-list 'eshell-preoutput-filter-functions 'xterm-color-filter)
(setq eshell-output-filter-functions (remove 'eshell-handle-ansi-color eshell-output-filter-functions))
(setenv "TERM" "xterm-256color")
For standalone compilation buffers use the following configuration:
(setq compilation-environment '("TERM=xterm-256color"))
(defun my/advice-compilation-filter (f proc string)
(funcall f proc (xterm-color-filter string)))
(advice-add 'compilation-filter :around #'my/advice-compilation-filter)
NOTE: This compilation-mode configuration will break ag.el and rg.el, since these packages expect ANSI control sequences to be part of compilation output so that they can be used for matching. Suggestions for these packages to improve the way they perform matching already exist.
For programmatic usage from Emacs Lisp, call xterm-color-filter
to propertize
strings that you can then insert into a buffer. All state is kept in
buffer-local variables which means that control sequences can span
xterm-color-filter
calls (state machine processing).
Example:
(let ((buffer (generate-new-buffer "*xterm-color-test*")))
(with-current-buffer buffer
(insert (xterm-color-filter "\x1b[0;1;3;4"))
(insert (xterm-color-filter ";35"))
(insert (xterm-color-filter ";51mThis is only a test"))
(insert (xterm-color-filter "\x1b[0m")))
(switch-to-buffer buffer))
M-x xterm-color-test
For comint or eshell:
M-x shell || M-x eshell
perl tests/xterm-colortest && perl tests/256colors2.pl
printf "\x1b[0;1;3;4;35;51mThis is only a test\x1b[0m\n"
Comparison with ansi-color.el:
M-x xterm-color-test-raw then M-x xterm-color-colorize-buffer
and contrast with
M-x xterm-color-test-raw then M-: (ansi-color-apply-on-region (point-min) (point-max))
The code comes with a BSD-style license so you can basically do with it whatever you want.
xristos (AT) sdf (DOT) org