《elisp 每日一练》——buffer属性

《elisp 每日一练》——buffer属性

Masimaro
2026-08-11 / 0 评论 / 3 阅读 / 正在检测是否收录...

前面我们介绍了buffer相关的操作,主要有buffer的获取、创建、删除、设置当前buffer。我们再最开始的时候为了方便理解buffer的概念,让大家将它类比成 char* const 类型,主要用来保存文本数据的缓冲。这条对也不对,buffer是Emacs维护的一个复杂的结构,可不单单是有个缓冲区的指针那么简单。它除了保存了文本的缓冲,也有各种属性。本篇我们将来介绍一些常用的属性

背景知识铺垫

首先是buffer的名称。我们在创建的时候都会给一个名称,后续也可以根据名称来获取buffer对象。可以说名称似乎就是获取buffer的 primary key

获取名称可以使用 buffer-name ,而修改名称可以使用 rename-bufferrename-buffer 有一个名为 UNIQUE的可选参数,表示是否允许名称重复,如果允许的话,在重名的情况下会在buffer名称后加上数字后缀,如果不允许也就是值为 nil 的时候,给出重复名称时会报错。

buffer-name 可以传入buffer 对象来获取不同buffer的名称,而 rename-buffer 只能修改当前buffer的名称。

第二个属性是它关联的文件。一般来讲如果我们希望修改的内容能持久化的保存,需要将buffer与磁盘上的物理文件关联,并在Emacs退出前进行保存。buffer-file-name 可以帮助我们获取当前buffer关联的文件的物理路径。如果我们要修改/设置某个buffer关联的物理文件,可以使用 set-visited-file-name

第三个属性是修改状态。当Emacs打开一个文件时,会将文件的内容加载到buffer中,并将二者进行关联。此时buffer处于未修改或者说干净的状态。如果我们执行操作修改了文件内容,那么此时buffer会变成修改但未保存到文件的状态,或者说是脏页状态。我们手动执行保存操作之后buffer又会恢复干净的状态。

如果我们关闭Emacs时,Emacs默认会遍历当前打开的buffer,对于哪些处于修改状态的buffer会弹出提示框询问我们是否需要保存。但是对于那些没有关联到文件上的则省去了询问的过程。

我们可以通过 buffer-modified-p 来查看当前buffer 是否被修改了。也可以通过 set-buffer-modified-p 来设置它的状态。

第四个属性是只读属性。如果尝试修改它会报错。我们可以通过 buffer-read-only 这个变量来确定当前buffer是否是只读的。例如我们可以写一个简单的函数来判断指定buffer是只读状态

(defun my/buffer-read-only-p (bname)
  (interactive "B输入对应的buffer:")
  (let ((buffer (get-buffer bname)))
    (if buffer
    (with-current-buffer buffer
      (if buffer-read-only
          (message "buffer %s 是只读的" bname)
        (message "buffer %s 不是只读" bname)))
      (message "未找到指定名称的buffer"))))

我们可以通过设置当前buffer的 inhibit-read-only 变量为t来临时的取消buffer的只读状态,例如我们可以尝试通过以下代码清空 Messages buffer

(defun my/clear-messages-buffer()
  (interactive)
  (let ((message-buffer (get-buffer "*Messages*")))
    (if message-buffer
    (with-current-buffer message-buffer
      (let ((inhibit-read-only t))
        (erase-buffer))))))

请注意我们这里使用的是 let 设置的变量值,而没有使用 setq。我们这里实际上创建的是同名的临时变量,用临时变量覆盖了buffer的“全局变量”。在临时变量存在的时候Emacs读取的是这个临时变量的值,此举会短暂性的将buffer修改为可写状态。在代码跳出let的作用域之后临时变量被销毁,inhibit-read-only 又恢复了初始值。而setq 就达不到这个效果。

在 Emacs Lisp 官方开发规范中,临时修改只读 Buffer 最标准的做法就是利用 let 绑定 inhibit-read-only

练习

有了这些基础,我们可以写一个批量保存的小工具。我们可以遍历当前所有打开的buffer,判断buffer是否是修改状态,如果被修改并且绑定到了具体的物理文件则执行保存操作。保存buffer到文件可以使用 save-buffer 函数

(defun my/save-all-buffers()
  (interactive)
  (dolist (buffer (buffer-list))
    (with-current-buffer buffer
      (when (and (buffer-modified-p) (buffer-file-name))
      (save-buffer)))))

总结

本篇我们介绍了,Emacs中关于buffer的一些常用属性,以及修改它们的函数或者变量。下面我将其列举出来

  • buffer-namerename-buffer
  • buffer-file-nameset-visited-file-name
  • buffer-modified-pset-buffer-modified-p
  • buffer-read-onlyinhibit-read-only
0

评论 (0)

取消