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。对于局部变量一般使用letlet*

  • 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极为常见,下面列举一部分:

  1. 在条件语句中执行多条代码
(if (> x 10)
    (progn                  ;;如果不使用progn,这里只能写一条表达式
      (message "x bigger!")
      (setq x 10)
      (beep)) ;;beep是让Emacs响铃
  (message "x ok"))
  1. 将多个表达式变成一个整体传输
(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
  1. 被隐含的progon
;;lambda体隐含progon是极为常见的用法,同样是上面的代码,可以直接省略progon
(add-hook 'emacs-startup-hook
          (lambda ()
            (message "Emacs have started")
            (toggle-frame-maximized)
            (switch-to-buffer "*scratch*")))

© 2024 - 2026 Aiser's Blog

欢迎来到我的博客!

Me

我的名字是Aiser,这是我的博客