Elisp

GNU Emacs原生库

C库

作用

editfns

文本编辑内建函数

src/editfns.c

eval

执行代码

src/eval.c

search

搜索逻辑

src/search.c

fns

通用函数

src/fn.c

alloc

堆分配

src/alloc.c

data

数据类型的操作

src/data.c

syntax

语法表解析

src/syntax.c

buffer

缓冲区操作

src/buffer.c

elisp库

作用

subr

最底层最重要的公共函数库

相当于std

lisp/subr.el

subr-x

subr的扩展

lisp/emacs-lisp/subr-x.el

seq

序列的接口

类似于rust的slice vec array

map

各种map 如 hash-table等

cl-lib

common-lisp的拓展

pcase

模式匹配

rust的match

nadvice

advice系统 动态修改函数

eieio

OO系统

json

json解析

url

http解析

project

官方project管理

xref

统一跳转接口

eglot什么的几乎都用这个

imenu

代码索引

compile

flymake

实时诊断

treesit

tree-sitter官方接口

syntax

语法分析

lisp/emacs-lisp/syntax.el

库介绍

buffer

generate-new-buffer-name

生成一个不会与现有buffer重名的buffer名称.

用于创建唯一buffer时调用

(generate-new-buffer-name name &optional IGNORE)

  • NAME: 希望使用的buffer名称

  • IGNORE: 一个buffer对象.若存在这个buffer 则在检测重名时忽略

示例

(generate-new-buffer-name "foo")

若不存在foo的缓冲区 则返回foo 存在则返回foo<2>

set-buffer

切换操作到BUFFER-OR-NAME buffer. 以便后续的insert等操作. 注意 emacs不会切换那个buffer,仅会给elisp用.

(set-buffer BUFFER-OR-NAME)

editfns

save-restriction

临时修改当前buffer的可见范围 执行BODY 然后恢复

(save-restriction &rest BODY)

save-excursion

(save-excursion &rest BODY): 临时移动编辑器状态 执行BODY中的代码 然后无条件恢复.

goto-char

(goto-char POSITION): 设置光标到POSITION 例如 buffer的开始是(point-min),结尾是(point-max) .

返回POSITION

point-min

返回缓冲区的开头

(point-min)

point-max

返回缓冲区的结尾

(point-max)

char-after

返回POS处的字符 默认为POINT

(char-after &optional POS)

eval

let

(let VARLIST BODY): 设置一些变量VARLIST 然后执行BODY

let*

设置变量 然后执行BODY. 与let的区别是 设置的变量可以互相赋值.

(let VARLIST BODY)

while

(while TEST BODY): 若TEST != nil 则执行BODY

示例

(while () ())

and

(and CONDITIONS): 对CONDITIONS逐个AND

示例

(and t t nil)
(and t t t)
(and t nil t)

catch

执行BODY 允许非局部退出 有点像rust的'label 其中label就是TAG

(catch TAG BODY...)

if

如果CONDnil 执行THEN 否则 ELSE

(if COND THEN ELSE)

unwind-protect

无论BODYFORM是正常结束 抛出错误 还是非局部跳转 UNWINDFORMS都会执行 同时返回 BODYFORM的返回值

(unwind-protect BODYFORM UNWINDFORMS...)

progn

合并执行BODY1 BODY1 返回最后一个值

(progn BODY...)

subr

not

(not OBJECT): 取反

示例

(not nil)

dotimes

循环固定次数 类似rust的 for i in 0..len.

(dotimes (VAR COUNT [RESULT]) BODY...)

when

COND为非nil 执行BODY 否则返回nil

(when COND &reset BODY)

when-let

SPEC中绑定变量 并条件执行BODY

(when-let SPEC &rest BODY)

derived-mode-p

判断当前Major模式是否是某个Mode的子Mode

(derived-mode-p &reset MODES)

if-let

绑定变量到SPEC 然后执行THEN

(if-let SPEC THEN &rest ELSE)

with-current-buffer

临时切换到BUFFER-OR-NAME执行BODY 然后回到当前buffer

(with-current-buffer BUFFER-OR-NAME &reset BODY)

fns

length

返回向量 列表或者序列的长度

(length SEQUENCE)

sort

稳定排序序列

(sort SEQ &key KEY LESSP REVERSE IN-PLACE)

  • SEQ: 排序的序列

  • &key: 标记后面的参数为按照名字传

  • KEY: 用于比较的键值

  • LESSP: 决定如何比较

  • REVERSE: 是否倒序

  • IN-PLACE: 是否原址

示例

(let ((list [0 1 3 2 4 4 0 2])) 
	(sort list)
)

string-distance

返回STRING1STRING2 之间的Levenshetin距离

Levenshetin距离指的是: 将STRING1变换为STRING2所需进行的 删除 插入 替换 总次数

(string-distance STRING1 STRING2 BYTECOMPARE)

  • 若BYTECOMPARE为nil或忽略 则以字符为单位计算距离 否则以字节

alloc

make-vector

创建向量 长度length 初始化为init

(make-vector length init)

data

eq

若两个对象是相同的Lisp对象 则返回t

(eq OBJ1 OBJ2)

aset

设置数组ARRAY 索引IDX上的值为NEWELT

(aset ARRAY IDX NEWELT)

aref

获取数组ARRAY 索引IDX上的值

(aref ARRAY IDX)

car

获取LIST的car

car代表cons-cell的car

(car LIST)

cdr

获取LIST的cdr

(cdr LIST)

syntax.c

parse-partial-sexp

从FROM到TO扫描lisp代码返回一个状态列表

(parse-partial-sexp FROM TO &optional TARGETDEPTH STOPBEFORE OLDSTATE COMMENTSTOP)

  • FROM: 开始解析的位置

  • TO: 解析到的位置

  • TARGETDEPTH: 最大目标括号深度

  • STOPBEFORE: 遇到一个sexp开始字符时停止

  • OLDSTATE: 从已有parser状态继续解析

  • COMMENTSTOP: 遇到commet/string停止

状态列表具有12个字段

  • 0 括号深度

  • 1 当前所在最内层lisp的开括号位置

  • 2 最近一个完整sexp结束的位置

  • 3 当前是否在字符串里

  • 4 当前是不是在注释里

  • 5 是否读到的是quote

  • 6 扫描过程中遇到的最低括号深度

  • 7 注释的类型 比如行注释 块注释

  • 8 当前comment或者string开始的位置

  • 9 当前打开的括号的位置

  • 10 处理两个字符组成的syntax 比如//这种 只扫到第一个/ 还没扫到第二个/

syntax.el

syntax-ppss

返回POS处 或者 point处的语法解析状态 同时会缓存这个状态 返回一个和parse-partial-sexp一样的列表.

注意 在syntax-ppss中的parse-partial-sexp列表 不保证2和6字段的正确性

(syntax-ppss &optional POS)

Lisp语法

函数

(defun square (x)
	(* x x)
)

语法

这里会列举出elisp的语法和形式

注释

语法

形式

普通注释

; text

注释的特殊标记

;####

文档注释标记类似JAVADOC

;@param

声明模式 告诉emacs使用何种主模式

;-- mode: 模式名 --

声明编码

; -- coding: utf-8 --

参数

语法

形式

声明参数

&optional arg1

声明参数的特殊语法

参数

行为

&optional

代表此参数可选 可以传入或不传入(只能使用一次 且置于必选参数后,&rest之前)

&rest

将后面的参数合并为列表

&key

将后面的参数按名字传

注释

特殊标记

注释

作用

;;;###autoload

用于实现自动加载 类似于lazy_init 只在使用时加载

原始函数

这些函数就像rust的原始类型一般 基本由C语言实现 内置于emacs中

integerp

这是一个C语言的内置函数 返回此函数是否为整数

(integerp OBJECT)

copy-marker

返回一个与 MARKER 指向相同位置的新标记。

这个标记会自动跟踪位置的更改

(copy-marker &optional MARKER TYPE)

point

返回现在光标位置

(point)

downcase

转换为小写

(downcase OBJ)

buffer-substring

返回start和end之间的字符串

(buffer-substring START END)

looking-at

如果光标后的字符与正则表达式 REGEXP 匹配 则返回 t.

(looking-at REGEXP &optional INHIBIT-MODIFY)

经常与match-end match-beginning match-data连用

match-end

返回上一次搜索所匹配文本的结束位置

(match-end SUBEXP)

SUBEXP是正则表达式的子表达式的序号

若SUBEXP=0 则返回整个正则表达式或整个字符串所匹配文本的结束位置

assoc

查询关联列表

(assoc KEY ALIST &optional TESTFN)

TESTFN是比较比较器 默认为equal

内置函数

这些函数也基本由c语言实现 内置于emacs中

interactive

interactive用于定义函数如何与用户交互(例如获取参数的方式) 并使函数可用用M-x调用

interactive是内置函数 由c语言编写

(interactive &optional ARG-DESCRIPTOR &rest MODES)

其中ARG-DESCRIPTOR是可选的参数描述符

通常,interactive的参数是一个包含代码字母的字符串,后面可选择性地跟一个提示信息。(有些代码字母不需要通过输入 / 输出来获取参数,因此也不需要提示信息。)要向命令传递多个参数,可以将各个字符串连接起来,并用换行符分隔它们。

可用的代码字母有:

a -- 函数名:具有函数定义的符号。
b -- 已存在缓冲区的名称。
B -- 缓冲区名称,可能不存在。
c -- 字符(不使用输入法)。
C -- 命令名:具有交互式函数定义的符号。
d -- 作为数字的点位置值。不进行输入 / 输出。
D -- 目录名。
e -- 调用此命令的参数化事件(即列表形式的事件)。
如果多次使用,第 N 个 'e' 返回第 N 个参数化事件。
这会跳过整数或符号形式的事件。
f -- 已存在的文件名。
F -- 可能不存在的文件名。
G -- 可能不存在的文件名,默认为仅目录名。
i -- 忽略,即始终为 nil。不进行输入 / 输出。
k -- 键序列(如有需要,将最后一个事件转为小写以获取定义)。
K -- 要重新定义的键序列(不将最后一个事件转为小写)。
m -- 作为数字的标记值。不进行输入 / 输出。
M -- 任意字符串。继承当前输入法。
n -- 通过迷你缓冲区读取的数字。
N -- 数字前缀参数,如果没有,则类似代码 'n' 的行为。
p -- 转换为数字的前缀参数。不进行输入 / 输出。
P -- 原始形式的前缀参数。不进行输入 / 输出。
r -- 区域:作为两个数字参数的点和标记,从小到大排列。不进行输入 / 输出。
s -- 任意字符串。不继承当前输入法。
S -- 任意符号。
U -- 被之前的 k 或 K 参数丢弃的鼠标释放事件。
v -- 变量名:是 'custom-variable-p' 的符号。
x -- 读取但不求值的 Lisp 表达式。
X -- 读取并求值的 Lisp 表达式。
z -- 编码系统。
Z -- 编码系统,如果没有前缀参数则为 nil。

此外,如果字符串以'*' 开头,则当缓冲区为只读时会发出错误信号。

如果字符串以 '@' 开头,并且用于调用命令的键序列包含任何鼠标事件,则在运行命令之前会选中与这些事件中的第一个相关联的窗口。

如果字符串以 '^' 开头且'shift-select-mode' 为非 nil,Emacs 会首先调用函数 'handle-shift-selection'。

你可以同时使用 '@'、'' 和 '^'。它们会按照出现的顺序处理,在读取任何参数之前。

如果存在 MODES,它应该是一个或多个此命令适用的模式名称(符号)。这样,'M-x TAB' 就能在当前缓冲区的模式与列表不匹配时,将此命令从补全候选列表中排除。

基于此信息排除哪些命令由 'read-extended-command-predicate' 的值控制,详见其说明。

数据结构

cons-cell

alist

关联列表 存储键值对

(setq alist '((name . "Alice") (age . 30) (city . "Beijing")))
(assoc 'age alist)

常用

play-sound

播放声音

SOUND 是一种形式为 (sound KEYWORD VALUE...) 的列表。

支持以下关键字:

:file FILE - 从文件 FILE 中读取声音数据。如果 FILE 不是绝对文件名,则会在 data-directory(数据目录)中搜索该文件。

:data DATA - 从字符串 DATA 中读取声音数据。

注意:必须且只能指定 :file 或 :data 中的一项。

:volume VOL - 将音量设置为 VOL。VOL 必须是 0..100 范围内的整数,或 0..1.0 范围内的浮点数。如果未指定,则不更改声音设备的音量设置。

:device DEVICE - 在设备 DEVICE 上播放声音。如果未指定,则使用与系统相关的默认设备名称。

注意:目前 Windows 系统不支持 :data 和 :device 关键字。

示例

计算 \(1! + 2! + .. + n!\)

这里使用类似霍纳规则的算法

\[ a_0 + a_0 * a_1 + a_0 * a_1 * a_2 = a_0(1 + a_1(1+ a_2)) \]

所以使用递归解决

(defun f (x y)
  (if (= x y)
      y
    (* x (+ 1 (f (+ x 1) y)))))