Emacs按键之乾坤大挪移1
Emacs按键之乾坤大挪移1
Table Of Contents
1 引子
使用Emacs不知不觉已经半年多了.最初Emacs进入我的视野,还是因为VI的缘故.
一再听说VI作为UNIX下的一大神器如何如何,心向往之,2011年春节过完年那会儿开始,下决心一定要熟练的使用VI, 我甚至打印了VI的按键图,贴在墙上,当时就抱着本O'reilly出版的Learning the vi and Vim Editors啃个大半个月, 除了会用HJKL,完全没有感觉.或者说,手部肌肉无法适应这种操作方式,
使用VI,要么想起不来该那个键,要么深感千篇一律,深受约束.完全不着调,我想很重要的一个原因,受Windows的组合 快捷键体系影响太深了吧.但是现在我知道,更重要的原因是骨子里的性格决定了最终我选择了Emacs.
当时,抱着VI铁打不换的心理,想试试Emacs到底是什么样子的.结果是显而易见的.一发不可收拾,从我开始尝试Emacs 那天起,我没有一天不鼓捣一会儿Emacs,从最简单的显示设置,到开始尝试自定义按键,再到后来的org-mode,GTD,ido, ,w3m,plantuml等等,兴趣越来越浓厚,不可自拔的陷入了Emacs的洪流中,在不断的尝试过程中,我深深感受到了自由 的力量,以及Emacs的高度可定制及博大精深(虽然我还很菜,甚至LISP也只是刚刚入门).
说了这么多,其实我只是想从不同的角度来表达自己的一个观点.那就是,作为一个大部分时间都在从事专业文字输入 的职业的人,假如必须要选择一个文本编辑器,VI及Emacs给人的感觉是那样的完全不同,以至于我认为,两者一定有一个 更适合你.更极端点说,如果你一开始就深深的喜欢其中一个,那另一个必定非常不习惯,很难适应.所以,我建议,有兴趣 的朋友不妨两个都试过后,再来绝对吧.
而作为一个程序员(虽然我目前还不是),Emacs的包容万象(emacs wiki几乎有你想到的一切解决方案)以及一体式操作 界面,很显然是更好的选择.而VI作为一个所有UNIX LIKE环境下几乎总是存在的一个统一的编辑界面,更似乎适合于在 文本终端(text-terminal)下编辑脚本,系统维护使用.不过,我觉得除了特殊的没有Emacs或者无法运行Emacs的环境, Emacs一点也不比VI差.这一点,这篇文章你看到后面就知道.
2 为什么要重新定义快捷键
以上一大堆废话,是菜鸟讲给菜鸟听的.老鸟可以无视之.下面言归正传. 正如标题所述,这篇文章主要是讲Emacs的快捷键设置.
我想很多新手一定和我一样,刚开始使用Emacs,很多快捷键很不适应. Emacs的默认快捷键布局也的确有很多不和谐的地方,以下列出一些我认为很不好的地方.
- 太多的键了Ctrl,长时间使用会使左手的小手指很不舒服. 据说Emacs发明那会儿的键盘,Ctrl键的位置其实在现在键盘Alt键的位置. 那明显用Alt比用Ctrl输入,一点都不奇怪了.
- 某个组合键对于东方人种的小手来说,间距貌似有点远.
- 对于我这种习惯于使用键盘左侧功能键的用户(多数都是吧?)有些键不是一般的绕…..
而我重新设定大量快捷键所遵循的标准如下:
- 四个手指尽量不离开或者少离开标准位置
- 因为我总在文本终端下使用Emacs,需要保证在Linux的文本终端所有的常用组合键都可用.
- 尽量保证在所有平台(WIN32,X,CONSOLE)按键的一致性.
- 尽量少用Ctrl,多用Alt.
以下所讲的快捷键主要是根据个人的喜好,针对默认快捷键做了大幅的修改.个人认为,至少在两点 上对于新手来说上手的确应该比默认容易的多.而且,键位更加合理,有效.适合长时间写作.
3 假设你已经掌握了以下知识
- 你可以熟练的盲打.并且知道标准盲打你的手指该放的位置.
- 这篇文章中,用到的功能键前缀约定.
简写 表达的组合键 C-c 表示Ctrl-c,按下Control的同时不放,再按下c M-c 表示Meta-c,Meta就是键盘上的Alt键 S-c 表示Shift-c H-c 表示Hyper-c,Hyper一般键盘上不存在,不过我们会做按键映射,有特殊用途
4 修改建个人配置文件
如果你运行过Emacs,在你的~目录一定会存在一个.emacs.d目录. 下面无论你用VI也好,nano也好,甚至ed,cat也行,无论什么办法,在.emacs.d目录下创建两个文件
- ~/.emacs.d/init.el,内容如下:
;;; init.el --- Where all the magic begins (if (file-exists-p "~/.emacs.d/.emacs") (load "~/.emacs.d/.emacs")) ;;; init.el ends here
- ~/.emacs.d/.emacs,内容如下:
;; -*-Emacs-Lisp-*- (global-set-key [(meta n)] 'window-move-up) (global-set-key [(meta p)] 'window-move-down) (global-set-key [(hyper l)] 'forward-char) (global-set-key [(hyper j)] 'backward-char) (global-set-key [(meta l)] 'forward-word) (global-set-key [(meta j)] 'backward-word) (global-set-key [(meta v)] 'scroll-up) (global-set-key [(meta q)] 'scroll-down) (global-set-key [(control q)] 'other-window-move-down) (global-set-key [(control v)] 'other-window-move-up) (global-set-key [(meta \1)] 'move-beginning-of-line) (global-set-key [(meta \2)] 'set-mark-command) (global-set-key [(meta \3)] 'move-end-of-line) (define-key key-translation-map [(control j)] [(hyper j)]) (define-key key-translation-map [(control l)] [(hyper l)]) (define-key key-translation-map [(control meta j)] [(hyper meta j)]) (define-key key-translation-map [(control meta l)] [(hyper meta l)]) (define-key key-translation-map [(meta ?\r)] [(control j)]) (define-key key-translation-map [(meta return)] [(control j)]) (global-set-key [(control x) (n)] 'switch-to-buffer) (global-set-key [(control x) (n)] 'switch-to-buffer) (global-set-key [(control x) (\4) (n)] 'switch-to-buffer-other-window) ; (global-set-key [(control x) (\5) (n)] 'switch-to-buffer-other-frame) ; (define-prefix-command 'meta-c-map) (global-set-key [(meta c)] 'meta-c-map) (add-hook 'isearch-mode-hook '(lambda () (define-key isearch-mode-map [(meta n)] 'isearch-repeat-forward) (define-key isearch-mode-map [(meta p)] 'isearch-repeat-backward) (define-key isearch-mode-map [(control r)] 'isearch-query-replace) (define-key isearch-mode-map [(meta r)] 'isearch-query-replace-regexp) (define-key isearch-mode-map [(meta f)] 'isearch-yank-word-or-char) (define-key isearch-mode-map [(meta y)] 'isearch-yank-kill) (define-key isearch-mode-map [(meta k)] 'isearch-yank-line) (define-key isearch-mode-map [(hyper l)] 'isearch-yank-char) (define-key isearch-mode-map [(hyper j)] 'isearch-delete-char) (define-key isearch-mode-map [(meta o)] 'isearch-occur) (define-key isearch-mode-map [(meta w)] 'isearch-forward-word) (define-key isearch-mode-map [(meta s)] 'isearch-repeat-forward) )) ;; ------------------------------函数定义------------------------------ (defun window-move-up (&optional arg) "Current window move-up 2 lines." (interactive "P") (if arg (scroll-up arg) (scroll-up 2))) (defun window-move-down (&optional arg) "Current window move-down 3 lines." (interactive "P") (if arg (scroll-down arg) (scroll-down 3))) (defun other-window-move-up (&optional arg) "Other window move-up 1 lines." (interactive "p") (scroll-other-window arg)) (defun other-window-move-down (&optional arg) "Other window move-down 2 lines." (interactive "P") (if arg (scroll-other-window-down arg) (scroll-other-window-down 2)))
5 光标移动相关的快捷键
功能 | 默认快捷键 | 改动后的快捷键 | 函数 |
---|---|---|---|
向右移动一个字符 | C-f | C-l | forward-char |
向右移动一个单词 | M-f | M-l | forward-word |
向左移动一个字符 | C-b | C-j | backward-char |
向左移动一个单词 | M-b | M-j | backward-word |
- 其实对于多数人来说,C-f和C-b还好了,不是很不舒服.但是C-f对于手小一点 的使用者,的确时间长了有点累,而C-b,因为我自己使用笔记本电脑,而且我不 用鼠标,主要使用键盘中间的指点杆,按下b键的时候,总是碰小红帽,不是很舒服. 改成这两个快捷键以后,彻底释放了左手,有时候,我甚至会把整个左手都放在 电脑掌托的左侧外面,用左手大拇指按Ctrl,而右手单手操作C-n,C-p,C-j,C-l. 也许有些使用者会说,C-j和C-;不是更好么? 使用起来感觉更像VIM了.我最初 也是这样设定的.不过后来到文本终端下,发现C-;是无效的按键.后来又改了回来.
- 因为C-j与C-l在很多Emacs的模式下都进行了重定义,为了一劳永逸,我使用了 一个技巧,就是将C-l,C-j使用key-translation-map重新定义了这两个键的keymap, 这两个键在任何模式下都自动转换为H-l,H-j.然后对H-l,H-j再重新定义即可. 顺便提一下,还有两个函数也可以实现类似功能,不过真的不好用.
6 窗口移动快捷键
功能 | 默认快捷键 | 改动后的快捷键 | 函数 |
---|---|---|---|
向下翻页 | C-v | M-v | scroll-up |
向上翻页 | M-v | M-q | scroll-down |
光标位置不变,内容向上移动2行 | C-u 2 C-v | M-n | window-move-up |
光标位置不变,内容向下移动3行 | C-u 3 M-v | M-p | window-move-down |
下一个窗口内容向上移动1行 | C-v | other-window-move-up | |
下一个窗口内容向下移动2行 | C-q | other-window-move-down |
- 基于对称才合理的理论,既然有C-n,C-p与M-n,M-p,那最好也有C-v,C-q与M-v,M-q与其对应.
- 中间两个我自己重写了函数,其实就是命令不同形式的打包而已,具体效果很难说清了,如果 你用过VIM,类似于^Y与^E了.,你可以照着默认 键试试就明白了. 我一直认为M-n,M-p应该是 Emacs故意预留给Emacs使用者,设定为最常使用的命令的. 我比较喜欢这种方式移动.因为这样 就不再需要C-l刷新啦!那实在是晕得很.
- 最后那两个,就是不用切换窗口,就可以向上或向下移动另一个窗口了.C-q,C-v这两个键的 Ctrl很不好按哦.建议按右边的.还好我一般也就在读帮助或者比较代码的时候偶尔用用.
7 标记文本及移动到行首行尾
功能 | 默认快捷键 | 改动后的快捷键 | 函数 |
---|---|---|---|
设定标记 | C-空格 | M-2 | set-mark-command |
移动到行首 | C-a | M-1 | move-beginning-of-line |
移动到行尾 | C-e | M-3 | Move-end-of-line |
标记单词 | M-@ | M-f | mark-word |
- 地球人都知道,C-space在WIN32下是不可用的. 也许你会说,还有C-@可以用呀! 相信我,C-@不管你双手怎么按,都是别扭.M-2就不一样了.你不妨像我一样, 大拇指按着左边的Alt,然后中指或无名指按下2键,是不是很简单?
- 标记选区从光标到行尾,M-2,M-3,也就是按着Alt不放,按下2,3就可以了. 到行首自然就是M-2 M-1喽.
- M-f配合M-j,可以对选区同时左右开弓,超酷的感觉不信你试试吧.
8 高级功能,Isearch模式快捷键的重新设定
首先说明,一下快捷键都是只在isearch模式下有效.要随时注意模式条上isearsh的标记.
功能 | 快捷键 | 函数 |
---|---|---|
搜索下一个结果 | M-n | repeat-forward |
搜索前一个结果 | M-p | repeat-backward |
查询替换 | C-r | search-replace |
正则替换 | M-r | query-replace-regexp |
向右标记单词作为搜索内容 | M-f | isearch-yank-word-or-char |
将光标到行尾作为搜索内容 | M-k | isearch-yank-line |
剪切板作为搜索内容 | M-y | isearch-yank-kill |
选择/取消选择单个字符 | C-l/C-j | isearch-yank/delete-char |
显示occur视图 | M-o | isearch-occur |
单词搜索 | M-w | isearch-word |
- 默认的快捷键搜索,感觉很是绕手,还好,我们使用的Emacs.只有你想不到, 没有做不到.
- 下面把我使用isearch的流程按照图片的形式显示出来.会更直观.用好 M-n M-p,会使搜索更有效率.
9 小结
还有两句有必要说下:
(define-prefix-command 'meta-c-map) (global-set-key [(meta c)] 'meta-c-map)
以上表示,定义M-c作为新的按键序列前缀.这样,我们可以方便定义M-c a M-c b等等. 我新定义了这个M-c前缀,主要是把跟编程有关的命令都单独定义在这个按键序列中. 你也可以自己这样做.当然,不一定非要M-c.谁说M-o不可以?
以上只是简单的介绍了一下这半年来本人有关Emacs快捷键的心得体会.
当然本人对快捷键的改动及新增远远不止这些,但是以上代码这些足够给Emacs新手足够的提示, 去自己修改属于自己的按键序列.
有什么不合适或不对的地方,欢迎指正.有任何建议,欢迎提出!
Org version 7.5 with Emacs version 23
Validate XHTML 1.0