可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I've found that terminal emacs does not render the correct colors unless I explicitly set TERM=xterm-256color. I use gnome-terminal, and from what I understand, TERM should be set to gnome-256color. Similarly, I tend to use tmux a lot, which advises against any TERM setting other than screen-256color. Unfortunately, both of those settings (within their respective context - gnome-terminal
or tmux
) result in emacs having wrong colors, whereas vim displays colors correctly. However, if I export TERM=xterm-256color
, the colors work just fine in emacs.
Can anyone explain what's going on, or offer a solution?
Update
Here's what I'm dealing with:
I can get the colors to look correct in the terminal by adding the following to my init.el
:
(defun terminal-init-gnome () "Terminal initialization function for gnome-terminal." ;; This is a dirty hack that I accidentally stumbled across: ;; initializing "rxvt" first and _then_ "xterm" seems ;; to make the colors work... although I have no idea why. (tty-run-terminal-initialization (selected-frame) "rxvt") (tty-run-terminal-initialization (selected-frame) "xterm"))
This feels really, really wrong though. There has to be a logical explanation for this...
P.S.
I have very little knowledge of terminfo and the precise role that $TERM
plays in the process of color terminal behavior. If it's safe to always use xterm-256color
(even when $TERM
"should" be gnome-256color
or screen-256color
), I'll go with that.
回答1:
Maybe I'm not understanding something, buy why don't you run emacs like this:
TERM=xterm-256color emacs -nw
This way Emacs has its own TERM setting that you know works. You can also make an alias or wrap this in shell-script.
回答2:
Terminals are a special type of device. When a process sends special byte sequences (called control sequences) to the terminal, it performs some action (like cursor positioning, change colors, etc).
You can read the ANSI terminal codes to find more detail about control sequences.
But terminals come from 70s, when hardware was limited in its capabilities, and a terminal cannot provide info about its capabilities (ie. which sequences it supports).
$TERM was used to resolve this issue - it allows programs to know what to send to the terminal to get the job done. termcap and terminfo are databases that store info about terminal capabilities for many $TERM names. If your $TERM is not in the db, you must ask an administrator to add it.
All terminal emulators inherit these limitations from old hardware terminals. So they need a properly set $TERM, and the terminfo/termcap DB MUST have data for this terminal. When a virtual terminal starts it sets the $TERM variable for you (and inside programs like bash). If $TERM is not in the terminfo/termcap you can quickly define an alias from $TERM to xterm-256color (you can find examples in the termcap file on how to do that).
回答3:
I am not that familiar with how emacs handles different terminals exactly. But looking at lisp/term
directory in emacs sources, I found out that the existence of a function terminal-init-xxx
allows you to add support for different terminals. For example, I've got:
(defun terminal-init-screen () "Terminal initialization function for screen." ;; Use the xterm color initialization code. (xterm-register-default-colors) (tty-set-up-initial-frame-faces))
in my .emacs
, which adds support for screen-256color
. You may try defining a similar function for gnome by renaming the above function to terminal-init-gnome
.
NOTE: If you are interested, you can try to track down the calls from tty-run-terminal-initialization
code. It first gets the terminal type using tty-type
function, then looks at certain locations to load a relevant terminal file, then tries to locate the matching terminal-init-xxx
function, and finally calls it. It may help you figure out the correct name for gnome-terminal
.
It looks like unless your TERM indicates that your terminal has 256 colors, emacs will only use 8. Changing TERM
to gnome-256color
allowed the color registration functions to work.
There is a way to cheat, after all. When I run gnome-terminal
, my terminal is set to xterm
by default. Instead of changing TERM
variable, it is possible to redirect xterm
to another terminal, say, gnome-256color
. Simply create the directory $(HOME)/.terminfo/x
, then run ln -s /usr/share/terminfo/g/gnome-256color ~/.terminfo/x/xterm
. I think this is better than setting TERM
manually in .bashrc
, because it only redirects a particular terminal to something else. A console login would still leave TERM
as linux
, and not xterm-256color
.
回答4:
This behavior has to do with the logic EMACS uses to determine whether the terminal background is dark or light. Run M-x list-colors-display
with TERM
set to either xterm-256color
or screen-256color
and you'll see that the exact same colors are listed. As you pointed out in the comments, the difference in color schemes that you've observed is due to the frame background mode. To see this, with your TERM
set to screen-256color
, compare the colors in
emacs -Q -nw --eval "(setq frame-background-mode 'light)"
and
emacs -Q -nw --eval "(setq frame-background-mode 'dark)"
The function frame-set-background-mode
(in frame.el
) checks to see whether the terminal type matches "^\\(xterm\\|\\rxvt\\|dtterm\\|eterm\\)"
if it can't deduce the background color otherwise.
Within a running session, you can change the color scheme to 'light
by evaluating
(let ((frame-background-mode 'light)) (frame-set-background-mode nil))
回答5:
On ubuntu 10.04 I too had noticed that running emacs -nw
inside byobu/tmux/screen
was using different colours from emacs -nw
in the regular gnome-terminal.
I found that this is because byobu
was setting TERM
to screen-bce
. Then setting TERM
to xterm
(for me, in the normal gnome-terminal
TERM=xterm
) gave me the same syntax highlighting when not running through byobu/screen
.
So still not sure what the proper solution is.
See also this post: Emacs Python-mode syntax highlighting