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

前面我们介绍了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是只读状态

emacs-lisp 复制代码
(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

emacs-lisp 复制代码
(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 函数

emacs-lisp 复制代码
(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
相关推荐
Masimaro9 小时前
《elisp 每日一练》—— Major Mode 管理 abbrev-table
emacs
AI情绪识别开源2 天前
检信AI学业生涯智选系统技术方案概述
emacs
Masimaro5 天前
《elisp 每日一练》—— Minor Mode 回顾与综合练习
emacs
aluluka6 天前
《elisp 每日一练》——状态栏显示管理与modeline 动态更新
emacs·lisp·elisp
aluluka7 天前
《elisp 每日一练》——minor mode 快捷键管理
emacs·lisp·elisp
Masimaro7 天前
《elisp 每日一练》——状态栏显示管理与modeline 动态更新
emacs
Masimaro9 天前
《elisp 每日一练》——minor mode 开关变量的管理
emacs
Masimaro10 天前
《elisp 每日一练》—— Minor Mode 变量生成机制与状态控制
emacs
Masimaro11 天前
《elisp 每日一练》——文件与目录的回顾与综合练习
emacs
Masimaro19 天前
《elisp 每日一练》——minibuffer输入读取和set-transient-map 临时热键状态机
emacs