===================================== Terminal Emulator 256 Color Support ===================================== :Author: Trent Buck :Date: 2007-09-10 :Abstract: I use emacs in screen in urxvt on Debian (and Ubuntu). I worked out how to get 256 color support working. This document describes how. Terminal emulator ====================================================================== At http://frexx.de/xterm-256-notes you can find a perl script by the name of 256colors2.pl that generates the 256 color escape codes that xterm implements. The second image on that page shows what the output *should* look like if you run the script in a terminal that supports 256 colors. Be sure to run the script directly in the terminal (rather than inside screen), because we haven't set up screen yet. I tested a number of terminal emulators in Ubuntu Edgy for 256 color support. Here are the results: :yes: mrxvt pterm xterm konsole :partial: rxvt-unicode :no: aterm aterm-ml eterm gnome-terminal hanterm-xf mlterm mrxvt-cjk mrxvt-mini multi-gnome-terminal powershell rxvt-beta rxvt-ml tilda wterm wterm-ml xfce4-terminal xvt According to http://bugzilla.gnome.org/168251, libvte (gnome-terminal, xfce4-terminal) will support 256 colors Real Soon Now. rxvt-unicode only supports 88 colours. Screen will accept 256 colours from clients, and then use the nearest approximation of the 88 colours under urxvt. The same principle applies when running screen (with 256 colour support) in an 8 colour or mono terminal. Now that you know your terminal supports 256 colors, you need to make sure that it is advertising the fact to clients. This is done with the TERM environment variable. When an application starts, it looks up the TERM value in the terminfo and/or termcap databases. You can check what the terminfo database reports for the current TERM thusly:: tput colors # should print 256 xterm ------------------------------------------------------------ The xterm in Debian Lenny and Ubuntu Edgy does not advertise 256 color support by default. To fix this you need to install a 256 color terminfo entry, and tell xterm to use it:: aptitude install ncurses-term echo XTerm.termName: xterm-256color \ >>~/.Xdefaults xrdb -merge ~/.Xdefaults Make sure .Xdefaults is loaded when you log in. Screen ====================================================================== Screen's 256 color support is a compile-time option (see http://bugs.debian.org/348099). If you use Etch/Edgy or older, you must recompile it:: cd `mktemp -d` echo deb-src http://archive.ubuntu.com/ubuntu edgy main \ >>/etc/apt/sources.list aptitude update apt-get build-dep screen apt-get source screen sed -i -e 'address@hidden/configure@& --enable-colors256@' \ screen-*/debian/rules sed -i -e '1s/(\([^)]\+\))/(\1+256color)/' \ screen-*/debian/changelog apt-get --build source screen dpkg -i screen_*.deb Like xterm, screen does not advertise 256 color support by default. You must create a terminfo entry and tell screen to use it. The following code places the compiled entry in ~/.terminfo, which is searched by default. The entry below is based closely on the xterm-256color entry from the ncurses-term package. I don't pretend to understand how it works. :: mkdir -p ~/.terminfo cat >~/.terminfo/terminfo.src <>~/.screenrc In theory screen's termcapinfo command can be used to advertise different terminal properties (to programs running inside screen) on the fly. Unfortunately it does not affect terminfo, only termcap. Emacs doesn't look at termcap, so this command is useless. Ideally we'd only set TERM to screen-256color if screen had been compiled with --enable-256color, but there's apparently no way to interrogate the screen binary to find this out programmatically. Garry Dolley notes that on OS X 10.4, vim couldn't "see" the new terminfo entry until he did :: cd ~/.terminfo && mv s 73 Emacs ====================================================================== Emacs does not know how to handle the screen-256color terminfo entry by default. From lisp/term/README: When Emacs starts, it checks the TERM environment variable to see what type of terminal the user is running on, checks for an elisp file named term/${TERM}.el, and if one exists, loads it. If that doesn't yield a file that exists, the last hyphen and what follows it is stripped. If that doesn't yield a file that exists, the previous hyphen is stripped, and so on until all hyphens are gone. So you need a file term/screen-256color.el in your load-path. Emacs 22 expects it to contain a terminal-init-screen defun. Emacs 21 expects it to contain a bunch of top-level forms. Here's what I use:: ;;; This is for GNU Emacs 22 (defun terminal-init-screen () "Terminal initialization function for screen." ;; Use the xterm color initialization code. (load "term/xterm") (xterm-register-default-colors) (tty-set-up-initial-frame-faces)) ;;; This is for GNU Emacs 21 (if (= 21 emacs-major-version) (load "term/xterm-256color")) For Emacs 21, you also need to install the xterm-256color.el file from http://www.splode.com/~friedman/software/emacs-lisp/src/term/xterm-256color.el If xterm, screen and emacs are all set up correctly, :: xterm -e screen emacs -nw -f list-colors-display should have a lot of colors; not necessarily exactly 256, but certainly more than sixteen. Problems ====================================================================== I've been running the above setup for a few months, and it causes a couple of niggling annoyances. Here's what they are, and what (if anything) can be done about them. Terminfo availability ------------------------------------------------------------ Whatever TERM value you use, the associated terminfo entry has to be available everywhere you go. The 256 color entries are less likely to be installed on esoteric systems, so you are likely to experience problems using ssh and chroot. If you can't install the terminfo entry, you have to degrade the TERM setting to something that *is* supported, e.g. :: TERM=screen ssh -t stupidhost screen emacs -nw Screen degrades colors stupidly ------------------------------------------------------------ Programs running inside screen (with TERM set to screen-256color) will always try to use 256 colors, even if screen itself is running in a sixteen color terminal. This mostly works pretty well, because screen automatically will degrade each of the 256 colors to the closest color supported by the parent terminal. The downside of this is that Screen isn't (and can't be) as smart about handling color reduction. For example, in a sixteen color terminal Emacs will use red and green for comments and strings respectively. In a 256 color terminal, emacs uses chocolate and salmon. But the closest approximation for *both* of those colors in a sixteen color terminal is red, so when running emacs inside screen inside a sixteen color terminal, you get red for both comments and string. There's really no way around this problem. For one thing, the terminal's capabilities are transmitted by the TERM environment variable, which can't be modified by a parent process. That is, if you detach screen from a 256 color xterm and reattach in a sixteen color xvt, there's no way for Screen to tell Emacs about this change. The fact that screen's -x option allows you to view the same screen window in both xterm and xvt at the same time only makes matters worse. This problem only matters if you run screen in a terminal that doesn't support 256 colors; hopefully that won't happen very often. Aptitude ------------------------------------------------------------ The aptitude bug http://bugs.debian.org/384699 affected 256-color support in Sarge and Edgy. It is now fixed.