简体   繁体   English

终端emacs颜色仅适用于TERM = xterm-256color

[英]Terminal emacs colors only work with TERM=xterm-256color

I've found that terminal emacs does not render the correct colors unless I explicitly set TERM=xterm-256color. 我发现除非我明确设置TERM = xterm-256color,否则终端emacs不会呈现正确的颜色。 I use gnome-terminal, and from what I understand, TERM should be set to gnome-256color. 我使用gnome-terminal,根据我的理解,TERM应该设置为gnome-256color。 Similarly, I tend to use tmux a lot, which advises against any TERM setting other than screen-256color. 同样,我倾向于使用tmux,它建议不要使用除screen-256color之外的任何TERM设置。 Unfortunately, both of those settings (within their respective context - gnome-terminal or tmux ) result in emacs having wrong colors, whereas vim displays colors correctly. 不幸的是,这两个设置(在各自的上下文中 - gnome-terminaltmux )导致emacs颜色错误,而vim正确显示颜色。 However, if I export TERM=xterm-256color , the colors work just fine in emacs. 但是,如果我export TERM=xterm-256color ,颜色在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 : 我可以通过在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... 必须有一个合乎逻辑的解释...

PS PS

I have very little knowledge of terminfo and the precise role that $TERM plays in the process of color terminal behavior. 我对terminfo以及$TERM在彩色终端行为过程中扮演的确切角色知之甚少。 If it's safe to always use xterm-256color (even when $TERM "should" be gnome-256color or screen-256color ), I'll go with that. 如果总是使用xterm-256color (即使$TERM “应该是gnome-256colorscreen-256color )也是安全的,我会继续使用它。

Maybe I'm not understanding something, buy why don't you run emacs like this: 也许我不理解某些东西,为什么不运行像这样的emacs:

TERM=xterm-256color emacs -nw

This way Emacs has its own TERM setting that you know works. 这样Emacs就有自己的TERM设置。 You can also make an alias or wrap this in shell-script. 您也可以在shell脚本中创建别名或包装它。

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. 您可以阅读ANSI终端代码以查找有关控制序列的更多详细信息。

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). 但终端来自70年代,当硬件的能力有限时,终端无法提供有关其功能的信息(即它支持的序列)。

$TERM was used to resolve this issue - it allows programs to know what to send to the terminal to get the job done. $ TERM用于解决此问题 - 它允许程序知道要发送到终端的内容以完成工作。 termcap and terminfo are databases that store info about terminal capabilities for many $TERM names. termcapterminfo是存储许多$ TERM名称的终端功能信息的数据库。 If your $TERM is not in the db, you must ask an administrator to add it. 如果$ TERM不在数据库中,则必须要求管理员添加它。

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. 所以他们需要一个正确设置的$ TERM ,而terminfo / termcap DB必须有这个终端的数据。 When a virtual terminal starts it sets the $TERM variable for you (and inside programs like bash). 当虚拟终端启动时,它会为您设置$ TERM变量(以及像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). 如果$ TERM不在terminfo / termcap中,您可以快速定义从$ TERMxterm-256color的别名(您可以在termcap文件中找到有关如何执行此操作的示例)。

I am not that familiar with how emacs handles different terminals exactly. 我并不熟悉emacs如何处理不同的终端。 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. 但是看看emacs源代码中的lisp/term目录,我发现函数terminal-init-xxx允许你添加对不同终端的支持。 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 . 在我的.emacs ,它增加了对screen-256color支持。 You may try defining a similar function for gnome by renaming the above function to terminal-init-gnome . 您可以尝试通过将上述函数重命名为terminal-init-gnome来为gnome定义类似的函数。

NOTE: If you are interested, you can try to track down the calls from tty-run-terminal-initialization code. 注意:如果您感兴趣,可以尝试从tty-run-terminal-initialization代码中跟踪调用。 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. 它首先使用tty-type函数获取终端类型,然后查看某些位置以加载相关的终端文件,然后尝试找到匹配的terminal-init-xxx函数,最后调用它。 It may help you figure out the correct name for gnome-terminal . 它可以帮助您找出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. 看起来除非你的TERM指示你的终端有256种颜色,否则emacs只会使用8.将TERM更改为gnome-256color允许颜色注册功能起作用。


There is a way to cheat, after all. 毕竟,有一种方法可以作弊。 When I run gnome-terminal , my terminal is set to xterm by default. 当我运行gnome-terminal ,我的终端默认设置为xterm Instead of changing TERM variable, it is possible to redirect xterm to another terminal, say, gnome-256color . 可以将xterm重定向到另一个终端,例如gnome-256color ,而不是更改TERM变量。 Simply create the directory $(HOME)/.terminfo/x , then run ln -s /usr/share/terminfo/g/gnome-256color ~/.terminfo/x/xterm . 只需创建目录$(HOME)/.terminfo/x ,然后运行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. 我认为这比在.bashrc手动设置TERM要好,因为它只会将特定终端重定向到其他位置。 A console login would still leave TERM as linux , and not xterm-256color . 控制台登录仍然会将TERM保留为linux ,而不是xterm-256color

This behavior has to do with the logic EMACS uses to determine whether the terminal background is dark or light. 此行为与EMACS用于确定终端背景是暗还是亮的逻辑有关。 Run Mx list-colors-display with TERM set to either xterm-256color or screen-256color and you'll see that the exact same colors are listed. 运行Mx list-colors-display ,将TERM设置为xterm-256colorscreen-256color ,您将看到列出完全相同的颜色。 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 要看到这一点,将你的TERM设置为screen-256color ,比较颜色

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. 函数frame-set-background-mode (在frame.el )检查终端类型是否匹配"^\\\\(xterm\\\\|\\\\rxvt\\\\|dtterm\\\\|eterm\\\\)"如果可以的话否则不会推断出背景颜色。

Within a running session, you can change the color scheme to 'light by evaluating 在正在运行的会话中,您可以通过评估将颜色方案更改为'light

(let ((frame-background-mode 'light)) (frame-set-background-mode nil))

Add this to your ~/.emacs : 将其添加到~/.emacs

(add-to-list 'term-file-aliases
    '("st-256color" . "xterm-256color"))

It tells emacs that if it sees TERM=st-256color then it should initialize the terminal as if it had seen TERM=xterm-256color . 它告诉emacs如果它看到TERM=st-256color那么它应该初始化终端,好像它已经看到TERM=xterm-256color


Longer answer: 更长的回答:

Emacs is showing strange colors because it thinks your terminal can only support 8 colors. Emacs显示奇怪的颜色,因为它认为您的终端只能支持8种颜色。 In Emacs, run Mx list-colors-display to see the colors it thinks are available. 在Emacs中,运行Mx list-colors-display以查看它认为可用的颜色。 The correct number of colors is detected during terminal-specific initialization . 特定终端的初始化期间检测到正确的颜色数。 It says, in part: 它部分说:

Each terminal type can have its own Lisp library that Emacs loads when run on that type of terminal. 每种终端类型都有自己的Lisp库,Emacs在该类型的终端上运行时会加载它。

On my machine, the terminal-specific initialization files are in /usr/local/share/emacs/25.*/lisp/term . 在我的机器上,特定于终端的初始化文件位于/usr/local/share/emacs/25.*/lisp/term It has files for xterm, rxvt, screen, etc. but nothing for st. 它有xterm,rxvt,screen等文件,但没有st。 We need to help Emacs find the right initialization file. 我们需要帮助Emacs找到正确的初始化文件。 The documentation further says: 文件进一步说:

If there is an entry matching TERM in the term-file-aliases association list, Emacs uses the associated value in place of TERM 如果在term-file-aliases关联列表中存在与TERM匹配的条目,则Emacs使用关联值代替TERM

So that association list is a recommended way to handle unknown terminals. 因此,关联列表是处理未知终端的推荐方法。 It works without you having to manually override the TERM environment variable. 无需您手动覆盖TERM环境变量即可运行。

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. 在ubuntu 10.04上我也注意到在byobu/tmux/screen中运行emacs -nw在常规gnome-terminal中使用emacs -nw中的不同颜色。

I found that this is because byobu was setting TERM to screen-bce . 我发现这是因为byobuTERM设置为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 . 然后将TERM设置为xterm (对我来说,在正常的gnome-terminal TERM=xterm ),在没有通过byobu/screen运行时给出了相同的语法突出byobu/screen

So still not sure what the proper solution is. 所以仍然不确定适当的解决方案是什么。

See also this post: Emacs Python-mode syntax highlighting 另见这篇文章: Emacs Python模式语法高亮

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM