浏览 3786 次
精华帖 (1) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2007-06-26
查找更多信息 可以通过C-h f查看函数的说明,C-h v查看变量的说明,这些说明就是Emacs Lisp代码中的文档字符串。 在20或更高版本以后,可以用describe-function(C-h f)将告诉你函数定义的位置。在文件名上按回车(这个操作是help-follow函数调用)将打开函数定义。 etags:在代码中如果想要查看函数源文件,可以使用find-tags函数跳转到源文件上去。find-tags可以处理多种语法,不限于 Lisp和C,也可以工作于非编程语言如Texinfo文档。在Texinfo文档里调用find-tags将跳转到对应的文件节点。 find-tags函数依赖于标签表'tags tables',它记录了函数、变量和其它信息的位置。 使用M-.调用find-tags函数,然后在提示符后要查找的函数名,比如mark-whole-buffer。Emacs将转到显示该函数源码缓冲区。 符号表'tags table'通常是一个名为TAGS的文件。Emacs源码的TAGS存储在/usr/local/share/emacs目录中。但可以通过M-x visit-tags-table命令指定一个符号表。 通过etags命令可以创建符号表。使用M-x cd命令或C-x d(dired)切换到要建立符号表的目录,然后运行编译命令执行etags *.el命令。例: M-x compile RET etags *.el RET 文件中的代码通常称为库。通过C-h p可以查看Emacs Lisp的标准库。 简化版的beginning-of-buffer函数定义 beginning-of-buffer命令将把光标移动到缓冲区起始位置,并把mark设置在前一个位置。通常被绑定到M-<上。 简化版本的函数具有与标准库版本类似的功能,但不包含完整的功能。 设想一下该函数的定义应包括:包含能让用户交互的表达式,比如按M-x beginning-of-buffer或按键C-<;必须包含能在原位置设置mark的代码;必须包含让光标移动到缓冲区起始位置的代码。 简化版本的代码: (defun simplified-beginning-of-buffer () "Move point to the beginning of the buffer; leave mark at previous position." (interactive) (push-mark) (goto-char (point-min))) 与其它函数一样,这个函数也包含了defun需要的五个部分: 1. 函数名,这里使用的:simplified-beginning-of-buffer。 2. 参数列表:这里是一个空列表()。 3. 文档字符串。 4. 交互表达式。 5. 函数体。 这个函数定义中,参数列表为空,意味着函数不需要任何参数。(查看完整函数定义时,我们可以看到它可能传递了可选的参数)。 interactive语句告诉Emacs函数允许交互。这个例子中interactive没有参数,因此调用simplified-beginning-of-buffer时也不需要参数。 函数体由两行代码组成: (push-mark) (goto-char (point-min)) (push-mark)执行时将在当前光标所在位置设置mark,之前的mark被保存到mark ring上。 (goto-char (point-min))将光标转移到缓冲区起始位置。 在阅读这些代码遇到陌生的函数时,比如goto-char,可以使用describe-function命令,按C-h f然后输入函数名。describe-function将在一个*Help*窗口打印出函数的帮助文档。 调用describe-function时,如果光标停留在函数名上,describe-function默认将把光标所在位置的函数名作为参数。 end-of-buffer的函数定义与beginning-of-buffer类似,只是用(goto-char (point-max))替换(goto-char (point-min))。 mark-whole-buffer的定义 mark-whole-buffer函数标把整个缓冲区标记为区域。把point设置在缓冲区开始位置,mark设置在缓冲区结束位置。通常被绑定到C-x h上。 mark-whole-buffer预览 在Emacs 20中,完整的函数代码如下: (defun mark-whole-buffer () "Put point at beginning and mark at end of buffer." (interactive) (push-mark (point)) (push-mark (point-max)) (goto-char (point-min))) 与函数定义模板类似: (defun name-of-function (argument-list) "documentation..." (interactive-expression...) body...) mark-whole-buffer的函数体 mark-whole-buffer的函数体仅有3行: (push-mark (point)) (push-mark (point-max)) (goto-char (point-min)) 第一行(push-mark (point))与simplified-beginning-of-bufer函数相同,那里写的是(push-mark。两种写法都是告诉解释器在当前光标所在位置设置mark。 下一行(push-mark (point-max))在缓冲区结尾设置mark。设置这个mark后,前一行设置的mark将进入mark ring。这意味着你可以通过按两次C-u C-<SPC>重新回到那个位置。 在Emacs 21里,(push-mark (point-max))看起来更复杂: (push-mark (point-max) nil t) 这个函数增加了两上参数,第二个参数为nil。这告诉函数,在设置mark后,需要显示消息:'Mark set'。第三个参数t,它告诉push-mark如果当Transient Mark mode是开启状态,则应该将mark设置为活动状态。Transient Mark mode将高亮显示当前活动的区域,它默认是关闭的。 最后一行(goto-char (point-min))与beginning-of-buffer完全一样。这个语句将光标移动到缓冲区开始位置。运行的结果:point被设置到缓冲区开始位置,mark被设置为缓冲区结束位置。整个缓冲区被标记为区域(region)。 append-to-buffer的定义 append-to-buffer函数从当前缓冲区中拷贝选中区域到指定的缓冲区中。 append-to-buffer函数预览 append-to-buffer命令使用insert-buffer-substring函数来拷贝区域。insert-buffer-substring函数将缓冲区的一部分作为字符串(substring)插入到另一个缓冲区。完整的函数代码如下: (defun append-to-buffer (buffer start end) "Append to specified buffer the text of the region. It is inserted into that buffer before its point. When calling from a program, give three arguments: a buffer or the name of one, and two character numbers specifying the portion of the current buffer to be copied." (interactive "BAppend to buffer: \nr") (let ((oldbuf (current-buffer))) (save-excursion (set-buffer (get-buffer-create buffer)) (insert-buffer-substring oldbuf start end)))) append-to-buffer函数中的交互表达式 append-to-buffer函数需要与用户交互,因此函数使用了interactive表达式。 (interactive "BAppend to buffer: \nr") 这个语句有一个双引号包含的字符串,该字符串被\n分隔为两部分。 第一部分BAppend to bufefer:这里的B告诉Emacs传递一个缓冲区给函数。Emacs将在回显区用B后面的字符串(Append to buffer:)提示用户输入缓冲区名称。然后Emacs将该缓冲区到参数buffer上。 \n分隔了交互表达式中的字符串。\n后的r告诉Emacs将point和mark的值分别绑定到参数buffer后面的两个参数上。 append-to-buffer的函数体 函数体是以let开头的。定义了局部变量,在函数中let将(current-buffer)的返回值绑定到oldbuf上。这个变量用于跟踪当前工作的缓冲区。 单独来看let语句: (defun append-to-buffer (buffer start end) "documentation..." (interactive "BAppend to buffer: \nr") (let ((variable value)) body...) let语句包含三个元素: 1. 符号let。 2. 变量列表,列表中的元素是只含有两个元素的列表。 3. let语句体。 append-to-buffer中的save-excursion let语句的body部分是一个save-excursion语句。它用于在执行完代码后恢复point,mark和buffer的值。 使用save-excursion函数处理过程与下面的模板类似: (save-excursion first-expression-in-body second-expression-in-body ... last-expression-in-body) 在函数定义中,save-excursion只包含了两个语句: (set-buffer (get-buffer-create buffer)) (insert-buffer-substring oldbuf start end) save-excursion依次执行这两条语句,save-excursion函数执行的最后一条语句被作为该次函数调用的返回值。 save-excursion的body部分的第一条语句set-buffer函数用于改变当前缓冲区到append-to-buffer函数调用时第一个参数所指定的缓冲区。(set-buffer变不改当前屏幕显示的内容,只在Lisp程序内部改变当前处理的缓冲区)。第二条语句执行了函数的主要工作。 (get-buffer-create buffer)语句根据名称获取缓冲区,如果缓冲区不存在,就创建一个同名的缓冲区。这意味着可以用append-to-buffer将文本放到一个之前不存在的缓冲区上。 get-buffer-create也使set-buffer可以从错误中恢复:set-buffer需要一个缓冲区才能工作;如果传递给它的缓冲区不存在,Emacs将报错。get-buffer-create将在缓冲区不存在时创建一个,因此set-buffer将总能获取到一个缓冲区。 最后一行append-to-buffer执行追加文本的工作: (insert-buffer-substring oldbuf start end) insert-buffer-substring函数从指定的缓冲区中拷贝字符串到当前缓冲区。在这里,传递给inset-buffer- substring的参数值是由let绑定的,并被命名为oldbuf,它是开始执行append-to-buffer时的当前缓冲区(执行命令时屏幕上显示的缓冲区)。 在insert-buffer-substring执行完后,save-excursion将恢复原缓冲区,append-to-buffer工作完成。 append-to-buffer的函数体工作骨架: (let (bind-oldbuf-to-value-of-current-buffer) (save-excursion ; Keep track of buffer. change-buffer insert-substring-from-oldbuf-into-buffer) change-back-to-original-buffer-when-finished let-the-local-meaning-of-oldbuf-disappear-when-finished 总结append-to-buffer的工作方式:它保存当前缓冲区到变量oldbuf。获取或者新建一个缓冲区并让Emacs切换到那个缓冲区(非屏幕上显示的缓冲区)。使用oldbuf变量从旧缓冲区中获取文本区域插入到新缓冲区;然后使用save-excursion函数回到最初的缓冲区。 查看append-to-buffer代码,探究了复杂的函数。它展示了如何使用let和save-excursion,如何从另一个缓冲区回到原来的缓冲区。许多函数定义中以这种方式使用了let、save-excursion和set-buffer。 回顾 * describe-function * describe-variable 打印函数或变量文档字符串。通常被绑定到C-h f和C-h v。 * find-tag 查找包含函数或变量的源码,并在缓冲区打开,并定位到对应的位置。通常绑定到M-.上。 * save-excursion 保存当前的point和mark,在传递给save-excursion的参数执行完后恢复这两个值。它也会记录下当前的缓冲区并重新回到这个缓冲区。 * push-mark 在某个位置设置mark并将之前的mark保存到mark ring里面去。mark是缓冲区中的一个位置,不管缓冲区中的文本添加或者删除,它都将保持它的相对位置。 * goto-char 设置point到参数指定的位置,参数可以是数字、mark或者返回位置数据的表达式,例如:(point-min). * insert-buffer-substring 从传递给它的第一个参数(缓冲区)对应的缓冲区拷贝区域中的文本到当前缓冲区。 * mark-whole-buffer 把整个缓冲区标记为一个区域。通常绑定到C-x h上。 * get-buffer-create * get-buffer 按名称查找缓冲区,如果缓冲区不存在就创建一个。get-buffer函数在查找不到缓冲区后将返回nil。 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |