目录

Emacs Lisp 常见函数

C-h f 查看函数,这里仅常用格式

光标和选区

API 说明 示例(在括号后 C-x C-e 尝试)
获取光标位置
(point) 获取光标位置 (point)
(point-min) buffer 开始位置 (point-min)
(point-max) buffer 结束位置 (point-max)
(region-beginning) 选区开始位置 (region-beginning)
(region-end) 选区结束位置 (regin-end)
(push-mark &optional LOCATION) 设定选区,光标到指定位置 (push-mark 10000)
(kill-region BEGIN END) 剪切选区 (kill-region 1 point))
(use-region-p) 是否有活动选区 (use-region-p)
mark-active 变量,是否有活动选区 (高亮的选区) (print mark-active)
光标位置获取文本
(buffer-substring-no-properties START END) 获取纯文本 (buffer-substring-no-properties 10 100)
(char-before) 光标之前字符 (char-before)
(char-after) 光标之后字符 (char-after)
(current-word) 光标下的单词 (current-word)
(thing-at-point THING) 光标下的元素 (按参数指定) (thing-at-point ‘word)
移动光标
(goto-char POSTION) 移动光标到给定位置 (goto-char 800)
(forward-char &optional N) 向之后移动光标, 默认移动 1 个字符 (forward-char 3)
(backward-char &optional N) 向之前移动光标,默认移动 1 个字符 (backward-char 3)
(beginning-of-line &optional N) 移动光标到行首,默认本行,或之前 N-1 行首 (beginning-of-line)
(end-of-line &optional N) 移动光标到行尾,默认本行,或之后 N-1 行首 (end-of-line 2)
(next-line) 移动光标垂直向下一行 (next-line)
(previous-line) 移动光标垂直向上一行 (previous-line)
(forward-line &optional N) 向之后移动光标 N 行,停在行首 (forward-line 2)
(line-move-visual N) 向之后垂直移动光标 N 行 (line-move-visual 2)
搜索并移动光标
(search-forward STRING) 向之后搜索,光标停在匹配文本后 (search-forward “sea”)
(search-backward STRING) 向之前搜索,光标停在匹配文本前 (search-backward “sea”)
(re-search-forward REGEXP) 用正则向之后搜索,光标停在匹配文本后 (re-search-forward “\n”)
(re-search-backward REGEXP) 用正则向之前搜索,光标停在匹配文本前 (re-search-backward “\n”)
(skip-chars-forward STRING) 往之后移动光标,跳过给定字符集合,停在匹配之后 (skip-chars-forward “\n\t\s”)
(skip-chars-forward STRING) 往之前移动光标,跳过给定字符集合,停在匹配之前 (skip-chars-backward “abc”)
保存状态
(save-excursion &rest BODY) 执行 BODY 后恢复光标原位置 (save-excursion (insert “test”))
(save-restriction &rest BODY) 执行 BODY 后,保存恢复用户操作 (save-restriction (narrow-to-region 1 100) (insert “$$$”))

文本编辑

API 说明 示例
插入文本
(insert &rest ARGS) 光标下插入文本 (insert “hello” “weifeng”)
删除文本
(delete-char N) 删除 N 个字符 (delete-char 3)
(delete-region START END) 删除给定选区 (delete-region 100 105)
(erase-buffer) 清空 buffer 内容 (erase-buffer)
(delete-and-extract-region START END) 删除给定选区,返回被删除内容 (delete-and-extract-region 100 105)
剪切、复制、粘贴、替换
(kill-region BEG END) 剪切文本到 kill-ring (粘贴环,可连续取) (kill-region 1 100)
(copy-region-as-kill BEG END) 拷贝到 kill-ring (copy-region-as-kill 1 100)
(kill-new STRING) 将文本放入 kill-ring (kill-new “fengweifeng.com”)
(yank) 粘贴到光标处 (yank)
(replace-match STRING) 先查找,在替换成字符串 (while (search-forward “AAA” nil t) (replace-match “BBB”))

数字

说明 demo
二进制 #b100 4

字符串 string

API 说明 示例
(length STRING) 字符串长度 (length “abcd”)
(substring STRING START END) 取子字符串 (substring “abcd” 1 3)
(concat &rest SEQ ) 合并多个字符串 (concat “abc” “def” “xyz”)
正则查找、替换
(string-match REGEXP STRING) 查找匹配位置 (string-match “\\([A-Z]+\) :\\ ([0-9]+\\) " “~TEL:123456”)
(match-string NUM &optional STRING) 返回上次正则匹配第 NUM 项 (match-string 1 “~TEL:123456”)
(replace-regexp-in-string REGEXP REPLACE STRING) 替换 (replace-regexp-in-string “[0-9]” “*” “pass:123”)
(split-string STRING &optional) 切分字符串,默认以空白字符分隔 (split-string “hi-wei-feng” “-”)
字符和数字转换
(string-to-number STRING) 字符串转数字 (string-to-number “123”)
(number-to-string NUM) 数字转字符串 (number-to-string 123)
(format STRING &rest OBJECTS) 使用格式化 (format “%d” 123)
大小写 (require ’s)
(s-upcase str) 变大写 (s-upcase “feng”)
(s-downcase str) 变小写 (s-downcase “FENG”)
使用 subr-x 库字符串函数:(require ‘subr-x)
(string-blank-p STRING) 是否空白字符串 (string-blank-p " “)
(string-empty-p STRING) 是否空字符串 (string-empty-p " “)
(string-join STRINGS &optional SEP) 合并字符串 (string-join ‘(“a” “b” “c”) “-”)
(string-reverse STRING) 反转字符串 (string-reverse “abc”)
(string-trim STRING) 两头去空白 (string-trim " abc “)
(string-trim-left STRING) 去除左侧空白 (string-trim-left " abc “)
(string-trim-right STRING) 去除右侧空白 (string-trim-right " abc “)
(string-remove-prefix PREFIX STRING) 去除头部 (string-remove-prefix “hi” “hifeng”)
(string-remove-suffix SUFFIX STRING) 去除尾部 (string-remove-suffix “wf” “fengwf”)

Buffer

API 说明 示例
属性
(buffer-name &optional BUFFER) 获取 buffer 名字 (buffer-name)
(buffer-file-name &optional BUFFER) 获取 buffer 文件名 (buffer-file-name)
(buffer-string) 获取 buffer 全部内容 (buffer-string)
(buffer-size) buffer 字符数
(buffer-hash) buffer hash 值 (buffer-hash)
(bufferp) 是否是 buffer (list (bufferp “scratch”) (bufferp (get-buffer “scratch”)))
(buffer-modified-p) buffer 是否被修改过 (buffer-modified-p)
(buffer-narrowed-p) buffer 是否被局部显示
(buffer-list) buffer 列表 (length (buffer-list))
操作
(with-current-buffer BUFFER-OR-NAME &rest BODY) 设置要操作的 buffer (with-current-buffer (current-buffer) (insert “ABC”))
(set-buffer BUFFER-OR-NAME) 设置要操作的 buffer (with-current-buffer (current-buffer) (set-buffer “Messages”))
(with-temp-buffer &rest BODY) 创建临时 buffer (with-temp-buffer (insert “ABC”) (message (buffer-string)))
(generate-new-buffer NAME) 创建带名称的 buffer (generate-new-buffer “feng”)
(get-buffer BUFFER-OR-NAME) 获取已有 buffer (get-buffer “scratch”)
(get-buffer-create BUFFER-OR-NAME) 获取已有或创建 buffer (setq buffer (get-buffer-create “feng”))
(kill-buffer &optional BUFFER-OR-NAME) 关闭当前或指定 buffer (kill-buffer “feng”)
(buffer-live-p BUFFER) buffer 是否已被关闭 (buffer-live-p (get-buffer-create “feng”))
Demo 示例
(buffer-substring-no-properties (region-beginning) (region-end)) 选区文本
(buffer-substring-no-properties (line-beginning-position) (line-end-position)) 当前行文本
(thing-at-point ‘filename) 光标下文件名
(mapcar #’thing-at-point ‘(symbol list sexp defun filename url email uuid word sentence whitespace line number page) ) 光标下各种元素

文件操作

API 说明 示例
打开、新建、保存文件
(find-file FILENAME) 打开或新建文件 (find-file “~/test.txt”)
(save-buffer) 保存文件 (save-buffer)
(write-region START END FILENAME) 保存部分区域到文件 (write-region (point-min) (point-max) “~/test.txt”)
(write-file FILENAME) 另存为 (write-file “~/test2.txt”)
(append-to-file START END FILENAME) 追加文件 (append-to-file 100 200 “~/test.txt”)
文件操作
(rename-file FILENAME NEW-FILENAME) 文件改名 (rename-file “~/test.txt” “~/test2.txt”)
(copy-file FILENAME NEW-FILENAME) 复制文件 (copy-file “~/test2.txt” “~/test.txt”)
(delete-file FILENAME) 删除文件 (delete-file “~/test.txt”)
(set-file-modes) 设置文件属性 (set-file-modes “~/test.txt” #o755)
(file-modes FILENAME) 读取文件属性 (file-modes “~/test.txt”)
(file-exists-p FILENAME) 文件是否存在 (file-exists-p “~/test.txt”)
(file-readable-p FILENAME) 文件是否可读
(file-writable-p FILENAME) 文件是否可写
(file-executable-p FILENAME) 文件是否可运行
目录操作
(directory-files DIR &optional FULL MATCH) 获取目录文件列表,可筛选 (directory-files “~/” t “\\.txt”)
(make-directory DIR) 创建目录 (make-directory “~/xxx”)
(delete-directory DIR &optional RECURSIVE TRASH) 删除空目录,可选递归删除、进垃圾桶 (delete-directory “~/xxx”)
(copy-directory DIR NEW-NAME) 拷贝目录 (copy-directory “~/xxx” “~/yyy”)
路径
(file-name-directory FILENAME) 获取目录路径 (file-name-directory “~/xxx”)
(file-name-nondirectory FILENAME) 获取文件名 (file-name-nondirectory “~/xxx”)
(file-name-extension FILENAME) 获取后缀名 (file-name-extension “~/test.txt”)
(file-name-sans-extension FILENAME) 获取不含后缀名的路径 (file-name-sans-extension “~/test.txt”)
(file-relative-name FILENAME &optional DIR) 获取相对当前路径的路径 (file-relative-name “~/test.txt”)
(expand-file-name NAME &optional DIR) 基于路径展开文件路径 (expand-file-name “test.txt”)
default-directory 变量,当前路径 (print default-directory)

让用户输入

API 说明 demo
(read-file-name PROMPT) 让用户输入文件 (read-file-name “输入文件地址: “)
(read-directory-name PROMPT) 让用户输入目录 (read-directory-name “输入文件夹: “)
(read-string PROMPT) 让用户输入文本 (read-string “输入名称:”)
(read-regexp PROMPT) 让用户输入正则 (read-regexp “输入正则:”)
(read-number PROMPT) 让用户输入数字 (read-number “输入数字:”)
(ido-completing-read PROMPT LIST) 让用户选择一项 (ido-completing-read “选择:” ‘(“A” “B” “C”))
(y-or-n-p PROMPT) 让用户确认是/否 (y-or-n-p “请确认?”)

list、vector、sequence

List、Vector、字符串都被称为 Sequence。 ”seq-“开头的函数可用于处理这些类型变量。|

  • list 长度可变,可头部插入,或从头部删除,访问元素速度得看和头部距离,如长度为 1000,则访问第 900 个元素则很慢;|

  • vector 长度固定,访问任一元素耗时一样,都很快;|

List 说明 Demo
列表变量 (setq a ‘(“a” “b” “c” “d”))
创建列表 (list 1 2 3)
按个数创建并设置初值 (make-list 4 0)
创建序列 (number-sequence 5 10)
打印列表 (message “%S” a)
空列表等于 nil (eq ‘() nil)
获取元素
获取首项 (car a)
获取最后一项 (car (last a))
获取指定序号项 (nth 2 a)
列表长度 (length a)
获取子列表
从第二个到最后 (cdr a)
指定序号到最后 (nthcdr 2 a)
去除尾部多项 (butlast a 2)
头部合并 (不修改原值) (cons “Hi” a)
遍历操作返回结果 (mapcar ‘upcase a)
遍历操作返回原列表 (mapc ‘print a)
排序 (seq-sort #’< ‘(1 3 2))
修改列表
删除元素(无副作用) (remove “b” a) ;a 变了
删除元素(有副作用) (delete “b” a) ;a 不变
头部插入一个 (push “hi” a)
头部删除一个 (pop a)
删除尾部多项 (nbutlast a 2)
替换首项 (setcar a “A”)
替换除首项的后面 (setcdr a ‘(“B” “C”))
指定序号设置 (setf (elt a 0) “A”)
Vector 说明 示例
设置变量 (setq v (vector 1 2 3))
按个数创建并设置初值 (make-vector 5 0)
创建,内部不展开 [a b c]
将元素统一修改 (fillarray v 4)
类型判断(Vector 属于 Array) (arrayp v)
获取
获取元素 (性能好) (aref v 2)
获取元素 (适用 Vector 和 List) (elt v 2)
设置
指定序号设置 (aset v 0 “a”)
转成 List (append v nil)

关联列表 alist 和 Hash Table

  • alist 表示方法: (cons key value) 也可写作 (key . value), key 可以重复,有序
  • Hash Table,key 唯一,无序,量大时,随机读取性能更高;
说明 示例
取值 (alist-get ‘y ‘((x . 1) (y . 2)))

属性列表 plist

plist 表示方法:’(key1 val1 key2 val2), key 不能重复,长度为偶数。key 类型只能为 lisp symbol,value 可为任意类型;

说明 示例
取值(eq 比较键值) (plist-get ‘(x 1 y 2) ‘x)
取值(equal 比较键值) (lax-plist-get ‘(“foo” 1 “bar” 2) “bar”)
修改值(eq 比较),返回新 plist (plist-put ‘(x 1 y 2) ‘x 3)
修改值(equal 比较) (let ((p ‘(“a” 1 “b” 2))) (setq p (lax-plist-put p “b” 200)))
获取查到的键到尾部列表 (plist-member ‘(x 1 y 2 z 3) ‘y)

网络请求

1
2
3
4
5
6
7
8
9
  ;; 同步网络请求
(with-current-buffer
(url-retrieve-synchronously "http://www.baidu.com")
(let ((data (buffer-string)))
(message "%s" data)))

;; 异步网络请求
(url-retrieve "http://www.baidu.com"
(lambda(status) (message (buffer-string))))

创建进程

1
2
3
4
5
6
7
8
(with-current-buffer (get-buffer-create "*baidu.com*")
(erase-buffer)
(make-process
:name "baidu"
:buffer (current-buffer)
:command '("curl" "-s" "www.baidu.com")
:connection-type 'pipe)
(switch-to-buffer-other-window "*baidu.com*"))

#<buffer *baidu.com*>

Lisp 的引号使用

` 和 ’ 类似,但 ` 可以和 , 或 @ 配合展开部分内部宏

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
' 用来表示后面跟着符号(symbol)
参考 https://emacs-china.org/t/namespace/8402
` 其实是一个宏 backquote 的别名 (backquote.el)
(defalias '\` (symbol-function 'backquote))
比如 `(1 2 3) 其实就是 (backquote (1 2 3))

For example:

b              => (ba bb bc)		; assume b has this value
`(a b c)       => (a b c)		; backquote acts like quote
`(a ,b c)      => (a (ba bb bc) c)	; insert the value of b
`(a ,@b c)     => (a ba bb bc c)	; splice in the value of b

Vectors work just like lists.  Nested backquotes are permitted.

(apply #'+ `(1 ,@(number-sequence 2 4) 5)) `(a (+ 3 4) ,(+ 3 4))

#‘foo 函数声明

下列三种写法功能相同

1
2
3
(lambda (x) (* x x))
(function (lambda (x) (* x x)))
#'(lambda (x) (* x x))

lambda (x) (* x x)

判断“相等”

说明 函数示例
数字比较 (= 1 1)
字符串比较 (equal “abc” “abc”)
数组比较(比较内部元素) (equal [1 2 3] [1 2 3])
列表比较(比较内部元素) (equal ‘(a b c) ‘(a b c))
对象比较(比较地址) (eq ‘a ‘a)