Elisp 基礎
C-j
計算當前光標到行首之間函數(shù)式結果,插入正文內容,結果內容最多只顯示2行,后面用省略號,What!!
使用C-0 C-j能把結果內容顯示全。
eval-expression-print-levelandeval-expression-print-length用來控制內容顯示的長度。
C-x C-e
計算當前光標到行首之間函數(shù)式結果,顯示在mini-buffer里。
Emacs Lisp 是一個函數(shù)式的語言。
*scratch*buffer
C-x 方向鍵切換到*scratch*buffer , 可以在其中測試 elisp 語句。
這個buffer是lisp-interaction-mode。
光標移動到函數(shù)式后,按下C-j或者C-x C-e,就可以執(zhí)行函數(shù)式計算。
基本寫法,如何測試
(+ 3 (+ 1 2))
;;? ? ? ? ? ^ 光標放到這里
;; 按下`C-j' 就會輸出 6
;; `C-j' 會在buffer中插入當前運算的結果
;; 而`C-xC-e' 則會在emacs最底部顯示結果,也就是被稱作"minibuffer"的區(qū)域
;; 為了避免把我們的buffer填滿無用的結果,我們以后會一直用`C-x C-e'
變量
setq設置當前緩沖區(qū)(Buffer)中的變量值
setq-default設 置的為全局的變量的值
;; `setq' 可以將一個值賦給一個變量
(setq my-name "Bastien")
;; `C-x C-e' 輸出 "Bastien" (在 mini-buffer 中顯示)
;; 定義變量
(setq name "username")
(message name) ; -> "username"
1
2
;; 設置光標樣式
(setq-default cursor-type 'bar)
quote 單引號
https://www.gnu.org/software/emacs/manual/html_node/elisp/Quoting.html
http://stackoverflow.com/questions/134887/when-to-use-quote-in-lisp
1
2
3
;; 下面兩行的效果完全相同的
(quote foo)
'foo
quote 的意思是不要執(zhí)行后面的內容,返回它原本的內容
1
2
(print '(+ 1 1)) ;; -> (+ 1 1)
(print (+ 1 1))? ;; -> 2
列表
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
;; 我們將一些名字存到列表中:
(setq list-of-names '("Sarah" "Chloe" "Mathilde"))
;; 用 `car'來取得第一個名字:
(car list-of-names)
;; 用 `cdr'取得剩下的名字:
(cdr list-of-names)
;; 用 `push'把名字添加到列表的開頭:
(push "Stephanie" list-of-names)
;; 注意: `car' 和 `cdr' 并不修改列表本身, 但是 `push' 卻會對列表本身進行操作.
;; 這個區(qū)別是很重要的: 有些函數(shù)沒有任何副作用(比如`car')
;; 但還有一些卻是有的 (比如 `push').
循環(huán)
http://www.gnu.org/software/emacs/manual/html_mono/cl.html#Loop-Facility
loop for ... in來自 cl 即 Common Lisp 擴展。
1
2
;; cl - Common Lisp Extension
(require 'cl)
for , in, collect 均為 cl-loop 中的 保留關鍵字。下面是一些簡單的 cl-loop 的使用示例:
1
2
3
4
5
6
7
8
9
;; 遍歷每一個緩沖區(qū)(Buffer)
(cl-loop for buf in (buffer-list)
? collect (buffer-file-name buf))
;; 尋找 729 的平方根(設置最大為 100 為了防止無限循環(huán))
(cl-loop for x from 1 to 100
? for y = (* x x)
? until (>= y 729)
? finally return (list x (= y 729)))
mapcar
1
2
3
4
5
6
7
8
9
10
11
;; 我們來對`list-of-names'列表中的每一個元素都使用hello函數(shù):
(mapcar 'hello list-of-names)
;; 將 `greeting' 改進,使的我們能夠對`list-of-names'中的所有名字執(zhí)行:
(defun greeting ()
? ? (switch-to-buffer-other-window "*test*")
? ? (erase-buffer)
? ? (mapcar 'hello list-of-names)
? ? (other-window 1))
(greeting)
while 循環(huán)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
(defun replace-hello-by-bonjour ()
? ? (switch-to-buffer-other-window "*test*")
? ? (goto-char (point-min))
? ? (while (search-forward "Hello")
? ? ? (replace-match "Bonjour"))
? ? (other-window 1))
;; (goto-char (point-min)) 將光標移到buffer的開始
;; (search-forward "Hello") 查找字符串"Hello"
;; (while x y) 當x返回某個值時執(zhí)行y這個s式
;; 當x返回`nil' (空), 退出循環(huán)
(replace-hello-by-bonjour)
;; 你會看到所有在*test* buffer中出現(xiàn)的"Hello"字樣都被換成了"Bonjour"
;; 你也會得到以下錯誤提示: "Search failed: Hello".
;;
;; 如果要避免這個錯誤, 你需要告訴 `search-forward' 這個命令是否在
;; buffer的某個地方停止查找, 并且在什么都沒找到時是否應該不給出錯誤提示
;; (search-forward "Hello" nil t) 可以達到這個要求:
;; `nil' 參數(shù)的意思是 : 查找并不限于某個范圍內
;; `t' 參數(shù)的意思是: 當什么都沒找到時,不給出錯誤提示
defun
1
2
3
4
5
6
7
8
9
10
11
12
13
;; 你可以把s式嵌入函數(shù)中
(defun hello () (insert "Hello, I am " my-name))
;; `C-xC-e' 輸出 hello
;; 現(xiàn)在執(zhí)行這個函數(shù)
(hello)
;; `C-xC-e' 輸出 Hello, I am Bastien
;; 帶參數(shù)的函數(shù)定義
(defun hello (name) (insert "Hello " name))
;; `C-xC-e' 輸出 hello
(hello "you")
;; `C-xC-e' 輸出 "Hello you"
progn
1
2
3
4
5
;; 你可以用 `progn'命令將s式結合起來:
(progn
? (switch-to-buffer-other-window "*test*")
? (hello "you"))
;; `C-xC-e' 此時屏幕分為兩個窗口,并且在*test* buffer中顯示"Hello you"
let
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
;; 你可以用 `let' 將一個值和一個局部變量綁定:
(let ((local-name "you"))
? (switch-to-buffer-other-window "*test*")
? (erase-buffer)
? (hello local-name)
? (other-window 1))
;; 我們再用`let'新建另一個函數(shù):
(defun greeting (name)
? (let ((your-name "Bastien"))
? ? (insert (format "Hello %s!nnI am %s."
? ? ? ? ? ? ? ? ? ? name? ? ? ; the argument of the function
? ? ? ? ? ? ? ? ? ? your-name? ; the let-bound variable "Bastien"
? ? ? ? ? ? ? ? ? ? ))))
;; 之后執(zhí)行:
(greeting "you")
交互命令 read-from-minibuffer
1
2
3
4
5
6
7
8
9
10
11
12
13
14
;; 有些函數(shù)可以和用戶交互:
(read-from-minibuffer "Enter your name: ")
;; 這個函數(shù)會返回在執(zhí)行時用戶輸入的信息
;; 現(xiàn)在我們讓`greeting'函數(shù)顯示你的名字:
(defun greeting (from-name)
? (let ((your-name (read-from-minibuffer "Enter your name: ")))
? ? (insert (format "Hello!nnI am %s and you are %s."
? ? ? ? ? ? ? ? ? ? from-name ; the argument of the function
? ? ? ? ? ? ? ? ? ? your-name ; the let-bound var, entered at prompt
? ? ? ? ? ? ? ? ? ? ))))
(greeting "Bastien")
lisp 操作 emacs
switch-to-buffer-other-window
1
2
3
4
5
6
7
;; 下面我們在新的窗口中新建一個名為 "*test*" 的buffer:
(switch-to-buffer-other-window "*test*")
;; `C-xC-e' 這時屏幕上會顯示兩個窗口,而光標此時位于*test* buffer內
;; 用鼠標單擊上面的buffer就會使光標移回。
;; 或者你可以使用 `C-xo' 使得光標跳到另一個窗口中
(goto-char (point-min)) 將光標移到buffer的開始
(search-forward “Hello”) 查找字符串”Hello”
global-set-key 設置快捷鍵
1
2
;; 設置快捷鍵
(global-set-key (kbd "<f1>") 'func-name)
其他lisp語法
insert
1
2
3
4
5
6
7
8
9
10
;; `insert' 會在光標處插入字符串:
(insert "Hello!")
;; `C-xC-e' 輸出 "Hello!"
(insert "Hello" " world!")
;; `C-xC-e' 輸出 "Hello world!"
;; 你也可以用變量名來代替字符串
(insert "Hello, I am " my-name)
;; `C-xC-e' 輸出 "Hello, I am Bastien"
format
1
2
3
4
5
;; 格式化字符串的方法:
(format "Hello %s!n" "visitor")
(defun hello (name)
? (insert (format "Hello %s!n" name)))