技术宅和经济盲

Sunday, January 15, 2012

从mac到remote emacs

经常要remote到linux上写code,有些自己的emacs上的设置很方便,偏生NX常常速度慢得不行,VNC啥的看上去跟Terminal也没啥区别,所以就考虑用terminal ssh搞定一个可以远程编辑的,跟图形界面不相上下的环境。


目标:Mac Terminal/ITerm -> ssh linux machine -> tmux -> emacs
解释:
- 用tmux的原因是可以保存干活的场景。这样在公司没做完的事情,回家打开环境什么都是一样的。不用screen的原因是它的代码我看不懂。
- 用emacs很直接,除了java之外所有的代码都是用emacs写来最方便。(hiahia,我期待以后可以写点go的东西,伊还是非常言简意赅的,而且貌似比python还漂亮一些)至于emacs的代码,我也看不懂,不过总算用的时间比较长,大约能就着manual (Ctrl-h f)看函数。
- ssh是必须的。
- Mac的term有很多,Terminal和Iterm是最有名的两个。所以就暂定是它们了。后来用了Iterm2,因为更方便的配置能力。

过程:
- 首先要确认Meta + Function Keys能正确的传。老实说,最后看下来这一步最累。
    以前完全不懂Linux的key stroke怎么最后转换成Application的Input的。X Windows底下是接受一些Events,想来Linux应该也差不多。但是emacs里面是确定的key-binding,比如:
    (global-set-key [(control next)] 'next-multiframe-window)
也就是说把multiple key events变成了一个了,term模式下应该也差不多。
    以上是猜,然后去看document。搞了将近六七个小时,大约有点明白敲键盘的时候会有scan code,然后根据loadkeys里面保存的keymap,可以将scan code按key code的方式转换成key symbols。事实上,我最后也没有具体去把它弄成key symbols,因为强大的emacs直接使用scan code了,这是后话。(这是term模式下的方式,如果是X下的话,loadkeys用xmodmap代替,两者的map按documents上的说法,大同小异)
    于是,第一步要搞清楚按键的scan code。文档里面有提到用console-tools里面的showkey,于是就试了试,没搞出来Ctrl-PgDn。讶异中去翻了一下showkey的代码:
http://codesearch.google.com/#F6AYLsPZoMQ/showkey.c&q=showkey&type=cs
然后就极度怀疑read(...)怎么可能把真实的东西读到?(事实上它做的挺正确的,因为前面又ioctl,已经设置了read(...)的模式了,事后才知道的)基于这样的怀疑,又开始找帖子、看代码,打算自己写一个这样的东西。貌似大家都用curses/ncurses这样的库,于是下了一个,写了个简单的代码如下:

#include <stdlib.h>
#include <ctype.h>
#include <curses.h>

int main(void)
{
  WINDOW *_window = initscr();
  int _rows;
  int _cols;

  cbreak();

  /* Accept all keys */
  keypad(_window, true);

  /* Don't echo things that are typed */
  noecho();

  /* Get the screen dimensions */
  getmaxyx(_window, _rows, _cols);

  /* Don't display cursor */
  curs_set(0);

  for (;;)
  {
    printw("Press a Key ");
    refresh();
    int key = wgetch(_window);
    printw("%d \n", key);
  }

  endwin();

  return 0;
}

按照文档的说法,程序看上去还比较靠谱,只是试来试去,跟showkey的结果就是一样,没反应。但是PgDn这样的又是对的,所以我开始觉着我的程序其实是对的了。

于是把程序放到client机器上跑了跑:在Terminal / Iterm 下跟在远程的结果是一样的。有点怀疑是terminal屏蔽了一些键,于是在windows下用putty连到linux上试了试,也是一样。(后来很后悔这一试,让我几乎认为不是屏蔽的问题了)好了好多时间都没试通,我宝贵的时间啊⋯⋯最后a还是反过头来怀疑屏蔽的问题,在mac下下了个X server(XQuartz),用里面的xterm试了试,过了   !&*#^*@$(*(*$*&@$  万恶的无尽的terms啊!

这个过了之后,很快用这个xterm连到linux上去试了试,也过了。用tmux试了试,废了。给tmux-users@报了问题,也差不多半夜了,就睡去了。

睡觉的时候忽然想,xterm可以过,没道理Iterm这样的不能用啊?第二天找来找去发现Iterm也有xterm模式,只是里面的设置少的可怜。记得Iterm2在跟tmux做integration,所以顺便下了个Iterm2,一下发现里面可以配置的东西非常多,于是就用了它。只是伊没有Ctrl-PgDn之类,需要自己把xterm上对应的scancode映射过来。

于是,终于搞定scan code映射的问题。

- 之后是tmux的问题。上面说了去tmux-users@报过问题了,第二天一早有位老兄就回信说我需要开xterm-keys option了。打开, 还是不对!用screen试了一下,过了,然后我又误会人家了。只是因为这个问题现在不是关键问题,我跳过去去搞emacs了。下午回来,调了下程序就发现原来我的.tmux.conf里面有错,伊没有正确enable xterm-keys,所以这个问题也过了。

这个时候,我的键盘输入已经可以传送到emacs了,只是传送的是scan code,不是像X下面的key symbols而已了。

- 显然我对emacs比对keycode mapping熟悉,于是就想,肯定有人直接用scan code给xterm用了吧?上网一找,就是xterm-extras.el吗。貌似最新的xterm.el也可以,不过我没有试。当我load好xterm-extras.el的时候,我就已经笑了,我的环境已经跟X底下差不多了,而且远程环境下快了很多。

- 最后还有一些小配置,就是前面说的Iterm2,还有我下了个最新版的emacs 24.0.92编了一把。没发现有什么新东西,只是把我的.emacs更新了一下。(ido被去掉了,不过貌似这东西现在也没太大用了)最悲伤的是,cua mode死活没试通。

TODO:
- tmux还需要有些设置,以方便转化成copy mode上下翻页看历史信息。
- Emacs cua-mode。

Labels:

0 Comments:

Post a Comment

<< Home