Emacs
Table of Contents
- 1. Emacs 简介
- 2. Emacs 基本用法
- 3. Emacs 高级用法
- 4. Emacs 小技巧
- 5. Emacs 常用 mode
- 6. 编程相关
- 7. Elisp
1. Emacs 简介
Emacs is the extensible, customizable, self-documenting real-time display editor.
GNU Emacs Manual: http://www.gnu.org/software/emacs/manual/html_node/emacs/index.html
GNU Emacs Reference Cards: https://www.gnu.org/software/emacs/refcards/
Richard Stallman 于 1981 年发表的 Emacs 介绍论文:http://www.gnu.org/software/emacs/emacs-paper.html
2. Emacs 基本用法
2.1. 帮助系统
Emacs 帮助文档相关快捷键如表 1, 2, 3, 4 所示。
hotkey | function | description |
---|---|---|
C-h c key | describe-key-briefly | 简要地查看热键的功能描述 |
C-h k key | describe-key | 查看热键的详细功能描述 |
C-h K key | Info-goto-emacs-key-command-node | 查看热键对应的文档 |
hotkey | function | description |
---|---|---|
C-h w command | where-is | 查看命令绑定的热键 |
C-h f command | describe-function | 查看命令对应的文档 |
C-h v variable | describe-variable | 查看变量的当前值以及对应的文档 |
说明:要设置变量的值,执行 M-x set-variable
即可。
hotkey | function | description |
---|---|---|
C-h a | apropos-command | 查找相关命令 |
(none) | apropos | 查找相关的函数或变量 |
(none) | apropos-variable | 查找相关的用户设置变量 |
C-h d | apropos-documentation | 查找相关的文档 |
hotkey | function | description |
---|---|---|
C-h m | describe-mode | 查看编辑模式 |
C-h b | describe-bindings | 查看绑定热键 |
C-h ? | help-for-help | 查看帮助列表 |
C-h n | view-emacs-news | 浏览 Emacs 新闻 |
C-h t | help-with-tutorial | 查看 Emacs 教程 |
C-h r | info-emacs-manual | 以 info mode 方式阅读 Emacs 手册 |
C-h C-c | describe-copying | 查看许可证信息 |
说明:执行 M-x locate refcard
可查找 emacs 自带的 refcard。
2.2. 文件基本操作
Emacs 文件基本操作相关快捷键如表 5 所示。
hotkey | function | description |
---|---|---|
C-x C-f | find-file | 打开文件 |
C-x C-r | find-file-read-only | 只读方式打开文件 |
C-x C-v | find-alternate-file | 关闭当前文件,打开另一文件 |
C-x 4 f | find-file-other-window | 在另一个 window 中打开文件 |
C-x 5 f | find-file-other-frame | 在另一个 frame 中打开文件 |
C-x C-s | save-buffer | 保存当前文件 |
C-x s | save-some-buffers | 保存所有文件 |
C-x C-w | write-file | 另存文件 |
(none) | write-region | 把当前选择区域另存到新文件 |
C-x C-q | toggle-read-only | 去掉或加上只读属性 |
C-x i | insert-file | 插入另一文件到当前文件 |
C-x C-c | save-buffers-kill-terminal | 退出 emacs |
2.2.1. 打开远程机器文件
按下 C-x C-f
后,输入 /ssh:yourUser@yourHost:/path/to/file
即可打开远程机器上对应的文件。如果你需要频繁操作远程机器上某个目录下的多个文件,可以按下 M-x dired
后,输入 /ssh:yourUser@yourHost:/path/to/dir
。
2.3. 移动光标
Emacs 移动光标相关快捷键如表 6 所示。
hotkey | function | description |
---|---|---|
C-f | forward-char | 向前一个字符 |
C-b | backward-char | 向后一个字符 |
C-p | previous-line | 上移一行 |
C-n | next-line | 下移一行 |
M-f | forward-word | 向前一个单词(Ctrl+左箭头) |
M-b | backward-word | 向后一个单词(Ctrl+右箭头) |
C-a | beginning-of-line | 移到行首 |
C-e | end-of-line | 移到行尾 |
M-e | forward-sentence | 移到句首 |
M-a | backward-sentence | 移到句尾 |
M-} | forward-paragraph | 下移一段 |
M-{ | backward-paragraph | 上移一段 |
C-v | scroll-up | 下移一屏 |
M-v | scroll-down | 上移一屏 |
C-x ] | forward-page | 下移一页(没有分页符,会移到文档头) |
C-x [ | backward-page | 上移一页(没有分页符,会移到文档尾) |
M-< | beginning-of-buffer | 移到文档头 |
M-> | end-of-buffer | 移到文档尾 |
M-g g n | goto-line | 移到第 n 行 |
(none) | goto-char | 移到第 n 个字符 |
C-l | recenter | 将当前位置放到页面中间(这个实用) |
C-M-n | forward-list | 往前跳转到匹配括号(当前光标应位于“闭括号”后面) |
C-M-p | backward-list | 往后跳转到匹配括号(当前光标应位于“开括号”前面) |
C-M-f | forward-sexp | 往前跳一个 balanced expression |
C-M-b | backward-sexp | 往后跳一个 balanced expression |
C-u C-@ | 回到光标的前一个位置(阅读代码时有用) |
2.4. 删除操作
hotkey | function | description |
---|---|---|
C-d | delete-char | 删除光标处字符(相当于 Delete) |
Backspace | delete-backward-char | 删除光标前字符 |
M-d | kill-word | 删除光标处一个单词 |
M-Backspace | backward-kill-word | 删除光标前的一个单词 |
C-k | kill-line | 删除一行(仅从光标处到行尾) |
C-S-Backspace | kill-whole-line | 删除整行(快捷键在 X 下有效,终端下一般无效) |
M-k | kill-sentence | 删除光标起一句 |
C-x Backspace | backward-kill-sentence | 删除光标前一句 |
(none) | kill-paragraph | 删除光标起段落 |
(none) | backward-kill-paragraph | 删除光标前段落 |
M-z char | zap-to-char | 删除到字符 char 为止 |
hotkey | function | description |
---|---|---|
M-\ | delete-horizontal-space | 删除光标前后的所有空格和 tab 字符 |
M-SPC | just-one-space | 删除光标前后的所有空格和 tab 字符,但保留一个 |
C-x C-o | delete-blank-lines | 删除多余的空白行,仅保留一行 |
M-^ | delete-indentation | 合并当前行到上行(两行内容间留且仅留 1 个空格) |
2.4.1. 删除重复行(调用外部工具 uniq 对 region 进行操作)
在 shell 中用 uniq 轻松完成。如何在 emacs 中完成呢?
首先选择整个 buffer,再执行下面命令:
C-u M-| uniq file.txt RET
参考:Emacs Manual, 31.3 Running Shell Commands from Emacs
2.4.1.1. delete-duplicate-lines
Emacs 24.4 中引入了函数 delete-duplicate-lines
,可以删除选择区域中的重复行。
2.4.2. 删除空行或匹配某正则表达式的行(flush-lines)
M-x flush-lines RET ^$ RET
参考:http://www.masteringemacs.org/articles/2011/03/16/removing-blank-lines-buffer/
2.4.3. 只留下匹配某正则表达式的行(keep-lines)
参考: C-h f keep-lines
2.5. 搜索和替换
2.5.1. 增量搜索
Emacs 增量搜索相关快捷键如表 9 所示。
hotkey | function | description |
---|---|---|
C-s | isearch-forward | 向前增量字符串搜索 |
C-r | iserach-backward | 向后增量字符串搜索 |
M-s w | isearch-forward-word | 向前增量单词搜索 |
Esc C-s | isearch-forward-regexp | 向前增量正则搜索 |
Esc C-r | isearch-backward-regexp | 向后增量正则搜索 |
说明:
- 增量搜索中“增量”的意思是边输入边查找。
- 要移动到下一个/上一个匹配处,多次按 C-s 或 C-r 即可。
- C-s C-w,会把当前光标下的单词自动输入到想要查找字符中。如果光标下的字符为 abc_def_123,按一次 C-w 只会输入 abc,可以连续按 C-w 把后面的部分全部补全!
- C-s M-c,临时改变本次搜索是否大小写敏感。
2.5.2. 替换
Emacs 替换字符串相关快捷键如表 10 所示。
hotkey | function | description |
---|---|---|
M-% | query-replace | 询问字符串替换 |
(none) | replace-string | 直接字符串替换 |
C-M-% | query-replace-regexp | 询问正则替换(可能有快捷键冲突) |
(none) | replace-regexp | 直接正则替换 |
2.5.3. 用 grep 搜索
M-x grep
M-x lgrep(仅在本层目录中搜索,不去子目录搜索)
M-x grep-find
M-x find-grep(和 grep-find 一样)
M-x rgrep
M-x zrgrep
M-x kill-grep
比如:
M-x grep grep -nH -e foo *.el | grep bar | grep toto
参考:
http://www.gnu.org/software/emacs/manual/html_node/emacs/Grep-Searching.html
2.5.3.1. 设置 rgrep 大小写不敏感
我们知道,用 rgrep 查找关键字时,如果关键字都为小写,则大小写不敏感,否则大小写敏感。
如何让 rgrep 大不写不敏感?加 C-u 前缀,这样执行命令前有机会编辑它,增加-i 选项即可。
C-u M-x rgrep
2.5.3.2. 跳转到下一个匹配处
C-x `
, 它会执行 next-error
.
2.5.4. 显示匹配正则表达式的所有行(occur)
list-matching-lines 是 occur
的别名,可列出当前 buffer 中所有匹配指定正则表达式的行。
如何快速查找当前 buffer 中光标下的单词?
在 isearch 状态中(即输入 C-s 且输入要查找的关键后)执行: M-s o
,即可运行 occur 查找相应单词,非常方便!
2.6. 正则表达式
emacs 正则表达式中的元字符如下:
. any character (but newline) * previous character or group, repeated 0 or more time + previous character or group, repeated 1 or more time ? previous character or group, repeated 0 or 1 time ^ start of line $ end of line [...] any character between brackets [^..] any character not in the brackets [a-z] any character between a and z \ prevents interpretation of following special char \| or \w word constituent \b word boundary \sc character with c syntax (e.g. \s- for whitespace char) \( \) start\end of group \< \> start\end of word \_< \_> start\end of symbol \` \' start\end of buffer\string \1 string matched by the first group \n string matched by the nth group \{3\} previous character or group, repeated 3 times \{3,\} previous character or group, repeated 3 or more times \{3,6\} previous character or group, repeated 3 to 6 times \= match succeeds if it is located at point
实例 1: 查找 6 个连续数字
emacs 中的正则表达式,不支持 \d
表示数字,要查询数字请用 [0-9]
。
Esc C-s [0-9]\{6\}
实例 2: 查找 A 和 B 之间有一个或多个空格
emacs 中,空格对应的正则为 \s-
,注意 \s
后还有个连字符。
Esc C-s A\s-+B
2.7. 转换大小写
Emacs 中转换大小写相关快捷键如表 11 所示。
hotkey | function | description |
---|---|---|
M-u | upcase-word | 光标下单词转大写 |
M-l | downcase-word | 光标下单词转小写 |
M-c | capitalize-word | 光标下单词第一个字符转大写 |
C-x C-u | upcase-region | region 中单词转大写 |
C-x C-l | downcase-region | region 中单词转小写 |
参考:GNU Emacs Manual, 22.6 Case Conversion Commands
2.8. 限制行宽(fill)
The maximum line width for filling is specified by the buffer-local variable fill-column. The default value is 70. The easiest way to set fill-column in the current buffer is to use the command C-x f (set-fill-column).
默认 fill-column 太窄,要设为 80,可把下面这行加入~/.emacs.d/init.el 中:
(setq-default fill-column 80)
要对一个 region 限制行宽,可以执行下面命令:
M-x fill-region
要自动限制行宽,可以打开 auto-fill-mode。
M-x auto-fill-mode
参考:http://www.gnu.org/software/emacs/manual/html_node/emacs/Filling.html
2.9. undo 和 redo
Emacs 中 undo 和 redo 相关快捷键如表 12 所示。
hotkey | function | description |
---|---|---|
C-/ | undo | 撤消 |
C-_ | undo | 撤消 |
C-x u | undo | 撤消 |
(none) | revert-buffer | 撤消所有未保存的修改 |
emacs 中没有 redo,要想实现 redo,可以在 undo 前执行下 C-g
。
2.10. 交换前后文本
Emacs 中交换前后文本相关快捷键如表 13 所示。
hotkey | function | description |
---|---|---|
C-t | transpose-chars | Transpose two characters |
M-t | transpose-words | Transpose two words |
C-x C-t | transpose-lines | Transpose two lines |
2.11. 多窗口操作
Emacs 中多窗口操作相关快捷键如表 14 所示。
hotkey | function | description |
---|---|---|
C-x 2 | split-window-vertically | 垂直拆分窗口 |
C-x 3 | split-window-horizontally | 水平拆分窗口 |
C-x 0 | delete-window | 关闭当前窗口 |
C-x 1 | delete-other-windows | 关闭其它窗口 |
C-x o | other-window | 切换到下一个窗口 |
C-M-v | scroll-other-window | 滚动下一个窗口 |
C-x 4 0 | kill-buffer-and-window | 关闭当前窗口和缓冲 |
C-x 4 b | switch-to-buffer-other-window | 在另一个窗口打开缓冲 |
C-x 4 C-o | display-buffer | 在另一个窗口打开缓冲,但不选中 |
C-x 4 f | find-file-other-window | 在另一个窗口打开文件 |
C-x 4 d | dired-other-window | 在另一个窗口打开文件夹 |
C-x 4 m | mail-other-window | 在另一个窗口写邮件 |
C-x 4 r | find-file-read-only-other-window | 在另一个窗口以只读方式打开文件 |
C-x ^ | enlarge-window | 增高当前窗口 |
C-x { | shrink-window-horizontally | 将当前窗口变窄 |
C-x } | enlarge-window-horizontally | 将当前窗口变宽 |
C-x - | shrink-window-if-larger-than-buffer | 如果窗口比缓冲大就缩小 |
C-x + | balance-windows | 所有窗口一样高 |
2.12. 键盘宏
Emacs 中键盘宏相关快捷键如表 15 所示。
hotkey | function | description |
---|---|---|
F3 | kmacro-start-macro-or-insert-counter | 开始记录,如果正在记录则插入宏计数器值。 |
F4 | kmacro-end-or-call-macro | 如果正在记录则停止,否则播放最后一个宏。 |
注:这种方法记录的只是一个临时的,没有名字的宏,仅当前 session 有效。
2.12.1. 命名键盘宏
给键盘宏命名: C-x C-k n
,其对应的命令是 kmacro-name-last-macro
宏有名字后,就可以用 M-x macro-name
执行宏了。
把已命名的键盘宏写入到文件:
先打开文件(如~/.emacs.d/init.el,这样每次打开 emacs,这个键盘宏都有效), M-x insert-kbd-macro
,输入宏名即可。会在打开的文件中产生一个 fset。
将键盘宏 macro-name 绑定到快捷键(如 F5):
(global-set-key (kbd "<f5>") 'macro-name)
2.12.2. 键盘宏的计数器
每个键盘宏都关联着一个计数器。键盘宏每执行一次计数器就会增加 1。
当你正在定义一个宏时,再次按下 F3 就能插入计数器的值。
实例:插入下列连接的数字到当前 buffer
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
第一步:定义下面键盘宏。
F3 F3 SPC F4
说明:第一个 F3 表示开始定义键盘宏,第二个 F3 表示插入宏计数器。
第二步:执行上面键盘宏 19 遍。
Esc 19 F4
2.13. registers
Emacs 中使用 registers 的相关快捷键如表 16 所示。
object | hotkey(store) | hotkey(retrieve) | notes |
---|---|---|---|
buffer/position | C-x r <SPC> R | C-x r j R | save buffer/position in register R, and jump back to it |
rectangle | C-x r r R | C-x r i R | save rectangle into register, and paste it |
window | C-x r w R | C-x r j R | save window configuration in register R, and jump back to it |
frame | C-x r f R | C-x r j R | save frame configuration in registerR, and jump back to it |
注:表中的字母 R 为 register 名字,可以修改为其它任意单个字母(大小写敏感)或数字。
查看 register 内容(以 register R 为例):
M-x view-register RET R
注:好像无法一次查看所有 registers 的内容。
2.14. bookmarks
Emacs 中 bookmarks 相关快捷键如表 17 所示。
hotkey | function | description |
---|---|---|
C-x r m | bookmart-set | 对当前文件当前位置设置 bookmark |
C-x r b NAME | bookmark-jump | 跳转到名为 NAME 的 bookmark 处 |
C-x r l | list-bookmarks | 列出所有的 bookmark |
(none) | bookmark-delete | 删除某个 bookmark |
(none) | bookmark-save | 保存 bookmark 到~/.emacs.bmk(默认位置),退出 emacs 时会自动保存 |
(none) | bookmark-write | 保存 bookmark 到文件(可任意指定文件名) |
(none) | bookmark-load | 从文件中加载 bookmark |
Emacs 中 bookmarks 和 registers 差不多,也可以保存光标的位置信息,但 registers 不是持久的,而 bookmarks 是持久的,关闭 emacs session 再启动 Emacs 时,bookmarks 仍然存在。
2.15. rectangles
首先选择一个矩形:用 C-@
设一个 mark,移动光标到另一点(注意,这不会只高亮一个矩阵块)。
然后用表 18 所示命令(都以 C-x r
开头)来进行矩形操作。
hotkey | function | description |
---|---|---|
C-x r k | kill-rectangle | 剪切一个矩形块 |
C-x r d | delete-rectangle | 删除一个矩形块 |
C-x r y | yank-rectangle | 粘贴一个矩形块 |
C-x r o | open-rectangle | 插入一个矩形块 |
C-x r c | clear-rectangle | 清除一个矩形块(使其变成空白) |
C-x r t | string-rectangle | 在选定区域的所有列前插入一个相同的字符串(会提示你输入) |
C-x <SPC> | rectangle-mark-mode | 无需提前选择矩形。Emacs 24.4 中引入 |
参考:http://www.gnu.org/software/emacs/manual/html_node/emacs/Rectangles.html#Rectangles
2.16. 版本控制
Emacs 中版本控制相关快捷键如表 19 所示。
hotkey | function | description |
---|---|---|
C-x v d | vc-directory | 列出目录下修改过的文件 |
C-x v l | vc-print-log | 显示改动历史记录 |
C-x v h | vc-insert-headers | 插入版本控制信息 |
C-x v v | vc-next-action | 进入提交改动状态 |
C-x v = | vc-diff | 显示改动 |
C-x v i | vc-register | 加入文件到版本控制中 |
C-x v r | vc-retrieve-snapshot | 取某一版本文件 |
C-x v u | vc-revert-buffer | 取消对当前文件的更改 |
C-x v ~ | vc-revision-other-window | 在另外一个窗口中打开文件的指定版本(非常实用) |
小技巧:当用 C-x v =
在“*vc-diff*”窗口中显示所做的改动后,可以用 C-c C-a
, 或 M-x diff-apply-hunk
取消/应用当前光标处的部分改动。
3. Emacs 高级用法
3.1. 画 ASCII diagrams
Artist mode, toggled by M-x artist-mode, lets you draw lines, squares, rectangles and poly-lines, ellipses, and circles with your mouse and/or keyboard. It is extremely useful when inserting text diagrams or figures in your source comments.
用 artist-mode 在 emacs 中可轻松画出下面图例:
+---------+ | | +--------------+ | NFS |--+ | | | | | +-->| CacheFS | +---------+ | +----------+ | | /dev/hda5 | | | | | +--------------+ +---------+ +-->| | | | | | |--+ | AFS |----->| FS-Cache | | | | |--+ +---------+ +-->| | | | | | | +--------------+ +---------+ | +----------+ | | | | | | +-->| CacheFiles | | ISOFS |--+ | /var/cache | | | +--------------+ +---------+
Reference:
http://www.cinsk.org/emacs/emacs-artist.html
http://unix.stackexchange.com/questions/126630/creating-diagrams-in-ascii
3.2. 编码设置
3.2.1. mode line 中直观显示文件编码
在 emacs 的 mode line 中能直观地显示文件的编码,如图 1 所示。
Figure 1: Coding is shown in Emacs mode line
图中 mode line 左侧有编码标记“UU-”,第一、二个编码标记分别指示 coding systems for keyboard input and terminal output(用 X 方式启动 emacs 没有这两个编码标记),第三个编码标记表示打开文件时使用的编码。
常用的编码标记有:
U 表示 utf-8
=表示二进制文件
c 表示 gbk 编码(或 gb2312 等)
1 表示 latin-1 编码
完整的编码标记列表及其含义可以通过下面命令得到。
M-x list-coding-systems
3.2.2. 对某后缀文件使用指定编码
Sometimes a file name indicates which coding system to use for the file. The variable file-coding-system-alist specifies this correspondence. There is a special function modify-coding-system-alist for adding elements to this list.
如设置打开.tt 文件时,使用 iso-8859-15 编码:
(modify-coding-system-alist 'file "\\.tt\\'" 'iso-8859-15)
3.2.3. 以指定编码重新打开当前文件
C-x <RET> r coding <RET>
Revisit the current file using the coding system coding(revert-buffer-with-coding-system).
3.2.4. 自动识别编码(多语言环境下很实用)
Mozilla Universal Charset Detector 有 emacs 对应的移植版本。
参考:http://www.emacswiki.org/emacs/Unicad
uchardet 的原理:http://www-archive.mozilla.org/projects/intl/UniversalCharsetDetection.html
3.2.5. 实现 dos2unix
C-x <RET> f unix <RET>
为方便可以在 init.el 中定义下面函数:
(defun dos2unix () "Not exactly but it's easier to remember" (interactive) (set-buffer-file-coding-system 'unix 't) )
3.3. 字体设置
By default, Emacs displays text on graphical displays using a 10-point monospace font. There are several different ways to specify a different font:
(1) Click on 'Set Default Font' in the 'Options' menu. This makes the selected font the default on all existing graphical frames. To save this for future sessions, click on 'Save Options' in the 'Options' menu.
(2) Add a line to your init file, modifying the variable default-frame-alist to specify the font parameter, like this:
(add-to-list 'default-frame-alist '(font . "DejaVu Sans Mono-10"))
This makes the font the default on all graphical frames created after restarting Emacs with that init file.
(3) Add an 'emacs.font' X resource setting to your X resource file, like this:
emacs.font: DejaVu Sans Mono-12
You must restart X, or use the xrdb command, for the X resources file to take effect.
(4) If you are running Emacs on the GNOME desktop, you can tell Emacs to use the default system font by setting the variablefont-use-system-font to t(the default isnil). For this to work, Emacs must have been compiled with Gconf support.
(5) Use the command line option -fn
(or --font
).
上面介绍了 5 种方法,前两种比较简单。
参考:http://www.gnu.org/software/emacs/manual/html_node/emacs/Fonts.html#Fonts
3.3.1. 怎么描述字体的名字(“font name”)
在 X 系统中,有 4 种方法来描述一个字体名字。
方法1:
The first is to use a Fontconfig pattern. Fontconfig patterns have the following form:
fontname[-fontsize][:name1=values1][:name2=values2]...
In addition, some property values are valid with only one kind of property name, in which case the 'name=' part may be omitted.
实例:
Monospace
Monospace-12
Monospace-12:bold
DejaVu Sans Mono:bold:italic
Monospace-12:weight=bold:slant=italic
方法2:
The second way to specify a font is to use a GTK font pattern. These have the syntax:
fontname [properties] [fontsize]
方法3:
The third way to specify a font is to use an XLFD (X Logical Font Description). This is the traditional method for specifying fonts under X.
The syntax for an XLFD is as follows:
-maker-family-weight-slant-widthtype-style-pixels-height-horiz-vert-spacing-width-registry-encoding
Each XLFD consists of fourteen words or numbers, separated by dashes, like this:
-misc-fixed-medium-r-semicondensed--13---*-c-60-iso8859-1
XLFD 一共 14 个字段,它们的含义参见:http://www.gnu.org/software/emacs/manual/html_node/emacs/Fonts.html#Fonts
方法4:
The fourth and final method of specifying a font is to use a "font nickname". Certain fonts have shorter nicknames, which you can use instead of a normal font specification. For instance, ‘6x13’ is equivalent to -misc-fixed-medium-r-semicondensed--13---*-c-60-iso8859-1
3.3.2. fontsets(字体集合)
要修改 fontsets,可以用 set-fontset-font
参考:
http://www.gnu.org/software/emacs/manual/html_node/emacs/Modifying-Fontsets.html#Modifying-Fontsets
http://www.emacswiki.org/emacs/FontSets
3.3.3. 查看光标下字体的设置(describe-char)
要查看光标下字符的字体设置等信息,可以使用快捷键 C-u C-x =
,或者直接执行 M-x describe-char
。
执行后,得到的信息和下面类似:
position: 23281 of 54117 (43%), column: 37 character: a (displayed as a) (codepoint 97, #o141, #x61) preferred charset: ascii (ASCII (ISO646 IRV)) code point in charset: 0x61 script: latin syntax: w which means: word category: .:Base, L:Left-to-right (strong), a:ASCII, l:Latin, r:Roman to input: type "C-x 8 RET HEX-CODEPOINT" or "C-x 8 RET NAME" buffer code: #x61 file code: #x61 (encoded by coding system utf-8-unix) display: by this font (glyph code) uniscribe:-outline-Source Code Pro-bold-normal-normal-mono-21-*-*-*-c-*-iso8859-1 (#x1C) Character code properties: customize what to show name: LATIN SMALL LETTER A general-category: Ll (Letter, Lowercase) decomposition: (97) ('a') There are text properties here: face org-level-3 fontified t [back]
3.4. 拼写检查
M-x ispell-region 对选定区域进行检查
M-x ispell-buffer 对整个当前 buffer 进行检查
M-x ispell-message 写邮件时对邮件进行拼写检查,但不包括引用的内容
M-x flyspell-mode
Enable Flyspell mode, which highlights all misspelled words.
M-$
Check and correct spelling of the word at point (ispell-word).
M-TAB
Complete the word before point based on the spelling dictionary(ispell-complete-word).
M-x ispell-minor-mode
仅在输入文本时,提示单词是否正确。
参考:
GNU Emacs Manual Version 24.1, 13.4 Checking and Correcting Spelling
3.5. 日程管理
执行 M-x calendar
可启动日历。
在日历中移动的相关快捷键如表 20 所示。
hotkey | function | description |
---|---|---|
C-f | calendar-forward-day | 前进一天 |
C-b | calendar-backward-day | 后退一天 |
C-n | calendar-forward-week | 前进一周 |
C-p | calendar-backward-week | 后退一周 |
M-} | calendar-forward-month | 前进一月 |
M-{ | calendar-backward-month | 后退一月 |
C-x ] | calendar-forward-year | 前进一年 |
C-x [ | calendar-backward-year | 后退一年 |
查看农历的相关快捷键如表 21 所示。
hotkey | function | description |
---|---|---|
p c | calendar-iso-print-date | 以 ISO 形式查看(可知第几周) |
p C | calendar-chinese-print-date | 以农历形式查看 |
p d | calendar-print-day-of-year | 查看某天是一年中第多少天 |
C-p | calendar-backward-week | 后退一周 |
其它命令参考表 22 。
hotkey | function | description |
---|---|---|
q | calendar-exit | 退出日历 |
. | calendar-goto-today | 回到当天 |
d | diary-view-entries | 显示某天的日历 |
s | diary-show-all-entries | 显示日历文件 |
m | diary-mark-entries | 标记设置有日历的那些天 |
u | calendar-unmark | 取消标记 |
H m | cal-html-cursor-month | 以 html 形式导出某月的日历 |
H y | cal-html-cursor-year | 以 html 形式导出某年的日历 |
设置提醒:
M-x appt-active
3.6. 查看和设置环境变量
- process-environment
- 该变量保存着进程的所有环境变量。
- initial-environment
- 该变量保存着从父进程继承过来的环境变量。
注:
M-x getenv,可查看 process-environment 中保存的环境变量
M-x setenv,设置环境变量,会保存在 process-environment 中。
3.7. emacs 中使用 terminal
M-x ansi-term
M-x term
M-x shell
M-x eshell
注:
- 请使用 M-x term 或 M-x ansi-term,它们功能更强大(如果使用的是 M-x shell,可能连 man ls 等命令都无法使用!)
- 进入到 ansi-term 后,想直接执行命令时,按 M-x 无效了,应该按 C-x M-x
3.8. emacs 中内置游戏
- gomoku
- 五子棋
- tetris
- 俄罗斯方块
- 5X5
- 游戏的目的是用#号填满整个方框。按下空格后,以光标为中心的十字会在空格和#号间变换
4. Emacs 小技巧
4.1. 对文件内容排序
首先选择要操作的内容,再用表 23 所示命令对其进行排序。
hotkey | function | description |
---|---|---|
(none) | sort-lines | 按字母序排序,如 12 会排在 9 前面 |
(none) | sort-fields | 加 numeric argument 即可指定对第几个 field 进行排序 |
(none) | sort-numeric-fields | 按数字序排序,如 9 会排在 12 前面 |
(none) | sort-columns | 选择哪列就对哪那排序 |
(none) | reverse-region | 反向排序 |
4.2. 插入特殊字符(Unicode)
表 24 是在 Emacs 中插入特殊字符的例子。
hotkey | produces | meaning |
---|---|---|
C-x 8 Y | ¥ | 日元符号,人民币符号 |
C-x 8 L | £ | 英镑符号 |
C-x 8 o | ° | Degrees |
C-x 8 R | ® | Registered |
C-x 8 C | © | Copyright |
直接插入 Unicode 对应字符:
输入 C-x 8
后紧接着按回车键(对应函数 insert-char
)后可以直接输入 Unicode 对应字符。
4.3. 空格和 tab 键互换
The commands tabify
and untabify
do just that.
参考:http://www.gnu.org/software/emacs/manual/html_node/emacs/Just-Spaces.html
4.4. emacs 命令行参数
常用的 emacs 命令行参数:
- -nw
- 不启动 GUI,以终端形式启动。
- -q
- 不加载启动文件。
- -Q
- Similar to
-q --no-site-file --no-splash
. Also, avoid processing X resources. - -l file
- 指定启动时要加载的文件。
- -u user
- Load user's init file.
- --debug-init
- This is useful for debugging problems in the init file.
4.4.1. emacs batch 模式(--batch)
指定 --batch
命令行选项,emacs 将进入 batch 模式(noninteractive 模式)。这时,emacs 不会加载“~/.emacs”, “~/.emacs.el”, “~/.emacs.d/init.el”文件(即相当于指定了 --no-init-file
)。
$ emacs --batch --eval '(message "Hello Emacs")' Hello Emacs
4.4.1.1. Batch 模式实例:批量格式化 C 代码
第一步,新建文件 format-code.el
(defun format-me () (c-set-style "linux") ; preferred c style (indent-region (point-min) (point-max) nil) ; format it (untabify (point-min) (point-max)) ; untabify (save-buffer))
第二步,在 shell 中执行下面命令
for i in `find -type f -regex ".*/.*\.\(c\|cpp\|cc\|h\|hh\)"`; do emacs --batch $i -l ~/format-code.el -f format-me; done
参考:http://redbrain.co.uk/2014/06/27/emacs-reformatting-a-huge-code-base/
4.4.2. 以脚本方式执行 elisp 文件(--script)
指定 --script
选项,可以让 emacs 以脚本方式执行 elisp 文件。如:
$ echo '(message "The current directory is %s" default-directory)' > 1.elisp $ emacs --script 1.elisp The current directory is ~/test/
4.4.3. 启动和关闭 emacs 服务端
下面方法可以启动 emacs 服务端。
方法 1:使用 --daemon
参数启动服务端。
emacs --daemon
方法 2:第一次启动 emacsclient 时自动启动服务端,这是利用 emacsclient 的 -a
参数。
emacsclient 的-a 参数用于指定连接不上服务器时使用的别的编辑器(alternate editor),当把-a 指定为空串时,它会自动启动服务端。
emacsclient -a "" file #指定了-a "",当emacs服务端没启动时会自动启动服务端
下面方法可以关闭 emacs 服务端。
方法 1:使用 pgrep emacs
,找到 emacs --daemon 进程,再 kill 它。
用上面这种方式关闭,如果 buffer 有未保存的内容,则不会保存到原文件,而是会生成备份文件#filename#。
方法 2:使用 emacsclient -e "(kill-emacs)"
这种方式的行为和前面一样,不会自动保存 buffer 到原文件,会生成备份文件。
方法 3:使用 emacsclient -e "(save-buffers-kill-emacs)"
退出前会在 emacsclient 的 minibuffer 区域提示你要不要保存 buffer,但如果所有的 emacsclient 都关闭了,则命令一直暂停在控制台没有自动退出。
Tips: 为方便地启动和关闭 emacs,可以在.bashrc 中定义相关的辅助函数。如:
function emacs-start { LC_CTYPE=zh_CN.UTF-8 /usr/bin/emacs --daemon } function emacs-stop { emacsclient --eval "(progn (setq kill-emacs-hook 'nil) (kill-emacs))" }
4.4.4. emacsclinet 的-c 和-t 选项
emacsclinet 的-c 和-t 选项
-c,会启动 X 窗口。
-t(或者--tty 或者-nw),Open a new Emacs frame on the current terminal。
注:如果既不加-c 又不加-t,会在之前已启动的 emacsclient 中编辑文件,这次启动的 emacsclient 仅显示 Waiting for Emacs...
4.5. 让 init.el 的改动立刻生效
如果修改了 emacs 启动文件 init.el,如何不重启 emacs 的情况下使更改生效?有下面几种方法:
C-x C-e
执行光标前面的一条语句(如果改动比较少的话很方便)。- 选择改动的 region, M-x eval-region
- M-x load-file ~/.emacs.d/init.el
- M-x eval-buffer
4.6. Linux 英文系统中输入中文
首先要安装 ibus 的 emacs 插件(Ubuntu 中可以这样安装 sudo apt-get install ibus-el)。
在启动 emacs 前,先设置 LC_CTYPE=zh_CN.UTF-8 即可,emacs 已经很智能了,它会根据 LC_CTYPE 来取消“Ctrl + Space”的内置绑定。
如果还有问题,可以在/etc/default/locale 中设置 LC_CTYPE=zh_CN.UTF-8
4.7. 遇到错误时进入调试器
有时 Emacs 遇到错误只会打印简单的错误信息,要想此时进入调试器,可以通过 M-x toggle-debug-on-error
设置。
4.8. 把 Caps Lock 改为 Ctrl
在 Emacs 中使用 Ctrl 的频率非常高,把 Caps Lock 键改为 Ctrl 键可以提高使用 Emacs 的舒适度。
5. Emacs 常用 mode
5.1. emacs 如何自动选择 Major Mode
emacs 在打开文件时可以自动地设置 Major Mode,它的规则是什么呢?
有几种方式(描述顺序不代表其优先级,详细优先级可以查看 emacs manual):
1.根据文件名自动设置
如打开.c 结尾的文件,就进入 C mode。文件名和 major mode 的对应关系保存在变量 auto-mode-alist 中。
2.根据#!后的解释器设置
当文件的内容以“#!”开头时,这时 Emacs 使用文件中指定的解释器的名字来选择 major mode,解释器和 major mode 的对应关系保存在变量 interpreter-mode-alist 中。
2.1 根据文件开头内容判断
把判断规则写入到 magic-mode-alist 中,如:
(add-to-list 'magic-mode-alist '("<!DOCTYPE html .+DTD XHTML .+>" . nxml-mode) )
2.2 根据定制函数返回值判断
magic-mode-alist 还有一种用法,如:
(add-to-list 'magic-mode-alist '(MATCH-FUNCTION . nxml-mode) )
只要 MATCH-FUNCTION 返回 non-nil 就会设置为 nxml-mode。
显然,这种方法的可定制性更强。
3.根据 File-local variables 设置
什么是 File-local variables?就是把变量写在文件中,Emacs 打开该文件时自动加载其中的变量。当然 File-local variables 要符合一定的规则,以使 emacs 正确识别其中的变量。
File-local variables 有两种形式:
3.1 使用-*-标记
应该成对出现。只能出现在文件第一行(如果第一行以#!开头,可以出现在第二行)。如:
/* -*- mode:lisp; tab-width: 4; indent-tabs-mode: t; -*- */
3.2 使用 Local Variables:和 End:标记
Local Variables:和 End:必须成对出现,可以在文件的开头或结尾位置。如:
;; Local Variables: ;; ;; mode:lisp ;; ;; tab-width:4 ;; ;; End: ;;
前缀;;和后缀;;的要求比较宽松,用/*和*/也行,都用##也行。
注:File-local variables 这种办法很强大,因为它仅仅可以定义 mode,还可以设置变量或运行函数等其它事件!但是不太安全!
参考:
Emacs Manual For Emacs 24.1, 20.3 Choosing File Modes.
Emacs Lisp Reference Manual For Emacs 24.1, 23.2.2 How Emacs Chooses a Major Mode.
5.1.1. 定制 emacs 的 mode 自动识别规则
正如前面所说,auto-mode-alist 决定着文件名和 Major mode 的对应关系。所以修改它即可定制 emacs 的 mode 自动识别规则。
把下面内容加入在 init.el 文件中,就可以使以点开始的文件名自动为 fundamental-mode,.C 结尾的文件自动打开为 c++-mode。
(setq auto-mode-alist (append ;; File name (within directory) starts with a dot. '(("/\\.[^/]*\\'" . fundamental-mode) ;; File name ends in '.C'. ("\\.C\\'" . c++-mode)) auto-mode-alist))
5.2. dired
Dired makes an Emacs buffer containing a listing of a directory, and optionally some of its subdirectories as well. You can use the normal Emacs commands to move around in this buffer, and special Dired commands to operate on the listed files.
参考:
http://www.gnu.org/software/emacs/manual/html_node/emacs/Dired.html
http://www.gnu.org/software/emacs/manual/html_node/dired-x/index.html
http://www.emacswiki.org/DiredExtra
5.2.1. 标记文件
- * *
- 标记所有可执行文件。
- * @
- 标记所有符号链接。
- * /
- 标记所有目录(不包括 . 和 .. )。
- * s
- 标记所有文件(不包括 . 和 .. )。
- * .
- 标记具有给定扩展名的文件。
- % m REGEXP <RET> 或 * % REGEXP <RET>
- 标记所有匹配到给定的正则表达式的文件。
- % g REGEXP <RET>
- 标记所有文件内容(而不是文件名)匹配到给定的正则表达式的文件。
5.2.2. 常用操作
- +
- 创建目录
- y
- 查看当前文件类型
- ^
- 访问父目录
- j
- 快速跳到指定文件
- C
- 拷贝文件。把 dired-recursive-copies 设为非 nil 的值可以递归拷贝目录,通常我们设定为 top ,这表示对于顶层目录 dired 会先进行询问是否要递归拷贝,而其中的子目录则不再询问。如果嫌询问太麻烦,可以直接设置为 always 。
- D
- 删除文件。类似的有一个 dired-recursive-deletes 变量可以控制递归删 除。
- R
- 重命名文件,也就是移动文件。
- H
- 创建硬链接。
- S
- 创建软链接。
- M
- 修改权限位,即 shell 里面的 chmod 命令。
- G
- 修改文件所属的组。
- O
- 修改文件的所有者。
- T
- 修改文件的修改时间,类似于 shell 命令 touch 。
- P
- 打印文件。
- Z
- 压缩或解压文件。
- L
- 把 Elisp 文件加载进 Emacs 。
- B
- 对 Elisp 文件进行 Byte compile 。
- A
- 对文件内容进行正则表达式搜索,搜索会在第一个匹配的地方停下,然后 可以使用 M-, 搜索下一个匹配。
- Q
- 对文件内容进行交互式的正则表达式替换。
参考:
http://www.cnblogs.com/leohxj/archive/2012/02/20/2360606.html
http://lifegoo.pluskid.org/wiki/EmacsAsFileManger.html
5.2.3. 使用更强大的 Dired Extra
(add-hook 'dired-load-hook (function (lambda () (load "dired-x"))))
Tips: Dired Extra 中可以方便打开当前文件所在的目录:
C-x C-j
5.2.4. dired 小技巧
5.2.4.1. 临时改变 ls 的选项
在 dired 中输入 C-u s,回车后,再输入新的 option 即可。
5.2.4.2. 快速重命名文件
使用快捷键 C-x C-q(dired-toggle-read-only),然后就可以修改 buffer 内容了,保存修改可以按 C-c C-c(wdired-finish-edit),取消修改可以按 C-c Esc(wdired-abort-changes)
注意:
C-c C-c 和 C-c Esc 快捷键只能连续按一次!因为它们仅在“可编辑状态”时才可用。而且按一次 C-c C-c 或 C-c Esc 就马上进入到了 read-only 状态。
5.3. 高亮关键字
5.3.1. hi-lock-mode
Emacs 自带 hi-lock-mode (hi-lock.el),里面提供了一下几个很有用的命令:
highlight-phrase (M-s h p)
highlight-regexp (M-s h r)
highlight-lines-matching-regexp (M-s h l)
使用时直接输入上面命令或快捷键即可,不用先打开 hi-lock-mode ,Emacs 会自动打开。
使用时 Emacs 会先问你要高亮什么内容,如果你不想手工输入的话,得事先拷贝好内容再在这里粘贴。
然后 Emacs 会问你使用那种风格(face)来显示高亮,除了 hi-lock.el 提供的 hi-yellow, hi-pink, hi-green 等颜色之外,你也可以使用 Emacs 里面其它的 face。
要去除高亮,用 M-x unhighlight-regexp (M-s h u),它会自动提供当前已有条目(刚才通过上 述三个命令输入的内容)供你选择。
参考:
http://www.cnblogs.com/bamanzi/archive/2012/12/03/emacs-find-modify-all-occurences.html
5.3.2. idle-highlight-mode
emacs 自动高亮光标处字符
可利用 idle-highlight-mode,但它不是 Emacs 自带的,需要自己下载。
5.4. 根据后缀名或主模式插入模板(auto-insert-mode)
如果新建一个.pl 文件,就自动在文件最前面输入“#!/usr/bin/env perl”等内容该多好啊。 auto-insert-mode 就是为这个功能而设计的。
(require 'autoinsert) (auto-insert-mode +1) ; enable auto-insert-mode (setq auto-insert-query nil) ; No prompt before insertion (eval-after-load 'autoinsert '(define-auto-insert '("\\.pl\\'" . "Perl skeleton") '(nil "#!/usr/bin/env perl" \n \n "use strict;" \n "use warnings;" \n \n _ \n)))
模板语法基于 Skeleton Mode,比如 _
表示光标位置等,详情可参考:Emacs Skeleton Language
5.5. diff mode
打开 patch 文件,会自动进入 diff 模式。下面 diff 模式中是常见功能对应的快捷键。
M-o diff-goto-source M-n diff-hunk-next M-p diff-hunk-prev M-N diff-file-next M-P diff-file-prev M-{ diff-file-prev M-} diff-file-next
5.6. ediff mode
Ediff provides a convenient way for simultaneous browsing through the differences between a pair (or a triple) of files or buffers (which are called 'variants' for our purposes).
参考:http://www.gnu.org/software/emacs/manual/html_node/ediff/index.html
ediff 比 KDiff3,Diffuse,Vimdiff Meld 强在哪?见图:http://jixiuf.github.io/emacs/ediff.html
hotkey | function | description |
---|---|---|
n 或 Space | ediff-next-difference | 下一个差异处 |
p 或 Del | ediff-previous-difference | 上一个差异处 |
j 或 [n]j | ediff-jump-to-difference | 有数字前缀[n]修饰,第 n 个差异处,n可为负数 |
v 或 C-v | ediff-scroll-vertically | 所有缓冲区同步向下滚动 |
V 或 M-v | ediff-scroll-vertically | 所有缓冲区同步向上滚动 |
< | ediff-scroll-horizontally | 所有缓冲区同步向左滚动 |
> | ediff-scroll-horizontally | 所有缓冲区同步向右滚动 |
| | ediff-toggle-split | 切换缓冲区布局方式为水平或竖直 |
a | ediff-copy-A-to-B | 把 Buffer-A 的内容复制到 Buffer-B |
b | ediff-copy-B-to-A | 把 Buffer-B 的内容复制到 Buffer-A |
ra 或 rb | ediff-restore-diff | 恢复 Buffer-A 或 Buffer-B 差异区域中的被修改的内容 |
A 或 B | ediff-toggle-read-only | 切换 Buffer-A 或 Buffer-B 的只读状态 |
C-l | ediff-recenter | 恢复先前的所有缓冲区比较的高亮差异区。 |
! | ediff-update-diffs | 重新比较并高亮差异区域 |
wa 或 wb | ediff-save-buffer | 保存 Buffer-A 或 Buffer-B 到磁盘 |
E | ediff-documentation | 打开 Ediff 帮助文档 |
z | ediff-suspend | 关闭 ediff control buffer,只是挂起,可在以后恢复 ediff 状态 |
q | ediff-quit | 关闭 ediff control buffer,并退出 ediff |
5.6.1. ediff-directories 比较两个目录
假设/home/newdir 下是最新的代码,/home/olddir 下是老代码,我们需要把老代码中的部分修改合入最新的代码。
首先启动 emacs,运行 M-x ediff-directories
命令,选择上述两个目录,第一个目录是“newdir”,我们认为他是“a”,第二个目录是“olddir”,我们叫他是“b”。
接着会进入“Ediff Session Group Panel”窗口,目录中的每个文件都是一个 session,在当前窗口可以选择对哪个 session 做什么操作。这里我们先使用“=h”来隐藏所有相同的文件,然后在相应的 session 上用“h”来隐藏你不想合并的文件,每一个待隐藏的 session 前都有一个“H”标记。运行“x”执行,所有的“H”标记的 session 都不见了。
把光标移动到每一个待合并的 session 上回车,进入比较画面,“?”可以显示命令帮助,“n”和“p”可以在差异之间跳转,如果当前差异需要从 b 合入 a,用“b”命令,完成后用“wa”保存在 a 窗口做的修改,用“q”退出当前 session。如果用“M”可以回到“Ediff Session Group Panel”窗口,但是当前打开的 session 前有“+”标识,这个时候即使你用“h”和“x”去隐藏也隐藏不了。如果是用“q”退出的 session,前面有用“-”做标识。完成后用“q”一路退出。
6. 编程相关
6.1. cedet
CEDET stands for “Collection of Emacs Development Environment Tools”.
CEDET 它包含很多子工具。
M-x cedet-version
会显示类似下面的结果:
CEDET Version: 2.0 Requested File Loaded Package Version Version Version ---------------------------------------------------------- cedet: 2.0 nil ok eieio: 1.4 nil ok semantic: 2.2 nil ok srecode: 1.2 nil Not Loaded ede: 1.2 nil Not Loaded speedbar: 1.0.4 nil 1.0 cogre: 1.2 nil Not Loaded cedet-contrib: 1.2 nil Not Loaded
6.1.1. semantic
Semantic is a suite of Emacs libraries and utilities for parsingsource code. At its core is a lexical analyzer and two parsergenerators (Bovinator and Wisent) written in Emacs Lisp.
Bovinator 是一个 LL generator,而 Wisent 是一个 LALR generator。
The Wisent parser is a port of bison to Emacs Lisp written by David Ponce.
参考:
http://www.gnu.org/software/emacs/manual/html_mono/semantic.html
http://www.randomsample.de/cedetdocs/semantic/
http://www.randomsample.de/cedetdocs/semantic-langdev/index.html
http://www.randomsample.de/cedetdocs/grammar-fw/index.html
How To Set Up Semantic Bovinator For A New Language: http://www.emacswiki.org/emacs/HowToSetUpSemanticBovinatorForANewLanguage
6.1.2. speedbar
Speedbar is a program for Emacs which can be used to summarize information related to the current buffer.
参考:http://www.gnu.org/software/emacs/manual/html_node/speedbar/index.html
speedbar 可以使用 etags,imenu,semantic 等工具做后台。
如果想显示在同一个 frame 中,可以用 sr-speedbar。
6.2. ecb (Emacs Code Browser)
ecb 不是 emacs 内置的,Ubuntu 中可以这样安装:sudo apt-get install ecb
参考:
http://www.xemacs.org/Documentation/packages/html/ecb.html
http://ecb.sourceforge.net/docs/index.html
6.3. jdee (Java Development Environment for Emacs)
JDEE stands for Java Development Environment for Emacs.
参考:
http://www.emacswiki.org/JavaDevelopmentEnvironment
http://blog.csdn.net/csfreebird/article/details/19033939
http://blog.csdn.net/csfreebird/article/details/7028174
安装步骤:
测试环境 Ubuntu 14.04 + Emacs 24.3
第一步,从http://sourceforge.net/projects/jdee/files/ 下载 jdee 最新版本文件,如 jdee-bin-2.4.1.tar.bz2
第二步,解压到~/.emacs.d
第三步,添加下面两行到~/.emacs.d/init.el 中
(add-to-list 'load-path "~/.emacs.d/jdee-2.4.1/lisp") (load "jde")
重启 Emacs,打开 java 文件,可发现菜单栏多了几个 java 相关的菜单。
6.4. emacs-eclim
什么是 Eclim?
Eclim provides the ability to access Eclipse code editing features (code completion, searching, code validation, and many more) via the command line or a local network connection, allowing those features to be integrated with your favorite editor. Eclim provides an integration with Vim, but third party clients have been created to add eclim support to other editors as well (emacs, sublime text 2, textmate).
说明:Eclim 能把 eclipse 的功能集成到 vim 中,通过第三方插件如 Emacs-eclim 也能把 eclispe 的功能集成到 emacs 中。
什么是 Emacs-eclim?
通过 Emacs-eclim 能使 Emacs 使用 eclim 的功能,而通过 eclim 可以使用 eclipse 的功能。
功能介绍可参考:http://www.skybert.net/emacs/java/
Emacs-eclim 非常的强大,代码自动补全,实时语法检查,重构等 eclispe 的功能都不在话下。
唯一的缺点是依赖太重了! Emacs-eclim 依赖于 eclim,而 eclim 依赖于 eclipse。
安装 eclim
http://eclim.org/install.html
安装配置 Emacs-eclim
https://github.com/senny/emacs-eclim
6.5. SLIME (Emacs mode for Common Lisp development)
SLIME stands for The Superior Lisp Interaction Mode for Emacs.
SLIME is a Emacs mode for Common Lisp development. Inspired by existing systems such Emacs Lisp and ILISP, we are working to create an environment for hacking Common Lisp in.
Reference:
SLIME homepage: https://common-lisp.net/project/slime/
SLIME User Manual: https://common-lisp.net/project/slime/doc/html/
6.5.1. 执行 Shortcuts
"Shortcuts" are a special set of REPL commands that are invoked by name. To invoke a shortcut you first press , (comma) at the REPL prompt and then enter the shortcut’s name when prompted.
在 repl 提示符中输入逗号后,可执行一些 shotcuts
shotcuts | aka | description |
---|---|---|
, cd | , !d | Change the current directory |
, pwd | Show the current directory | |
, quit | Quit the current Lisp | |
, sayoonara | Quit all Lisps and close all SLIME buffers | |
, compile-and-load | , cl | Compile (if necessary) and load a lisp file |
, change-package | , !p or , in-package | Change the current package |
, defparameter | , ! | Define a new global, special, variable |
, help | , ? | Display the help |
参考:https://common-lisp.net/project/slime/doc/html/Shortcuts.html#Shortcuts
6.5.2. SLIME 中常用快捷键
hotkey | function | description |
---|---|---|
C-RET | slime-repl-closing-return | 补全括号并执行 |
C-c M-o | slime-repl-clear-buffer | 清空 buffer |
C-c C-o | slime-repl-clear-output | 清空上次结果 |
C-c C-l | slime-load-file | 加载文件 |
C-c C-k | slime-compile-and-load-file | 编译加载当前文件 |
C-c C-] | slime-close-all-parens-in-sexp | 补全剩余的括号 |
C-c Tab | slime-complete-symbol | Complete the symbol at point |
参考:https://common-lisp.net/project/slime/doc/html/Key-Index.html#Key-Index
6.6. emacs 中调试 perl
参考:
Perl Debug (调试): http://jianlee.ylinux.org/Computer/Perl/perl-debug.html
Beginning Perl Programing with Emacs: http://cpansearch.perl.org/src/YEWENBIN/Emacs-PDE-0.2.16/lisp/doc/QuickStartEn.html
6.7. emacs 中使用 gdb
直接用 M-x gdb 启动 gdb(不要用 M-! gdb 的方式启动 gdb)。
M-x gdb-many-windows
可以打开很多窗口(默认 6 个)来辅助调试,这个命令只有在启动 gdb 后才能使用。
6.8. 注释源码
- M-;
- Insert or realign comment on current line; if the region is active, comment or uncomment the region instead (comment-dwim).
- C-u M-;
- Kill comment on current line (comment-kill).
- C-x ;
- Set comment column (comment-set-column).
参考:http://www.gnu.org/software/emacs/manual/html_node/emacs/Comment-Commands.html#Comment-Commands
6.8.1. 自动格式化注释(M-q)
选择注释后,按 M-q
可以重新格式化注释,它可以自动使选择的注释不超过变量 fill-column
指定的列数。
6.9. etags
etags
参考:
http://www.gnu.org/software/emacs/manual/html_node/emacs/Tags.html#Tags
生成 tag 文件
如:对当前文件夹的 perl 文件生成 tag
$ find . -name "*.pl" -o -name "*.pm" |etags -
常用操作
M-. tag RET
转到 tag 的定义处(如果不指定 tag,就默认为光标处的 tag)。
M-*
回到上次运行 M-.时的位置。
C-x 4 . tag RET
转到 tag 的定义处,但在新窗口中显示。
C-u M-.
查找下一个 tag 的位置。
C-u - M-.
回到上一个 tag 的位置。
C-M-. pattern RET
Find a tag whose name matches pattern (find-tag-regexp).
C-u C-M-.
Find the next tag whose name matches the last pattern used.
etags 缺点
etags 生成的 TAGS 文件中仅保存了函数的定义,所以无法利用 etags 找到一个函数的所有引用。
下面命令可以实现这个功能:
M-x rgrep
默认把光标处的单词作为查找目标。(搜索内容时,支持一些预定义的别名,比如 ch 表示所有的 c++代码文件,hh 表示所有的 c++头文件等等)
M-x lgrep
仅在本层目录进行搜索,不去子目录中搜索,l是指 local 的意思。
6.10. imenu
Imenu is a feature that lets users select a definition or section in the buffer, from a menu which lists all of them, to go directly to that location in the buffer.
参考:
http://www.gnu.org/software/emacs/manual/html_node/elisp/Imenu.html
http://emacswiki.org/emacs/ImenuMode
用 imenu 比用 etags 更好的地方——不用生成 TAGS 文件。
M-x imenu
提示输入一个名称(按 table 键会列出所有合法名称),emacs 将跳转到这个名称的定义处。
M-x imenu-add-to-menubar
运行命令后,会提示输入一个名称,确定后 emacs 会生成一个菜单,事先定义好的文件的结构会列在这个菜单下。
6.10.1. 对某个 mode 增加“Index”菜单
如何对某个 mode 增加“Index”菜单(菜单中会列出当前文件的所有函数等信息)呢?
以 c-mode 为例,可以这样做:
(add-hook 'c-mode-hook 'imenu-add-menubar-index)
6.10.2. 怎么对一个新语言进行定制呢?
方法一
imenu-generic-expression
imenu-case-fold-search
imenu-syntax-alist
方法二
imenu-prev-index-position-function
imenu-extract-index-name-function
方法三
imenu-create-index-function
6.11. flycheck-mode
Flycheck is a modern on-the-fly syntax checking extension, and a modern alternative to Flymake.
Flycheck-mode 不是 emacs 内置的,要手动安装。
6.12. cscope
Emacs 中 cscope 相关的常用快捷键如表 28 所示。
Shotcuts | Description |
---|---|
C-c s a | 设定初始化目录,一般指定为代码码根目录 |
C-c s I | 对目录中的相关文件建立列表并进行索引 |
C-c s s | Find symbol. |
C-c s d | Find global definition. |
C-c s g | Find global definition (alternate binding). |
C-c s G | Find global definition without prompting. |
C-c s c | Find functions calling a function. (看看指定函数被哪些函数所调用) |
C-c s C | Find called functions. (看看指定函数调用了哪些函数) |
C-c s t | Find text string. |
C-c s e | Find egrep pattern. |
C-c s f | Find a file. |
C-c s i | Find files #including a file. (看看指定的文件被哪些文件 include). |
C-c s b | Display cscope buffer. |
C-c s B | Auto display cscope buffer toggle. |
C-c s n | Next symbol. |
C-c s N | Next file. |
C-c s p | Previous symbol. |
C-c s P | Previous file. |
C-c s u | Pop mark. |
7. Elisp
Emacs Lisp is a dialect of the Lisp programming language used by the GNU Emacs and XEmacs text editors. It is used for implementing most of the editing functionality built into Emacs, the remainder being written in C (as is the Lisp interpreter itself). Emacs Lisp is also referred to as Elisp.
Elisp Cookbook: http://emacswiki.org/emacs/ElispCookbook
Emacs Lisp Reference Manual: http://www.gnu.org/software/emacs/manual/html_node/elisp/index.html
An Introduction to Programming in Emacs Lisp: https://www.gnu.org/software/emacs/manual/eintr.html
Practical Emacs Lisp: http://ergoemacs.org/emacs/elisp.html
7.1. 调试工具
7.1.1. trace-function, untrace-function
用 trace-function
可以方便地查看 elisp 函数执行时的参数和返回值(默认显示在*trace-buffer*中),这要调试函数时非常有用;要取消对某个函数或所有函数的“监视”,可以使用 untrace-function
或 untrace-all
。
M-x trace-function M-x trace-function-background M-x untrace-function M-x untrace-all
效果演示:
;; (defun fact (n) ;; (if (= n 0) 1 ;; (* n (fact (1- n))))) ;; fact ;; ;; (trace-function 'fact) ;; fact ;; ;; Now, evaluating this... ;; ;; (fact 4) ;; 24 ;; ;; ...will generate the following in *trace-buffer*: ;; ;; 1 -> fact: n=4 ;; | 2 -> fact: n=3 ;; | | 3 -> fact: n=2 ;; | | | 4 -> fact: n=1 ;; | | | | 5 -> fact: n=0 ;; | | | | 5 <- fact: 1 ;; | | | 4 <- fact: 1 ;; | | 3 <- fact: 2 ;; | 2 <- fact: 6 ;; 1 <- fact: 24
7.1.2. Edebug
把光标放到想要调试的 Elisp 函数的定义处,按 M-x edebug-defun RET
即可调试该函数。
单步执行:space
设置断点:b
取消断点:u
运行到断点处:g
退出调试:q
参考:https://www.gnu.org/software/emacs/manual/html_node/elisp/Using-Edebug.html
7.2. advice
The advice feature lets you add to the existing definition of a function, by advising the function. This is a cleaner method for a library to customize functions defined within Emacs—cleaner than redefining the whole function.
一句话总结:advice 可以改变现有函数的行为,而不必重新定义它。
7.2.1. advice 实例:让 align-regexp 仅使用空格
align-regexp 可以用来对齐代码,但它默认可能使用 tabs 字符,如果想仅用空格做对齐,可以用 advice 对其进行修改。把下面代码加入 init.el 中即可。
;; Align with spaces only (defadvice align-regexp (around align-regexp-with-spaces) "Never use tabs for alignment." (let ((indent-tabs-mode nil)) ad-do-it)) (ad-activate 'align-regexp)
7.3. load-file, load, require, autoload 区别
变量 features 中保存着当前已经加载的 feature(系统中可能存在能加载但没有加载的 feature)。
Function | Purpose | Tech Detail | Comment |
---|---|---|---|
load-file | Load a file | Load one specific file. | Use this if you have one very SPECIFIC file at one particular file path. |
load | Load a file | Load a file by searching thru var "load-path". Also, tries to load a compiled version (.elc) if exists. | Use this if the path for the file is not known in advance, and you are using a file name without full path, such as "undo" or "undo.el", and you want to load the compiled version if it exists (undo.elc). |
require | Load a package if it has not already been loaded | Checks the var "features", if symbol is not there, then call load to load it. | Best used in elisp source code, similar to other lang's "require" or "import". |
autoload | Load a file only when a function is called | Associate a function name with a file path. When the function is called, load the file, and execute the function. | If you are writing a major mode, it's good to have your package installation go by autoload (if possible). It saves startup time. |
7.4. 检查函数,变量,feature 等是否定义或可用
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;; Check if a function is defined (fboundp 'info) ; t (fboundp 'setq) ; t (fboundp 'xyz) ; nil ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;; Check if a variable is defined (boundp 'auto-mode-alist) ; t (boundp 'default-input-method) ; t (boundp 'nil) ; t (boundp 'xyz) ; nil ;; The fboundp actually check a symbol's function cell. ;; Similarly, the boundp checks a symbol's value cell. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;; Check if a "feature" (package) has been loaded (featurep 'expand-region)
Reference: http://ergoemacs.org/emacs/elisp_check_defined.html
7.5. 增加自定义菜单
Here's a example of how to add your own menu. Suppose you want a menu named "MyMenu" that comes after the "Tools" menu. Suppose your menu will have 2 menu items: "Next Line" and "Previous Line", each should call the emacs command next-line and previous-line. Here's the elisp code to do it:
;; Creating a new menu pane in the menu bar to the right of "Tools" menu (define-key-after global-map [menu-bar mymenu] (cons "MyMenu" (make-sparse-keymap "hoot hoot")) 'tools ) ;; Creating a menu item, under the menu by the id “[menu-bar mymenu]” (define-key global-map [menu-bar mymenu nl] '("Next Line" . next-line)) ;; creating another menu item (define-key global-map [menu-bar mymenu pl] '("Previous Line" . previous-line)) ;; code to remove the whole menu panel ;; (global-unset-key [menu-bar mymenu])
参考:
http://ergoemacs.org/emacs/elisp_menu.html
http://www.gnu.org/software/emacs/manual/html_node/elisp/Keymaps.html
7.6. set, setq, setq-default 区别
setq 和 set 有什么区别?下面两个设置等价:
(set 'some-variable t) (setq some-variable t) ; same as above
setq 和 setq-default 有什么区别?
Some variables in Emacs are “buffer-local”, meaning that each buffer is allowed to have a separate value for that variable that overrides the global default. tab-width
is a good example of a buffer-local variable.
If a variable is buffer-local, then setq
sets its local value in the current buffer and setq-default
sets the global default value.
If a variable is not buffer-local, then setq
and setq-default
do the same thing.
7.7. 在 minibuffer 中执行 elisp 代码(M-:)
对于简短的 elisp 代码可以直接在 minibuffer 中执行。
如生成 1 到 20 的数字序列:
M-: (dotimes (i 20) (insert (format "%2d\n" (1+ i))))
参考:http://stackoverflow.com/questions/1509688/emacs-macro-to-generate-a-sequence
7.8. 如何为新语言创建 mode
参考:
An Emacs language mode creation tutorial: http://emacswiki.org/emacs/ModeTutorial
How to Write a Emacs Major Mode for Syntax Coloring: http://ergoemacs.org/emacs/elisp_syntax_coloring.html
7.9. customization
Emacs 中,可以通过菜单中的[Options] -> [Customize Emacs]来方便定制 Emacs,可定制的项非常多,它们通过 groups 来组织。
大部分 Emacs package 都有自己的 main customization group,在 main customization group 可能有很多 subgroups。
参考:
http://www.gnu.org/software/emacs/manual/html_node/emacs/Easy-Customization.html
http://www.gnu.org/software/emacs/manual/html_node/elisp/Customization.html
7.9.1. 增加 user options
如何给自己新写的包增加 user options(又称 Customizable variables),以方便用户配置呢?使用 defgroup 和 defcustom 可完成任务。
第一步:先用宏 defgroup
定义一个 group,在定义时可以把这个 group 放入到合适的 Customization group 下。
执行 M-x customize-browse
可以查看 Emacs 中存在的所有 Customization Groups:
[-]-\ [Group] Emacs [+]-- [Group] Editing [+]-- [Group] Convenience [+]-- [Group] Files [+]-- [Group] Text [+]-- [Group] Data [+]-- [Group] External [+]-- [Group] Communication [+]-- [Group] Programming [+]-- [Group] Applications [+]-- [Group] Development [+]-- [Group] Environment [+]-- [Group] Faces [+]-- [Group] Help [+]-- [Group] Multimedia [+]-- [Group] Local
下面语句定义了一个新 group,其名为 tabbar,并且它位于 group convenience 下。
(defgroup tabbar nil "Display a tab bar in the header line." :group 'convenience)
第二步:定义好 group 后,用宏 defcustom
在这个 group 下定义 user options。
下面语句定义了一个 user option: tabbar-auto-scroll-flag,并且位于 group tabbar 下。
(defcustom tabbar-auto-scroll-flag t "*Non-nil means to automatically scroll the tab bar. That is, when a tab is selected outside of the tab bar visible area, the tab bar is scrolled horizontally so the selected tab becomes visible." :group 'tabbar :type 'boolean)