8
24
2011
22

改变终端下的光标颜色,包括 screen 和 tmux!

本文来自依云's Blog,转载请注明。

曾经在Ubuntu中文论坛里看到一个改变光标颜色的方法,用光标颜色来指示是在 Vim 的普通模式还是插入模式下(因为 gnome-terminal 不支持使用转义序列改变光标形状)。Vim Wiki 上的 tip

if &term =~ "xterm\|rxvt"
  silent !echo -ne "\e]12;HotPink\007"
  let &t_SI="\e]12;RoyalBlue1\007"
  let &t_EI="\e]12;HotPink\007"
  autocmd VimLeave * :!echo -ne "\e]12;green\007"
endif

可惜它不适用于当时我正在使用的 screen。现在我改用 tmux 了,偶然改变TERM变量测试的时候,发现光标颜色竟然改变了——虽然还附带一些“不良反应”。我想到:一定有办法来正确地改变光标颜色的!

于是求助于 Google,很快找到了这个,有了用于 screen 的转义序列。不过依旧不适用于 tmux。把“tmux”也加到关键词里再搜,终于找到了这个。根据这个帖子,screen 和 tmux 比 xterm 多出来的那些字符序列是告诉 screen 或者 tmux 把其中的字符序列直接发送到终端模拟器处理。

于是,我的 vimrc 又可以更新了:

let color_normal = 'HotPink'
let color_insert = 'RoyalBlue1'
let color_exit = 'green'
if &term =~ 'xterm\|rxvt'
  exe 'silent !echo -ne "\e]12;"' . shellescape(color_normal, 1) . '"\007"'
  let &t_SI="\e]12;" . color_insert . "\007"
  let &t_EI="\e]12;" . color_normal . "\007"
  exe 'autocmd VimLeave * :!echo -ne "\e]12;"' . shellescape(color_exit, 1) . '"\007"'
elseif &term =~ "screen"
  if !exists('$SUDO_UID')
    if exists('$TMUX')
      exe 'silent !echo -ne "\033Ptmux;\033\e]12;"' . shellescape(color_normal, 1) . '"\007\033\\"'
      let &t_SI="\033Ptmux;\033\e]12;" . color_insert . "\007\033\\"
      let &t_EI="\033Ptmux;\033\e]12;" . color_normal . "\007\033\\"
      exe 'autocmd VimLeave * :!echo -ne "\033Ptmux;\033\e]12;"' . shellescape(color_exit, 1) . '"\007\033\\"'
    else
      exe 'silent !echo -ne "\033P\e]12;"' . shellescape(color_normal, 1) . '"\007\033\\"'
      let &t_SI="\033P\e]12;" . color_insert . "\007\033\\"
      let &t_EI="\033P\e]12;" . color_normal . "\007\033\\"
      exe 'autocmd VimLeave * :!echo -ne "\033P\e]12;"' . shellescape(color_exit, 1) . '"\007\033\\"'
    endif
  endif
endif
unlet color_normal
unlet color_insert
unlet color_exit

因为 tmux 的TERM变量和 screen 的一致,所以得使用TMUX变量来判断是在 tmux 里还是在 screen 里。

最后,说下指定颜色的方法。可以使用和 HTML 中一样的#rrggbb甚至简写#rgb,也可以使用颜色名。这里有个 xterm 的颜色名表。

2011年8月25日更新:

写了个 zsh 函数:

if [[ $TERM == xterm* ]] || [[ $TERM == *rxvt* ]]; then # {{{2 设置光标颜色
  cursorcolor () { echo -ne "\e]12;$*\007" }
elif [[ $TERM == screen* ]]; then
  if [[ -n "$TMUX" ]]; then
    cursorcolor () { echo -ne "\ePtmux;\e\e]12;$*\007\e\\" }
  else
    cursorcolor () { echo -ne "\eP\e]12;$*\007\e\\" }
  fi
fi
Category: Linux | Tags: vim 终端 screen zsh tmux | Read Count: 27218
Fermat 说:
Aug 24, 2011 07:56:44 PM

习惯性的完成输入立即到Normal模式。Insert模式除了插入啥也干不了,我可不愿意长时间在Insert模式。

Firm 说:
Aug 24, 2011 10:12:46 PM

备注,下次我也自己实现看看,技术盲来着。

poet 说:
Aug 25, 2011 10:19:19 AM

我用 screen 。

实测用 #rrggbb 的模式貌似无效,执行到
exe 'silent !echo -ne "\033P\e]12;"' . color_normal . '"\007\033\\"'

这一行就报错。在这里 # 号被当做 alternate file 无法解析。

Avatar_small
依云 说:
Aug 25, 2011 10:37:23 AM

需要转义下。代码已更新。

Avatar_small
VT 说:
Aug 26, 2011 12:02:21 AM

补个显示彩条的 zsh 函数
<code>
color-blocks () {
echo
local width=$(( ($COLUMNS / 16) -1 ))
local chars
local pre=$(( ( $COLUMNS - ($width+1)*16)/2 ))
for ((i=0; i<$width; i++)); chars+="░"
for ((i=0; i<$pre; i++)); echo -n " "
for ((i=0; i<=7; i++)); echo -en "\e[3${i}m${chars} \e[1;3${i}m${chars}\e[m "; echo; echo
unset i
}
</code>

Ansen 说:
Aug 31, 2011 02:28:55 PM

大概看了下,纯技术控~

Avatar_small
Rykka 说:
Sep 05, 2011 12:37:22 AM

好吧。我的色彩插件galaxy发布了。
其中的terminal cursor 部分就是把你这里的东西copy过去的:)

js 说:
Sep 05, 2011 11:13:47 AM

这个在screen里是会同时改变所有窗口的颜色的。

不知道tmux里什么样子。还是用你找的那几封邮件讨论的方法吧,我看到最后的那个patch已经在1.5里了。

Avatar_small
依云 说:
Sep 05, 2011 12:30:35 PM

一样的。光标是终端模拟器管的东西,screen/tmux 也不过是将相应的字符串交给终端模拟器处理了。

js 说:
Sep 05, 2011 01:10:22 PM

嗯。那个thread里讨论的就是让tmux支持光标颜色。

Avatar_small
VT 说:
Sep 16, 2011 12:24:47 AM

另一种思路

au InsertEnter * hi StatusLine ctermfg=196 guifg=#d53873
au InsertLeave * hi StatusLine ctermfg=130 guifg=#cd5907

Avatar_small
依云 说:
Sep 16, 2011 12:52:04 PM

这主意也不错。还可以改 colorscheme 呢。

Rykka 说:
Sep 20, 2011 10:16:34 PM

我的coloscheme就是直接改状态栏的,tmux里面改光标颜色没有效果。

海盗 说:
Jan 14, 2013 09:31:50 PM

搜索 tmux 和 vim 来到这里,我遇到的问题是,使用ubuntu1204+unity+zsh,在zsh下我的vim的色彩和进入tmux之后的色彩完全不一样,请问何故?

Avatar_small
依云 说:
Jan 14, 2013 09:51:46 PM

echo $TERM 看看是不是 TERM 环境变量的问题,比如终端打开后设置其为 xterm-256color,Vim 认出来这是个支持 256 色的终端,但是进入 tmux 后 tmux 把终端设置成 screen,Vim 就不知道它可以显示 256 色了。

海盗 说:
Jan 14, 2013 10:05:47 PM

感谢!根据提示找到了解决办法:在tmux配置文件中将终端设置为xterm,然后 alias tmux = tmux -2 就行了。

还有一个问题要麻烦你,我的vim有一个快捷键是 ctrl W + 方向,是在vim的window中导航用的,我将其映射成 alt + 方向键,在 tmux 中会失效,不进入tmux不会失效。ctrl W + 方向则可以使用,不知何故?

Avatar_small
依云 说:
Jan 14, 2013 10:29:16 PM

你把终端设置成 screen-256color,不要用不正确的名字(tmux 应当对应 screen)。
你在插入模式下按 Ctrl-V 再按有问题的快捷键,看显示的键码长什么样。另外试试 tmux 里设置 set-window-option -g xterm-keys on。

海盗 说:
Jan 14, 2013 10:57:41 PM

没有设置set-window-option -g xterm-keys on前, 是^[, 其中[占两个位置. 设置之后则是^[[1;3C]

Avatar_small
依云 说:
Jan 14, 2013 11:09:40 PM

那就是要开那个选项不然不支持啦。

海盗 说:
Jan 15, 2013 02:20:45 PM

但他的作用不是切换window……怎么看[1;3C]对应的命令?

Avatar_small
依云 说:
Jan 15, 2013 05:11:34 PM

:h :map
是不是和在 tmux 外面的键值不一样?你再 map 下它试试。


登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter

| Theme: Aeros 2.0 by TheBuckmaker.com