Emacs才是世界上最强大的IDE - 用Emaci阅读文件
相信有很多人平时要阅读大量文件, 而且阅读文件比编辑文件的时间要多的多, 在Emacs里编辑文件的时候, 阅读文件很不方便, 只能用C-v M-v上下滚屏. Emacs下有个view-mode专门是为阅读文件而准备的, 在view-mode里, u向上滚半屏, d向下滚半屏, SPC向下滚一屏, 阅读文件方便多了, 但是还不够, 为什么? 因为经常在阅读文件的时候, 你看到什么不对的地方需要修改, 而在view-mode下, 文件是只读的, 而且有时候, 你在编辑文件的时候, 也需要阅读文件, 那么这两种情况下, 你都要不停的切换view-mode, 非常的不方便, 而且在view-mode里面上下左右移动还得用C-n, C-p, C-f, C-b, 也是非常的不方便, 还有前进一个单词M-f, 后退一个单词M-b, 操作起来都还是很麻烦.
大家都知道vi, 它的快捷键是出名的短, 在vi的命令模式, 上下左右以字符前进是hjkl, 是vi最著名的地方了, 非常方便, 还有它的以单词前进和后退的快捷键w, b, e, 还有好多类似移动光标的命令, 都非常的方便. Emacs下有好多模拟vi的插件, vi-mode就是一个, 它是Emacs内置的, 它模拟了好多vi的特性, 简单的光标移动命令更是当然支持了. 用它来阅读文件的话, 也是不错的, 但是还是有两方面缺点, 一是在vi-mode下好多下, 好多Emacs本身的快捷键就用不了, 比如C-a, C-y等, 二是vi本身固有的缺点(个人观点), 那就是虽然那些快捷键比较短, 但是基本上要在命令模式下运行, 想想, 当你在编辑文件的时候, 想要上下左右移动光标, 然后继续编辑, 再来个上下半屏移动光标, 再来个编辑, 然后再搜索某个单词, 再来个编辑, 就得不停的在编辑模式和命令模式来回切换, 个人觉得非常的不方便, 所以用vi-mode来阅读文件也不是最理想的选择.
鉴于以上理由, 个人自己写了个minor mode, 结合Emacs的优点和部分vi的优点, 所以它的名字Emaci就是由EMACs和vI组成, Emacs占了四个字符, vi却只占了1个字符, 因为Emaci偏向于Emacs的功能更多.
安装好Emaci(只要(require ‘emaci))后, M-x emaci-mode (我把它绑定到了M-s上, 非常方便)进入emaci-mode. 由于大部分情况下打开一个文件浏览的情况比较多, 所以我写了一个函数emaci-exist-file, 这个函数的作用就是判断当前文件是否存在, 存在的话就自动打开emaci-mode, 我把这个函数加到了find-file-hook里面, 这样当你打开一个文件的时候就自动进入了emaci-mode, 打开新文件则不会进入emaci-mode.
进入emaci-mode后, 和vi类似, hjkl上下左右以字符单位移动光标, f, b前进和后退一个单词, I回到行首并且退出emaci-mode, A回到行尾并且退出emaci-mode. 和view-mode类似, u向上滚半屏, SPC向下滚半屏, w向上滚一屏, d向下滚一屏, <和>回到buffer头和buffer尾, 这个也和view-mode一样. g也是回到buffer头, J和K则是向下和向上移动7行, B执行eval-buffer, 1最大化当前window, 2把当前buffer垂直分成两半,3把当前buffer水平非常两半,q退出emaci-mode. 我的配置里,当安装了highlight-symbol后,n向前搜索当前光标处的下一个单词,p则向后搜索,非常方便。这样配置:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | (defun highlight-symbol-settings-for-emaci () "`highlight-symbol' settings for `emaci'." (eval-when-compile (require 'cl)) ;;;###autoload (defun emaci-n () "Command bind to key n." (interactive) (if (edebug-active) (edebug-next-mode) (if (equal major-mode 'gud-mode) (call-interactively 'gud-next) (call-interactively 'highlight-symbol-next)))) (define-key-list emaci-mode-map `(("p" highlight-symbol-prev)))) (eval-after-load "emaci" `(highlight-symbol-settings-for-emaci)) |
与vi和view-mode相比最大的差异的地方也是我觉得最方便的地方, 是在emaci-mode下也可以进行一些编辑工作, 比如你在浏览某个文件的时候, 发现某一行不需要, 直接用C-k删除即可, 然后再用C-y复制一下刚才拷贝的东西, 当然同样, 可以删除一个区域, 一个单词, 一个字符, 删除字符还可以用vi中的x命令. 这些编辑操作都不需要你退出emaci-mode, 编辑完之后, 用C-x C-s保存即可. 只有当你需要敲一堆文字的时候, 因为可能会涉及到jkhl等快捷键, 这时候才需要用q退出emaci-mode. 这时候你就想了, 那是不是每次编辑之前还要看一下当前是否开了emaci-mode, 那岂不是非常麻烦? 不用担心, 开启了emaci-mode后, mode-line上会显示一个非常显眼的”Emaci”样, 我特地用白底红字标示出来, 就像这样:
当然,这个颜色你也可以控制的,该颜色是由颜色变量emaci-mode-line-face来控制的。
而且, 我一般把M-s绑定到了emaci-mode-on, M-S绑定到emaci-mode-off上面, 这样, 你想编辑的时候按下M-S, 浏览的时候按下M-s, 即使不用看那个白底红字的”Emaci”字样, 也不会出错的. 这点view-mode就不行, 它和其他的minor mode一样, 都是默认的颜色, 我一般开启了好多minor mode, 这样, 你想编辑的时候, 还得盯着mode-line看半天当前是否打开了view-mode.
emaci还对常用的一些mode, 比如view-mode(所以你如果不喜欢在emaci-mode里面能修改文件, 只想只读的阅读文件的话, 可以考虑view-mode, 它的配置文件在这里), Man-mode, apropos, diff-mode, help-mode等定制了通用的hjkl等方便的快捷键, 这些是通过emaci-brief-key-defs变量来控制的, 这个变量是一个list, list的每一个元素是由两个元素构成的list, 第一个元素是快捷键, 快捷键的写法和kbd宏的参数一样, 第二个参数是该快捷键对应的命令, 这个变量默认值如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | (defcustom emaci-brief-key-defs `(("h" backward-char) ("l" forward-char) ("j" next-line) ("k" previous-line) ("J" roll-down) ("K" roll-up) ("b" backward-word) ("w" am-forward-word-or-to-word) ("o" other-window) ("G" end-of-buffer) ("a" move-beginning-of-line) ("e" move-end-of-line)) "Key pairs used bind in modes `emaci-maps-to-bind-brief-keys'. Each element of this variable is two-elements list, and first element is key like argument of `kbd', and second element is command." :type 'list :group 'emaci) |
而待绑定这些快捷键的keymap是由变量emaci-maps-to-bind-brief-keys控制的, 其默认值如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | (defcustom emaci-maps-to-bind-brief-keys `(view-mode-map Man-mode-map apropos-mode-map completion-list-mode-map log-view-mode-map compilation-mode-map diff-mode-map help-mode-map ,(if (>= emacs-major-version 21) 'grep-mode-map) color-theme-mode-map) "List used for `emaci-bind-modes-keys'. Element of this list either a list whose first element is load file, and second element is map, or a string which means load file, or a map." :group 'emaci) |
此变量是一个keymap的list, list中的元素是keymap或者是nil。
如果你修改了以上两个变量后, 执行一下M-x emaci-bind-brief-keys使你的修改生效.
Emaci的配置文件在这里,配置如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | ;; -*- Emacs-Lisp -*- ;; Time-stamp: <2010-04-19 10:15:52 Monday by ahei> (require 'util) (require 'emaci) (apply-define-key global-map `(("M-s" emaci-mode-on) ("M-S" emaci-mode-off))) (defun emaci-settings () "settings for `emaci'." (eal-define-keys 'emaci-mode-map `(("/" describe-symbol-at-point) ("'" switch-to-other-buffer) ("L" count-brf-lines) ("t" sb-toggle-keep-buffer) ("." find-symbol-at-point) ("," find-symbol-go-back) ("]" goto-paren))) (setq emaci-brief-key-defs (append emaci-brief-key-defs `(("]" goto-paren)))) (emaci-bind-brief-keys) ;;;###autoload (defun switch-major-mode-with-emaci () "Run `switch-major-mode' with `emaci-mode'." (interactive) (let ((emaci emaci-mode)) (call-interactively 'switch-major-mode) (emaci-mode (if emaci 1 -1)))) (eal-define-keys-commonly global-map `(("C-x q" switch-major-mode-with-emaci)))) (eval-after-load "emaci" `(emaci-settings)) (provide 'emaci-settings) |
听完我的介绍, 怎么样, 是不是你也一直期待这样的功能呢, 那赶快试试吧. 这里下载Emaci, Emaci还依赖ahei-misc, eval-after-load两个包,读者均可在DEA里面下载。

loading...

用 Emacs 很久以来都是从手册和 emacswiki.org 去学东西,一个意外的机会发现了 emacser.com 阅读下来感觉受益良多。
这里想和大家探讨一下关于按键绑定的问题。。。希望使用的功能总是越多越好,越方便越好,但是可以绑的按键就是那么
有限的几个,尤其是需要 global 绑定的时候。比如说我有下面从一开始使用 Emacs 就有的一些绑定
;;
;; copy paste operations
(global-set-key (kbd “C-=”) (quote set-mark-command))
(global-set-key (kbd “C-c l”) (quote copy-line))
(global-set-key (kbd “C-c w”) (quote copy-word))
(global-set-key (kbd “C-c a”) (quote copy-string-to-mark))
(global-set-key (kbd “C-c p”) (quote copy-paragraph))
(global-set-key (kbd “C-c q”) (quote copy-in-quote-to-mark))
(global-set-key (kbd “C-c d”) (quote delete-region))
;;
那个 C-c a 原来是绑定在 C-c s 上面的,s stands for string,非常直观,可以拷贝当前光标位置的 string 粘贴到的指
定的 mark, 如果是在 shel-mode,就直接拷贝粘贴到当前提示符的最后。这样可以节省很多的拷贝粘贴的操作。后来为了模
拟 vim 里的直接查找当前光标下的word,把这个绑定占用了。这个 copy-string-to-mark 的功能就被挤到了 C-c a 这里了。
至于为什么使用 C-c a 呢?基本上就是因为,毕竟这俩键是紧挨着的,比较容易记住这个变化。
;;
那么自从升级到了 Emacs 23 以后,大量的在使用 org-mode,那么 org-mode 推荐的一些默认绑定也都是从 C-c a 开始的。
这个冲突到现在为止我还没有想出合适解决办法。毕竟上面那些绑定的确都是 global 的,我没道理进到 org-mode 以后就
把他们换掉。所以目前为止还一直都在使用 M-x org-agenda a 这样的方式。最最郁闷的就是需要 M-x org-store-link,
然后 M-x org-insert-link. 不是一般的不方便。
;;
现在使用 emaci-mode,我就不得不把那个 (add-hook ‘find-file-hook ‘emaci-exist-file) 去掉,因为我目前没法方便
的在 emaci-mode-on 和 emaci-mode-off 之间进行切换,我的 M-s 被 (anything-isearch-again) 占用了。总之就是说很难
在使用了大量的各种功能之后还可以方便的找出一些确实方便,易记的按键绑定出来。
;;
;;
大家有没有一些这方面的使用经验和体会可以交流一下吗?
[回复]
ahei 回复:
五月 30th, 2010 at 8:15 上午
@小和平鸽, 全局的命令比如你的copy-string-to-mark最好用全局的按键prefix,比如C-x,这样冲突就少了.你M-s被占了,你可以换一个其他你认为方便的啊.BTW quote你为啥不用单引号代替.
[回复]
使用 viper-mode 的飘过……
其实楼主所说的 vi 的缺点(虽然个人并不认同)正可以通过 viper-mode 克服。viper-mode 有两种模式,按 ESC 进入 vi 模式,可以用 vi 的所有命令比如 hjkl;退出 vi 模式进入编辑模式后,可以用 emacs 的所有编辑命令比如 C-a, C-v, C-e。
像楼主所举的编辑的例子,可以进入 emacs 编辑模式,然后全部使用 emacs 快捷键完成全部修改,再按 ESC 退出到 vi 模式,方便的用 hjkl 来 view。
[回复]
ahei 回复:
六月 5th, 2010 at 2:48 下午
@yswzing, 呵呵,我文中说了,我觉得来回切换非常麻烦.我的emaci可以在不需要退出emaci-mode,照样可以使用emacs自己的编辑功能
[回复]
楼主的 emaci-mode 在需要较多编辑操作时不需要切换吗?如果我没有理解错的话,你文中的意思是说在做较简单的编辑比如 C-k/C-y 时,可以直接在 emaci-mode 下完成;而如果需要较复杂的编辑,还是需要退出 emaci-mode。在我看来,这和 viper-mode 没有任何区别(除了快捷键不同,或许你的重点在此?)。
楼主可能没有用过 vi,vi 在命令模式下也可以做编辑。从你文中所述功能来看,没有哪个是 viper-mode 做不到的,并且切换也不比 viper-mode 的少。
当然,楼主的快捷键还是比较有特色的,很适合文本浏览。
[回复]
yswzing 回复:
六月 6th, 2010 at 1:28 上午
@yswzing,
点错回复位置了,楼主勿怪啊
[回复]
ahei 回复:
六月 6th, 2010 at 1:41 上午
@yswzing, emaci-mode与viper-mode的不同处,也是我认为方便的地方在于:
1. 在emaci-mode和emacs的正常编辑模式下切换非常方便,M-s和q
2. mode-line上显示非常明显的标志,让你一眼能看到emaci-mode是否开着了
3. 在emaci-mode下照样可以用emacs里面的快捷键,但是在viper-mode下却不能使用emacs正常编辑下的某些快捷键,比如C-a, C-y等,文中也说明了
当然以上3点,应该也可以通过定制让viper-mode也能做到,不过可能就麻烦了点了.
[回复]
yswzing 回复:
六月 6th, 2010 at 2:06 上午
@ahei,
> 1. 在emaci-mode和emacs的正常编辑模式下切换非常方便,M-s和q
viper-mode 切换更方便:ESC(我一般把 CapsLock 当作 ESC 用)进入 viper-mode,I/A/i/a/s/S/C 等有无数键均可以进入编辑模式。当然,这么多键可能会吓住一些人,只记住 ESC 和 i 即可。
> 2. mode-line上显示非常明显的标志,让你一眼能看到emaci-mode是否开着了
viper-mode 和正常编辑 mode 的光标不同,一眼就可以看出,当然你可能一下找不到光标,如果是这样的话,还是 emaci-mode 方便一些。建议 emaci-mode 在浏览和编辑的时候可以把光标的形状换一下。
> 3. 在emaci-mode下照样可以用emacs里面的快捷键,但是在viper-mode下却
不能使用emacs正常编辑下的某些快捷键,比如C-a, C-y等,文中也说明了
viper-mode 可以使用 C-a/C-e 等,但是一般在 viper-mode 下有更好的快捷键,你所说的 C-a 可以用 0 代替,C-y 可以用 p 代替。
如果考虑定制的话,viper-mode 可以任意调整快捷键设置,比如你可以在命令模式下使用大部分的 vi 快捷键+一些方便的 emacs 快捷键,在编辑模式下使用全部的 emacs 快捷键。
[回复]
ahei 回复:
六月 6th, 2010 at 2:16 上午
@yswzing, 1. Emacs的按键定制坚持这样的原则,宁愿多用一些离键盘中心比较近的键,也不少用一些离键盘中心比较远的键,这点我非常喜欢,所以我非常不喜欢按那个ESC键,ESC键在有些键盘上特别远.在vi里面你可以试试C-c,99%的情况下可以代替ESC
2. 目前cursor-change只在只读和可写两种状态下切换, 而且emaci-mode下其实是可写的, 所以切不切换光标状态是有争议的.你可以自己定制一下curchg-change-cursor-on-overwrite/read-only函数,等我有空的时候我加个切换光标的条件的变量,这样用户更方便的定制了.
3. 你这样的话,用户按C-a C-y之前还要考虑是否在viper-mode下,而是否在viper-mode下还不是很容易看的出来,我想这样会严重降低用户体验的,你觉得呢.我写emaci-mode下一个非常重要的目的就是让用户不必区分是否在emaci-mode下,而可以使用Emacs正常编辑下的快捷键,因为像C-a C-y等快捷键还是非常方便的,我个人觉得C-a比0方便,还是因为C-a离键盘中心更近的原因,如果你把capslock和右ctrl键交换过了的话, 会更方便的.
[回复]
匿名 回复:
六月 6th, 2010 at 3:43 上午
@ahei,
说到快捷键的方便程度,就仁者见仁,智者见智了,这个跟个人习惯有关。我个人一般是能用单键的不用组合键,所以我用 CapsLock 替代 ESC,而不是用 C-c 替代 ESC。
对于不用 viper-mode 的人(应该占绝大部分)来说,楼主的 emaci-mode 还是非常方便的。不用学习一套新的键绑定,只要记住几个快捷键就行了。其中 Space/u/d 翻页还是很酷的。
[回复]
ahei 回复:
六月 6th, 2010 at 3:48 上午
@, 呵呵,你用capslock代替ESC,是方便了,但是你其他control的快捷键就不方便了啊,毕竟在Emacs下还是有非常多的以control开头的键.emaci的快捷键和less比较象,我非常喜欢,浏览起来非常方便.
[回复]
jayklx 回复:
九月 1st, 2010 at 7:48 下午
@,
vi来说C-[绝对是王道啊~两个小拇指轻轻一点,就ok了~比esc好按多了, 也更加通用(esc在一些时候会失效)
我觉得提esc提的太多了,导致很多人都忽略了C-[
[回复]
ahei 回复:
九月 1st, 2010 at 7:50 下午
@jayklx, 比C-c好用?
[回复]
jayklx 回复:
九月 1st, 2010 at 9:49 下午
@blizz,
差不多吧,我比较习惯C-[
小拇指平常一个放在A上,另一个放在L上, 两个稍微挪一点点就行了, C-c我映射成关闭
窗口了
很多终端上C-[是等同于esc的, 这样还是有点好处的吧..
[回复]
不小心搞成匿名了:)
[回复]
在emaci-mode下编辑操作和浏览操作会有一些不方便。
比如在这个模式下,我想输入文本”copyright”,其中文本p, g, h会与vi中的命令有冲突。
在emaci-mode下,我现在只想要“浏览(jkhlaegG…..) +粘贴删除等(C-k, C-y, delete, backspace….)”, 即禁止在该模式下输入文本字符,请问我该如何设置呢?
[回复]
ahei 回复:
六月 30th, 2010 at 2:18 上午
@凌狐, emaci就是这样设计的,你如果想那样的话,你直接用view-mode就可以了
[回复]
凌狐 回复:
六月 30th, 2010 at 2:46 上午
@ahei, view-mode下缺少直接粘贴和删除的功能
[回复]
ahei 回复:
六月 30th, 2010 at 2:48 上午
@凌狐, 哈哈,那你既然知道这个,就应该知道了为啥输入某些未绑定的字母键能修改buffer了吧?你别按错不就是了,而且在emaci可以输入中文,多爽阿
[回复]
凌狐 回复:
六月 30th, 2010 at 2:58 上午
@ahei, emaci-mode哪都好,就是这点让我抓狂.
It’s a real pain in the neck. That always makes me awful.
jkhlaedxgGnpo这么多vi命令. 当你输入文本的时候能一下子反应过来吗? 有没有办法
禁止非命令字符的输入, 当输入这些东西的时候提示无效? 请明示.
[回复]
ahei 回复:
六月 30th, 2010 at 3:05 上午
@凌狐, 你输入英文文本的时候用q退出emaci-mode不就行了吗?
[回复]
凌狐 回复:
六月 30th, 2010 at 4:40 上午
@ahei, q退出emaci-mode是一个解决方法.
不过我的问题是这样的, 经常忘记开了emaci-mode, 即使它很人性化的显示为红色.
当我文本输入的时候, 比方说输入”right”, ri是上屏了,可g命令又使光标到了文件头,
而且在此写入了后面的字符.
鉴于我的忘事,我想改emaci-mode为”基本的vi浏览命令(jkhlaegG…) +
删除粘贴命令(C-k, C-y, delete…)”, 而且明确禁用非vi命令的文本输入, 并提示我
此模式下不能输入, 需要q退出.
我该如何禁用文本输入呢, 你有什么建议吗?
[回复]
ahei 回复:
六月 30th, 2010 at 4:57 上午
@凌狐, 忘了的话,就还原一下吧,很方便的。你可以把buffer设置成只读的,然后定义一些删除的命令,这些命令首先把buffer改成可写的,删除完后再改成只读的就可以了。
[回复]
楼主,
我看到你的配置文件中的 dot-mode 可以模拟vi的”.”。 我搜索配置文件,发现按键”.” 对应命令”emaci-.”。 但我找不到”emaci-.” 到定义。请问”emaci-.” 是在那里定义的。或者这个按键”.”是如何模拟的vi中到”.”。
谢。
[回复]
ahei 回复:
三月 13th, 2012 at 1:33 下午
@weikent, 你仔细看下dot-mode的使用说明
[回复]
我尝试修改emaci.el 增加功能发现不行啊. 我想自己映射某些键.却不生效.求教如何修改
[回复]