目录
老骥伏枥,志在千里。(曹操)
光标和选区
| API (C-h f 查看函数,这里仅常用格式) | 说明 | 示例(在括号后 C-x C-e 尝试) |
|---|---|---|
| 获取光标位置 | ||
| (point) | 获取光标位置 | (point) |
| (point-min) | buffer 开始位置 | (point-min) |
| (point-max) | buffer 结束位置 | (point-max) |
| (point-at-bol) | 行首 | (point-at-bol) |
| (point-at-eol) | 行尾 | (point-at-eol) |
| (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 |
字符串
| 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)) |
| 修改列表 | |
|---|---|
| 删除元素(有副作用) | (delete "b" a) ;a变了 |
| 删除元素(无副作用) | (remove "b" a) ;a不变 |
| 头部插入一个 | (push "hi" a) |
| 头部删除一个 | (pop a) |
| 尾部插入一个(有副作用) | (nconc a '("x")) |
| 尾部插入一个(无副作用) | (append a '("x")) |
| 删除尾部多项 | (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)
网络请求
;; 同步网络请求
(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 "%s" (buffer-string))))创建进程
(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 的引号使用
` 和 ' 类似,但 ` 可以和 , 或 @ 配合展开部分内部宏
' 用来表示后面跟着符号(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 函数声明
下列三种写法功能相同
(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) |
编写一个major mode
(define-derived-mode new-plugin-mode text-mode "new-plugin"
(interactive)
(kill-all-local-variables) ; 删除 buffer 下所有的局部变量, 避免其他 mode 的干扰
(setq major-mode 'new-plugin-mode) ; 设置当前的 mode 为 new-plugin-mode
(setq mode-name "new-plugin") ; 设置 mode 的名称
(new-plugin-highlight-keywords) ; 根据正则表达式提供语法高亮
(use-local-map new-plugin-mode-map) ; 加载 mode 对应的快捷键
(run-hooks 'new-plugin-mode-hook)) ; 加载 mode 对应的 hook, 注意 new-plugin-mode-hook 会自动生成
(defvar new-plugin-mode-map
(let ((map (make-sparse-keymap)))
(define-key map (kbd "M-m") #'new-plugin-function) ; 绑定 new-plugin-function 函数到快捷键 Alt-m 上
map)
"Keymap used by `new-plugin-mode'.")
(defun new-plugin-highlight-keywords ()
"Highlight keywords."
;; Add keywords for highlight.
(font-lock-add-keywords
nil
'(
("regexp-string" . 'font-lock-constant-face) ; 当 buffer 内容匹配正则, 就会自动按照 font-lock-constant-face 提供颜色高亮
))
;; Enable font lock.
(font-lock-mode 1)) ; 开启语法高亮