# 基础 ELisp

因为本科捣鼓过一点 Lisp 相关的东西,这里就放些简单例子,有需要再详细学习。

;; 2 + 2
(+ 2 2)
;; 2 + 3 * 4
(+ 2 (* 3 4))
;; 定义变量
(setq name "username")
(message name) ; -> "username"
;; 定义函数
(defun func ()
  (message "Hello, %s" name))
;; 执行函数
(func) ; -> Hello, username
;; 设置快捷键
(global-set-key (kbd "<f1>") 'func)
;; 使函数可直接被调用可添加 (interactive)
(defun func ()
  (interactive)
  (message "Hello, %s" name))

# 循环

;; 遍历每一个缓冲区(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

;; 下面两行的效果完全相同的
(quote foo)
'foo
(print '(+ 1 1)) ;; -> (+ 1 1)
(print (+ 1 1))  ;; -> 2

# 配置

# 前置知识

Emacs 的配置文件默认保存在 ~/.emacs.d/init.el 文件中。(如果其不存在可自行创建, 配置文件也可保存在 ~/.emacs 文件中,通常 ~/.emacs 的优先级更高)。

注意: 如果希望把配置放在~/.emacs.d/init.el 文件中,那么需要手工删除~/.emacs 文件。

为了便于管理,我们采用模块化的方式来存储我们的配置文件。

一般 ~/.emacs.d/ 目录中的结构如下:

├── auto-save-list # 自动生成的保存数据
├── elpa           # 下载的插件目录
├── init.el        # 我们的配置文件
└── recentf        # 最近访问的文件列表

通常我们只保存配置文件并对其进行版本控制,其他的插件均在第一次使用编辑器时再通过网络重新下载。

由于 Elisp 中并没有命名空间(Namespace),所有的变量均为全局变量,所以其命名方法就变的非常重要。一种简单的命名规则如下:

#自定义变量可以使用自己的名字作为命名方式(可以是变量名或者函数名)
my/XXXX
#模式命名规则
ModeName-mode
#模式内的变量则可以使用
ModeName-VariableName

通常情况使用一个 init.el 文件便足以存储配置的内容,但是当配置内容较多时,使用模块化的设计更加便于管理。我们通常可以将配置文件分为以下几个部分:

init-packages.el        # 插件管理
init-ui.el              # 视觉层配置
init-better-defaults.el # 增强内置功能
init-keybindings.el     # 快捷键绑定
init-org.el             # Org 模式相关的全部设定
custome.el              # 存放使用编辑器接口产生的配置信息

在目录中的结构如下:

├── init.el
└── lisp
    ├── custom.el
    ├── init-better-defaults.el
    ├── init-helper.el
    ├── init-keybindings.el
    ├── init-packages.el
    ├── init-ui.el
    └── init-org.el

此时 init.el 是所有配置内容的入口,我们可以快速定位想要更改的配置的位置。

# Major Mode 与 Minor Mode

Emacs 中存在 Major Mode 与 Minor Mode 两种 Mode。Major Mode 通常定义对于一种文件类型编辑的核心规则,例如语法高亮、缩进、快捷键绑定等。 而 Minor Mode 是除去 Major Mode 所提供的核心功能以外的额外的编辑功能(辅助功能)。例如在下面的配置文件中 tool-bar-modelinum-mode 等均为 Minor Mode。

一种文件类型同时只能存在一种 Major Mode,但是它可以同时激活一种或多种 Minor Mode。如果想知道当前的模式信息,可以使用 C-h m 来显示当前所有开启的全部的 Minor Mode 的信息。

Emacs 中,Major Mode 又分为三种,

  • text-mode ,用于编辑文本文件;
  • special-mode ,特殊模式(很少见);
  • prog-mode ,所有的编程语言的父模式;

在每一个模式(mode)中它的名称与各个变量还有函数都有特定的命名规则,比如所有的模式都被命名为 ModeName-mode ,里面所设置的快捷键则为 ModeName-mode-key-map ,而所有的钩子则会被命名为 ModeName-mode-hook

# 插件包配置

./lisp/init-packages.el 中写入以下内容:

;;  __        __             __   ___
;; |__)  /\  /  ` |__/  /\  / _` |__
;; |    /~~\ \__, |  \ /~~\ \__> |___
;;                      __   ___        ___      ___
;; |\/|  /\  |\ |  /\  / _` |__   |\/| |__  |\ |  |
;; |  | /~~\ | \| /~~\ \__> |___  |  | |___ | \|  |
(when (>= emacs-major-version 24)
    (require 'package)
    (package-initialize)
    (setq package-archives '(("gnu"   . "http://elpa.emacs-china.org/gnu/")
			 ("melpa" . "http://elpa.emacs-china.org/melpa/"))))
;; 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)

init.el 中的入口内容如下:

(package-initialize)
(add-to-list 'load-path "~/.emacs.d/lisp/")
;; Package Management
;; -----------------------------------------------------------------
(require 'init-packages)

从以上内容我们可以简单总结出配置模块化的一个方法。首先将某部分内容的配置写入相关的文件中,然后和在文件的末尾添加 (provide 'module-name) 以使得其在入口文件中能够被调用。而在入口文件中,我们首先添加 (add-to-list 'load-path "~/.emacs.d/lisp/") ,从而使得程序能够找到配置文件的位置,然后写入 (require 'module-name) 便能够引入相关配置。

# 配置推荐

对于 Emacs 初学者而言,陷入到配置文件的细节中往往会打消其学习的热情。这里推荐一个比较成熟的配置。[1]

这是 purcell 开源的一套配置,在 GitHub 上目前有超过 6k 个 star,且目前依旧保持更新。

通过命令:

git clone https://github.com/purcell/emacs.d.git ~/.emacs.d

将仓库克隆下来,然后就可以直接使用了。这里需要对 init.el 做些微修改,更换插件源为 Emacs China 中文社区的镜像。由于配置的内容较多,初次打开 Emacs 时需要等待一段时间下载并应用插件。

如果有自己想要定义的配置,那么可以自己新建一个 .el 文件,按照前文模块化配置的方式加入自己所需的配置。

# 中文乱码问题

Emacs 的 GUI 模式不能很好的支持中文。通过 emacs -nw 可以在终端界面显示 Emacs 的界面,这个和 Vim 的显示方式比较相似,且无中文支持的问题。可以在 .bashrc 之类的文件中通过 alias emacs=emacs -nw 来默认终端方式启动。


  1. Emacs 配置推荐 ↩︎