ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

《elisp 每日一练》——跨 Buffer 文本提取

《elisp 每日一练》——跨 Buffer 文本提取 在之前的文章中我们通过with-current-buffer和buffer-substring实现了一个从指定buffer中拷贝文本到本buffer的功能。这个算是我们入门了跨buffer操作。实际上Emacs为这种需求提供了专门的函数背景知识Emacs中的跨buffer文本操作的基础函数是(insert-buffer-substring BUFFER optional START END)。它用于将参数中BUFFER指定的缓冲区中从START到END这个范围内的文本插入到当前缓冲区的光标所在位置。我们可以用下面的代码感受一下(defunmy/copy-messages-buffer-to-this()(interactive)(let((message-buffer(get-buffer*Messages*)))(whenmessage-buffer(let((start)(end))(with-current-buffermessage-buffer(save-restriction(widen)(setqstart(point-min))(setqend(point-max))))(insert-buffer-substringmessage-buffer start end)))))因为START和END参数实际上是对应的是BUFFER中的范围。所以我们需要切入到对应的buffer中去获取这个坐标的最大和最小值。基于这个函数我们可以实现很多好用的跨buffer的文本操作例如将当前buffer中的内容拷贝到目标buffer中或者将目标buffer中的内容替换为我们想要的内容等等。因为各种跨buffer的文本操作实在是太频繁了所以Emacs提供很多有用的函数下面我列举一些常用的函数append-to-buffer: 从当前buffer中提取START和END范围内的文本并追加到参数BUFFER所指定的缓冲区的光标位置copy-to-buffer: 从当前 buffer 中提取START和END范围内的文本并对参数中BUFFER所指定的缓冲区进行替换上述这些函数提取的内容都带有文本属性如果我们只想提取文本本身可以使用buffer-substring-no-properties。查阅相关文档我们发现buffer-substring-no-properties实际上对标的是buffer-substring都是提取当前buffer的文本而不涉及到改变buffer。在跨buffer的函数中只有insert-buffer-substring是使用底层C函数编写的代码而其他两个都是依靠这个函数在lisp层面实现的。所以说关于跨buffer的文本操作我们只需要掌握基本的insert-buffer-substring其他的函数我们可以自己实现。这有点像数学上学的时候老师告诉我初中的几何只有三条基本公理其他的定理和自己利用这三条推导出来。Emacs也是这样只提供基本的功能其余高级的功能可以自己利用基本函数实现出来。但是也提供了这些高级函数的官方实现。练习今天我们来实现一个日志收集的功能。我们将当前用户选中的行记录到一个名为Log-Collection的buffer中该buffer平时不允许写入只能通过调用特定的函数进行收集。如果用户选择并激活了一个区间则提取区间的内容进行激活否则提取当前所在行的文本。(defunmy/collection-log()(interactive)(let((log-buffer(get-buffer-create*Log-Collection*))(cur-buf(current-buffer))(start)(end))(if(use-region-p);; 激活了选区则按照选取来决定范围(progn(setqstart(region-beginning))(setqend(region-end)));; 未激活选取则按照光标所在行来决定范围(progn(setqstart(line-beginning-position))(setqend(line-end-position))))(with-current-bufferlog-buffer(let((inhibit-read-onlyt))(goto-char(point-max))(insert-buffer-substringcur-buf start end)))))总结本节介绍的重点函数只有一个insert-buffer-substring因为功能导致它的参数比较割裂BUFFER是目标buffer、而START和END对应着源buffer的位置。这也就意味着想要成功调用该函数无论如何都得使用with-current-buffer进行buffer的切换无法一步到位其余的函数我们可以自己实现所以就不在这里列举了。
返回列表