Emacs简单入门
星期五, 2月 6, 2026 | 2分钟阅读 | 更新于 星期五, 2月 6, 2026
一个简单的用来入门emacs的笔记
前言
现在人们常说的Emacs包含有多个分支,一般指的是GNU Emacs,Emacs是1975年被开发出来的,被称为神的编辑器。我的笔记用来记述我的学习历程,或许可以对一些想入坑的道友们有所帮助。
Elisp
Lisp是由约翰·麦卡锡在1958年设计出来的编程语言,它是继FORTRAN之后,仍在使用的最古老的编程语言。Lisp有着一个极为庞大的家族,一般称之为Lisp的方言。而Elisp(Emacs Lisp)因其作为Emacs的开发语言而闻名遐迩。在学习Emacs之前,需要掌握一些Elisp的基础,不是很难。
计算
我用计算开启整个elisp的简单教学,因为它较为不同且极易被发现。现在将各种运算符(+、-、*、/ ……)通称为操作符,而将数字称为实参,对于1+1的计算我们可以使用下列的方式:
(+ 1 1)
和以往我们接触的编程语言不同,lisp采用一种称为前序表达式的表达式,它是lisp中极为优秀的设计的最简单演示。比如我们计算1+2+3 ,在日常表示法中得采用完整的书写,而在lisp中,你只需要一个实参就能完成这个计算。甚至在lisp中你可以不添加实参,如下代码
(+) ;;这是合法的操作
它最终会返回0 。
求值
Elisp是一个不那么纯粹的函数式语言,大部分操作符在lisp中都是函数。Lisp的求值需要输入它可以理解的东西,一旦它不能理解,就会报错。在Emacs中,只要遇到括号Elisp就要去执行它,你的有些配置会被当作函数执行,这时一旦Elisp理解不了配置中的东西就会报错(或者你根本就不想让表达式被执行)。为此让Elisp不求值就需要被使用了。在Elisp中使用quote操作符保证原样传递数据,如下代码所示:
(quote (+ 1 1))
;; 它将返回原实参
> (+ 1 1)
但是每次都需要再写一个quote操作符,确实有够烦人的,只需要将quote操作符换为'就可以了,它是quote的缩写:
'(+ 1 1)
;; 仍返回原实参
> (+ 1 1)
赋值与插入
赋值与插入是Elisp中极为常见的操作。最常用的赋值方式就是setq,经它赋值的将是全局变量,如下代码所示:
(setq aiser "hello")
(message aiser) ;; 将返回hello
> hello
;; setq支持一次赋多个值
(setq q 10
Aiser "hello"
a '(1 2))
可以看到,setq操作符并不会对第一个实参求值(即aiser),一旦你使用(setq 'aiser "hello")这样的表达式,将会得到报错qaq。对于局部变量一般使用let和let*
- let的赋值是同时发生的,也就是所谓的平行绑定
(let ((a 1)
(b 2))
;; 只能在局部使用变量
(message "%s %s" a b))
- let*的赋值是顺序绑定,后面的可以用前面的值
(let* ((x 5)
(y (+ x 10))) ;;可以使用前面x的值
(message "y = %d" y)) ;;返回值为15
> 15
Elisp的插入实际上就是把东西塞到光标所在的位置,最常用的操作符就是insert,如下代码所示:
(insert "Hello, Aiser!") ;;当你执行此代码,你的光标后面就会出现Hello, Aiser!
insert主要用在构建emacs的自动化脚本上,知道有这个东西就可以了。
定义函数
Elisp定义函数使用defun宏,它极为简单且高效,基本使用见如下代码:
(defun say-hello () ;;没有参数
"just say hello" ;;你可以输入一些函数文档,它们可以在help mode中被检索
(message "Hello, Aiser!"))
;;调用函数也特别简单,只需要用括号包裹,elisp将执行它
(say-hello)
假设我们想要携带参数
- 对于普通参数的函数的使用:
(defun add-two (x y)
(+ x y))
;; 要使用这个函数需要提供参数
(add-two 3 1)
> 4
- 对于可选参数的函数的使用:
(defun greet (name &optional greeting)
(message "%s, %s!" (or greeting "Hello") name))
;;这个函数中的greeting参数就是可选参数,可以选择提供greeting参数,也可不提供
(greet "Aiser" "Goodday")
(greet "Aiser")
- defun还提供了interactive以让用户在minibuffer输入参数:
(defun my-greet-user (name)
(interactive "sWhats your name: ") ;; s代表string,限制用户的输入
(message "Hello,%s!Welcome Emacs!" name))
执行
progn是Elisp中最基础、最常用的顺序执行特殊形式,它把把多个表达式按顺序执行一遍,最后返回最后一个表达式的值。如果里面什么都没有将会返回nil。progn极为常见,下面列举一部分:
- 在条件语句中执行多条代码
(if (> x 10)
(progn ;;如果不使用progn,这里只能写一条表达式
(message "x bigger!")
(setq x 10)
(beep)) ;;beep是让Emacs响铃
(message "x ok"))
- 将多个表达式变成一个整体传输
(add-hook 'emacs-startup-hook ;;一个常用钩子,在Emacs启动后触发,add-hook用于注册钩子
(lambda () ;;匿名函数,这里不需要名字,没必要用defun
(progn
(message "Emacs have started")
(toggle-frame-maximized) ;;最大化Emacs窗口
(switch-to-buffer "*scratch*"))));;切换到scrath buffer
- 被隐含的progon
;;lambda体隐含progon是极为常见的用法,同样是上面的代码,可以直接省略progon
(add-hook 'emacs-startup-hook
(lambda ()
(message "Emacs have started")
(toggle-frame-maximized)
(switch-to-buffer "*scratch*")))