3
19
2011
10

Ubuntu下折腾分区后休眠不能唤醒问题的解决

我自以为把 Linux 的分区相关的东西折腾得比较熟了,所以就大胆地在本机上折腾分区,结果有一天就发现,在我在 /etc/fstab 里把 swap 区从UUID指定改成用LABEL指定之后,休眠可以成功,但唤醒失败。在开机后应当从 swap 分区恢复的时候,出现错误,然后就直接启动了,其间还毁掉了 swap 分区的内容。这么试过了两次,都失败了,于是我带着迷惑,再也没有试过了。

前天在群里看到这个链接,终于恍然大悟——原来还有个配置文件/etc/initramfs-tools/conf.d/resume!它指明了唤醒时从哪个分区恢复。当初改 swap 后我只改了fstab但没有改它,所以可以正常使用却不能唤醒。不过重新生成 initrd 时为什么没有自动更新 resume 文件呢?而且休眠时系统也不检查下resume文件,郁闷。不知道休眠时能不能指定休眠到哪个分区上呢?

resume文件的内容相当简单,就一行,像这样RESUME=LABEL=swapRESUME=后面的格式和 fstab 的第一栏一样。改了后还要sudo update-initramfs -u更新 initrd。

另外,唤醒不成功的时候我曾尝试过 s2disk 这个工具,但昨天发现,虽然它在休眠时有进度显示,可是在唤醒的时候失败了——当进度达到 100% 时就没动作了,我的桌面也就没能回来……

Category: Linux | Tags: linux ubuntu
3
16
2011
22

关于“Linux”被翻译为“你牛叉”等的一些想法

昨天,我就在我所建立的vim-cn Gtalk群上看到了在Debian官方简体中文首页将“Debian”翻译为“蝶变”、“Linux”翻译为“你牛叉”,当时还以为是某人的恶作剧。今天,又见到这篇文章,才知道真相。

最开始读的时候,看到大量的翻译破坏,我想到是不是使用的机器翻译,随后意识到不可能。又以为是Linux反对者的发泄。但我还是错了。

做这件事的人是“沈卓斌”,在多个 Wiki 上的 ID 是“jobinson99”。他除了做这些莫名其妙的翻译更改外,也做了一些妥当的翻译,让恢复变得困难起来。我在ArchLinux上的几个页面改掉了他的一些翻译,更多的翻译还得依靠Google来找出了。在改的过程中我发现部分页面有相互复制的情况。不过我没精力管了。至于维基百科,其中文社区比较强大,针对其的破坏已经被恢复。其他的Debian啊、FreeBSD啊我就没心思去管了。

有些人可能对此不太在意,但我很早就读了中文维基百科的一些方针指引之类的,很快便认定这是“破坏行为“。尽管他的这些翻译看起来是善意的,但是其行为却不会被接受。首先不说他的翻译是否准确恰当,首先一点就是——没有共识。我认为,再好的翻译,只有极少数人知道,它也不应当被作为通用或者正式的名称,不然,就像使用世界语一样,大部分人根本就不知道你在说什么,更别说搜索引擎了。哪天你有某个Linux问题,Google数日未解决,却蓦然发现,原来写有解决方案的Wiki中使用的是“你牛叉”而导致你没有找到,岂不郁闷!更何况,这些翻译多似恶搞,不是所有人都会接受的,我最开始就以为是反对者来着。

我很不明白,各开源项目的维基上尚有大量资料需要翻译,中文 man 手册既少又旧以至于我都不敢用了,wget 的中文翻译错误虽然在 Ubuntu 下已经更正了,但在 ArchLinux 下依旧存在。还有这么多可以做的,他却以为无聊的翻译可以推广开源?新手安装 Linux,谁不需要安装指导?遇到问题了,为什么可能的解决办法都是用英文写的?命令不会用,man 一下,为什么没有中文翻译?很多新手在尝试Linux时都遇到各种困难而放弃,很多老鸟都在遇到问题时苦苦挣扎,我多么希望所有的开源资料能有中文翻译!很多人说Linux难用。是啊,不会英语又没人指导就根本无法使用的系统怎么会好用呢?

至于jobinson99,我想说,如果你真的蛋疼得不行的话,就把翻译放伪基百科上去啊。


附:我在 ArchWiki 上发现的不妥翻译列表:

%s/开天辟地你牛叉/LFS/ge
%s/你牛叉龙骨/ArchLinux/ge
%s/龙骨/Arch/ge
%s/你牛叉/Linux/ge
%s/共努/GNU/ge
%s/荟萃/Wiki/ge
%s/有奔头/Ubuntu/ge
%s/蝶变/Debian/ge
%s/合成/编译/gce
%s/优盘/U盘/gce

 

Category: Linux | Tags: linux 中文支持
3
12
2011
3

果断放弃 pidgin 及解决 empathy 打开链接极度缓慢的问题

不知从什么时候起,我发现直接点击 Empathy 中的链接会花较长时间,在此期间整个 Empathy 的所有窗口皆冻结而不响应操作。次数多了之后,我注意到等待的时长和链接的响应时间有关,想到曾经在HTTP服务器看到的包含 gvfs 字样的访问记录,我想就是它了。但除了发现有一个杀死又复活的 gvfsd-http 进程之外别无收获。

昨天不知道究竟是什么原因,Empathy 经常反应迟钝,于是我终于换 pidgin 了。两天已经过去,我又换回 Empathy 了,虽然 pidgin 有很多的优点,如截图、HTML 消息、联系人手动排序、*粗体* 和 _斜体_ 支持、重新发送好友请求、XMPP 控制台、好友响应可能性预测、自动弹出消息窗口、链接识别更准确、支持富文本格式的剪贴板、可取消选择区内的表情符号、支持终端(finch)、各种未知的插件等等,但是,我依旧要换 Empathy 了,因为 pidgin 的几个非常影响我使用的 bug。一是点击对话窗口,焦点不会自动移动到输入区,虽然依旧可以输入文字,但绕过了输入法,所以必须按下 Tab 或者点下输入区,否则无法输入中文。二是输入区文本选中后会清除选择区剪贴板的内容,但并不把选中文本放到剪贴板中。其三,也是我最不能忍受的是,在它的输入框输入文本时无法使用 fcitx 的第二三码选词键。

回到 Empathy,于是又要面对它打开链接缓慢的问题。虽然改用选中再粘贴的方式也不太费事,但是,看到带有下划线的浅蓝色链接难道你就不会下意识地去点吗?

Google 了很久,没找到任何有用的东西。于是开始 strace——

strace -p `pgrep empathy` -r -f

结果用 sort + tail,很容易看到最耗时的地方。我之前还在 Vim 中手动看那近一万行的记录,真是被这些问题搞晕了头了。。。

[pid  6130]      0.000149 connect(27, {sa_family=AF_FILE, path=@"/dbus-vfs-daemon/socket-jCww54HT"}, 35) = 0
...
[pid  6130]     46.212892 recvmsg(27, {msg_name(0)=NULL, msg_iov(1)=[{"l\3\1\1\"\0\0\0\1\0\0\0G\0\0\0\4\1s\0)\0\0\0org.glib"..., 2048}], msg_controllen=0, msg_flags=MSG_CMSG_CLOEXEC}, MSG_CMSG_CLOEXEC) = 122

gvfs 毫无疑问是元凶了。接收消息竟然用了 46 秒!后来我又想到去 strace gvfsd-http,最终发现真相——gvfsd-http 在 HEAD 那个 URL!真不知它想做什么。用 dpkg 查到它属于 gvfs-backends 这个软件包。看了下,依赖它的只有 deb-gview,几乎从来没用过的东西。于是果断卸载之。

卸载完后,回过头把 gvfsd-http 杀掉,终于敢放心大胆地点击 Empathy 中的链接了。

Category: Linux | Tags: Empathy linux
3
4
2011
4

Python3.2mu 与 Vim

曾经,我辛苦两星期自以为终于弄好了 Vim 的 +python3 特性,却未曾想到,编译新发布的安装 Python3.2 后 Vim 的 Python3 支持再次悲剧……

事情是这样的。在vim-cn群有人编译 Python3.2 出错问我。我于是把之前为尝新鲜而 make 的 Python3.2 又 make install 了。然后 ./configure 时就出问题了。具体错误不记得了,反正是找不到什么文件。后来我找出了我以前写的一个从 C 调用 Python 代码的小程序,编译通过,链接时找不到某些符号。折腾了好久,才知道是 Python3.2 的安装出错了,./configure 时要加 --enable-shared 参数。当然,我还比较习惯加上 --with-wide-unicode 参数。

于是我的 C 小程序编译运行成功。但 Vim 的依旧悲剧。看了 src/configure.in,注意到它并没有使用 pkg-config,而是按以前 Python 的头文件和库文件的规律硬编码进去的。这时我才发现 Python 的相关文件/目录都多了个 mu 后缀:

>>> pkg-config --cflags --libs python-3.2
-I/usr/local/include/python3.2mu  -L/usr/local/lib -lpython3.2mu
>>> ls -li /usr/local/bin/python*
163890 -rwxr-xr-x 3 root root 10877 2011-03-01 23:16 /usr/local/bin/python3
163890 -rwxr-xr-x 3 root root 10877 2011-03-01 23:16 /usr/local/bin/python3.2
164216 lrwxrwxrwx 1 root root    18 2011-03-01 23:18 /usr/local/bin/python3.2-config -> python3.2mu-config
163890 -rwxr-xr-x 3 root root 10877 2011-03-01 23:16 /usr/local/bin/python3.2mu
164107 -rwxr-xr-x 1 root root  1827 2011-03-01 23:18 /usr/local/bin/python3.2mu-config
164252 lrwxrwxrwx 1 root root    16 2011-03-01 23:18 /usr/local/bin/python3-config -> python3.2-config

这个 mu 后缀是什么意思呢?搜了半天,终于找到了:m 是普通版,u 是宽字符版(--with-wide-unicode),还有个 d 表示使用了 --with-pydebug 参数编译的。加了这些后缀,于是 Vim 配置脚本的硬编码就失败了。(它为什么要硬编码呢……T.T)对于 mu 版,修改方法是这样的:

# For Python3.2
if which python3 >/dev/null 2>&1 && [ $(python3 -c 'import sys; print(sys.version_info.minor)') -ge 2 ]; then
  sed -i -e 's|-lpython${vi_cv_var_python3_version}[dmu]*|-lpython${vi_cv_var_python3_version}mu|' \
         -e 's|python${vi_cv_var_python3_version}/config[^"]*|python${vi_cv_var_python3_version}/config-3.2mu|' \
         -e 's|include/python${vi_cv_var_python3_version}[dmu]*|include/python${vi_cv_var_python3_version}mu|' \
    src/configure.in
  # Fixed: no longer needed.
  # sed -i -e 's|PyEval_InitThreads();|/* PyEval_InitThreads(); */|' \
  #   src/if_python3.c
  autoconf=1
fi

[ $autoconf -eq 1 ] && (cd src && autoconf)

后面那个对 src/if_python3.c 的修改我也不知道是为什么,反正不这样的话调用 Python 时就 SIGABRT 出错退出,而这样改了之后好像也没什么负面影响。至于找出这个语句的办法嘛,当然是不知比 jdb 好用多少倍的 gdb 啰。


2011年4月19日更新修正了 Python3 接口的内存泄漏问题,发现已不再需要删掉那句代码了(删掉后反而出错)。

Category: python | Tags: python vim 编译
2
27
2011
9

Wine QQ隐私保护器

鉴于QQ 4 Linux实在太不好用,有些不得不使用QQ的Linux用户使用Wine来运行QQ,我经过努力也成功了,但依旧不用,因为在去年的3Q大战中我们看到腾讯实在难以信任。想想我的ssh密钥、GPG密钥、getmail和msmtp的配置文件等等非常重要的文件QQ皆可轻易扫描并上传……

想过使用另外的低权限用户来wine QQ。然而即使这样,我自己的众多文件QQ依然可以看到,心中还是不安,而且这样作为QQ的重要功能之一——互传文件——将很不方便。于是终于有一天,我开始折腾chroot了。为了不需要总是sudo,我用C写的,可以使用Linux的suid特性,同时也练习下C编程。在man相关系统调用的时候,我还发现了unshare这个调用,竟然可以把挂载的文件系统设置成只在新的挂载命名空间(mount namespace)中可见。这样就可以把为了chroot而mount --bind的项目全部隐藏起来,免得mount输出一大堆不想看到的东西。至于umount嘛,不管了,反正只是mount --bind的。

/* ===================================================================== *
 * chrooted wine QQ
 * ===================================================================== */
#define _GNU_SOURCE
#include<unistd.h>
#include<sys/stat.h>
#include<sys/types.h>
#include<sys/mount.h>
#include<linux/limits.h>
#include<sched.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<errno.h>
#define ROOT "/tmp/.rwine"
#define PROGRAM "你的QQ的目录"
/* 文件共享目录;若不存在会自动创建 */
#define SHAREDIR "哪个目录作为共享?"
#define BIN "Bin/QQ.exe"
#define ROOTD(dir) ROOT dir
#define MKDIR(dir) mkdir(ROOTD(dir), 0777)
#define MOUNTBIND(dir) mountbind(dir, ROOTD(dir))
int mountbind(const char *source, const char *target);
/* --------------------------------------------------------------------- */
int main(int argc, char **argv){
  int ret;
  ret = unshare(CLONE_NEWNS);
  if(ret){
    perror("unshare");
    exit(1);
  }
  seteuid(getuid());
  ret = mkdir(ROOT, 0777);
  seteuid(0);
  if(ret && errno != EEXIST){
    perror("mkdir new root dir");
    exit(1);
  }

  seteuid(getuid());
  mkdir(SHAREDIR, 0700);
  seteuid(0);
  setgid(0);
  MKDIR("/lib");
  MKDIR("/usr");
  MKDIR("/usr/share");
  MKDIR("/usr/bin");
  MKDIR("/usr/lib");
  MKDIR("/etc");
  MKDIR("/etc/fonts");
  MKDIR("/program");
  MKDIR("/dev");
  MKDIR("/tmp");
  MKDIR("/tmp/share");
  chmod(ROOTD("/tmp"), 01777);

  ret = MOUNTBIND("/lib")
    || MOUNTBIND("/usr/share")
    || MOUNTBIND("/usr/bin")
    || MOUNTBIND("/usr/lib")
    || MOUNTBIND("/etc/fonts")
    || MOUNTBIND("/dev")
    || mountbind(PROGRAM, ROOTD("/program"))
    || mountbind(SHAREDIR, ROOTD("/tmp/share"));
  if(ret){
    perror("mount --bind");
    exit(1);
  }

  char path[PATH_MAX];
  char path2[PATH_MAX];
  char *p;
  strcpy(path, getenv("HOME"));
  strcat(path, "/.wine");
  strcpy(path2, ROOT);
  p = strtok(path, "/");
  seteuid(getuid());
  while(p){
    strcat(path2, "/");
    strcat(path2, p);
    mkdir(path2, 0777);
    p = strtok(NULL, "/");
  }
  seteuid(0);
  /* path changed by strtok */
  strcpy(path, getenv("HOME"));
  strcat(path, "/.wine");
  strcpy(path2, ROOT);
  strcat(path2, path);
  ret = mountbind(path, path2);
  if(ret){
    perror("mount --bind user's wine dir");
    exit(1);
  }
  strcpy(path, getenv("HOME"));
  strcat(path, "/.fonts");
  if(access(path, X_OK) == 0){
    strcpy(path2, ROOT);
    strcat(path2, path);
    seteuid(getuid());
    mkdir(path2, 0777);
    seteuid(0);
    ret = mountbind(path, path2);
    if(ret){
      perror("mount --bind user's font dir");
      exit(1);
    }
  }
  strcpy(path, getenv("HOME"));
  strcat(path, "/.fontconfig");
  if(access(path, X_OK) == 0){
    strcpy(path2, ROOT);
    strcat(path2, path);
    seteuid(getuid());
    mkdir(path2, 0777);
    seteuid(0);
    ret = mountbind(path, path2);
    if(ret){
      perror("mount --bind user's fontconfig dir");
      exit(1);
    }
  }

  ret = chroot(ROOT);
  if(ret){
    perror("chroot");
    exit(1);
  }
  chdir("/tmp");
  ret = setuid(getuid());
  if(ret){
    perror("setuid");
    exit(1);
  }
  execl("/usr/bin/wine", "/usr/bin/wine", "/program/"BIN, NULL);
  /* execl("/usr/bin/wine", "/usr/bin/wine", "notepad", NULL); */
  perror("execl");
  return 1;
}
int mountbind(const char *source, const char *target){
  return mount(source, target, NULL, MS_BIND | MS_NOSUID, NULL);
}
/* ===================================================================== *
 * vim modeline                                                          *
 * vim:se fdm=expr foldexpr=getline(v\:lnum)=~'^\\S.*{'?'>1'\:1:         *
 * ===================================================================== */

程序名为rwine。这里的“r”可不是rsync或者rcp中的“r”,而是“rbash”、“rzsh”、“rvim”中的“r”的意思。在代码的最开头有几个宏是用来配置路径的。suid程序嘛,像这种东西还是硬编码进去好了。因为只是自己使用,所以没有做太多的错误检查之类的,健壮性应该不怎么样。对于这个程序我只要没有安全漏洞就OK了。

另外说个小插曲。在调试这段代码的时候,我发现用户的路径总是挂载得不对,检查了好久,才注意到strtok的声明是

char *strtok(char *str, const char *delim);

第一个参数那里没有const!再仔细看看man文档,果然,它把传进去的参数给改了。

Category: Linux | Tags: C代码 linux QQ 腾讯
2
24
2011
10

让 Vim 的 Align 插件记住常用的对齐方式

今读到 LinuxToy 上介绍 Tabular 的文章,不由得又折腾了下功能更加强大的 Align 插件。这个插件我装了很久了,也曾读过它的文档,但是实际用得却并不多,原因除了我一般写的时候就对齐好了之外,还有一点很重要——要让它精确地按照自己所希望的方式对齐一些文本可以,但得敲好长的命令,而且还需要思考,比如对齐CSS样式声明:Align! WP0p1l: :\@<=

于是我就想,能不能把常用的对齐指令都以某种方式记录下来,需要时再调用。我首先想到的是映射或者命令。实际上Align自带了一个 AlignMapsPlugin.vim,其中就定义了很多常见的映射,但是不太容易记忆,而且不知道怎么添加。每种对齐方式定义个命令有点麻烦,于是就考虑用一个命令加参数的办法,于是就写了以下函数:

function Lilydjwg_Align(type) range
  try
    let pat = g:Myalign_def[a:type]
  catch /^Vim\%((\a\+)\)\=:E716/
    echohl ErrorMsg
    echo "对齐方式" . a:type . "没有定义"
    echohl None
    return
  endtry
  call Align#AlignPush()
  call Align#AlignCtrl(pat[0])
  if len(pat) == 3
    call Align#AlignCtrl(pat[2])
  endif
  exe a:firstline.','.a:lastline."call Align#Align(0, '". pat[1] ."')"
  call Align#AlignPop()
endfunction

其中对齐样式的定义是这样子的:

let g:Myalign_def = {
      \   'css': ['WP0p1l:', ':\@<=', 'v \v^\s*/\*|\{|\}'],
      \ }

Myalign_def的值是一个列表,各项分别是对齐方式的控制序列、分隔符正则、可选的用于筛选选区的控制序列。

想到以后定义的对齐方式多了之后,那些自定义的名字会有些不记得,于是补全函数不可少:

function Lilydjwg_Align_complete(ArgLead, CmdLine, CursorPos)
  return keys(g:Myalign_def)
endfunction

现在函数和变量定义都有了,可以定义命令了:

command -nargs=1 -range -complete=customlist,Lilydjwg_Align_complete
      \ LA <line1>,<line2>call Lilydjwg_Align("<args>")

用的时候只要选中需要对齐的文本,然后按:LA 已定义的对齐方式名即可。


PS: Align 的中文对齐速度很慢,而且还有移动光标位置等“不良行为”,因此 patch 之:

--- autoload/Align.vim
+++ autoload/Align.vim
@@ -984,6 +984,11 @@
 "           nonzero value.  Solution from Nicolai Weibull, vim docs
 "           (:help strlen()), Tony Mechelynck, and my own invention.
 fun! s:Strlen(x)
+  " lilydjwg: vim7.3 有 strwidth 函数
+  if exists('*strwidth')
+       return strwidth(a:x)
+  endif
+
 "  call Dfunc("s:Strlen(x<".a:x.">")
   if g:Align_xstrlen == 1
    " number of codepoints (Latin a + combining circumflex is two codepoints)
@@ -1006,6 +1011,8 @@
    call setline(line("."),a:x)
    let ret= virtcol("$") - 1
    d
+   " lilydjwg: 这样才不会让光标乱跑
+   normal k
    let &l:mod= modkeep

 

Category: Vim | Tags: vim
2
22
2011
3

Vim7.3 的 Python3 支持修正补丁

Vim 7.3 增加了对 Python3 的支持,但其有不少 bug,从不能正确地向缓冲区中添加中文文本,到 buffer 对象不支持 slice 操作,vim.error 不是 BaseException 的子类而是一个 str,以及各种中文乱码/UnicodeDecodeError,让我这个 Python3 的坚定支持者非常郁闷,于是趁假期把 Vim 好好修理了一番。

此次修正历时两周,涉及 src/if_{py_both.h,python.c,python3.c},共 3 files changed, 308 insertions(+), 265 deletions(-),修正的具体项目为

  • 向缓冲区添加文本时正确处理编码
  • buffer 对象支持 slice 赋值
  • vim.error 不再是字符串
  • py3file 让 Python 检测文件编码
  • 向 Python 传递缓冲区字符串时使用正确的编码(这解决了 gundo 在非 UTF-8 编码时的解码出错)
  • py3 命令输入使用 'encoding' 解码后再以 UTF-8 编码(这解决了在 'encoding' 非 UTF-8 时含中文的 py3 命令的 SyntaxError)
  • 向标准输出写文本时使用正确的编码(这样 print() 之类不会输出乱码)

以上数据要感谢git工具。

目前我在 Ubuntu Linux 10.10 32bit 和 Windows XP SP3 (使用 MinGW 编译)上测试没有问题,有兴趣的请帮忙再测试下。下载地址

另外,附上 gundo 的 Python 2 & 3 兼容版以及使用 Python3 支持的 Python 补全插件 python3complete.vim(放到 ~/.vim/autoload 下)。


PS:Python3.2 发布了,增加了一些很好的新特性,比如argparse模块,str.format_map方法等等。


2011年3月3日更新:给 Vim 编译 Python3.2 支持也有些艰难,参见这篇文章

2011年4月19日更新:今天解决了内存泄漏的问题,补丁已更新。另外,本补丁将在陈列室维护。

2011年6月19日更新:此补丁已被官方采纳。

Category: Vim | Tags: C代码 python vim
1
19
2011
3

Vim 的 Ruby 支持终于不 crash 了!

Vim7.3 的 Ruby 支持 bug 无限,刚开始是编译了 Perl 支持在调用 Ruby 时就 crash。我不编译 Perl 支持,不 crash 了,但是 lusty-explorer 还是得修改后才能用,因为$curbuf.number恒为零,后来才知道编译时加上--disable-largefile选项就可以没有这个问题

今天,101号补丁的发布终于解决了这些问题!

Category: Vim | Tags: vim
1
6
2011
14

编译了 Vim7.3.98 for Win32

vim_dev邮件列表看到Bram又发布了好些补丁,想起不久前看到梧桐在找支持Ruby的Vim二进制文件,所以我又编译了下Vim。上次编译Win版时Lua好不容易弄好了,Ruby却不能用。有些相关的补丁发出来了,这次也尝试下,欣喜地发现这个bug已经解决了~

对了,我尝试过使用Make_cyg.mak在Cygwin环境下编译,结果失败了,好像是gcc不支持这么编译了,所以还是用的MinGW。

文件放dbank网盘了,外链地址。因为有些涉及到文档什么的补丁,所以runtime文件也打包传了上去。另外说下,dbank虽然上传文件速度很快,但操作界面的时候,网速却极慢(用HttpFox看过了,不是JS导致的慢)。

注:支持的Python版本是2.7,Ruby是1.9.2,Lua还是静态编译的,5.2。


2011年3月29日更新:

把自己编译的 Windows 版 Vim 放这里了,会不时更新。

Category: Vim | Tags: vim windows
1
1
2011
47

让Vim在图形界面与终端中的Alt组合键相同

首先祝大家新年快乐!


一直都感觉Vim下快捷键不够用,于是在某一天,我开始使用Alt开头的组合键,然后发现了问题——

在很多终端中,Alt 组合键发送的是 Esc 前缀键码,而图形界面中则是置位最高位。举例来说,Alt-x在图形界面下向Vim发送的是ø(在Vim插入模式下使用Ctrl-V Alt-x可以看到),其编码为0xf1,而x的编码为0x78,区别在于前者二进制编码的最高位是 1,而后者是 0。

而在gnome-terminal、konsole中则是另外一番景象。Alt-x和快速地按Esc x的效果是一样的,仅有xterm 和 rxvt 等终端可选地支持像图形界面的那样处理(参见Vim手册:help :map-alt-keys)。而且,使用置位最高位的终端将导致shell中的Alt-f之类的键绑定失效。

Emacs能处理这种不一致,但Vim不能,于是我一直是使用脚本,使得在终端下和图形界面下使用不同的键绑定。这样图形界面下没什么问题,但终端下比较郁闷:因为映射了Esc开头的键,而Esc是用于回到普通模式的,于是每次按Esc想退回到普通模式时都得等一秒('timeoutlen的值)。这个值又不能设小,不然\ww这种需要多次按键的映射就难用了。

前些天,偶然在帮助文档里看到了这个:

					*:set-termcap* *E522*
需要 {option} 的地方,可以使用 "t_xx" 形式来设置终端选项。这些选项覆盖相应的
termcap 值。设置后,可以用于映射。如果 "xx" 包含特殊字符,须用 <t_xx> 形式: >
	:set <t_#4>=^[Ot
也可用来翻译普通键的特殊键码。例如,如果 Alt-b 产生 <esc>b,可用: >
	:set <m-b>=^[b
(这里 ^[ 是真正的 <esc>,用 CTRL-V <esc> 来输入)
这个方法优于映射之处在于它能适用于所有情况。

也就是说,可以在终端下把Alt组合键都设置到Esc开头的键码,这样一是不用每次设置键映射时设置两个,更重要的是,其本质变了:这样的设置不是键映射,而是指定键码!这样会使用'ttimeoutlen'的值来等待后续键码,和映射无关了,我完全可以把它设置得很小。于是写出新的脚本:

 1 " escalt.vim    控制台下让用 <M-x> 也可用
 2 " Author:       lilydjwg <lilydjwgATgmail.com>
 3 " Last Change:  2010年12月15日
 4 " ----------------------------------------------------------
 5 " Load Once:
 6 if &cp || exists("g:loaded_escalt") || has("gui_running")
 7   finish
 8 endif
 9 let s:keepcpo = &cpo
10 let g:loaded_escalt = 1
11 set cpo&vim
12 " ----------------------------------------------------------
13 " Functions:
14 function Escalt_console()
15   for i in range(65, 90) + range(97, 122)
16     exe "set <M-".nr2char(i).">=\<Esc>".nr2char(i)
17   endfor
18   set ttimeoutlen=50
19   if &term =~ 'xterm'
20     set <F1>=^[OP
21     set <F2>=^[OQ
22     set <F3>=^[OR
23     set <F4>=^[OS
24     set <Home>=^[OH
25     set <End>=^[OF
26   endif
27   for i in ["", "c", "i", "x"]
28     exe i . "map Ï1;2P <S-F1>"
29     exe i . "map Ï1;2Q <S-F2>"
30     exe i . "map Ï1;2R <S-F3>"
31     exe i . "map Ï1;2S <S-F4>"
32   endfor
33 endfunction
34 " ----------------------------------------------------------
35 " Call Functions:
36 call Escalt_console()
37 " ----------------------------------------------------------
38 "  Restoration And Modelines:
39 let &cpo= s:keepcpo
40 unlet s:keepcpo
41 " vim:fdm=expr:fde=getline(v\:lnum-1)=~'\\v"\\s*-{20,}'?'>1'\:1

注意到其中对于F1到F4等键进行了特殊的设置。没办法,这几个键特殊,这样设置我觉得是最优的解了。设置'ttybuiltin'也可以,但是经过一些时间的试用后发现有副作用,具体是什么我忘记了。


PS: SyntaxHighlighter 不支持 Vimscript,还好 Vim 有TOhtml命令。

最新脚本在 GitHub 有。直接复制上面高亮过的代码是不行的。

Category: Vim | Tags: linux vim

| Theme: Aeros 2.0 by TheBuckmaker.com