Emacs 简易教程
Table of Contents
更新记录:
2018/06/22:本文以不再维护,请移步到我的 Emacs Wiki。
2015/01/20: 一开始我总是想让 Emacs 干所有的事情,后来我发现我装的插件严重拖累了 Emacs 的使用速度,但是我却没有用过它。这也可能是很多新手经常会犯的错误,盲目的追求功能,而忽略了最原始的需求。这次更新文档会砍掉很多不常用的插件,适配最新的的配置文件。
另外: 笔者是服务器开发,常用 Emacs 开发(C/C++, Python, shell…)和写文章(markdown not org-mode)。我的配置文件:https://github.com/zhangjie2012/_emacs.d。
最早开始文本编辑器的时候是 Vi(m) ,实在不习惯频繁的 Esc 和编辑模式切换,就选择了 Emacs。
现在看来编辑器无谓好坏,只是个人习惯而已。Emacs 没有 Vi(m) 的编辑快感和编辑速度,但是它可以随意定制,用更少的键做更多的事情。
世界上有三种程序员,一种是用 Vim 的,一种是用 Emacs 的,另外一种是用其它编辑器的。本文介绍 Emacs 的基本使用。
1. Emacs24 的安装
安装过程:
wget https://github.com/mirrors/emacs/archive/emacs-24.3.92.zip unzip emacs-24.3.92.zip cd emacs-24.3.93 ./autogen.sh ./configure --without-makeinfo make -j2 sudo make install
添加 alias em
'env TERM=xterm-256color emacs -nw= 到 ~/.bashrc
中,这样就可以直接用 em
打开 Emacs 了。
Emacs24 集成了很多插件,比之前的版本好用很多,而且很多新的插件都是基于 24 的,所以建议用 Emacs24, 而非 Emacs23-,本文也仅仅针对 24 做适配。
2. 基本快捷键
这里列出在没有打开任何 mode 的情况下,原生 Emacs 所支持的快捷键。
C-
: Ctrl 键M-
: Alt/ESC 键,S-
: Shift 键C-g
: 撤销命令(没事多摁几下,我都是没事摁着玩的)C-z
: 挂起 EmacsC-x C-c
: 关闭 Emacs
2.1. 光标移动
C-n
: 下一行C-p
: 上一行C-f
: 前进一个字符C-b
: 后退一个字符M-f
: 前进一个单词M-b
: 后退一个单词C-v
: 向下翻页M-v
: 向上翻页C-l
: 光标所在行移动到屏幕中央C-a
: 行首C-e
: 行尾M-a
: 句首M-e
: 句尾M-{
: 段首M-}
: 段尾M-<
: 文件首M->
: 文件尾
2.2. 文档编辑
<Backspace>
: 向前删除一个字符C-d
<DEL>
: 向后删除一个字符,我一般用C-d
M-d
M-<DEL>
: 向后删除一个单词C-k
: 删除光标到行尾,删除一行用C-a, C-k
(Vim 中的 dd)。M-k
: 删除光标到句尾C-@
: 标记(Mark set), 标记之后配合光标移动快捷键,可以选中一个区域M-w
: 复制C-w
: 剪切C-y
: 粘贴C-/
: 撤销(UNDO)
大小写转换:
M-l
: Convert following word to lower case (downcase-word).M-u
: Convert following word to upper case (upcase-word).M-c
: Capitalize the following word (capital-word).C-x C-l
: Convert region to lower case (downcase-region).C-x C-u
: Convert region to upper case (upcase-region).
块操作:
C-x r k
: Kill the text of the region-rectangle, saving its contents as the "last killed rectangle" (kill-rectangle).C-x r M-w
: Save the text of the region-rectangle as the "last killed rectangle" (copy-rectangle-as-kill).C-x r d
: Delete the text of the region-rectangle (delete-rectangle).C-x r y
: Yank the last killed rectangle with its upper left corner at point (yank-rectangle).C-x r o
: Insert blank space to fill the space of the region-rectangle (open-rectangle). This pushes the previous contents of the region-rectangle to the right.C-x r N
: Insert line numbers along the left edge of the region-rectangle (rectangle-number-lines). This pushes the previous contents of the region-rectangle to the right.C-x r c
: Clear the region-rectangle by replacing all of its contents with spaces (clear-rectangle).M-x delete-whitespace-rectangle
: Delete whitespace in each of the lines on the specified rectangle, starting from the left edge column of the rectangle.C-x r t string <RET>
: Replace rectangle contents with string on each line (string-rectangle).M-x string-insert-rectangle <RET> string <RET>
: Insert string on each line of the rectangle.
删除空白字符(Deleting whitespace):
M-\\
: 删除光标周围的空格和 tab。M-<SPC>
: 删除光标周围的空格和 tab,但是保留一个。C-x C-o
: 删除周围行附近的空行。M-^
: Join two lines by deleting the intervening newline, along with any indentation following it. With a prefix (C-u M-^) it joins the current with the next line.
选中:
M-h
: Move point to the beginning of the current paragraph, and set mark at the end.C-M-h
: Move point to the beginning of the current defun, and set mark at the end.C-x h
: Move point to the beginning of the buffer, and set mark at the end.C-x SPC
: Makes a rectangular region (new in Emacs 24.4).
2.3. 搜索
C-s
: 向前搜索C-r
: 向后操作C-g
: 回到搜索开始前的位置M-%
: 询问并替换M-s .
: 当前单词搜索。
2.4. 文件操作(缓冲区)
Emacs 可以打开很多文件,一个文件可以理解成一个 buffer,你可以在多个文件中来回切换。
C-x f
: 打开一个文件 ->find-file
C-x s
: 保存C-x C-w
: 另存为C-x C-v
: 关闭当前缓冲区,并打开新文件C-x C-b
: 打开缓冲区列表C-x b
: 切回最近的 buffer ->switch-to-buffer
C-x k
: 关闭当前缓冲区C-x C-b
,d
,x
: 关闭用 d 标记 bufferM-x find-file-at-point
,M-x ffap
C-x 5 0
:delete-frame
2.5. 窗口(WINDOWS)操作
C-x 1
: 只保留当前窗口C-x 2
: 水平切分C-x 3
: 垂直切分C-x o
: 切换到另外一个窗口C-x 0
: 关闭当前窗口(并不是删除buffer)C-x 4 C-f
: 在另外一个窗口打开文件 ->find-file-other-window
2.6. 查阅命令
M-x man
:M-x info
: 所有的 Emacs 手册
2.7. 代码编辑
M-;
: 块注释C-M-h
: 选中一个函数
2.8. 目录操作
M-x dired
: 打开一个目录
2.9. 书签
C-x r m
: 设置一个书签 ->bookmark-set
C-x r b
: 跳转到一个书签 ->bookmark-jump
C-x r l
: 显示所有书签列表, 管理书签的方式和Direcd
模式一样RET
: 打开一个书签p
: 前一个书签n
: 后一个书签s
: 保存当前书签到一个文件中o
: 在另外一个窗口中打开文件r
: 重命名书签d
: 标记要删除的书签x
: 执行删除动作u
: 撤销标记
2.10. Occur
把所有的搜索结果都列到一个名为 *Occur*
buffer 中。使用 M-s o
调用
occur
函数,搜索当前文档。
M-g n
: 下一个匹配项M-g p
: 上一个匹配项e
: 进入 =occur-edit-mode=,可以编辑搜索结果C-c C-c
: 退出编辑模式g
: 刷新搜索结果
2.11. Dired
C-x d
: 选个一个目录,在当前窗口打开C-x 4 d
: 选一个目录,在另外一个目录打开i
: 打开子目录
2.12. 版本控制(Version Control)
c-x v +
,M-x vc-update
: 更新文件C-x v v
,M-x vc-next-action
: 提交当前文件C-x v =
,M-x vc-diff
C-x v ~
,M-x vc-revision-other-window
: 显示指定版本C-x v l
,M-x vc-print-log
: 查看日志C-x v u
,M-x vc-revert
C-x v C-h
: 查看所有可用的 vc 命令
3. 基本设置(独立于插件)
Emacs 默认找的配置文件为 ~/.emacs
或者
~/.emacs.d/init.el=。我用的是后者,这样就可以把所有的配置放到一个目录下面,方便管理。默认的
Emacs 的快捷键有些不好用,比如 =c-x c-f
时,没有任何提示。再如窗口切换使用 =c-x o=,当 buffer
多时,非常不方便,这一节介绍 emacs 通用的定制(不针对某种开发/编辑环境)。
零散的设置:
- 用
y/n
代替yes/no
:(fset 'yes-or-no-p 'y-or-n-p)
- 关闭自动保存:
(setq auto-save-default nil)
- 关闭自动备份:
(setq make-backup-files nil)
- 多个 Emacs 打开同一份文件时,会自动产生一个 .#xxx
的文件,很烦人,去掉:
(setq create-lockfiles nil)
- 屏蔽挂起键(经常按错):
global-unset-key (kbd "C-z"))
设置编码为 UTF-8:
(setq locale-coding-system 'utf-8) (set-terminal-coding-system 'utf-8) (set-keyboard-coding-system 'utf-8) (set-selection-coding-system 'utf-8) (prefer-coding-system 'utf-8)
打开 Eshell 绑定快捷键: C-c e
打开, C-c l
清空:
(defun clear-eshell-buffer () (interactive) (let ((inhibit-read-only t)) (delete-region (point-min) (point-max)))) (global-set-key (kbd "C-c l") 'clear-eshell-buffer) (global-set-key (kbd "C-c e") 'eshell)
Tab 设置(空格替代,4字符):
(setq-default indent-tabs-mode nil) (setq-default tab-width 4)
括号匹配、对齐、补全:
(show-paren-mode t) (require 'electric) (electric-indent-mode t) ;;(electric-pair-mode t) (electric-layout-mode t)
我不喜欢括号自动补全,所有就注释掉了。
Tip: M-x eval-buffer
可以使配置文件立即生效,调试非常方便。
4. 高级定制
这一节针对不同的应用,介绍一些插件。
4.1. 外观
自动换行: (global-visual-line-mode 1)
行号宽度定制:
(setq linum-format "%3d|") ;;(global-linum-mode 1)
默认情况下,不显示行号,需要的时候,=M-x linum-mode=。
代码参考线: fill-column-indicator
(require 'fill-column-indicator) (setq fci-rule-color "#D15FEE") (setq fci-rule-column 80) (define-globalized-minor-mode global-fci-mode fci-mode (lambda () (fci-mode 1))) ;;(global-fci-mode 1) (global-set-key (kbd "M-|") 'global-fci-mode)
默认不显示,快捷键绑定到 =M-|=,随时切换。
主题: ample-theme。
4.2. 缓冲区使用优化
使用 helm, 最牛逼的 Emacs 插件之一:
(require 'helm) (require 'helm-config) (require 'helm-eshell) (add-hook 'eshell-mode-hook #'(lambda () (define-key eshell-mode-map (kbd "C-c C-l") 'helm-eshell-history))) (global-set-key (kbd "C-c h") 'helm-command-prefix) (define-key helm-map (kbd "<tab>") 'helm-execute-persistent-action) (define-key helm-map (kbd "C-i") 'helm-execute-persistent-action) (define-key helm-map (kbd "C-z") 'helm-select-action) (when (executable-find "curl") (setq helm-google-suggest-use-curl-p t)) (setq helm-split-window-in-side-p t helm-move-to-line-cycle-in-source t helm-ff-search-library-in-sexp t helm-scroll-amount 8 helm-ff-file-name-history-use-recentf t ) (global-set-key (kbd "M-x") 'helm-M-x) (global-set-key (kbd "M-y") 'helm-show-kill-ring) (global-set-key (kbd "C-x b") 'helm-mini) (global-set-key (kbd "M-y") 'helm-show-kill-ring) (global-set-key (kbd "C-c h o") 'helm-occur) (setq helm-M-x-fuzzy-match t) ;;(helm-autoresize-mode 1) (helm-mode 1)
比较详细的一篇文档,A Package in a league of its own: Helm,这里不再赘述了,简单演示一下几个常用的功能(其实 helm 的功能都很常用):
Figure 1: helm
Buffer 切换(windows-numbering.el):
;; 使用 M-(1,2,3...9)窗口切换 (require 'window-numbering) (setq window-numbering-assign-func (lambda () (when (equal (buffer-name) "*Calculator*") 9))) (window-numbering-mode 1)
4.3. 编辑优化
相同符号高亮(highlight-symbol.el):
(require 'highlight-symbol) (global-set-key (kbd "M--") 'highlight-symbol-at-point) (global-set-key (kbd "M-n") 'highlight-symbol-next) (global-set-key (kbd "M-p") 'highlight-symbol-prev)
自动补全(auto-complete & yasnippet):
(require 'popup) (require 'auto-complete) (require 'auto-complete-config) (add-to-list 'ac-dictionary-directories "~/.emacs.d/auto-complete/dict") (ac-config-default) (setq ac-use-quick-help nil) (setq ac-use-menu-map t) (define-key ac-menu-map "\C-n" 'ac-next) (define-key ac-menu-map "\C-p" 'ac-previous) (global-set-key "\M-/" 'auto-complete) (add-to-list 'ac-modes 'protobuf-mode) (require 'yasnippet) ;;(yas-global-mode 1)
C/C++ 头文件自动补全(auto-complate-c-headers):
(defun my:ac-c-headers-init () (require 'auto-complete-c-headers) (add-to-list 'ac-sources 'ac-source-c-headers) (add-to-list 'achead:include-directories '"/usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../include/c++/4.4.7") (add-to-list 'achead:include-directories '"/usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../include/c++/4.4.7/x86_64-redhat-linux") (add-to-list 'achead:include-directories '"/usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../include/c++/4.4.7/backward") (add-to-list 'achead:include-directories '"/usr/local/include") (add-to-list 'achead:include-directories '"/usr/lib/gcc/x86_64-redhat-linux/4.4.7/include") (add-to-list 'achead:include-directories '"/usr/include")) (add-hook 'c++-mode-hook 'my:ac-c-headers-init) (add-hook 'c-mode-hook 'my:ac-c-headers-init)
区域标记(expand-region),Emacs 这下牛逼了,我给绑定了一些快捷键:
(require 'expand-region) (global-set-key (kbd "M-m") 'er/expand-region) (global-set-key (kbd "M-s s") 'er/mark-symbol) (global-set-key (kbd "M-s p") 'er/mark-outside-pairs) (global-set-key (kbd "M-s P") 'er/mark-inside-pairs) (global-set-key (kbd "M-s q") 'er/mark-outside-quotes) (global-set-key (kbd "M-s Q") 'er/mark-inside-quotes) (global-set-key (kbd "M-s m") 'er/mark-comment) (global-set-key (kbd "M-s f") 'er/mark-defun)
4.4. 常用语言 Mode
Markdown: markdown-mode
(autoload 'markdown-mode "~/.emacs.d/lisp/markdown-mode/markdown-mode.el" "Major mode for editing Markdown files" t) (setq auto-mode-alist (cons '("\\.md" . markdown-mode) auto-mode-alist)) (setq auto-mode-alist (cons '("\\.markdown" . markdown-mode) auto-mode-alist))
Python: python-mode
(require 'python-mode)
Google Protobuf Buffer: protobuf-mode
(require 'protobuf-mode) (add-to-list 'auto-mode-alist '("\\.proto$" . protobuf-mode))
lua: lua-mode
(autoload 'lua-mode "lua-mode" "lua editing mode. " t) (add-to-list 'auto-mode-alist '("\\.lua$" . lua-mode)) (add-to-list 'interpreter-mode-alist '("lua" . lua-mode))
(require 'web-mode) (add-to-list 'auto-mode-alist '("\\.html?\\'" . web-mode))
5. 学习资源
一些学习资源推荐,也是本文档的参考资料。
- Emacs Mini Mannual : Emacs Mini 手册
- Emacs Themes : 主题集合
- MELPA : 插件集合,同时也可以感受一下 Emacs 的强大
- GNU Emacs Manuals Online : Emacs 官方手册
- Emacs Redux
- Emacs Markdown Mode
- 一年成为Emacs高手(像神一样使用编辑器)
- Emacs as a Python IDE
- Emacs快速参考
- Case Conversion Commands
- 曹乐: 在Emacs下用C/C++编程