Emacs Lisp 编程总结
文章目录
lisp介绍
Lisp(历史上拼写为LISP)是具有悠久历史的计算机编程语言家族,有独特和完全括号的前缀符号表示法。起源于公元1958年,是现今第二悠久而仍广泛使用的高端编程语言。只有FORTRAN编程语言比它更早一年。Lisp编程语族已经演变出许多种方言。现代最著名的通用编程语种是Clojure、Common Lisp和Scheme。
Lisp最初创建时受到阿隆佐·邱奇的lambda演算的影响,用来作为计算机程序实用的数学表达。因为是早期的高端编程语言之一,它很快成为人工智能研究中最受欢迎的编程语言。在计算机科学领域,Lisp开创了许多先驱概念,包括:树结构、自动存储器管理、动态类型、条件表达式、高端函数、递归、自主(self-hosting)编译器、读取﹣求值﹣输出循环(英语:Read-Eval-Print Loop,REPL)。
“LISP"名称源自“列表处理器”(英语:LISt Processor)的缩写。列表是Lisp的主要数据结构之一,Lisp编程代码也同样由列表组成。因此,Lisp程序可以把源代码当作数据结构进行操作,而使用其中的宏系统,开发人员可将自己定义的新语法或领域专用的语言,嵌入在Lisp编程中。
代码和数据的可互换性为Lisp提供了立即可识别的语法。所有的Lisp程序代码都写为S-表达式或以括号表示的列表。函数调用或语义形式也同样写成列表,首先是函数或操作符的名称,然后接着是一或多个参数:例如,取三个参数的函数f即为(f arg1 arg2 arg3)。
Lisp语言的主要现代版本包括Common Lisp, Scheme,Racket以及Clojure。1980年代盖伊·史提尔二世编写了Common Lisp试图进行标准化,这个标准被大多数解释器和编译器所接受。还有一种是编辑器Emacs所派生出来的Emacs Lisp(而Emacs正是用Lisp作为扩展语言进行功能扩展)非常流行,并创建了自己的标准。
Elisp
概览
运行emacs-lisp的几种方式
key | command | description |
---|---|---|
`C-x C-e` | `eval-last-sexp` | 在S表达式结尾运行,在minibuffer显示结果 |
`C-j` | `eval-print-last-sexp` | 在S表达式结尾运行,打印运行结果 |
`M-:` | `eval-expression` | 在minibuffer输入命令并执行 |
`M-x ielm` | `ielm` | 使用IELM解释器运行代码 |
创建命令(interactive函数)
|
|
emacs探索
key | command | description |
---|---|---|
`C-h k` | `describe-key` | 运行命令后,继续按键,查看此时按键绑定的函数 |
`C-h b` | `describe-bindings` | 在\*Help\*界面搜索 `Major Mode Bindings:` 可以查看所有与当前major mode相关的按键。 |
`C-h f` | `describe-function` | 查看函数文档及详细代码 |
elisp编程的基本设置
三个有用的pcakage:
- rainbow-delimiters: 不同颜色区分不同层级的括号
- paredit: 检查括号匹配
- company: elisp代码补全
基本运算
算术
|
|
比较
|
|
列表
|
|
类型判断和Literals
Emacs Literals
|
|
基本类型判断
Type | Predicate | Literal | Description |
---|---|---|---|
Nil | null | nil '() | Test if argument is nil |
Numbers | numberp | 100, 200e3 | Test if it is number. |
String | stringp | "hello" | Test if it is string |
Symbol | symbolp | 'sym :keyworkd | Test if it is a symbol. |
Atom | atom | 'x "h" :key 200 | Everything that is not a list or pair is an atom. |
List | listp | '(1 2 x y) | Test if it is a list |
Pair | consp | '(a . 200) | Test if it is a pair (cons cell) |
Vector | vectorp | [1 200 'sym] | Test if it is a vector |
Object | Predicate |
---|---|
Buffer | bufferp |
Window | windowp |
Frame | framep |
Process | processp |
|
|
获取对象类型
|
|
变量定义
|
|
函数定义
定义简单函数
语法: (defun
|
|
匿名函数/Lambda函数
语法: (lambda (
|
|
函数作为参数
语法: (caller-function #’
在函数内部,使用 funcall
调用函数作为参数
|
|
多参函数
|
|
可选参数函数
|
|
含属性列表参数函数
|
|
Closures
elisp方言默认不支持closure,所以下面的代码不会像Scheme或Common Lisp一样执行。
参考:
-
https://www.jamesporter.me/2013/06/14/emacs-lisp-closures-exposed.html
-
Technical Dresese: A brief demonstration of emacs new lexical bindings
123456789101112131415161718(defun make-adder (x)(lambda (y) (+ x y)))ELISP>ELISP> (make-adder 3)(lambda(y)(+ x y))ELISP> ((make-adder 3) 4)** Eval error ** Invalid function: (make-adder 3)ELISP> (funcall (make-adder 3) 4)** Eval error ** Symbol's value as variable is void: xELISP> (map (make-adder 3) '(1 2 3 4 5))** Eval error ** Symbol's value as variable is void: xELISP>
支持closure的代码:
|
|
在 ~/.emacs.d/init.el
中添加如下配置以支持closure.
|
|
列表操作
参考:
-
https://www.fincher.org/tips/Languages/Emacs.shtml
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213;; Defining a List;;;; An emacs list can contain elements of almost any type.;;ELISP> '( "a" 2323 "b" 21.2323 "hello" "emacs" nil () (34 134) '(+ 2 3 5))("a" 2323 "b" 21.2323 "hello" "emacs" nil nil(34 134)'(+ 2 3 5))ELISP> (quote (1 3 3 4 5))(1 3 3 4 5);;;;; Empty List;;ELISP> nilnilELISP> '()nilELISP>;; Length of a listELISP> (length '(1 2 3 4 5 6))6ELISP>;; nth element of a list;;ELISP> (nth 0 '(0 1 2 3 4 5))0ELISP> (nth 2 '(0 1 2 3 4 5))2ELISP> (nth 5 '(0 1 2 3 4 5))5ELISP> (nth 10 '(0 1 2 3 4 5))nilELISP>;; Membership test;; member returns null if the element is not member of the list;;ELISP> (member 2 '(0 1 2 3 4 5))(2 3 4 5)ELISP> (member 10 '(0 1 2 3 4 5))nilELISP>;; Position of list element (prior to emacs 24.4);;ELISP> (position 7 '(5 6 7 8))2ELISP> (position 17 '(5 6 7 8))nilELISP>;; Position of list element (emacs 24.4 or later);;ELISP> (cl-position 7 '(5 6 7 8))2ELISP> (cl-position 17 '(5 6 7 8))nilELISP>;; cdr;;;; Removes first element of the list, returns the list tail.;;ELISP> (cdr '(1 2 3 4 5))(2 3 4 5);; car;;;; Returns the first list element;;ELISP> (car '(1 2 3 4 5))1ELISP>;; cons;;;; List constructor;;ELISP> (cons 10 '(1 2 3 4))(10 1 2 3 4)ELISP> (cons 1 (cons 2 (cons 3 (cons 4 (cons 5 '())))))(1 2 3 4 5);; Last element of a list;;;;ELISP> (car (last '(1 2 3 4 5)))5ELISP>;; Reverse a list;;ELISP> (reverse '(1 2 3 4 5))(5 4 3 2 1);; Append lists;;;; Note: nil also means an empty list;;ELISP> (append '(1 2) '( "a" "b" "c" "d"))(1 2 "a" "b" "c" "d")ELISP> (append '(1 2) nil '( "a" "b" "c" "d") nil)(1 2 "a" "b" "c" "d");; Filter list elements given a predicate function;;;;ELISP> (remove-if-not (lambda (x) (> x 2)) '(1 2 3 4 5 6 7 8 9 10))(3 4 5 6 7 8 9 10);; Test if list is empty;;ELISP> (null '(1 2 3 4 5))nilELISP> (null '())tELISP> (null nil)tELISP>;; Drop the firsts n elements of a list;;;;ELISP> (nthcdr 2 '(1 2 3 4))(3 4)ELISP> (nthcdr 3 '(1 2 3 4))(4)ELISP> (nthcdr 13 '(1 2 3 4))nilELISP>;; Delete an element of a list;;;;ELISP> (delq 1 '(1 2 3 4))(2 3 4)ELISP> (delq 10 '(1 2 3 4))(1 2 3 4);; It doesn't work to delete sublists;;ELISP> (delq (5) '(1 2 (5) 3 4))** Eval error ** Invalid function: 5ELISP> (delq '(5) '(1 2 (5) 3 4))(1 2(5)3 4)ELISP> (delete '(5) '(1 2 (5) 3 4))(1 2 3 4);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Convert Vector to List;;;;ELISP> (coerce [1 2 3] 'list)(1 2 3);; Convert List to Vector;;ELISP> (coerce '(1 2 3) 'vector)[1 2 3]ELISP> (number-sequence 0 10 2)(0 2 4 6 8 10)ELISP> (number-sequence 9 4 -1)(9 8 7 6 5 4);; Modify list variables.;;ELISP> alist(a b c d e)ELISP> (push 'f alist)(f a b c d e)ELISP> alist(f a b c d e)ELISP> (pop alist)fELISP> alist(a b c d e)ELISP> (pop alist)aELISP> alist(b c d e)ELISP>
关联列表和属性列表
概览
关联列表是一系列cons对,这里我可以称作 clist
或者 由两个元素组成的列表的集合,可以称为 alist
关联列表类型:clist
键: a, x, 2 and 4 值: b, y, 3 and (1 2 3 4 5)
|
|
关联列表类型:alist
|
|
alist
不像 clist
有歧义。
属性列表:Plist
属性列表是连续的键值对集合,它的优势是括号少和可读性高。
|
|
关联列表/Alist
|
|
例:过滤多个键
|
|
属性列表
|
|
转换Alist成Plist和vice-versa
|
|
字符串
|
|
elisp符号/字符串转换
|
|
读取字符串中的S表达式
|
|
符号
|
|
类型转换
类型查询
|
|
类型判断
|
|
数字/字符串转换
|
|
符号/字符串转换
|
|
S表达式/字符串转换
-
read: 解析S表达式
12345678910111213141516171819202122232425ELISP>ELISP> (setq raw "(:x 10 :y 20 :z 30 :w \"hello world\")")"(:x 10 :y 20 :z 30 :w \"hello world\")"ELISP>ELISP> (read raw)(:x 10 :y 20 :z 30 :w "hello world")ELISP> (plist-get (read raw) :x)10ELISP> (plist-get (read raw) :w)"hello world"ELISP>- prin1-to-string: 序列化S表达式ELISP> (setq sexp '(:x 10 :y 20 :z 30 :w "hello world"))(:x 10 :y 20 :z 30 :w "hello world")ELISP> sexp(:x 10 :y 20 :z 30 :w "hello world")ELISP> (prin1-to-string sexp)"(:x 10 :y 20 :z 30 :w \"hello world\")"ELISP>
求值
S表达式求值
|
|
字符串求值
|
|
S表达式格式化为字符串
|
|
Elisp中的求值命令
命令 | 功能 |
---|---|
M-x eval-defun | 函数求值 |
M-x eval-region | 区域内表达式求值 |
M-x eval-buffer | buffer内表达式求值 |
M-x eval-expression | 输入框输入求值 |
M-x load-file | 文件加载 |
Defalias
内置宏 defalias
可以为emaca函数定义简短的名字。
参考:Emacs: Use Alias for Fast M-x
|
|
控制结构
Conditional Statement
If Else 语句
|
|
When语句
|
|
Cond - Case Switch
|
|
CL-Case - Case Switch
|
|
循环
Dolist
|
|
Dotimes
|
|
Loop
最好使用 map
和 filter
代替 loops
, 详见 Functional Programming
|
|
Loop Collecting / Summing / For
|
|
Do Loop
|
|
函数式编程
Dash 是emacs经常使用的函数式编程库。
- Map and Filter
Mapcar / Equivalent to map
|
|
Filter
|
|
-
匿名函数/lambda函数
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061ELISP> (lambda (x)(* x 10))(lambda(x)(* x 10))ELISP>ELISP> (funcall (lambda (x)(* x 10)) 5)50ELISP>ELISP> (setq my-lambda (lambda (x) (+ (* x 10) 5))) ;; 10 * x + 5(lambda(x)(+(* x 10)5))ELISP> (funcall my-lambda 10)105ELISP> (mapcar my-lambda '(1 2 3 4 5))(15 25 35 45 55)ELISP> (setq double (function (lambda (x) (+ x x)) ))(lambda(x)(+ x x))ELISP> (funcall double 22)44ELISP>;;;; Apply a function to a list of arguments;;;;;;;;;;;;;ELISP> (apply #'+ '(1 2 3 4 5))15ELISP>ELISP>ELISP> (defun f (x y z) (+ (* 10 x) (* -4 y) (* 5 z)))fELISP> (f 2 3 5)33ELISP> (apply 'f '(2 3 5))33ELISP> (mapcar (lambda (x) (apply 'f x)) '( (2 3 5) (4 5 6) (8 9 5)))(33 50 69);; Create Higher Order Functions;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -
Function Composition ????
12345678910111213ELISP> ;; ID: f0c736a9-afec-3e3f-455c-40997023e130(defun compose (&rest funs)"Return function composed of FUNS."(lexical-let ((lex-funs funs))(lambda (&rest args)(reduce 'funcall (butlast lex-funs):from-end t:initial-value (apply (car (last lex-funs)) args)))))composeELISP> (funcall (compose 'prin1-to-string 'random* 'exp) 10)"4757.245739507558"ELISP> -
Interactive Functions
1234(defun some-interactive-function ()"Documentation"(interactive)...) -
List Recursive Functions
Map
|
|
Filter
|
|
Take
|
|
Drop
|
|
Map-apply
|
|
Zip
|
|
Zipwith
|
|
Foldr
|
|
Foldl
|
|
Map Pairs
|
|
Map pairs xy
|
|
Juxt
|
|
Map Juxt
|
|
Lambda Function Macro
|
|
Partial Application
|
|
Structures
|
|
宏和元编程
Quasi-quote
|
|
宏
定义lambda函数语法糖:λ
|
|
Set variable to nil
|
|
Create Clojure def, defn and fn special forms
|
|
……
Emacs API
Emacs术语
Emacs Terminology | Description |
---|---|
Point | Cursor position, number of characters from beggining of the buffer to current cursor position. |
Buffer | Place where the user edit something. Not all buffers are bound to a file. |
Mark | Beginning of the selected area. |
Region | Selected area/ text |
Frame | The current window of emacs |
Windows | Each frame can be split in sections that Emacs documentation calls windows |
Fill | Word Wrap |
Yank | Copy |
Kill Region | Cut |
Kill Ring | Clipboard |
Kill Buffer | Close Buffer |
Mode Line | Status Bar |
Font Locking | Syntax Coloring |
Ben’s Journal: 11 Concepts The Emacs Newbie Should Master
Emacs API
API对象
- Buffer
- Temporary Buffer
- Modes
- Mode Hooks
- Mode Map
- Window
- Frame
- Point
- Process
- Network Process
- Minibuffers
Buffers
Buffer Attributes
|
|
列出打开文件
|
|
创建新buffer
|
|
Buffer Mode
Show Buffers Mode
|
|
Get Buffer Contents / Selection / Line
Get Buffer Content as String
|
|
Get Selected text in current buffer as string
|
|
Get current line in current buffer
|
|
Search and Replace in the entire Buffer
|
|
Point, Region, Line and Buffer
Point
Point
Function | Description |
---|---|
(point) | Current cursor position |
(point-min) | Minimum cursor position in current buffer. (always returns 1) |
(point-max) | Maximum cursor position in current buffer. |
(line-beginning-position) | Point of the beginning of current line. |
(line-end-position) | Point of the end of current line. |
(region-beginning) | Position of the beginning current region (selected text). |
(region-end) | Position of the end current region. |
(bounds-of-thing-at-point |
Returns the cons pair '(beginning . end) position of thing at point. |
Point Interface Functions
Function | Description |
---|---|
(goto-char |
Move the cursor to a given point. |
(insert |
Insert text at current point. |
(buffer-substring [pmin] [pmax]) | Returns the text with properties between the points |
(buffer-substring-no-properties [pmin] pmax]) | Returns the text without properties between the points. |
(delete-region [pmin] [pmax]) | Deletes the text between |
|
|
Thing at Point API
???
Message / Output
|
|
Files, Directories and Path
Basic Functions
|
|
File Name Components
|
|
Read / Write file to a string
Read File
|
|
Write to File
|
|
Window Functions
Basic Window Functions
|
|
Manipulate Buffer in Another Window
http://caiorss.github.io/Emacs-Elisp-Programming/Elisp_Programming.html#sec-3-9-2
Window Configuration
|
|
OS Interface
Find the current operating system
Value | Description |
---|---|
gnu | GNU Hurd system. |
gnu/linux | GNU/Linux system. |
gnu/kfreebsd | GNU system with a FreeBSD kernel. |
darwin | Darwin (GNU-Darwin, Mac OS X) |
ms-dos | MS-DOS application. |
windows-nt | native W32 application. |
cygwin | compiled using the Cygwin library |
|
|
Date and Time
|
|
Call External Commands or Apps
|
|
Environment Variables
|
|
Process Management
|
|
Interfaces
Creating Quick Access Menu
|
|
Add Icons to toolbar
http://caiorss.github.io/Emacs-Elisp-Programming/Elisp_Programming.html#sec-3-11-2
Timer
run-with-timer
|
|
Emacs Modes
Mode Association with Files
|
|
Lisp Routines to introspect modes??
|
|
Mode Specific Key Bindings
|
|
Special Variables
|
|
Network
http://caiorss.github.io/Emacs-Elisp-Programming/Elisp_Programming.html#sec-3-15
正则表达式
Emacs Regex
Special characters
. | any character (but newline) |
\* | previous character or group, repeated 0 or more time |
+ | previous character or group, repeated 1 or more time |
? | previous character or group, repeated 0 or 1 time |
^ | start of line |
$ | end of line |
[…] | any character between brackets |
[^..] | any character not in the brackets |
[a-z] | any character between a and z |
\\ | prevents interpretation of following special char |
\\ | or |
\w | word constituent |
\b | word boundary |
\sc | character with c syntax (e.g. \s- for whitespace char) |
start\end of group | |
\\< | \\> start\end of word |
\\\` | \\' start\end of buffer |
\\1 | string matched by the first group |
\n | string matched by the nth group |
\\{3\\} | previous character or group, repeated 3 times |
\\{3,\\} | previous character or group, repeated 3 or more times |
\\{3,6\\} | previous character or group, repeated 3 to 6 times |
POSIX Character classes
[:digit:] | digit, same as [0-9] |
[:upper:] | letter in uppercase |
[:space:] | whitespace character, as defined by the syntax table |
[:xdigit:] | hexadecimal digit |
[:cntrl:] | control character |
[:ascii:] | ascii character |
Syntax Classes
\s- | whitespace character | \s/ | character quote character |
\sw | word constituent | \s$ | paired delimiter |
\s\_ | symbol constituent | \s' | expression prefix |
\s. | punctuation character | \s< | comment starter |
\s( | open delimiter character | \s> | comment starter |
\s) | close delimiter character | \s! | generic comment delimiter |
\s" | string quote character | \s | generic string delimiter |
\s\\ | escape character |
Emacs X Perl Regex
Emacs Regex | Perl Regex | Description |
---|---|---|
( ) | Capture group | |
\\{ \\} | { } | |
\s- | \s | White space |
\\1, \\2, \\3, \\4 | $1, $2, $3 | Result of capture: search, replace. |
[ ] | [ ] | Character class |
[0-9] or [:digit:] | \d | Digit from 0 to 9 |
\b | \b | Word boundary |
\w | \w | Word character |
Regex Commands
C-M-s | incremental forward search matching regexp |
C-M-r | incremental backward search matching regexp |
Buffer Commands
M-x replace-regexp | replace string matching regexp |
M-x query-replace-regexp | same, but query before each replacement |
M-x align-regexp | align, using strings matching regexp as delimiters |
M-x highlight-regexp | highlight strings matching regexp |
M-x grep | call unix grep command and put result in a buffer |
M-x lgrep | user-friendly interface to the grep command |
M-x rgrep | recursive grep |
M-x dired-do-copy-regexp | copy files with names matching regexp |
M-x dired-do-rename-regexp | rename files matching regexp |
M-x find-grep-dired | display files containing matches for regexp with Dired |
Line Commands
Command (M-x command) | Alias | Description |
---|---|---|
keep-lines | delete-non-matching-lines | Delete all lines except those containing matches |
flush-lines | delete-matching-lines | Delete lines containing matches |
highlight-lines-matching-regexp | hi-lock-line-face-buffer | Highlight lines matching regexp |
occur | list-matching-lines | Show lines containing a match |
multi-occur | Show lines in all buffers containing a match | |
how-many | count-matches | Count the number of strings matching regexp |
Regex Functions
match-string
match-end
match-beginning
re-search
re-search-forward
replace-string-in-regexp
replace-string
Build regex interactively
M-x re-builder
M-x query-replace-regexp
Emacs Regex rx-notation
|
|
Description | rx notation | Emacs regex |
---|---|---|
Beginning of Line | bol | ^ |
End of Line | eol | $ |
Begining of String | bos | \\\\\` |
End of String | eos | `\\'` |
Beginning of Word | bow | \\\\< |
End of Word | eow | \\\\> |
Digit 0 to 9 | digit | \lbr\lbr:digit:\rbr\rbr |
Hexadecimal digit | hex | \lbr\lbr:xdigit:\rbr\rbr |
Match ascii character | ||
Match anything lower case | lower | \lbr\lbr:lower:\rbr\rbr |
Match anything upper case | upper | \lbr\lbr:upper:\rbr\rbr |
word | \sw |
example
|
|
Color Scheme
http://caiorss.github.io/Emacs-Elisp-Programming/Elisp_Programming.html#sec-5
Key Bindings
http://caiorss.github.io/Emacs-Elisp-Programming/Elisp_Programming.html#sec-6