剪切和存储文本
当使用'kill'命令剪切文本时,Emacs将它存储到一个列表中,可以用'yank'命令重新获取到。
存储文本到列表
当文本被剪切出缓冲区时,它将被存储到一个list中。文本块连续的存储在list中,这个列表看如下面的形式:
(cons "another piece" '("a piece of text" "previous piece"))执行上面的语句,回显区将显示
("another piece" "a piece of text" "previous piece")使用car和nthcdr函数,可以获取到list中任意的一个文本块。。例:
(car (nthcdr 1 '("another piece" "a piece of text" "previous piece"))) => "a piece of text"当然,Emacs中实际处理这些时更复杂一些。Emacs中编写的剪切函数能猜想出你需要的是list的哪个元素。
包含这些文本块的list被称作kill ring。
zap-to-char
完整的zap-to-char实现
这个函数将移除光标和指定的字符之间的文本。被移除的文本被放入kill ring中,可以用C-y(yank)获取到。如果命令带了数字前缀参数n(C-u),它将移除当前光标位置至遇到的第n个字符之间的文本。
如果指定的字符不存在,zap-to-char将显示"Search failed"。
为了决定要移除多少文本,zap-to-char使用了search函数。搜索在文本处理代码中使用得非常广泛。
下面是zap-to-char在Emacs 19中的完整代码:
(defun zap-to-char (arg char) ; version 19 implementation "Kill up to and including ARG'th occurrence of CHAR.Goes backward if ARG is negative; error if CHAR not found." (interactive "*p/ncZap to char: ") (kill-region (point) (progn (search-forward (char-to-string char) nil nil arg) (point)))interactive语句
zap-to-char的interactive语句如下:
(interactive "*p/ncZap to char: ")引号中的部分"*p/ncZap to char: ",指定了3个不同的东西。第一,星号,如果当前缓冲区是只读缓冲区将产生一个错误信息。这意味着如果将zap-to-char用于只读缓冲将得到错误信息"Buffer is read-only"。
在Emacs21的实现中没有包含星号。函数与Emacs19中一样能工作,但在只读缓冲区中它不会移除文本,它将复制文本并将文本放到kill ring中。在这种情况下,两个版本中都将显示错误信息。
在Emacs19中的实现也能从只读缓冲区中复制文本,这只是interactive的一个Bug。interactive的文档中说明了,星号将阻止zap-to-char函数对只读缓冲区做任何操作,这个函数不应该复制文本到kill ring中。
在Emacs21中interactive的实现是正确的。因此星号不得不被移除。如果你在这个这个函数的定义中插入了星号,并重新执行函数定义,下次你再在只读缓冲区上运行zap-to-char时,将不能再复制文本到kill ring里。
从这点来看,两个版本中的zap-to-char是一致的。
"*p/ncZap to char: "中的第二个部分是p。这个部分与下一部分用/n分隔了。p表示参数应该是一个前缀参数'processed prefix',这个参数是用C-u加数字或者M-加数字传递的。如果调用时没有加参数,1将作为默认的参数值。
"*p/ncZap to char: "中的第三个部分是"cZap to char: ",小写的c指定了参数必须是一个字符。c后面的字符串Zap to char: 是提示字符串。
zap-to-char的函数体
zap-to-char函数体包含kill当前光标位置至指定字符之间文本的代码。代码的第一部分如下:
(kill-region (point) ...(point)是光标的当前位置
代码的下一个部分是一个progn语句。progn的body部分由search-forward和point组成。
在学习完search-forward后,很容易懂progn。
search-forward函数
search-forward函数被用于定位字符(zapped-for-character)。如果查找成功, search-forward会将point设置在要查找的目标字符串的最后一个字符的后面。(zap-to-char中目标字符串只有一个字符)如果是 向后查找,则search-forward会将point设置在查找目标字符串第一个字符的前面。查找成功后,search-forward将返回t。
在zap-to-char中,search-forward函数部分如下:
(search-forward (char-to-string char) nil nil arg)search-forward函数包含四个参数:
第一个参数是要查询目标,必须是一个字符串,比如"z"。
传递给zap-to-char是一个字符。Lisp解释器对字符串和字符的处理是不同的。因为search-forward函数查询的是一个字符 串,传递给zap-to-char函数接收到的是一个字符,因此参数必须被转换为字符串,否则search-forward将报错。char-to- string用于处理这种转换。
第二个参数限制查询的范围;它是一个缓冲区位置。在这里,可以查询到缓冲区的结束位置,因此第二个参数为nil。
第三个参数告诉函数如果查询失败该如何做:比如打印错误信息或者返回nil。第三个参数为nil将在查询失败时显示错误信息。
search-forward的第四个参数用于指定重复查询的次数。这个参数是可选,如果没有传递,则默认为1.如果参数是一个负数,查询将向后查询。
使用search-forward语句的模板:
(search-forward "target-string" limit-of-search what-to-do-if-search-fails repeat-count)progn
progn是一个特殊的form。它使传递给它的参数依次被执行,并返回最后一个值。前面部分只是被执行,它们的返回值被丢弃。
progn语句的模板:
(progn body...)zap-to-char中的progn语句做了两件事:将point设置到正确的位置;返回point的位置以便kill-region知道要操作的范围。
progn的第一个参数是search-forward。当search-forward找到了字符串,它会将point设置在查找目标字符串的最 后一个字符的后面。(这里目标字符串只有一个字符长)如果是向后查找,search-forward会将poing设置在查找目标的第一个字符的前面。 point的移动是side effect(单方面的,不影响界面)。
progn的第二个参数是表达式(point)。这个表达式返回point的值,即search-forward设置的那个值。这个值被作为progn语句的返回值将作为kill-region的第二个参数传递给kill-region函数。
zap-to-char的总结
前面了解了search-forward和progn是如何工作的,我们可以看到整个zap-to-char函数是如何工作的。
kill-region的第一个参数是执行zap-to-char命令时的光标位置。在progn的内部,查找函数将poing移动到要查找目标 (zapped-to-character)的后面。kill-region函数将这两个point中的第一个作为操作区域(region)的开始位置, 第二个参数作为结束位置,然后移除这个区域。
progn是必需的,因为kill-region命令需要两个参数;如果把search-forward和point语句直接作为kill-region的参数将报错。progn语句是一个单独的参数,它的返回值将作为传递给kill-region的第二个参数。
kill-region
zap-to-char函数使用了kill-region函数。函数将从一个region中clip文本到kill ring中。
在Emacs 21中这个函数使用了condition-case和copy-region-as-kill,这两个函数都将在后面解释,confition-case是一个特别重要的form。
实际上,kill-region函数调用了condition-case,它需要3个参数。第一个参数不做什么,第二个参数包含了正常工作时需要执行的代码。第三个参数包含了出错时需要执行的代码。
完整的kill-region定义
下面将介绍condition-case。首先来看kill-region的完整定义:
(defun kill-region (beg end) "Kill between point and mark.The text is deleted but saved in the kill ring." (interactive "r") ;; 1. `condition-case' takes three arguments. ;; If the first argument is nil, as it is here, ;; information about the error signal is not ;; stored for use by another function. (condition-case nil ;; 2. The second argument to `condition-case' ;; tells the Lisp interpreter what to do when all goes well. ;; The `delete-and-extract-region' function usually does the ;; work. If the beginning and ending of the region are both ;; the same, then the variable `string' will be empty, or nil (let ((string (delete-and-extract-region beg end))) ;; `when' is an `if' clause that cannot take an `else-part'. ;; Emacs normally sets the value of `last-command' to the ;; previous command. ;; `kill-append' concatenates the new string and the old. ;; `kill-new' inserts text into a new item in the kill ring. (when string (if (eq last-command 'kill-region) ;; if true, prepend string (kill-append string (
然而在一些复杂的情况下。程序不应该在出错的时候只是简单的停止程序执行。在kill-region函数中,一个典型的错误是,如果在只读缓冲区中 删除文本时,文本将不会被删除。因此kill-region函数包含了处理这种情况的代码。这些代码在kill-region函数中condition- case语句的内部。
condition-case的模板如下:
(condition-case var bodyform error-handler...)如果没有发生错误,解释器将执行bodyform语句。
错误发生时,函数将产生错误信息,定义一个或者多个错误条件名称(condition name)。
condition-case的第三个参数是一个错误处理器。一个错误处理器包含了两个部分,一个condition-name和一个body。如 果错误处理器的condition-name与发生错误时的condition-name匹配,错误处理器的body部分将执行。
错误处理器中的错误条件名称(condition-name)可以是一个单一的condition name也可以是包含多个condition name的list。
condition-case语句可以包含一个或多个错误处理器。当错误发生时,第一个被匹配的处理器被执行。
最后,condition-case语句的第一个参数var,有时被绑定到包含错误信息的变量上。如果它为nil,比如在kill-region中,错误消息将被丢弃。
简单来说,在kill-region函数中,condition-case的工作如下:
If no errors, run only this code but, if errors, run this other code.delete-and-extract-region
一个condition-case语句有二个部分,一个是正常时执行的,但它有可能会产生错误。另一个部分用于出错时执行。
先来看kill-region中正常运行的代码:
(let ((string (delete-and-extract-region beg end))) (when string (if (eq last-command 'kill-region) (kill-append string (
这里的let语句将delete-and-extract-region的返回值赋给局部变量string中。这也就是从缓冲区中删除的文本。
如果变量string指向了文本,那些文本就被添加到kill ring,如果变量值为nil则表示没有文本被删除。
这里使用了when来检查变量string是否指向了文本块。when语句是程序员的一种简便写法。when语句是没有else部分的if语句。可以把when理解为if。
技术上来说,when是一个Lisp宏。Lisp宏允许你定义新的控制结构和其它语言功能。它告诉解释器如何计算另一个Lisp语句的值,并返回计算的结果。这里的'另一个表达式'就是一个if表达式。C语言里也提供了宏。但这是不同的,但它们同样很有用。
如果string变量有内容,另一个条件表达式被执行。这是一个包含了then部分和else部分的if语句。
(if (eq last-command 'kill-region) (kill-append string ( last-command是一个Emacs变量。通常,当一个函数被执行,Emacs将设置last-command的值为前一个命令。 在这段定义中,if语句检查前一个命令是否为kill-region。 (kill-append string ( 如果前一个命令不是kill-region,kill-new函数将被执行,它将文本作为kill ring中的最后一个元素添加进去,然后将变量kill-ring-yank-pointer设置到上面。 delete-and-extract-region delete-and-extract-region函数移除region中的内容且不能恢复。 与其它代码不同,delete-and-extract-region不是用Emacs Lisp编写的;它是用C编写的,这也是Emacs的一个基础系统。 与其它Emacs原生函数一样,delete-and-extract=region是C宏,宏是一个代码模板。完整宏如下: DEFUN ("delete-and-extract-region", Fdelete_and_extract_region, Sdelete_and_extract_region, 2, 2, 0, "Delete the text between START and END and return it.") (start, end) Lisp_Object start, end;{ validate_region (&start, &end); return del_range_1 (XINT (start), XINT (end), 1, 1);}DEFUN与Lisp中的defun是同样的用途。DEFUN后面括号中有七个部分: "Set point to POSITION, a number or marker./n/ Beginning of buffer is position (point-min), end is (point-max).在C宏中,紧接在后面是正式的参数,和参数类型语句,接下来就是宏的'body'部分。delete-and-extract-region的'body'包含了两行: validate_region (&start, &end);return del_range_1 (XINT (start), XINT (end), 1, 1);第一个函数validate_region检查传递的区域起始位置和结束位置是否是在规定的范围内,检查参数类型是否正确。第二个函数del_range_1,执行删除文本的操作。 传递给del_range的两个参数XINT (start) and XINT (end)值得研究一下。 C语言中,start和end是标记了被删除区域的开始位置和结束位置的两个整数。 早期版本的Emacs中,这两个数字是32bits长,但这个代码运行比较慢。三个bit被用于指定类型信息,四个bit被用于处理内存;其它bits被作为'content'。 XINT是一个C宏它从bits集合中解析出相关的数字;4个bits被丢弃。 delete-and-extract-region命令看起来如下: del_range_1 (XINT (start), XINT (end), 1, 1);它删除start和end之间的region。 从这点来看Emacs Lisp很简单;它隐藏了大量复杂的工作。 使用用defvar初始化变量 在Emacs Lisp中kill-ring之类的变量是用defvar创建和初始化的。这个名称来源于"define variable"。 defvar与setq设置变量类似。与setq不同的两点:第一,它只给未赋值的变量赋值,如果变量已经有值,defvar将不会覆盖已经存在的值。第二,defvar有一个文档字符串。 (另一个特别的form是defcustom,被设计为可以让用户自定义。它比defvar有更多的功能。) 查看变量的当前值 Documentation:List of killed text sequences.Since the kill ring is supposed to interact nicely with cut-and-pastefacilities offered by window systems, use of this variable shouldinteract nicely with `interprogram-cut-function' and`interprogram-paste-function'. The functions `kill-new',`kill-append', and `current-kill' are supposed to implement thisinteraction; you may want to use them instead of manipulating the killring directly.kill ring是使用defvar按下面的方法定义的: 当使用defvar设定变量时,可以在文档字符串的第一个位置添加*号来来区分变量是否为可以设值的变量。比如: (defvar shell-command-default-error-buffer nil "*Buffer name for `shell-command' ... error output.... ")这表示你可以使用edit-options命令临时修改shell-command-default-error-buffer的值。 copy-region-as-kill 如果在调用kill-region后立即调用copy-region-as-kill,Emacs会将新的文本追加到前一个复制的文本中。这意味着 你使用yank时将得前面两次操作的所有文本。另一方面,如果在copy-region-as-kill之前执行了一些命令,则函数复制的文本块将不会放 在一起。 完整的copy-region-as-kill函数定义 (defun copy-region-as-kill (beg end) "Save the region as if killed, but don't kill it.In Transient Mark mode, deactivate the mark.If `interprogram-cut-function' is non-nil, also savethe text for a window system cut and paste." (interactive "r") (if (eq last-command 'kill-region) (kill-append (buffer-substring beg end) ( (defun copy-region-as-kill (argument-list) "documentation..." (interactive "r") body...)参数是beg、end和参数为"r"的交互式函数,因此这两个参数将指向region的开始位置和结束位置。 一旦设置了一个mark,缓冲区就总会包含一个region。可以使用Transient Mark模式来高亮显示region。(没人会希望region一直处理于高亮状态,因此Transient Mark模式下只会在适当的时候才会高亮显示。许多人都关掉了Transient Mark模式,因此region从不会高亮显示) copy-region-as-kill函数体是一个以if开头的子句。这个子句区分了两种情况:这个命令的前一个命令是否是kill- region命令。第一种情况,新的region被追加到前一个被复制的文本块中。否则,它将插入一个新的文本块到kill ring中。 copy-region-as-kill的body部分 与kill-region相同,copy-region-as-kill函数也使用了last-command(它保持了对次Emacs命令调用的跟踪)变量。 last-command和this-command 在copy-region-as-kill函数的body部分,一个if语句检查了last-command的值是否为kill-region。如 果是,则if语句被执行;它使用kill-append函数将本次函数调用复制的文本合并到kill ring的第一个元素(CAR)中。如果last-command不为kill-region,则copy-region-as-kill函数将使用 kill-new函数在kill ring中添加一个新的元素。 这个if语句如下,它使用了eq函数: (if (eq last-command 'kill-region) ;; then-part (kill-append (buffer-substring beg end) ( kill-append函数 (defun kill-append (string before-p) "Append STRING to the end of the latest kill in the kill ring.If BEFORE-P is non-nil, prepend STRING to the kill.If `interprogram-cut-function' is set, pass the resulting kill toit." (kill-new (if before-p (concat string (car kill-ring)) (concat (car kill-ring) string)) t))kill-append函数使用了kill-new函数。 (if before-p ; if-part (concat string (car kill-ring)) ; then-part (concat (car kill-ring) string)) ; else-part如果被kill的region位于前一个命令kill的region的前面,那么它将被合并到前一次删除的资源的前面,如果被删除的文本在前次删除文本的后面,那它将被合并到前次删除资源的后面。if语句使用before-p决定如何放置。 新文本加到前面时,执行: (concat string (car kill-ring))新文本加到后面时,执行: (if (and replace kill-ring) ;; then (setcar kill-ring string) ;; else (setq kill-ring (cons string kill-ring)) (if (> (length kill-ring) kill-ring-max) ;; avoid overly long kill ring (setcdr (nthcdr (1- kill-ring-max) kill-ring) nil))) (setq kill-ring-yank-pointer kill-ring) (if interprogram-cut-function (funcall interprogram-cut-function string (not replace))))条件测试(and replace kill-ring),如果两个kill ring中有内容,并且replace变量为true则返回true。 kill-append函数将replace设置为true;然后当kill ring至少有一个元素时,setcar语句被执行: (setcar kill-ring string)setcar函数将kill-ring的第一个元素修改为string的值。它替换了原来的元素。 (setq kill-ring (cons string kill-ring))(if (> (length kill-ring) kill-ring-max) (setcdr (nthcdr (1- kill-ring-max) kill-ring) nil))语句先通过在原来的kill ring前添加新元素string,而构造了一个新的kill ring。然后执行了第二个if子句。第二个if子名防止了kill ring增长过大。 setq的这行将string添加到旧的kill ring组成的新list重新设置给kill-ring。 第二个if子名,防止了kill ring增长得过长。 (if (> (length kill-ring) kill-ring-max) (setcdr (nthcdr (1- kill-ring-max) kill-ring) nil))这段代码检查kill ring的长度是否已经超过了允许的最大长度——kill-ring-max(默认为60)。如果kill ring过长,则将kill ring的最后一个元素设置为nil。执行这个操作使用了两个函数:nthcdr和setcdr。 例: (setq trees '(maple oak pine birch)) => (maple oak pine birch)(setcdr (nthcdr 2 trees) nil) => niltrees => (maple oak pine)setcdr返回值为nil,是因为它设置的CDR是nil。 (setq kill-ring-yank-pointer kill-ring)kill-ring-yank-pointer也是一个全局变量,它被设置为kill-ring。 现在,回到函数的最前面的两行: (and (fboundp 'menu-bar-update-yank-menu) (menu-bar-update-yank-menu string (and replace (car kill-ring))))这个语句第一个元素是函数and。 在这里,语句测试了menu-bar-update-yank-menu是否是一个函数,如果是则调用它。如果测试的参数符号是一个函数定义而不是'is not void',则fboundp返回true,如果函数未定义则我们将得到错误信息。 这个and和if语句效果如下: if the-menu-bar-function-exists then execute-itmenu-bar-update-yank-menu函数允许用户使用'Select and Paste'菜单操作,并且可以在菜单上看到文本块。 最后一个语句kill-new函数添加新的文本到窗口系统中,以便在不同的程序中进行复制粘贴操作。比如:在XWindow系统中x-select-text函数将文本存储在X系统操作的内存中,你可以在另一个程序中粘贴。 语句结构如下: (if interprogram-cut-function (funcall interprogram-cut-function string (not replace))))如果interprogram-cut-function存在,则Emacs执行funcall,它将第一个参数作为函数,并将其它参数传递给这个函数。 回顾 例: (car '(1 2 3 4 5 6 7)) => 1(cdr '(1 2 3 4 5 6 7)) => (2 3 4 5 6 7)cons 例: (cons 1 '(2 3 4)) => (1 2 3 4)nthcdr 例: (nthcdr 3 '(1 2 3 4 5 6 7)) => (4 5 6 7)setcar 例: (setq triple '(1 2 3))(setcar triple '37)triple => (37 2 3)(setcdr triple '("foo" "bar"))triple => (37 "foo" "bar")progn 例: (progn 1 2 3 4) => 4save-restriction search-forward 它接收4个参数: 要查找的字符串
zap-to-char命令使用了delete-and-extract-region函数,它使用了另外两个函数, copy-region-as-kill和del_range_1。copy-region-as-kill函数将在下节讨论;它复制了region的一 份拷贝到kill ring中,因此内容可以yanked回来。
第一个部分给出了Lisp函数的名称,delete-and-extract-region
第二部分是C函数的名称,Fdelete_and_extract_region。习惯上以F开头。因为C不能在函数名中使用连字符,因此用下划线替代了。
第三个部分是记录了供函数内部使用的信息的C常量结构。它的名称与C函数名一致但它以S开头。
第四和第五个部分指定了最小和最大的参数个数。这个函数需要2个参数。
第六部分与Lisp编写的函数中的交互式语句类似:一个字符后跟着可选的提示信息。两者不同之处在于Lisp没有参数时不需要写参数。在这个宏里需要写成0(null string)。
第七个部分是文档字符串与Lisp编写的函数中的相同。不同之处在于换行时,需要在/n后面添加一个反斜线并添加回车。
因此,goto-char的文档字符串的前两行如下:
del_range_1是一个复杂的函数我们不深入研究。它修改缓冲区并执行其它操作。
与delete-and-extract-region函数不同,copy-region-as-kill函数是用 Emacs Lisp编写的。它内部有两个函数kill-append和kill-new,复制缓冲区区域中的信息到变量kill-ring中。这节讨论kill- ring变量是如何被defvar创建和初始化的。
可以使用describe-variable函数查看任何变量的当前值,通常可以用C-h v来调用。比如可以C-h v然后输入kill-ring将看到 当前kill ring的值,同时也能看到kill-ring的文档字符串:
(defvar kill-ring nil "List of killed text sequences....")这个变量定义中,变量初始化为nil。这意味着如果没有保存任何东西,使用yank时将不会获取到任何信息。文档字符串的写法与使用defun时的文档字 符串是一样的,文档字符串的第一行必须是一个完整的语句,因为一些命令,比如apropos只打印文档字符串的第一行。后面的行不应该使用缩进;否则如果 用C-h v(describe-variable)查看时将会混乱。
defvar时使用星号
以前,Emacs使用defvar来定义希望被用户修改的变量和不希望被用户修改的变量。尽管你可以用defvar定义自定义变量,但是请使用defcustom来代替。
edit-options设置的值只在当前编辑会话中有用。新值并不会被保存。每次Emacs启动时它将读取原始值,除非你在.emacs文件中设定它。
这个函数从缓冲区中复制区域中的内容(使用kill-append或kill-new)并保存到kill-ring上。
下面是Emacs 21中copy-region-as-kill函数定义:
copy-region-as-kill函数和kill-function的工作很相似。两者都是为了将同一行中的两次或多次kill操作合并到同一个块中。如果用yank回来,将一次获得所有的文本块。并且,不管是向前删除还是向后删除,文本块都保持了正确的位置。
通常,任何一个函数被执行,Emacs将在函数被挪时设置this-command为被执行的函数。同时,Emacs将last-command的值设置为this-command的前一个值。
kill-append函数如下:
首先来看传递给kill-new的参数。它使用了concat连接新文本和kill ring的CAR。是合并到CAR元素的前面还是合并到CAR元素后面取决于if语句:
符号before-p是kill-append的参数。当kill-append被执行时,它被绑定到实际参数计算出来的值上。在这里是表达式 (
(concat (car kill-ring) string))我们可以意识到kill-append修改了kill ring。kill ring是一个list,它的每个元素保存了文本。kill-append函数使用kill-new函数,kill-new函数使用了setcar函数。
kill-new函数
(defun kill-new (string &optional replace) "Make STRING the latest kill in the kill ring.Set the kill-ring-yank pointer to point to it.If `interprogram-cut-function' is non-nil, apply it to STRING.Optional second argument REPLACE non-nil means that STRING will replacethe front of the kill ring, rather than being added to the list." (and (fboundp 'menu-bar-update-yank-menu) (menu-bar-update-yank-menu string (and replace (car kill-ring)))) (if (and replace kill-ring) (setcar kill-ring string) (setq kill-ring (cons string kill-ring)) (if (> (length kill-ring) kill-ring-max) (setcdr (nthcdr (1- kill-ring-max) kill-ring) nil))) (setq kill-ring-yank-pointer kill-ring) (if interprogram-cut-function (funcall interprogram-cut-function string (not replace))))先看下面的部分:
如果kill ring为空,或者replace为false,则条件语句的else部分将执行:
依次来看这两个语句。
setcdr设置list的CDR部分,setcar设置list的CAR部分。在这里,setcdr不会设置kill ring的CDR部分;nthcdr函数限制了设置CDR的位置。
kill-new函数中的下一行语句是:
尽管kill-ring-yank-pointer被称为pointer,实际上却是kill ring变量。但选用名字是为了帮助人们懂得这个变量起的作用。这个变量用于yank和yank-pop等函数。
and将依次对每个参数求值只到某个参数返回值为nil,这种情况下and语句将返回nil;如果没有参数返回值为nil,返回值将是最后一个参数 的值。(这种情况下返回值不会为nil,在Emacs Lisp里可以作为true)。换言之,and语句只有在所有参数都返回true的情况下才返回true。
car
cdr
car返回list的第一个元素;cdr返回list中从第二个元素开始的list。
cons将第一个参数添加到第二个参数前面。
返回对list求'n'次CDR的值。
setcdr
setcar修改list中的第一个元素;setcdr修改list中第二个元素开始的list。
依次执行各个参数并返回最后一个参数的值。
记录当前缓冲区的任何narrowing,在执行完它的参数后,恢复narrowing。
查找字符串,如果找到则将point设置到那个位置。
可选参数,是一个缓冲区位置,它用于限制查询范围
可选参数,查询失败执行的代码,返回nil或者显示错误信息
查询的次数,如果为负数则向前查找
kill-region
delete-region
copy-region-as-kill
kill-region剪切point和mark间的文本到kill ring上,可以用yanking恢复。
delete-and-extract-region移除point和mark间的文本并丢弃。不能恢复。
copy-region-as-kill复制point和mark间的文本到kill ring,可以用yanking恢复。这个函数并不移除原来的文本。