GitHub Spacemacs Rocks 作者 zilongshanren 编者 li-xinyang
在这一季中我们计划用 21 天学习 Emacs 以及 Spacemacs 的使用。从基础安装开始到可以运用到工作生产环节中。为了确保学习质量,请务必完成和理解计划中的每一项学习任务。
视频地址如下
说在最前面
如果你第一次听说 Emacs 你可以在性感的 Emacs(Emacs is Sexy)一文中找到使用它的理由!我相信你一定会被它的强大所吸引。
如果你还没有安装 Emacs 可以在 Mac OS X 安装链接以及 Window 安装链接找到它。本文我们使用的为 Emacs 25.0.x Pretest 版本,一些配置在 Emacs 24 中可能并不适用。
在开始本教程之前请务必先完成 Emacs 提供的官方教程(完成时间大约 30 分钟),它可以通过使用 C-h t
(同时按住 Ctrl 与 h 键,接着按 t 键 t
在这里代表 tutorial) 在 Emacs 中直接将其打开。
Emacs Lisp 是 Emacs 所用的编程语言,你可以在阅读这篇教程(Learn X in Y Minutes)后很快地了解它的基础用法。
因为 Control 键在 Emacs 中极为常用,所以为了更方便地使用 Emacs 的键位修改,需要对其做出修改。建议将大写锁定键(Caps Lock)替换为 Control 键。这里是一个可以参考的把大写锁定键替换为 Control 键的教程:移动 Control 键 (Moving The Ctrl Key)。如果这个的教程不适用于你的操作系统,请自行搜索其它的修改方式。
常见符号所代表的意义如下
- M(eta),在 Mac 下为 Option 键
- s(uper),在 Mac 环境下为左 Command 键
- S(Shift)
- C(trl)
光标的移动是编辑器中最常用的操作所以必须熟知。
C-f
为前移一个字符,f
代表 forward。C-b
为后移一个字符,b
代表 backward。C-p
为上移至前一行,p
代表 previous。C-n
为上移至下一行,n
代表 next。C-a
为移至行首,a
可以理解为最前端。C-e
为移至行尾,e
代表 end。
常用的文件操作快捷键组合也必须熟记。
C-x C-f
为打开目标文件,f
代表 find/fileC-x C-s
为保存当前缓冲区(Buffer),s
代表 save
C-x
是 Emacs 的快捷键中常用的前缀命令。这些前缀命令常常代表了一系列有关联的指令,十分重要,请特别牢记。其它常见的还有 C-c
, C-h
。
打断组合键为 C-g
,它用于终端取消之前的指令。快捷键就是用预先绑定好的方式告诉 Emacs 去执行指定的命令。(之后会介绍到更多有关绑定的内容)
Emacs 功能强大,但是部分功能默认情况下并未开启。下面就有几个例子,
编辑器内显示行号可使用 M-x linum-mode
来开启。
获取帮助
Emacs 是一个富文档编辑器(Self document, extensible editor)而下面的三种方法在学习 Emacs 的过程中也非常重要。他们分别是,
C-h k
寻找快捷键的帮助信息C-h v
寻找变量的帮助信息C-h f
寻找函数的帮助信息
请务必完成这篇教程(Learn X in Y Minutes)来了解 Elisp 的使用(阅读时间大约 15 分钟),你也可以在这里找到它的中文版。Emacs Lisp 为一个函数式的语言,所以它全部功能都是由函数来实现的。
下面为一些简单的例子
;; 2 + 2
(+ 2 2)
;; 2 + 3 * 4
(+ 2 (* 3 4))
;; 定义变量
(setq name "username")
(messasge name) ; -> "username"
;; 定义函数
(defun func()
(message "Hello, %s" username))
;; 执行函数
(func) ; -> Hello, username
;; 设置快捷键
(global-set-key (kbd "<f1>") 'func)
;; 使函数可直接被调用可添加 (interactive)
(defun func()
(interactive)
(message "Hello, %s" username))
Emacs 的配置文件默认保存在 ~/.emacs.d/init.el
文件中。(如果其不存在可自行创建,配置文件也可保存在 ~/.emacs
文件中,他们之间的区别我们会在后面做讨论)
在开始配置之前让我们先来区别 Emacs 中 Major Mode 与 Minor Mode 的区别。Major Mode 通常是定义对于一种文件类型编辑的核心规则,例如语法高亮、缩进、快捷键绑定等。而 Minor Mode 是除去 Major Mode 所提供的核心功能以外的额外编辑功能(辅助功能)。例如在下面的配置文件中 tool-bar-mode
与 linum-mode
等均为 Minor Mode*。
简单来说就是,一种文件类型同时只能存在一种 Major Mode 但是它可以同时激活一种或多种 Minor Mode。如果你希望知道当前的模式信息,可以使用 C-h m
来显示当前所有开启的全部 Minor Mode 的信息。
简单的编辑器自定义
下面是一些简单的编辑器配置信息,你需要做的就是将其写入你的配置文件中( ~/.emacs.d/init.el
)即可。
;; 关闭工具栏,tool-bar-mode 即为一个 Minor Mode
(tool-bar-mode -1)
;; 关闭文件滑动控件
(scroll-bar-mode -1)
;; 显示行号
(global-linum-mode 1)
;; 更改光标的样式(不能生效,解决方案见第二集)
(setq cursor-type 'bar)
;; 关闭启动帮助画面
(setq inhibit-splash-screen 1)
;; 关闭缩进 (第二天中被去除)
;; (electric-indent-mode -1)
;; 更改显示字体大小 16pt
;; http://stackoverflow.com/questions/294664/how-to-set-the-font-size-in-emacs
(set-face-attribute 'default nil :height 160)
;; 快速打开配置文件
(defun open-init-file()
(interactive)
(find-file "~/.emacs.d/init.el"))
;; 这一行代码,将函数 open-init-file 绑定到 <f2> 键上
(global-set-key (kbd "<f2>") 'open-init-file)
在每次编辑配置文件后,刚刚做的修改并不会立刻生效。这时你需要重启编辑器或者重新加载配置文件。重新加载配置文件你需要在当前配置文件中使用 M-x load-file
双击两次回车确认默认文件名,或者使用 M-x eval-buffer
去执行当前缓冲区的所有 Lisp 命令。你也可以使用 C-x C-e
来执行某一行的 Lisp 代码。这些可使刚刚修改的配置文件生效。当然你也可以将这些函数绑定为快捷键。
使用默认的插件管理系统(可在菜单栏 Options > Manage Emacs Packages
中找到)安装 Company 插件,他是一个用于代码补全的插件。它的名字代表补全一切的意思( Comp lete Any thing)。因为默认的插件管理系统提供的插件十分有限,所以我们会在之后的几天中继续将其强化。
使用的下面的配置将 Company-mode 在全局模式下激活
; 开启全局 Company 补全
(global-company-mode 1)
简单的 Org-mode 使用,它可以列出提纲,并方便地使用 tab
键来对其进行展开与关闭。 C-c C-t
可以将一个条目转换成一条待办事件。
* 为一级标题
** 为二级标题
*** 为三级标题并以此类推
视频地址如下
说在最前面
如果你想深入学习 Emacs Lisp 可以阅读 GNU 提供的 An Introduction to Programming in Emacs Lisp 。(也可以 M-x info
然后选择 Emacs Lisp Intro)
我们先解决前一天中遇到的一些问题。首先是在对象是一个缓冲区局部变量(Buffer-local variable)的时候,比如这里的 cursor-type
,我们需要区分 setq
与 setq-default
: setq
设置当前缓冲区(Buffer)中的变量值, setq-default
设置的为全局的变量的值(具体内容可以在 StackOverflow 找到)。下面是一个例子,用于设置光标样式的方法。
(setq-default cursor-type 'bar)
今天我们需要将第一天关闭的自动缩进 (electric-indent-mode
) 从配置文件中去除,它是 Emacs 24.4 中加入的新特性,你可以在这篇文章中找到更多关于它的内容。我们之前关闭它是因为,它存在不理想的缩进效果(在 Emacs Lisp 中用分号做注释时 fancy-comment
会造成很远的缩进,其实解决方法是使用 Emacs Lisp 推荐的两个分号而不是一个 ;;
,这样就可以避免这个问题。于是我们也就将其从配置文件中删除)
因为通常我们的配置文件以及项目文件均使用版本控制系统,所以自动生成的备份文件就显得有些多余。我们还可以禁止 Emacs 自动生成备份文件,例如 init.el~
。( ~
为后缀的文件为自动生成的备份文件)我们可以使用下面的方法将其关闭。
(setq make-backup-files nil)
关于分屏的使用,如果你已经读过 Emacs 自带的教程,现在你应该已经掌握了基本的分屏操作方法了。关于分屏的更多内容你可以在这里找到。
C-x 1
仅保留当前窗口C-x 2
将当前窗口分到上边C-x 3
将当前窗口分到右边
使用下面的配置来加入最近打开过文件的选项让我们更快捷的在图形界面的菜单中打开最近编辑过的文件。
(require 'recentf)
(recentf-mode 1)
(setq recentf-max-menu-item 10)
;; 这个快捷键绑定可以用之后的插件 counsel 代替
;; (global-set-key (kbd "C-x C-r") 'recentf-open-files)
require
的意思为从文件中加载特性,你可以在杀哥的网站读到关于 Emacs Lisp 库系统的更多内容,文章在这里。
使用下面的配置文件将删除功能配置成与其他图形界面的编辑器相同,即当你选中一段文字之后输入一个字符会替换掉你选中部分的文字。
(delete-selection-mode 1)
下面的这些函数可以让你找到不同函数,变量以及快捷键所定义的文件位置。因为非常常用所以我们建议将其设置为与查找文档类似的快捷键(如下所示),
find-function
(C-h C-f
)find-variable
(C-h C-v
)find-function-on-key
(C-h C-k
)
在我们进入下一个部分之间让我们来看看使用 ~/.emacs.d/init.el
与 ~/.emacs
的区别(更多关于他们区别的讨论可在这里找到)。简单来说请使用前者,因为它有下面的两个优点,
- 它可以更好将所有 Emacs 相关的文件整合在一个目录内(干净的
HOME
,网盘备份等优点) - 更好的版本控制
配置插件源
在进行美化之前我们需要配置插件的源(默认的源非常有限),最常使用的是 MELPA (Milkypostman’s Emacas Lisp Package Archive)。它有非常多的插件(3000 多个插件)。一个插件下载的次数多并不能说明它非常有用,也许这个插件是其他的插件的依赖。在这里你可以找到其安装使用方法。添加源后,我们就可以使用 M-x package-list-packages
来查看所有 MELPA 上的插件了。在表单中可以使用 I
来标记安装 D
来标记删除, U
来更新,并用 X
来确认。
你可以直接将下面的代码复制到你的配置文件顶端,从而直接使用 Melpa 作为插件的源。你可以将你需要的插件名字写在 my/packages
中,Emacs 在启动时会自动下载未被安装的插件。
(when (>= emacs-major-version 24)
(require 'package)
(package-initialize)
(add-to-list 'package-archives '("melpa" . "http://melpa.org/packages/") t))
;; cl - Common Lisp Extension
(require 'cl)
;; Add Packages
(defvar my/packages '(
;; --- Auto-completion ---
company
;; --- Better Editor ---
hungry-delete
swiper
counsel
smartparens
;; --- Major Mode ---
js2-mode
;; --- Minor Mode ---
nodejs-repl
exec-path-from-shell
;; --- Themes ---
monokai-theme
;; solarized-theme
) "Default packages")
(setq package-selected-packages my/packages)
(defun my/packages-installed-p ()
(loop for pkg in my/packages
when (not (package-installed-p pkg)) do (return nil)
finally (return t)))
(unless (my/packages-installed-p)
(message "%s" "Refreshing package database...")
(package-refresh-contents)
(dolist (pkg my/packages)
(when (not (package-installed-p pkg))
(package-install pkg))))
;; Find Executable Path on OS X
(when (memq window-system '(mac ns))
(exec-path-from-shell-initialize))
关于上面这段配置代码有几个知识点,首先就是这段配置文件中用到了 loop for ... in
,它来自 cl
即 Common Lisp 扩展。 for
, in
, collect
均为 cl-loop
中的保留关键字。下面是一些简单的 cl-loop
的使用示例:
;; 遍历每一个缓冲区(Buffer)
(cl-loop for buf in (buffer-list)
collect (buffer-file-name buf))
;; 寻找 729 的平方根(设置最大为 100 为了防止无限循环)
(cl-loop for x from 1 to 100
for y = (* x x)
until (>= y 729)
finally return (list x (= y 729)))
你可以在这里找到更多关于循环的使用说明。
其次就是它使用到了 quote
, 它其实就是我们之前常常见到的 '
(单引号)的完全体。因为它在 Lisp 中十分常用,所以就提供了简写的方法。
;; 下面两行的效果完全相同的
(quote foo)
'foo
quote
的意思是不要执行后面的内容,返回它原本的内容(具体请参考下面的例子)
(print '(+ 1 1)) ;; -> (+ 1 1)
(print (+ 1 1)) ;; -> 2
更多关于 quote
的内容可以在这里找到,或者在这里找到 StackOverflow 上对于它的讨论。
这样我们就可以区分下面三行代码的区别,
;; 第一种
(setq package-selected-packages my/packages)
;; 第二种
(setq package-selected-packages 'my/packages)
;; 第三种
(setq package-selected-packages (quote my/packages))
第一种设置是在缓冲区中设置一个名为 package-selected-packages
的变量,将其的值设定为 my/packages
变量的值。第二种和第三种其实是完全相同的,将一个名为 package-selected-packages
的变量设置为 my/packages
。
我们可以用下面代码将 Emacs 设置为开启默认全屏,
(setq initial-frame-alist (quote ((fullscreen . maximized))))
我们也可以启用自动括号匹配(Highlight Matching Parenthesis),随后会介绍插件来增强这个匹配的功能。你可以在这里读到关于钩子的更多信息。
(add-hook 'emacs-lisp-mode-hook 'show-paren-mode)
高亮当前行,当文本内容很多时可以很容易找到光标的位置。
(global-hl-line-mode 1)
安装主题
(add-to-list my/packages 'monokai-theme)
然后使用下面的配置使其每次打开编辑器时加载主题,
(load-theme 'monokai 1)
推荐插件
- company
- hungry-delete
- Smex (如果你使用 Counsel 来增强你的
M-x
,那么就不需要再安装 Smex 了) - Swiper & Counsel
- smartparens
使用 M-x customize-group
后选择对应的插件名称,可以进入可视化选项区对指定的插件做自定义设置。当选择 Save for future session 后,刚刚做的设计就会被保存在你的配置文件( init.el
)中。关于各个插件的安装与使用方法通常都可以在其官方页面找到(GitHub Pages 或者是项目仓库中的 README 文件)。我们强烈建议大家在安装这些插件后阅读使用方法来更好的将它们使用到你的日常工作当中使效率最大化。
Emacs 提供的默认 JavaScript Major Mode 并不是非常好用。所以我们可以将默认的模式替换成 js2-mode 一个比默认模式好用的 Major Mode。我们可以通过 MELPA 来下载它,然后用下面的代码将其启用。
(setq auto-mode-alist
(append
'(("\\.js\\'" . js2-mode))
auto-mode-alist))
你可以在这里(How Emacs Chooses a Major Mode)找到 Emacs 是如何选择何时该选用何种 Major Mode 的方法。
在这里我们需要知道 auto-mode-alist
的作用,这个变量是一个 AssociationList,它使用正则表达式(REGEXP)的规则来匹配不同类型文件应使用的 Major Mode。 下面是几个正则表达式匹配的例子,
(("\\`/tmp/fol/" . text-mode)
("\\.texinfo\\'" . texinfo-mode)
("\\.texi\\'" . texinfo-mode)
("\\.el\\'" . emacs-lisp-mode)
("\\.c\\'" . c-mode)
("\\.h\\'" . c-mode)
…)
下面是如何添加新的模式与对应文件类型的例子(与我们配置 js2-mode
时相似的例子),
(setq auto-mode-alist
(append
;; File name (within directory) starts with a dot.
'(("/\\.[^/]*\\'" . fundamental-mode)
;; File name has no dot.
("/[^\\./]*\\'" . fundamental-mode)
;; File name ends in ‘.C’.
("\\.C\\'" . c++-mode))
auto-mode-alist))
在 js2-mode
模式中会提供
- 语法高亮
- 语法检查器(Linter)
执行缓冲区的代码可以使用 nodejs-repl
插件,它需要你的机器上已经安装了 NodeJS。然而在 Mac OS X 上可能会出现找不到 NodeJS 可执行文件的问题,要解决这个问题你需要安装另外一个 exec-path-from-shell
的插件并将其启用。
(when (memq window-system '(mac ns))
(exec-path-from-shell-initialize))
有了 nodejs-repl
我们就可以方便的测试和开发我们的 JavaScript 代码了(你可以在这里找到更多关于它的使用方法)。
在 Org-mode 中你可以直接开启新的缓冲区(Buffer)直接用相应的 Major Mode 来编辑代码块内的内容。在代码块中使用 C-c '
会直接打开对应模式的缓冲区(不仅限于 Lisp)。这样就使在 Org-mode 中编辑代码变的十分方便快捷。
使用 <s
然后 Tab 可以直接插入代码块的代码片段(Snippet),更多类似的代码片段(Org-mode Easy Templates)可以在这里找到。
#+BEGIN_SRC emacs-lisp ;; Your code goes here ;; 你的代码写在这里 #+END_SRC
添加 Org-mode 文本内语法高亮
(require 'org)
(setq org-src-fontify-natively t)
在 Org-mode 中重置有序列表序号可以直接使用 M-<RET> 。
Agenda 的使用
;; 设置默认 Org Agenda 文件目录
(setq org-agenda-files '("~/org"))
;; 设置 org-agenda 打开快捷键
(global-set-key (kbd "C-c a") 'org-agenda)
你只需将你的 *.org
文件放入上面所指定的文件夹中就可以开始使用 Agenda
模式了。
C-c C-s
选择想要完成的时间C-c C-d
选择想要结束的时间C-c a
可以打开 Agenda 模式菜单并选择不同的可视方式(r
)
视频地址如下
将不同的配置代码放置到不同的文件中,使其模块化,这让我们的后续维护变得更加简单。下面是我们现在的 ~/.emacs.d/
目录中的样子,
├── auto-save-list # 自动生成的保存数据 ├── elpa # 下载的插件目录 ├── init.el # 我们的配置文件 └── recentf # 最近访问的文件列表
通常我们只保存配置文件和对其进行版本控制,其他的插件均为在第一次使用编辑器时再通过网络重新下载,当然你也可以选择将全部配置文件进行版本控制来保证自己时刻拥有最稳定的生产环境。
Elisp 中并没有命名空间(Namespace),换句话说就是所有的变量均为全局变量,所以其命名方法就变的非常重要。下面是一个简单的命名规则,
#自定义变量可以使用自己的名字作为命名方式(可以是变量名或者函数名) my/XXXX #模式命名规则 ModeName-mode #模式内的变量则可以使用 ModeName-VariableName
遵守上面的命名规则可以最大程度的减少命名冲突发生的可能性。
现在我们想将原本混合在一起的配置文件分为下面的几个模块(每一个模块为一个独立的配置文件并将其保存在指定的子目录中),它们分别是
init-packages.el # 插件管理 init-ui.el # 视觉层配置 init-better-defaults.el # 增强内置功能 init-keybindings.el # 快捷键绑定 init-org.el # Org 模式相关的全部设定 custome.el # 存放使用编辑器接口产生的配置信息
下面为将配置文件进行模块化后的目录结构,
├── init.el └── lisp ├── comstom.el ├── init-better-defaults.el ├── init-helper.el ├── init-keybindings.el ├── init-packages.el ├── init-ui.el └── init-org.el
使用模块化配置就可以让我们在之后的配置中迅速的定位与更改配置内容,让整个过程变得更有条理也更加高效。
和之前一样 init.el
是配置文件的入口,现在它便成为了所有模块配置文件的入口,所以要使用这些模块时,我们需要在其中引用需要加载的模块。下面以 init-packages.el
(此配置为添加插件的模块) 为例,详细说明如何模块化以及应用的方法。
下面是在模块化配置之前,我们所使用的配置文件 ~/.emacs.d/init.el
的样子,我们将所有的配置代码都放置在了同一个文件中(如下所示)
下面为 ~/.emacs.d/init.el
文件的内容
;; __ __ __ ___
;; |__) /\ / ` |__/ /\ / _` |__
;; | /~~\ \__, | \ /~~\ \__> |___
;; __ ___ ___ ___
;; |\/| /\ |\ | /\ / _` |__ |\/| |__ |\ | |
;; | | /~~\ | \| /~~\ \__> |___ | | |___ | \| |
(when (>= emacs-major-version 24)
(require 'package)
(package-initialize)
(add-to-list 'package-archives '("melpa" . "http://melpa.org/packages/") 1))
;; cl - Common Lisp Extension
(require 'cl)
;; Add Packages
(defvar my/packages '(
;; --- Auto-completion ---
company
;; --- Better Editor ---
smooth-scrolling
hungry-delete
swiper
counsel
smartparens
;; --- Major Mode ---
js2-mode
markdown-mode
;; --- Minor Mode ---
;; Quick Note Taking
deft
;; JavaScript REPL
nodejs-repl
;; Find OS X Executable Helper Package
;; ...
之前为了更好的区分不同的区域我使用的方法是使用 ASCII Art 然后再以关键字来做搜索跳转,但是这样再编辑工程中依旧十分缓慢和麻烦。于是我们现在要将配置文件全部模块化,把不同部分的配置代码放置在不同的配置文件中,并在入口文件( ~/.emacs.d/init.el
)中依次引用不用的模块。
下面为 ~/.emacs.d/lisp/init-packages.el
模块中的代码
;; __ __ __ ___
;; |__) /\ / ` |__/ /\ / _` |__
;; | /~~\ \__, | \ /~~\ \__> |___
;; __ ___ ___ ___
;; |\/| /\ |\ | /\ / _` |__ |\/| |__ |\ | |
;; | | /~~\ | \| /~~\ \__> |___ | | |___ | \| |
(when (>= emacs-major-version 24)
(require 'package)
(package-initialize)
(add-to-list 'package-archives '("melpa" . "http://melpa.org/packages/") 1))
;; cl - Common Lisp Extension
(require 'cl)
;; Add Packages
(defvar my/packages '(
;; --- Auto-completion ---
company
;; --- Better Editor ---
smooth-scrolling
hungry-delete
swiper
counsel
smartparens
popwin
;; --- Major Mode ---
js2-mode
markdown-mode
;; ...
;; 文件末尾
(provide 'init-packages)
下面为 ~/.emacs.d/init.el
入口文件中的代码
(package-initialize)
(add-to-list 'load-path "~/.emacs.d/lisp/")
;; Package Management
;; -----------------------------------------------------------------
(require 'init-packages)
模块化要做的其实非常简单,我们要做的其实就是把某一个更改编辑器某定部分(例如,插件管理,显示层,快捷键绑定等)的配置代码写入一个独立的文件中并在末尾为其添加 (provide 'modul-name)
(这里我们的模块名为 init-packages
)使其可以在入口文件中被调用,然后再在入口文件中将其引用既可。
这里需要注意的是,我们需要在入口文件中添加 (add-to-list 'load-path "~/.emacs.d/lisp/")
这可以让 Emacs 找到需要加载的模块所处的位置。
更多模块化的配置文件可以在这里找到。
在这一节我们将详细介绍 Major Mode 与 Minor Mode 去区别。每一个文件类型都对应一个 Major Mode,它提供语法高亮以及缩进等基本的编辑支持功能,然后而 Minor Mode 则提供其余的增强性的功能(例如 linum-mode
)。
在 Emacs 中,Major Mode 又分为三种,
text-mode
,用于编辑文本文件special-mode
,特殊模式(很少见)prog-mode
,所有的编程语言的父模式
在每一个模式(mode)中它的名称与各个变量还有函数都是有特定的命名规则,比如所有的模式都被命名为 ModeName-mode
,里面所设置的快捷键则为 ModeName-mode-key-map
,而所有的钩子则会被命名为 ModeName-mode-hook
。
注明:为了保持阅读的完整性,部分第三天的关于默认编辑器优化的内容被移至第四天。
视频地址如下
在这一部分我们首先需要知道的是什么是 features
。在 Emacs 中每一个 feature
都是一个 Elisp 符号,用于代表一个 Lisp 插件(Package)。
当一个插件调用 (provide 'symbol_name)
函数时,Emacs 就会将这个符号加入到 features
的列表中去。你可以在这里读到更多关于 feature 的内容。
接着我们需要弄明白的是 load-file
, load
, require
, autoload
之间的区别。(他们之间区别的链接已经再前面贴过了,你也可以在这里找到之前同样的链接)
简单来说, load-file
用于打开某一个指定的文件,用于当你不想让 Emacs 来去决定加载某个配置文件时( .el
或者 .elc
文件)。
load
搜索 load-path
中的路径并打开第一个所找到的匹配文件名的文件。此方法用于你预先不知道文件路径的时候。
require
加载还未被加载的插件。首先它会查看变量 features
中是否存在所要加载的符号如果不存在则使用上面提到的 load
将其载入。(有点类似于其他编程语言中的 import
)
autoload
用于仅在函数调用时加载文件,使用此方法可以大大节省编辑器的启动时间。
在这一节我们会配置我们的编辑器使其有更好的使用体验。整个过程就如同搭积木一般,将更好的体验建立在已有的功能基础之上。这样的优化使整个过程变得更高效,也更有趣。
下面的代码可以是 Emacs 自动加载外部修改过的文件。
(global-auto-revert-mode 1)
使用下面的代码可以关闭自己生产的保存文件(之前我们已经关闭过了 Emacs 自动生产的备份文件了,现在是关闭自动保存文件)。
(setq auto-save-default nil)
如果你发现你在使用中发现了那些编辑行为与你预期的不相符时,你可以通过搜索引擎去寻找解决方案然后将其加入你的配置中并打造一个真正属于你的神器!
popwin
插件可以自动将光标移动到,新创建的窗口中。使用下面的代码将其启用,
(require 'popwin)
(popwin-mode 1)
也许你并不喜欢听到错误时的“哔哔”的警告提示音,使用下面的代码你可以关闭 Emacs 中的警告音,
(setq ring-bell-function 'ignore)
每一次当 Emacs 需要与你确认某个命令时需要输入 (yes or no)
比较麻烦,所有我们可以使用下面的代码,设置一个别名将其简化为只输入 (y or n)
。
(fset 'yes-or-no-p 'y-or-n-p)
indent-region
可以帮我们重新缩进所选区域的代码,但是每一次都选中十分麻烦。使用下面的代码可以一次重新缩进全部缓冲区的代码。(之后也会介绍更好用的,代码格式美化的插件)
(defun indent-buffer()
(interactive)
(indent-region (point-min) (point-max)))
(defun indent-region-or-buffer()
(interactive)
(save-excursion
(if (region-active-p)
(progn
(indent-region (region-beginning) (region-end))
(message "Indent selected region."))
(progn
(indent-buffer)
(message "Indent buffer.")))))
然后再将其用下面的代码将其绑定为快捷键,第一个 \
用于将紧跟的 \
进行逃脱(escape)。
(global-set-key (kbd "C-M-\\") 'indent-region-or-buffer)
使用下面的代码我们可以开启 abbrev
模式并定义一个缩写表,每当我们输入下面的缩写并以空格结束时,Emacs 就会将其自动展开成为我们所需要的字符串。
(abbrev-mode 1)
(define-abbrev-table 'global-abbrev-table '(
;; Shifu
("8zl" "zilongshanren")
;; Tudi
("8lxy" "lixinyang")
))
上面的缩写前使用的 8
也类似于命名空间的作用,使其不会与我们所常用的字符串冲突。
Company 有时候补全功能并不是非常理想,这时就可以使用 Hippie Expand 来完成补全。Company Mode 补全效果不理想的原因是在不同的区域中会使用不同的后端函数来完成补全,但是当后端补全函数不能被激活时,则补全就不会被激活。
我们可以将下面的代码加入到我们的配置文件中,来增强 Hippie Expand 的功能,
(setq hippie-expand-try-function-list '(try-expand-debbrev
try-expand-debbrev-all-buffers
try-expand-debbrev-from-kill
try-complete-file-name-partially
try-complete-file-name
try-expand-all-abbrevs
try-expand-list
try-expand-line
try-complete-lisp-symbol-partially
try-complete-lisp-symbol))
然后将其绑定为快捷键,使我们可以更方便的使用它。
(global-set-key (kbd "s-/") 'hippie-expand)
Dired Mode 是一个强大的模式它能让我们完成和文件管理相关的所有操作。
使用 C-x d
就可以进入 Dired Mode,这个模式类似于图形界面系统中的资源管理器。你可以在其中查看文件和目录的详细信息,对他们进行各种操作,甚至复制粘贴缓冲区中的内容。下面是一些常用的操作(下面的所有键均需在 Dired Mode 下使用),
+
创建目录g
刷新目录C
拷贝D
删除R
重命名d
标记删除u
取消标记x
执行所有的标记
这里有几点可以优化的地方。第一是删除目录的时候 Emacs 会询问是否递归删除或拷贝,这也有些麻烦我们可以用下面的配置将其设定为默认递归删除目录(出于安全原因的考虑,也许你需要保持此行为。所有文中的配置请务必按需配置)。
(setq dired-recursive-deletes 'always)
(setq dired-recursive-copies 'always)
第二是,每一次你进入一个回车进入一个新的目录中是,一个新的缓冲区就会被建立。这使得我们的缓冲区列表中充满了大量没有实际意义的记录。我们可以使用下面的代码,让 Emacs 重用唯一的一个缓冲区作为 Dired Mode 显示专用缓冲区。
(put 'dired-find-alternate-file 'disabled nil)
;; 主动加载 Dired Mode
;; (require 'dired)
;; (defined-key dired-mode-map (kbd "RET") 'dired-find-alternate-file)
;; 延迟加载
(with-eval-after-load 'dired
(define-key dired-mode-map (kbd "RET") 'dired-find-alternate-file))
使用延迟加载可以使编辑器加载速度有所提升。
启用 dired-x
可以让每一次进入 Dired 模式时,使用新的快捷键 C-x C-j
就可以进入当前文件夹的所在的路径。
(require 'dired-x)
使用 (setq dired-dwin-target 1)
则可以使当一个窗口(frame)中存在两个分屏(window)时,将另一个分屏自动设置成拷贝地址的目标。
最后如果你是 Mac OS X 的用户,可以安装 reveal-in-osx-finder
这个插件(你可以在这里找到它),它可以将任意文件直接在 Finder 中打开。你想安装这个插件,将其添加至第二天的插件列表中即可,下次启动 Emacs 时,它就会自动帮你完成下载。
Org-mode 下的文学编程将颠覆你对于 Emacs 的看法。因为我们也可以使用 Org 来管理 Emacs 的配置文件(笔者和他的师傅其实更倾向于模块管理配置文件)。
你需要将下面的代码放入配置入口文件( init.el
)中,
(package-initialize)
(require 'org-install)
(require 'ob-tangle)
(org-babel-load-file (expand-file-name "org-file-name.org" user-emacs-directory))
之后我们需要做的仅仅只是将所有的配置文件放入 Org 模式中的代码块即可,并使用目录结构来表述你的配置文件再把它保存在与入口文件相同的目录中即可(文件名为 org-file-name.org
)。Emacs 会提取其中的配置并使其生效。这样做的好处是可以使自己和他人更直观的,理解你的配置文件或者代码。
视频地址如下
照例我们先修复一些现在存在的小问题。首先是自动配对的小问题,在 Emacs Lisp 中我们有时候只需要一个 '
但是 Emacs 很好心的帮我们做了补全,但这并不是我们需要的。我们可以通过下面的代码来让使 Emacs Lisp 在 Emacs 中的编辑变得更方便(可以将其添加至 init-default.el
配置文件中)。
(sp-local-pair 'emacs-lisp-mode "'" nil :actions nil)
(sp-local-pair 'lisp-interaction-mode "'" nil :actions nil)
;; 也可以把上面两句合起来
(sp-local-pair '(emacs-lisp-mode lisp-interaction-mode) "'" nil :actions nil)
在添加配置代码后重启 Emacs 使其生效。当然这个方法你也可以运用在其他的各个 Major Mode 中,如果你不想 Emacs 对某些符号进行类似的自动匹配补全。
show-paren-mode
可以使鼠标在括号上是高亮其所匹配的另一半括号,然而我们想要光标在括号内时就高亮包含内容的两个括号,使用下面的代码就可以做到这一点。
(define-advice show-paren-function (:around (fn) fix-show-paren-function)
"Highlight enclosing parens."
(cond ((looking-at-p "\\s(") (funcall fn))
(t (save-excursion
(ignore-errors (backward-up-list))
(funcall fn)))))
Lisp 的宏(Macro)类似于 C++ 中的模板,并可以生产新的代码(你可以在这里找到更多关于宏的讨论)。使用它,我们可以增强某个函数的功能而不去更改这个函数的代码。
还有一个小问题就是解决在不同系统中的换行符,例如在 DOS 系统下的 \r(^M)
换行符,这让我们有时候在 Unix 系统中很是头疼,因为它的存在会使版本控制误以为整行的代码都被修改过而造成不必要的麻烦。(你可以在这里找到更多关于 \r(^M)
的信息)
我们用两种方式来处理这个问题,隐藏这个换行符或者将其删除。首先下面是隐藏的方法,
(defun hidden-dos-eol ()
"Do not show ^M in files containing mixed UNIX and DOS line endings."
(interactive)
(unless buffer-display-table
(setq buffer-display-table (make-display-table)))
(aset buffer-display-table ?\^M []))
使用下面的代码则可以定义函数将此换行符删除,
(defun remove-dos-eol ()
"Replace DOS eolns CR LF with Unix eolns CR"
(interactive)
(goto-char (point-min))
(while (search-forward "\r" nil t) (replace-match "")))
Emacs 自带的 HTML Mode 使用起来并不是那么的方便,而 web-mode 则是一个非常常用也很强大的用于编辑前端代码的 Major Mode(你可以在这里找到更多关于它的信息)。
首先我们需要安装它,照例我们需要将其添加至我们的插件列表中去。
(defvar xinyang/packages '(
;; 你其他的插件在这里
web-mode
) "Default packages")
在安装完成后我们就可以开始配置它了,首先我们需要做的是将所有的 *.html
文件都使用 web-mode 来打开。
(setq auto-mode-alist
(append
'(("\\.js\\'" . js2-mode))
'(("\\.html\\'" . web-mode))
auto-mode-alist))
这样所有的 HTML 代码在 Emacs 中就会之间启用 web-mode 而非默认的 HTML Mode 了。你可以阅读它的文档来学习更多 web-mode 详细的使用方法。
例如使用 M-;
就可以注释当前行代码或选中行的代码。
接下来我们来做更多细节的配置,首先是缩减的大小的设置。因为 web-mode 支持在 HTML 文件中存在多语言,所以我们可以对不同的语言的缩减做出设置。下面的代码用于设置初始的代码缩进,
(defun my-web-mode-indent-setup ()
(setq web-mode-markup-indent-offset 2) ; web-mode, html tag in html file
(setq web-mode-css-indent-offset 2) ; web-mode, css in html file
(setq web-mode-code-indent-offset 2) ; web-mode, js code in html file
)
(add-hook 'web-mode-hook 'my-web-mode-indent-setup)
下面的函数可以用于在两个空格和四个空格之间进行切换,
(defun my-toggle-web-indent ()
(interactive)
;; web development
(if (or (eq major-mode 'js-mode) (eq major-mode 'js2-mode))
(progn
(setq js-indent-level (if (= js-indent-level 2) 4 2))
(setq js2-basic-offset (if (= js2-basic-offset 2) 4 2))))
(if (eq major-mode 'web-mode)
(progn (setq web-mode-markup-indent-offset (if (= web-mode-markup-indent-offset 2) 4 2))
(setq web-mode-css-indent-offset (if (= web-mode-css-indent-offset 2) 4 2))
(setq web-mode-code-indent-offset (if (= web-mode-code-indent-offset 2) 4 2))))
(if (eq major-mode 'css-mode)
(setq css-indent-offset (if (= css-indent-offset 2) 4 2)))
(setq indent-tabs-mode nil))
(global-set-key (kbd "C-c t i") 'my-toggle-web-indent)
js2-refactor 是一个用于重构 JavaScript 的插件,它是一个 Minor Mode,你可以在 GitHub 找到更多关于这个插件的信息。
我们使用刚刚所提到的方法来安装 js2-refactor 插件。
在安装完成后,添加一个钩子(Hook):
(add-hook 'js2-mode-hook #'js2-refactor-mode)
(js2r-add-keybindings-with-prefix "C-c C-m")
我们可以使用 C-c C-m
然后输入功能前缀,例如 em
是 extract-method 的前缀。更多的功能和使用方法也可以在上面给出的链接中找到,所有的前缀也可以在这里找到。
下面的代码用于配置 Occur Mode 使其默认搜索当前被选中的或者在光标下的字符串:
(defun occur-dwim ()
"Call `occur' with a sane default."
(interactive)
(push (if (region-active-p)
(buffer-substring-no-properties
(region-beginning)
(region-end))
(let ((sym (thing-at-point 'symbol)))
(when (stringp sym)
(regexp-quote sym))))
regexp-history)
(call-interactively 'occur))
(global-set-key (kbd "M-s o") 'occur-dwim)
dwim
是按我说的做的缩写(Do what I mean)。
Occur 可以用于显示变量或函数的定义,我们可以通过 popwin 的 customize-group 将定义显示设置为右边而不是默认的底部( customize-group > popwin > Popup Window Position
设置为 right),也可以在这里对其宽度进行调节。
Occur 与普通的搜索模式不同的是,它可以使用 Occur-Edit Mode (在弹出的窗口中按 e
进入编辑模式) 对搜索到的结果进行之间的编辑。
imenu 可以显示当前所有缓冲区的列表,下面的配置可以让其拥有更精确的跳转,
(defun js2-imenu-make-index ()
(interactive)
(save-excursion
;; (setq imenu-generic-expression '((nil "describe\\(\"\\(.+\\)\"" 1)))
(imenu--generic-function '(("describe" "\\s-*describe\\s-*(\\s-*[\"']\\(.+\\)[\"']\\s-*,.*" 1)
("it" "\\s-*it\\s-*(\\s-*[\"']\\(.+\\)[\"']\\s-*,.*" 1)
("test" "\\s-*test\\s-*(\\s-*[\"']\\(.+\\)[\"']\\s-*,.*" 1)
("before" "\\s-*before\\s-*(\\s-*[\"']\\(.+\\)[\"']\\s-*,.*" 1)
("after" "\\s-*after\\s-*(\\s-*[\"']\\(.+\\)[\"']\\s-*,.*" 1)
("Function" "function[ \t]+\\([a-zA-Z0-9_$.]+\\)[ \t]*(" 1)
("Function" "^[ \t]*\\([a-zA-Z0-9_$.]+\\)[ \t]*=[ \t]*function[ \t]*(" 1)
("Function" "^var[ \t]*\\([a-zA-Z0-9_$.]+\\)[ \t]*=[ \t]*function[ \t]*(" 1)
("Function" "^[ \t]*\\([a-zA-Z0-9_$.]+\\)[ \t]*()[ \t]*{" 1)
("Function" "^[ \t]*\\([a-zA-Z0-9_$.]+\\)[ \t]*:[ \t]*function[ \t]*(" 1)
("Task" "[. \t]task([ \t]*['\"]\\([^'\"]+\\)" 1)))))
(add-hook 'js2-mode-hook
(lambda ()
(setq imenu-create-index-function 'js2-imenu-make-index)))
(global-set-key (kbd "M-s i") 'counsel-imenu)
使用同样的方法将 expand-region 添加至我们的插件列表中,重启 Emacs 安装插件。
再为其绑定一个快捷键,
(global-set-key (kbd "C-=") 'er/expand-region)
使用这个插件可以使我们更方便的选中一个区域。(更多使用方法和文档可以在这里找到)
iedit 是一个可以同时编辑多个区域的插件,它类似 Sublime Text 中的多光标编辑。它的 GitHub 仓库在这里。
我们将其绑定快捷键以便更快捷的使用这个模式( C-;
为默认快捷键),
(global-set-key (kbd "M-s e") 'iedit-mode)
我们可以使用 Customized-group 来更改其高亮的背景色,将 highlight
改为 region
。
使用 C-c C-e
可以将 Org-mode 文档导出为你需要的格式,例如 HTML 或者 PDF 文件。你现在看到的这本教程就是由 Org-mode 所导出生成的。
视频地址如下
在开始前我们需要注意的是之前模块化的配置文件 init-keybindings.el
应该放在所有调用模块的最后面,因为也许在设置快捷键时某些函数还未被加载。
我们可以使用下面的配置来在 Company-mode 中使用 C-n
与 C-p
来选择补全项,
(with-eval-after-load 'company
(define-key company-active-map (kbd "M-n") nil)
(define-key company-active-map (kbd "M-p") nil)
(define-key company-active-map (kbd "C-n") #'company-select-next)
(define-key company-active-map (kbd "C-p") #'company-select-previous))
在学习代码片段和语法检查器(Linter)之前,我们先来学习一下如何使用 Org-mode 来做学习笔记和安排工作时间。我们用下面的配置代码来设置一个模板(其中设置了待办事项的优先级还有触发键),
(setq org-capture-templates
'(("t" "Todo" entry (file+headline "~/.emacs.d/gtd.org" "工作安排")
"* TODO [#B] %?\n %i\n"
:empty-lines 1)))
我们也可以为其绑定一个快捷键,
(global-set-key (kbd "C-c r") 'org-capture)
这个功能除了可以记录待办事项还有其他许许多多的功能例如获取将当前浏览器中的 URL(下面的例子只在 Mac OS X 平台有效)。
(defun YOUR_NAME/retrieve-chrome-current-tab-url()
"Get the URL of the active tab of the first window"
(interactive)
(let ((result (do-applescript
(concat
"set frontmostApplication to path to frontmost application\n"
"tell application \"Google Chrome\"\n"
" set theUrl to get URL of active tab of first window\n"
" set theResult to (get theUrl) \n"
"end tell\n"
"activate application (frontmostApplication as text)\n"
"set links to {}\n"
"copy theResult to the end of links\n"
"return links as string\n"))))
(format "%s" (s-chop-suffix "\"" (s-chop-prefix "\"" result)))))
更多有关 Org-capture 的内容可以在这里找到。
Org-pomodoro 是一个番茄时间工作法的插件(更多关于这个工作法的信息可以在这里找到)。它的 GitHub 地址在这里。在 (require 'org-pomodoro)
后可以通过 Customize-group 来对其进行设置,包括不同休息种类的时长。
因为每次保存中文的时候都需要选择解码,我们可以使用下面的配置将文本解码设置默认为 UTF-8,
(set-language-environment "UTF-8")
当 org-mode 不能生效时,我们需要将与 Org 相关的配置放置于 with-eval-after-load
中,
(with-eval-after-load 'org
;; Org 模式相关设定
)
C-x C-q
就可以直接在 Dired Mode 中进行编辑,使用之前学的 iedit-mode 和区域选择就可以直接对多个文件进行重命名编辑了。
全局搜索在我们的编辑工作中是不可缺少的,今天我们介绍的是 ag。它是非常快速的命令行搜索工具,它是 Linux 的所有搜索工具中最快的。
ag > pt > ack > grep
在使用 ag 前我们需要进行安装,下面是 Mac OS X 与 Ubuntu 下的安装方法,
# Mac OS X 通过 Homebrew 安装 brew install the_silver_searcher # Ubuntu 下安装 apt-get install silversearcher-ag
安装好 ag 后我们就可以安装 helm-ag 插件了。(它的 GitHub 仓库地址在这里)在安装完成后可以为其设置快捷键,
(global-set-key (kbd "C-c p s") 'helm-do-ag-project-root)
使用这个插件我们同样可以在缓冲区对搜索到的结果进行直接的修改,这样就可以做到快速的搜索与替换。
语法检查器可以在开发动态语言(Interpreted/Dynamic Programming Language)时极大的提高你的开发效率,它会实时的检查你的代码并将句法错误(Syntax Error)与静态语义(Static Semantic Error)错误进行高亮与提示。
我们在这里使用的例子是 JavaScript 的语法检查器 eslint 它的安装方法可以在这里找到。
在安装好语法检查器后就可以安装 flycheck 的插件了,它的 GitHub 的地址在这里。
使用下面的代码可以将 flycheck-mode 在特定模式下激活(下面的例子就是只有在打开 JavaScript 时才会激活语法检查器),
(add-hook 'js2-mode-hook 'flycheck-mode)
使用 flycheck-verify-setup
可以进行语法检查器的选择。
eslint 检查器的配置也可以使用项目目录下的 .eslintrc
来进行配置,更多配置方法可以在这里找到。
yasnippet
是一个代码块补全的插件(GitHub 地址)。使用下面的配置文件将其在所有的编程语言的模式中激活。
(yas-reload-all)
(add-hook 'prog-mode-hook #'yas-minor-mode)
自定义代码块的方法可以在上面提供的链接中找到。
auto-yasnippet 也是一个非常好用代码块补全插件。安装并未其设置快捷键,
(global-set-key (kbd "H-w") #'aya-create)
(global-set-key (kbd "H-y") #'aya-expand)
简单的使用方法就是使用 ~
来定义模板,然后调用 aya-create
再使用 aya-expand
来使用模板。
视频地址如下,
开始之前我们先将 C-w
来使其可以向后删除一个单词,这样就可以与 Shell 中的快捷键操作同步。
(global-set-key (kbd "C-w") 'backward-kill-word)
如果你不是 Vim 的用户,你可以选择跳过这一天的内容。但是我们强烈建议你花一些时间来学习基本的 Vim 操作,即使 Emacs 是你的最爱 Vim 的快捷键也在一定程度会增加你的编辑效率。基础的 Vim 操作可以在这里学会。
Evil 模式中的 State 就相当与 Vim 中的模式,常用的模式有下面几种(后面对于了相应的 Emacs 中的 State),
- Normal Mode -> Normal State
- Insert Mode -> Insert State
- Visual Mode -> Visual State
- Motion Mode -> Motion State
还有一个 Emacs 中的特殊状态是 Emacs State。
照例我们需要将 Evil 插件添加至我们的插件列表中来完成安装。在重启 Emacs 完成安装后可以添加下面的代码将其激活。
(evil-mode 1)
在激活 Evil 模式后就可以,在 Emacs 中使用 Vim 的快捷键了。有一点需要注意 C-u
在 Emacs 中有特殊的功所(Universal args)以能我们可以通过使用 customize-group
来对 Evil 模式进行修改,将 Evil Want C U Scroll
设置为开启。
下面的代码可以将 insert state map
中的快捷键清空,使其可以回退(Fallback)到 Emacs State 中,这样我们之前的 Emacs State 里面定义的 C-w
等快捷键就不会被 evil insert minor mode state
所覆盖,
(setcdr evil-insert-state-map nil)
(define-key evil-insert-state-map [escape] 'evil-normal-state)
这样你就可以使用 Evil 来在 Emacs 中完成百分之八十作用的快捷键操作了。
完整的 Evil Mode 的 PDF 版本的操作指南可以在这里找到,建议从 Vim 转 Emacs 的用户多次阅读来完整的掌握这个模式的使用方法。
在 Emacs 中使用 Leader Key 可以通过 evil-leader 来实现。你需要做的就是在安装后将其激活即可。
(global-evil-leader-mode)
Leader Key 可以通过 customize-group 来进行设置(Evil Leader/Leader)。因为之后我们会转移至 Spacemacs 所以我们可以将其设置为空格键 SPC
。
在通过下面的配置来设置简单的结合 Leader Key 快捷键组合(我们使用不同的键讲不同的功能分组,例如我们使用 f
键来做关于文件的操作,使用 b
键来做关于缓冲区(Buffer)的操作),
(evil-leader/set-key
"ff" 'find-file
"bb" 'switch-to-buffer
"0" 'select-window-0
"1" 'select-window-1
"2" 'select-window-2
"3" 'select-window-3
"w/" 'split-window-right
"w-" 'split-window-below
":" 'counsel-M-x
"wM" 'delete-other-windows
)
注意上面窗口跳转相关的设置需要 window-numbering 安装后方可生效。
这个插件可以让我们快速的使用 Leader Key 与数字键的组合来在多个窗口之间进行跳转。它的 GitHub 地址可以在这里找到。
下载安装后通过下面的代码可以将其激活,
(window-numbering-mode 1)
Evil-surround 是一个 Vim 上非常常用的插件改写的,使用它可以快速的将选中区域进行匹配的操作,例如选中区域两边同时进行添加或修改括号,引号等操作。
下载安装后使用下面的代码将其激活,
(require 'evil-surround)
(global-evil-surround-mode)
简单的使用方法就是在选中所选区域后,使用 S(
来将选中区域包括在括号之中。如果想将括号改变成 "
可以在选中后使用 cs("
这是一个快速添加与取消注释的插件,它的 GitHub 地址在这里。
使用下面代码可以将其激活,
(evilnc-default-hotkeys)
使用下面的代码将其与 Evil 模式进行绑定,这里我们选择使用 ,/
作为快捷键。
(define-key evil-normal-state-map (kbd ",/") 'evilnc-comment-or-uncomment-lines)
(define-key evil-visual-state-map (kbd ",/") 'evilnc-comment-or-uncomment-lines)
which-key 可以显示当前组合键下所有可以使用的全部组合键的选项。使用这个插件可以很好的解决快捷键太多的问题,我们无需在记忆任何快捷键,而是根据自己的需求使用不同分组的快捷键后再在其中去需找自己需要的功能。
在下载后可以使用下面的代码进行激活,
(which-key-mode 1)
C-c a
中可以根据提示使用 s
来进行关键字所搜。使用 t
则可以进行代办事项的搜索。