1 Star 0 Fork 3

rookieagle/Elisp

forked from advanceflow/Elisp 
加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
28-缓冲区.org 47.56 KB
一键复制 编辑 原始数据 按行查看 历史
advanceflow 提交于 2022-05-28 10:12 . finish s2

28 缓冲区

缓冲区是包含要编辑的文本的 Lisp 对象。 缓冲区用于保存正在访问的文件的内容; 也可能存在未访问文件的缓冲区。 虽然一次可能存在多个缓冲区,但在任何时候只有一个缓冲区被指定为当前缓冲区。 大多数编辑命令作用于当前缓冲区的内容。 每个缓冲区,包括当前缓冲区,可能会或可能不会显示在任何窗口中。

28.1 缓冲区基础

缓冲区是包含要编辑的文本的 Lisp 对象。 缓冲区用于保存正在访问的文件的内容; 也可能存在未访问文件的缓冲区。 尽管通常存在多个缓冲区,但在任何时候只有一个缓冲区被指定为当前缓冲区。 大多数编辑命令作用于当前缓冲区的内容。 每个缓冲区,包括当前缓冲区,可能会或可能不会显示在任何窗口中。

Emacs 编辑中的缓冲区是具有不同名称并保存可编辑文本的对象。 缓冲区对于 Lisp 程序来说是一种特殊的数据类型。 您可以将缓冲区的内容视为可以扩展的字符串; 插入和删除可能发生在缓冲区的任何部分。 见文本。

Lisp 缓冲区对象包含大量信息。 程序员可以通过变量直接访问其中的一些信息,而其他信息只能通过专用函数访问。 例如,访问的文件名可以通过变量直接访问,而点的值只能通过原始函数访问。

可直接访问的特定于缓冲区的信息存储在缓冲区局部变量绑定中,这些绑定是仅在特定缓冲区中有效的变量值。 此功能允许每个缓冲区覆盖某些变量的值。 大多数主要模式都以这种方式覆盖变量,例如填充列或注释列。 有关缓冲区局部变量及其相关函数的更多信息,请参阅缓冲区局部变量。

有关访问缓冲区中文件的相关函数和变量,请参阅访问文件和保存缓冲区。 有关在窗口中显示缓冲区的相关函数和变量,请参阅缓冲区和窗口。

Function: bufferp object ¶

如果 object 是缓冲区,则此函数返回 t,否则返回 nil。

28.2 当前缓冲区

通常,Emacs 会话中有许多缓冲区。 在任何时候,它们中的一个都被指定为当前缓冲区——大多数编辑发生的缓冲区。 大多数用于检查或更改文本的原语都隐式地在当前缓冲区上运行(请参阅文本)。

通常,所选窗口中显示的缓冲区(请参阅选择窗口)是当前缓冲区,但并非总是如此:Lisp 程序可以临时将任何缓冲区指定为当前缓冲区,以便对其内容进行操作,而不会更改显示的内容屏幕。 指定当前缓冲区的最基本功能是设置缓冲区。

Function: current-buffer ¶

此函数返回当前缓冲区。

  (current-buffer)
	   ⇒ #<buffer buffers.texi>
Function: set-buffer buffer-or-name ¶

此函数使 buffer-or-name 成为当前缓冲区。 buffer-or-name 必须是现有缓冲区或现有缓冲区的名称。 返回值是当前缓冲区。

该函数不会在任何窗口中显示缓冲区,因此用户不一定能看到缓冲区。 但是 Lisp 程序现在将在其上运行。

当编辑命令返回到编辑器命令循环时,Emacs 会自动在所选窗口中显示的缓冲区上调用 set-buffer(请参阅选择窗口)。 这是为了防止混淆:它确保当 Emacs 读取命令时光标所在的缓冲区是该命令应用到的缓冲区(请参阅命令循环)。 因此,您不应该使用 set-buffer 明显地切换到不同的缓冲区; 为此,请使用在窗口中切换到缓冲区中描述的函数。

在编写 Lisp 函数时,不要依赖命令循环的这种行为来在操作后恢复当前缓冲区。 编辑命令也可以被其他程序调用为 Lisp 函数,而不仅仅是来自命令循环; 如果子程序不改变当前的缓冲区,调用者会很方便(当然,除非这是子程序的目的)。

要在另一个缓冲区上临时操作,请将 set-buffer 放在 save-current-buffer 表单中。 例如,这里是命令追加到缓冲区的简化版本:

 (defun append-to-buffer (buffer start end)
   "Append the text of the region to BUFFER."
   (interactive "BAppend to buffer: \nr")
   (let ((oldbuf (current-buffer)))
     (save-current-buffer
	(set-buffer (get-buffer-create buffer))
	(insert-buffer-substring oldbuf start end))))

在这里,我们绑定一个局部变量来记录当前缓冲区,然后 save-current-buffer 安排稍后再次使其成为当前缓冲区。 接下来,set-buffer 使指定的缓冲区成为当前缓冲区,并且 insert-buffer-substring 将字符串从原始缓冲区复制到指定的(现在是当前的)缓冲区。

或者,我们可以使用 with-current-buffer 宏:

 (defun append-to-buffer (buffer start end)
   "Append the text of the region to BUFFER."
   (interactive "BAppend to buffer: \nr")
   (let ((oldbuf (current-buffer)))
     (with-current-buffer (get-buffer-create buffer)
	(insert-buffer-substring oldbuf start end))))

在任何一种情况下,如果附加到的缓冲区恰好显示在某个窗口中,则下一次重新显示将显示其文本如何更改。 如果它没有显示在任何窗口中,您将不会立即在屏幕上看到更改。 该命令使缓冲区临时变为当前缓冲区,但不会显示它。

如果您为可能也具有缓冲区本地绑定的变量进行本地绑定(使用 let 或函数参数),请确保相同的缓冲区在本地绑定范围的开头和结尾都是当前的。 否则,您可能会在一个缓冲区中绑定它并在另一个缓冲区中解除绑定!

不要依赖使用 set-buffer 将当前缓冲区改回来,因为如果在错误的缓冲区是当前缓冲区时发生退出,那将无法完成这项工作。 例如,在前面的示例中,这样做是错误的:

(let ((oldbuf (current-buffer)))
  (set-buffer (get-buffer-create buffer))
  (insert-buffer-substring oldbuf start end)
  (set-buffer oldbuf))

正如我们所做的那样,使用 save-current-buffer 或 with-current-buffer 可以正确处理退出、错误和抛出以及普通评估。

Special Form: save-current-buffer body… ¶

save-current-buffer 特殊形式保存当前缓冲区的标识,评估正文形式,最后将该缓冲区恢复为当前缓冲区。 返回值是正文中最后一个表单的值。 即使在通过 throw 或 error 异常退出的情况下也会恢复当前缓冲区(请参阅非本地退出)。

如果从 save-current-buffer 退出时曾经是当前的缓冲区已被杀死,那么它当然不会再次成为当前缓冲区。 相反,无论哪个缓冲区在退出之前是当前的,都会保持当前状态。

Macro: with-current-buffer buffer-or-name body… ¶

with-current-buffer 宏保存当前缓冲区的标识,使缓冲区或名称成为当前缓冲区,评估主体形式,最后恢复当前缓冲区。 buffer-or-name 必须指定现有缓冲区或现有缓冲区的名称。

返回值是正文中最后一个表单的值。 即使在通过 throw 或 error 异常退出的情况下也会恢复当前缓冲区(请参阅非本地退出)。

Macro: with-temp-buffer body… ¶

with-temp-buffer 宏使用临时缓冲区作为当前缓冲区来评估正文表单。 它保存当前缓冲区的标识,创建一个临时缓冲区并使其成为当前缓冲区,评估主体形式,最后在杀死临时缓冲区的同时恢复先前的当前缓冲区。

默认情况下,撤消信息(请参阅撤消)不会记录在此宏创建的缓冲区中(但如果需要,主体可以启用它)。 临时缓冲区也不会运行钩子 kill-buffer-hook、kill-buffer-query-functions(请参阅 Killing Buffers)和 buffer-list-update-hook(请参阅缓冲区列表)。

返回值是正文中最后一个表单的值。 您可以使用 (buffer-string) 作为最后一种形式返回临时缓冲区的内容。

即使在通过 throw 或 error 异常退出的情况下也会恢复当前缓冲区(请参阅非本地退出)。

另请参阅写入文件中的 with-temp-file。

28.3 缓冲区名称

每个缓冲区都有一个唯一的名称,它是一个字符串。 许多作用于缓冲区的函数接受缓冲区或缓冲区名称作为参数。 任何称为缓冲区或名称的参数都属于这种类型,如果它既不是字符串也不是缓冲区,则会发出错误信号。 任何称为 buffer 的参数都必须是实际的缓冲区对象,而不是名称。

短暂且用户通常不感兴趣的缓冲区的名称以空格开头,因此 list-buffers 和 buffer-menu 命令不会提及它们(但如果这样的缓冲区访问文件,则会提及)。 以空格开头的名称最初也会禁用记录撤消信息; 请参阅撤消。

Function: buffer-name &optional buffer ¶

此函数将缓冲区的名称作为字符串返回。 buffer 默认为当前缓冲区。

如果 buffer-name 返回 nil,则表示缓冲区已被杀死。 请参阅杀死缓冲区。



  (buffer-name)
	   ⇒ "buffers.texi"


  (setq foo (get-buffer "temp"))
	   ⇒ #<buffer temp>

  (kill-buffer foo)
	   ⇒ nil

  (buffer-name foo)
	   ⇒ nil

  foo
	   ⇒ #<killed buffer>
Command: rename-buffer newname &optional unique ¶

此函数将当前缓冲区重命名为 newname。 如果 newname 不是字符串,则会发出错误信号。

通常,如果 newname 已在使用中,rename-buffer 会发出错误信号。 但是,如果 unique 不为零,它会修改 newname 以生成一个未使用的名称。 交互式地,您可以使用数字前缀参数创建唯一的非零。 (这就是命令 rename-uniquely 的实现方式。)

此函数返回实际赋予缓冲区的名称。

Function: get-buffer buffer-or-name ¶

此函数返回由 buffer-or-name 指定的缓冲区。 如果 buffer-or-name 是一个字符串并且没有具有该名称的缓冲区,则值为 nil。 如果 buffer-or-name 是一个缓冲区,则按给定返回; 这不是很有用,所以参数通常是一个名称。 例如:



  (setq b (get-buffer "lewis"))
	   ⇒ #<buffer lewis>

  (get-buffer b)
	   ⇒ #<buffer lewis>

  (get-buffer "Frazzle-nots")
	   ⇒ nil

另请参阅创建缓冲区中的函数 get-buffer-create。

Function: generate-new-buffer-name starting-name &optional ignore ¶

此函数返回一个新缓冲区的唯一名称,但不会创建缓冲区。 它以起始名称开头,并通过在“<…>”中附加一个数字来生成一个当前未用于任何缓冲区的名称。 它从 2 开始并不断增加数字,直到它不是现有缓冲区的名称。

如果可选的第二个参数 ignore 不是 nil,它应该是一个字符串,一个潜在的缓冲区名称。 这意味着认为潜在的缓冲区是可接受的,如果它被尝试,即使它是现有缓冲区的名称(通常会被拒绝)。 因此,如果存在名为 ‘foo’、’foo<2>’、’foo<3>’ 和 ‘foo<4>’ 的缓冲区,

  (generate-new-buffer-name "foo")
	   ⇒ "foo<5>"
  (generate-new-buffer-name "foo" "foo<3>")
	   ⇒ "foo<3>"
  (generate-new-buffer-name "foo" "foo<6>")
	   ⇒ "foo<5>"

请参阅创建缓冲区中的相关函数 generate-new-buffer。

28.4 缓冲区文件名

缓冲区文件名是在该缓冲区中访问的文件的名称。 当一个缓冲区没有访问一个文件时,它的缓冲区文件名是 nil。 大多数时候,缓冲区名与缓冲区文件名的非目录部分相同,但缓冲区文件名和缓冲区名是不同的,可以独立设置。 请参阅访问文件。

Function: buffer-file-name &optional buffer ¶

此函数返回缓冲区正在访问的文件的绝对文件名。 如果 buffer 没有访问任何文件,则 buffer-file-name 返回 nil。 如果未提供缓冲区,则默认为当前缓冲区。

(buffer-file-name (other-buffer))
     ⇒ "/usr/user/lewis/manual/files.texi"
Variable: buffer-file-name ¶

此缓冲区局部变量包含当前缓冲区中正在访问的文件的名称,如果不访问文件,则为 nil。 它是一个永久的局部变量,不受 kill-all-local-variables 的影响。

  buffer-file-name
	   ⇒ "/usr/user/lewis/manual/buffers.texi"

在不做各种其他事情的情况下更改此变量的值是有风险的。 通常最好使用 set-visited-file-name (见下文); 那里完成的一些事情,例如更改缓冲区名称,并不是绝对必要的,但其他一些事情对于避免混淆 Emacs 是必不可少的。

Variable: buffer-file-truename ¶

这个缓冲区局部变量保存当前缓冲区中访问的文件的缩写真名,如果没有访问文件,则为 nil。 它是一个永久的局部变量,不受 kill-all-local-variables 的影响。 请参见 Truenames 和 abbreviate-file-name。

Variable: buffer-file-number ¶

这个缓冲区局部变量保存当前缓冲区中访问的文件的文件号和目录设备号,如果没有文件或不存在的文件被访问,则为 nil。 它是一个永久的局部变量,不受 kill-all-local-variables 的影响。

该值通常是一个形式为 (filenum devnum) 的列表。 这对数字在系统上可访问的所有文件中唯一标识该文件。 有关它们的更多信息,请参阅文件属性中的函数文件属性。

如果 buffer-file-name 是符号链接的名称,则两个数字都指递归目标。

Function: get-file-buffer filename ¶

该函数返回缓冲区访问文件filename。 如果没有这样的缓冲区,则返回 nil。 必须是字符串的参数文件名被扩展(请参阅扩展文件名的函数),然后与所有活动缓冲区的访问文件名进行比较。 请注意,缓冲区的缓冲区文件名必须与文件名的扩展完全匹配。 此函数不会识别同一文件的其他名称。

   (get-file-buffer "buffers.texi")
	  ⇒ #<buffer buffers.texi>

在不寻常的情况下,可能有多个缓冲区访问同一个文件名。 在这种情况下,此函数返回缓冲区列表中的第一个此类缓冲区。

Function: find-buffer-visiting filename &optional predicate ¶

这类似于 get-file-buffer,只是它可以返回访问文件的任何缓冲区,可能以不同的名称访问文件。 即缓冲区的缓冲区文件名不需要完全匹配文件名的扩展,它只需要引用同一个文件。 如果谓词非零,它应该是一个参数的函数,一个缓冲区访问文件名。 如果谓词返回非零,则缓冲区仅被视为合适的返回值。 如果找不到合适的缓冲区返回,find-buffer-visiting 返回 nil。

Command: set-visited-file-name filename &optional no-query along-with-file ¶

如果 filename 是一个非空字符串,则该函数将当前缓冲区中访问的文件的名称更改为 filename。 (如果缓冲区没有访问过的文件,这给它一个。)下次保存缓冲区时,它将进入新指定的文件。

该命令将缓冲区标记为已修改,因为它不(据 Emacs 所知)匹配文件名的内容,即使它匹配之前访问过的文件。 它还会重命名缓冲区以对应于新文件名,除非新名称已在使用中。

如果 filename 为 nil 或空字符串,则表示“没有访问过的文件”。 在这种情况下,set-visited-file-name 将缓冲区标记为没有访问过的文件,而不更改缓冲区的修改标志。

通常,此函数要求用户确认是否已经存在缓冲区访问文件名。 如果 no-query 不是 nil,则阻止提出这个问题。 如果已经有一个缓冲区访问文件名,并且用户确认或 no-query 为非 nil,则此函数通过在文件名中附加一个 ‘<…>’ 内的数字来使新的缓冲区名称唯一。

如果连同文件是非零,这意味着假设以前访问的文件已被重命名为文件名。 在这种情况下,该命令不会更改缓冲区的修改标志,也不会更改访问文件修改时间报告的缓冲区记录的最后文件修改时间(请参阅缓冲区修改时间)。 如果连同文件是零,这个函数清除记录的最后文件修改时间,之后访问文件修改时间返回零。

当交互式调用函数 set-visited-file-name 时,它​​会提示输入 minibuffer 中的文件名。

Variable: list-buffers-directory ¶

对于没有访问文件名的缓冲区,此缓冲区局部变量指定一个字符串,以显示在访问文件名所在的缓冲区列表中。 Dired 缓冲区使用此变量。

28.5 缓冲区修改

Emacs 为每个缓冲区保留一个称为修改标志的标志,以记录您是否更改了缓冲区的文本。 每当您更改缓冲区的内容时,此标志设置为 t,并在保存时清除为 nil。 因此,该标志显示是否有未保存的更改。 标志值通常显示在模式行中(请参阅模式行中使用的变量),并控制保存(请参阅保存缓冲区)和自动保存(请参阅自动保存)。

一些 Lisp 程序明确地设置了这个标志。 例如,函数 set-visited-file-name 将标志设置为 t,因为文本与新访问的文件不匹配,即使它与以前访问的文件相比没有变化。

修改缓冲区内容的函数在文本中描述。

Function: buffer-modified-p &optional buffer ¶

如果缓冲区缓冲区自上次从文件读入或保存后已被修改,则此函数返回 t,否则返回 nil。 如果未提供缓冲区,则测试当前缓冲区。

Function: set-buffer-modified-p flag ¶

如果 flag 为非 nil,此函数将当前缓冲区标记为已修改,如果 flag 为 nil,则此函数将其标记为未修改。

调用此函数的另一个效果是无条件地重新显示当前缓冲区的模式行。 实际上,函数 force-mode-line-update 就是这样工作的:

(set-buffer-modified-p (buffer-modified-p))
Function: restore-buffer-modified-p flag ¶

与 set-buffer-modified-p 类似,但不强制重新显示模式行。

Command: not-modified &optional arg ¶

该命令将当前缓冲区标记为未修改,不需要保存。 如果 arg 不为零,则将缓冲区标记为已修改,以便在下一个合适的场合保存。 交互式地, arg 是前缀参数。

不要在程序中使用此功能,因为它会在回显区域打印一条消息; 改用 set-buffer-modified-p(上图)。

Function: buffer-modified-tick &optional buffer ¶

此函数返回缓冲区的修改计数。 这是一个每次修改缓冲区时递增的计数器。 如果 buffer 为 nil(或省略),则使用当前缓冲区。

Function: buffer-chars-modified-tick &optional buffer ¶

此函数返回缓冲区的字符更改修改计数。 对文本属性的更改使该计数器保持不变; 但是,每次在缓冲区中插入或删除文本时,计数器都会重置为 buffer-modified-tick 返回的值。 通过比较两个 buffer-chars-modified-tick 调用返回的值,您可以判断在调用之间该缓冲区中是否发生了字符更改。 如果 buffer 为 nil(或省略),则使用当前缓冲区。

有时需要以一种不会真正更改其文本的方式修改缓冲区,例如仅更改其文本属性。 如果您的程序需要修改缓冲区而不触发任何对缓冲区修改作出反应的钩子和功能,请使用 with-silent-modifications 宏。

Macro: with-silent-modifications body… ¶

执行 body 假装它不修改缓冲区。 这包括检查缓冲区的文件是否被锁定(参见 File Locks)、运行缓冲区修改挂钩(参见 Change Hooks)等。请注意,如果 body 实际修改了缓冲区文本(与其文本属性相反),它的撤消数据可能会变为损坏。

28.6 缓冲区修改时间

假设您访问一个文件并在其缓冲区中进行更改,同时文件本身在磁盘上也发生了更改。 此时,保存缓冲区将覆盖文件中的更改。 有时这可能是您想要的,但通常它会丢失有价值的信息。 因此,Emacs 在保存文件之前使用下面描述的函数检查文件的修改时间。 (请参阅文件属性,了解如何检查文件的修改时间。)

Function: verify-visited-file-modtime &optional buffer ¶

此函数将其访问文件的修改时间记录的缓冲区(默认情况下,当前缓冲区)与操作系统记录的文件的实际修改时间进行比较。 这两者应该是相同的,除非在 Emacs 访问或保存文件后有其他进程写入了该文件。

如果最后的实际修改时间和 Emacs 记录的修改时间相同,则函数返回 t,否则返回 nil。 如果缓冲区没有记录最后修改时间,它也返回 t,即如果访问文件修改时间将返回零。

对于没有访问文件的缓冲区,它总是返回 t,即使访问文件修改时间返回一个非零值。 例如,它总是为 dired 缓冲区返回 t。 对于访问不存在且从未存在的文件的缓冲区,它返回 t,但对于文件已被删除的文件访问缓冲区,它返回 nil。

Function: clear-visited-file-modtime ¶

该函数清除当前缓冲区正在访问的文件的最后修改时间记录。 因此,下次保存此缓冲区的尝试不会抱怨文件修改时间的差异。

此函数在 set-visited-file-name 和其他不应该进行通常测试以避免覆盖已更改文件的特殊位置调用。

Function: visited-file-modtime ¶

此函数返回当前缓冲区记录的最后文件修改时间,作为 Lisp 时间戳(请参阅时间)。

如果缓冲区没有记录最后修改时间,则此函数返回零。 例如,如果缓冲区没有访问文件,或者时间已被 clear-visited-file-modtime 明确清除,就会出现这种情况。 但是请注意,visited-file-modtime 也会返回一些非文件缓冲区的时间戳。 例如,在列出目录的 Dired 缓冲区中,它返回该目录的最后修改时间,由 Dired 记录。

如果缓冲区正在访问一个不存在的文件,则此函数返回 -1。

Function: set-visited-file-modtime &optional time ¶

该函数将访问文件的最后修改时间的缓冲区记录更新为 time 指定的值,如果 time 不为零,否则更新为访问文件的最后修改时间。

如果时间既不是 nil 也不是visited-file-modtime 返回的整数标志,它应该是一个 Lisp 时间值(参见时间)。

如果缓冲区没有从文件中正常读取,或者文件本身由于某些已知的良性原因而被更改,则此函数很有用。

Function: ask-user-about-supersession-threat filename ¶

当文件比缓冲区文本更新时,此函数用于询问用户在尝试修改缓冲区访问文件文件名后如何进行。 Emacs 检测到这一点是因为磁盘上文件的修改时间比上次保存时间要新,并且其内容已更改。 这意味着其他一些程序可能已经更改了该文件。

根据用户的回答,函数可能会正常返回,在这种情况下会继续修改缓冲区,或者它可能会用数据(文件名)发出文件替换错误信号,在这种情况下,建议的缓冲区修改是不允许的。

Emacs 在适当的情况下会自动调用此函数。 它存在,因此您可以通过重新定义它来自定义 Emacs。 有关标准定义,请参见文件 userlock.el。

另请参阅文件锁定中的文件锁定机制。

28.7 只读缓冲区

如果缓冲区是只读的,则您无法更改其内容,尽管您可以通过滚动和缩小来更改内容视图。

只读缓冲区用于两种情况:

访问写保护文件的缓冲区通常是只读的。

在这里,目的是通知用户编辑缓冲区以将其保存在文件中可能是徒劳的或不可取的。 尽管如此,想要更改缓冲区文本的用户可以在使用 Cx Cq 清除只读标志后执行此操作。 Dired 和 Rmail 等模式在使用通常的编辑命令更改内容时将缓冲区设为只读,这可能是一个错误。

这些模式的特殊命令将 buffer-read-only 绑定到 nil(使用 let)或 bind-inhibit-read-only 到 t 在它们自己更改文本的位置周围。

Variable: buffer-read-only ¶

此缓冲区局部变量指定缓冲区是否为只读。 如果此变量非零,则缓冲区是只读的。 但是,仍然可以修改具有禁止只读文本属性的字符。 请参阅禁止只读。

Variable: inhibit-read-only ¶

如果此变量非零,则只读缓冲区,并且根据实际值,可能会修改部分或全部只读字符。 缓冲区中的只读字符是那些具有非零只读文本属性的字符。 有关文本属性的更多信息,请参阅具有特殊含义的属性。

如果 inhibitor-read-only 为 t,则所有只读字符属性均无效。 如果 inhibitor-read-only 是一个列表,那么如果它们是列表的成员,则只读字符属性无效(与 eq 进行比较)。

Command: read-only-mode &optional arg ¶

这是只读次要模式(缓冲区本地次要模式)的模式命令。 开启模式时,buffer-read-only在缓冲区中为非nil; 禁用时,缓冲区中的缓冲区只读为零。 调用约定与其他次要模式命令相同(请参阅编写次要模式的约定)。

这种次要模式主要用作缓冲区只读的包装器; 与大多数次要模式不同,没有单独的只读模式变量。 即使禁用只读模式,具有非零只读文本属性的字符仍然是只读的。 要暂时忽略所有只读状态,请绑定禁止只读,如上所述。

启用只读模式时,如果选项 view-read-only 为非零,则此模式命令也会启用查看模式。 请参阅 GNU Emacs 手册中的 Miscellaneous Buffer Operations。 禁用只读模式时,如果启用了查看模式,它将禁用查看模式。

Function: barf-if-buffer-read-only &optional position ¶

如果当前缓冲区是只读的,则此函数会发出缓冲区只读错误信号。 如果位置处的文本(默认为点)设置了禁止只读文本属性,则不会引发错误。

如果当前缓冲区是只读的,请参阅使用交互,以获取另一种发出错误信号的方法。

28.8 缓冲区列表

缓冲区列表是所有活动缓冲区的列表。 此列表中缓冲区的顺序主要基于每个缓冲区在窗口中显示的最近时间。 几个函数,尤其是 other-buffer,使用这种排序。 为用户显示的缓冲区列表也遵循此顺序。

创建缓冲区会将其添加到缓冲区列表的末尾,而终止缓冲区会将其从该列表中删除。 A buffer moves to the front of this list whenever it is chosen for display in a window (see Switching to a Buffer in a Window) or a window displaying it is selected (see Selecting Windows). 当一个缓冲区被掩埋时,它会移动到列表的末尾(参见下面的 bury-buffer)。 Lisp 程序员没有可用的函数直接操作缓冲区列表。

除了刚刚描述的基本缓冲区列表之外,Emacs 还为每一帧维护了一个本地缓冲区列表,其中首先显示了在该帧中显示(或选择了它们的窗口)的缓冲区。 (此顺序记录在帧的缓冲区列表帧参数中;请参阅缓冲区参数。)该帧中从未显示的缓冲区随后出现,根据基本缓冲区列表排序。

Function: buffer-list &optional frame ¶

此函数返回缓冲区列表,包括所有缓冲区,甚至包括名称以空格开头的缓冲区。 这些元素是实际的缓冲区,而不是它们的名称。

如果 frame 是一个帧,则返回帧的本地缓冲区列表。 如果 frame 为 nil 或省略,则使用基本缓冲区列表:缓冲区按最近显示或选择的顺序出现,无论它们显示在哪些帧上。



   (buffer-list)
	   ⇒ (#<buffer buffers.texi>
	       #<buffer  *Minibuf-1*> #<buffer buffer.c>
	       #<buffer *Help*> #<buffer TAGS>)


   ;; Note that the name of the minibuffer
   ;;   begins with a space!
   (mapcar #'buffer-name (buffer-list))
	  ⇒ ("buffers.texi" " *Minibuf-1*"
	      "buffer.c" "*Help*" "TAGS")

buffer-list返回的列表是专门构造的; 它不是 Emacs 内部的数据结构,修改它对缓冲区的顺序没有影响。 如果要更改基本缓冲区列表中缓冲区的顺序,这里有一个简单的方法:

(defun reorder-buffer-list (new-list)
  (while new-list
    (bury-buffer (car new-list))
    (setq new-list (cdr new-list))))

使用此方法,您可以为列表指定任何顺序,但不会有丢失缓冲区或添加不是有效活动缓冲区的内容的危险。

要更改特定帧的缓冲区列表的顺序或值,请使用 modify-frame-parameters 设置该帧的缓冲区列表参数(请参阅访问帧参数)。

Function: other-buffer &optional buffer visible-ok frame ¶

此函数返回缓冲区列表中除缓冲区之外的第一个缓冲区。 通常,这是出现在最近选择的窗口中的缓冲区(在帧帧或所选帧中,请参阅输入焦点),除了缓冲区。 根本不考虑名称以空格开头的缓冲区。

如果未提供缓冲区(或者如果它不是实时缓冲区),则 other-buffer 返回所选帧的本地缓冲区列表中的第一个缓冲区。 (如果 frame 不是 nil,则返回 frame 的本地缓冲区列表中的第一个缓冲区。)

如果 frame 有一个非 nil 缓冲区谓词参数,则 other-buffer 使用该谓词来决定要考虑哪些缓冲区。 它为每个缓冲区调用一次谓词,如果值为 nil,则忽略该缓冲区。 请参阅缓冲区参数。

如果 visible-ok 为 nil,则 other-buffer 避免返回在任何可见帧上的任何窗口中可见的缓冲区,除非作为最后的手段。 如果 visible-ok 不为零,那么缓冲区是否显示在某处并不重要。

如果不存在合适的缓冲区,则返回缓冲区 *scratch*(并在必要时创建)。

Function: last-buffer &optional buffer visible-ok frame ¶

此函数返回帧缓冲区列表中除缓冲区之外的最后一个缓冲区。 如果 frame 被省略或为零,它使用选定帧的缓冲区列表。

参数 visible-ok 与 other-buffer 一样处理,见上文。 如果找不到合适的缓冲区,则返回缓冲区 *scratch*。

Command: bury-buffer &optional buffer-or-name ¶

此命令将 buffer-or-name 放在缓冲区列表的末尾,而不更改列表中任何其他缓冲区的顺序。 因此,此缓冲区成为其他缓冲区返回的最不理想的候选者。 参数可以是缓冲区本身,也可以是缓冲区的名称。

该函数对每个帧的缓冲区列表参数以及基本缓冲区列表进行操作; 因此,您埋入的缓冲区将在 (buffer-list frame) 的值和 (buffer-list) 的值中排在最后。 此外,它还将缓冲区放在所选窗口的缓冲区列表的末尾(请参阅窗口历史记录),前提是它显示在该窗口中。

如果 buffer-or-name 为 nil 或省略,这意味着要掩埋当前缓冲区。 此外,如果当前缓冲区显示在所选窗口中(请参阅选择窗口),这将确保窗口被删除或显示另一个缓冲区。 更准确地说,如果选定的窗口是专用的(请参阅专用窗口)并且其框架上有其他窗口,则该窗口将被删除。 如果它是其框架上的唯一窗口,并且该框架不是其终端上的唯一框架,则通过调用 frame-auto-hide-function 指定的函数来解除该框架(请参阅退出窗口)。 否则,它会调用 switch-to-prev-buffer(参见 Window History)以在该窗口中显示另一个缓冲区。 如果 buffer-or-name 显示在其他窗口中,它仍然显示在那里。

要在显示它的所有窗口中替换缓冲区,请使用 replace-buffer-in-windows,请参阅缓冲区和窗口。

Command: unbury-buffer ¶

此命令切换到所选帧的本地缓冲区列表中的最后一个缓冲区。 更准确地说,它调用函数 switch-to-buffer(参见 Switching to a Buffer in a Window),以在所选窗口中显示 last-buffer 返回的缓冲区(参见上文)。

Variable: buffer-list-update-hook ¶

每当缓冲区列表更改时,这是一个正常的钩子运行。 运行此钩子的函数(隐式)是 get-buffer-create(参见创建缓冲区)、rename-buffer(参见缓冲区名称)、kill-buffer(参见终止缓冲区)、bury-buffer(参见上文)和 select-window (请参阅选择窗口)。 对于由 get-buffer-create 或 generate-new-buffer 使用非 nil 参数禁止缓冲区钩子创建的内部或临时缓冲区,不会运行此挂钩。

由该钩子运行的函数应避免使用 nil norecord 参数调用 select-window,因为这可能导致无限递归。

28.9 创建缓冲区

本节介绍用于创建缓冲区的两个原语。 get-buffer-create 如果没有找到具有指定名称的现有缓冲区,则创建一个缓冲区; generate-new-buffer 总是创建一个新的缓冲区并给它一个唯一的名字。

这两个函数都接受一个可选参数禁止缓冲区钩子。 如果它不是 nil,则他们创建的缓冲区不会运行 hooks kill-buffer-hook、kill-buffer-query-functions(请参阅 Killing Buffers)和 buffer-list-update-hook(请参阅缓冲区列表)。 这可以避免减慢从未呈现给用户或传递给其他应用程序的内部或临时缓冲区。

可用于创建缓冲区的其他函数包括 with-output-to-temp-buffer(请参阅临时显示)和 create-file-buffer(请参阅访问文件)。 启动子进程也可以创建缓冲区(请参阅进程)。

Function: get-buffer-create buffer-or-name &optional inhibit-buffer-hooks ¶

此函数返回一个名为 buffer-or-name 的缓冲区。 返回的缓冲区不会成为当前缓冲区——此函数不会更改哪个缓冲区是当前缓冲区。

buffer-or-name 必须是字符串或现有缓冲区。 如果它是一个字符串并且具有该名称的活动缓冲区已经存在,则 get-buffer-create 返回该缓冲区。 如果不存在这样的缓冲区,它会创建一个新的缓冲区。 如果 buffer-or-name 是一个缓冲区而不是一个字符串,它会按给定的形式返回,即使它已经死了。

  (get-buffer-create "foo")
	   ⇒ #<buffer foo>

新创建的缓冲区的主要模式设置为基本模式。 (变量 major-mode 的默认值在更高级别处理;请参阅 Emacs 如何选择主要模式。)如果名称以空格开头,则缓冲区最初禁用撤消信息记录(请参阅撤消)。

Function: generate-new-buffer name &optional inhibit-buffer-hooks ¶

此函数返回一个新创建的空缓冲区,但不会使其成为当前缓冲区。 缓冲区的名称是通过将名称传递给函数 generate-new-buffer-name 来生成的(请参阅缓冲区名称)。 因此,如果没有名为 name 的缓冲区,那么它就是新缓冲区的名称; 如果正在使用该名称,则将“<n>”形式的后缀(其中 n 是整数)附加到名称。

如果 name 不是字符串,则会发出错误信号。

  (generate-new-buffer "bar")
	   ⇒ #<buffer bar>

  (generate-new-buffer "bar")
	   ⇒ #<buffer bar<2>>

  (generate-new-buffer "bar")
	   ⇒ #<buffer bar<3>>

新缓冲区的主要模式设置为基本模式。 变量主模式的默认值在更高级别处理。 请参阅 Emacs 如何选择主要模式。

28.10 终止缓冲区

杀死一个缓冲区会使 Emacs 不知道它的名字,并使它占用的内存空间可用于其他用途。

只要有任何东西引用它,已被终止的缓冲区的缓冲区对象就一直存在,但它被特别标记,因此您无法使其成为当前或显示它。 然而,被杀死的缓冲区保留了它们的身份; 如果你杀死两个不同的缓冲区,它们根据 eq 保持不同,尽管两者都死了。

如果你杀死一个当前的或显示在窗口中的缓冲区,Emacs 会自动选择或显示一些其他的缓冲区。 这意味着杀死缓冲区可以更改当前缓冲区。 因此,当你杀死一个缓冲区时,你还应该采取与更改当前缓冲区相关的预防措施(除非你碰巧知道被杀死的缓冲区不是当前的)。 请参阅当前缓冲区。

如果您终止一个缓冲区,该缓冲区是一个或多个间接缓冲区的基本缓冲区(请参阅间接缓冲区),那么间接缓冲区也会被自动终止。

当且仅当缓冲区被杀死时,缓冲区的缓冲区名称为 nil。 未被杀死的缓冲区称为活动缓冲区。 要测试缓冲区是活动的还是终止的,请使用函数 buffer-live-p(见下文)。

Command: kill-buffer &optional buffer-or-name ¶

此函数会杀死缓冲区 buffer-or-name,释放其所有内存以供其他用途或返回给操作系统。 如果 buffer-or-name 为 nil 或省略,它会终止当前缓冲区。

任何将此缓冲区作为进程缓冲区的进程都会发送 SIGHUP(挂起)信号,这通常会导致它们终止。 请参阅向进程发送信号。

如果缓冲区正在访问一个文件并且包含未保存的更改,kill-buffer 会在缓冲区被杀死之前要求用户确认。 即使不以交互方式调用它也会这样做。 为防止请求确认,请在调用 kill-buffer 之前清除修改标志。 请参阅缓冲区修改。

此函数调用 replace-buffer-in-windows 来清理当前显示要被杀死的缓冲区的所有窗口。

杀死一个已经死亡的缓冲区没有任何效果。

如果它实际上杀死了缓冲区,则此函数返回 t。 如果用户拒绝确认或者 buffer-or-name 已经失效,则返回 nil。

  (kill-buffer "foo.unchanged")
	   ⇒ t
  (kill-buffer "foo.changed")

  ---------- Buffer: Minibuffer ----------
  Buffer foo.changed modified; kill anyway? (yes or no) yes
  ---------- Buffer: Minibuffer ----------

	   ⇒ t
Variable: kill-buffer-query-functions ¶

在确认未保存的更改之前,kill-buffer 按出现的顺序调用列表 kill-buffer-query-functions 中的函数,不带参数。 被杀死的缓冲区是调用它们时的当前缓冲区。 此功能的想法是这些功能将要求用户确认。 如果其中任何一个返回 nil,kill-buffer 会保留缓冲区的生命。

对于由 get-buffer-create 或 generate-new-buffer 使用非 nil 参数禁止缓冲区钩子创建的内部或临时缓冲区,不会运行此挂钩。

Variable: kill-buffer-hook ¶

这是一个正常的钩子,由 kill-buffer 在询问了它要问的所有问题之后,在实际杀死缓冲区之前运行。 当钩子函数运行时,要杀死的缓冲区是当前的。 请参阅挂钩。 这个变量是一个永久的局部变量,所以它的局部绑定不会通过改变主要模式来清除。

对于由 get-buffer-create 或 generate-new-buffer 使用非 nil 参数禁止缓冲区钩子创建的内部或临时缓冲区,不会运行此挂钩。

User Option: buffer-offer-save ¶

该变量,如果在特定缓冲区中非零,则告诉 save-buffers-kill-emacs 提供保存该缓冲区,就像它提供保存文件访问缓冲区一样。 如果在第二个可选参数设置为 t 的情况下调用 save-some-buffers,它也会提供保存缓冲区。 最后,如果此变量始终设置为符号,则 save-buffers-kill-emacs 和 save-some-buffers 将始终提供保存。 请参阅保存一些缓冲区的定义。 变量 buffer-offer-save 在出于任何原因设置时会自动变为缓冲区本地。 请参阅缓冲区局部变量。

Variable: buffer-save-without-query ¶

此变量,如果在特定缓冲区中非零,则告诉 save-buffers-kill-emacs 和 save-some-buffers 保存此缓冲区(如果已修改)而不询问用户。 当出于任何原因设置时,该变量会自动变为缓冲区本地。

Function: buffer-live-p object ¶

如果 object 是活动缓冲区(尚未被杀死的缓冲区),则此函数返回 t,否则返回 nil。

28.11 间接缓冲区

间接缓冲区共享某个其他缓冲区的文本,该缓冲区称为间接缓冲区的基本缓冲区。 在某些方面,对于缓冲区,它类似于文件之间的符号链接。 基本缓冲区本身可能不是间接缓冲区。

间接缓冲区的文本始终与其基本缓冲区的文本相同; 通过编辑其中一个所做的更改会立即在另一个中可见。 这包括文本属性以及字符本身。

在所有其他方面,间接缓冲区和它的基本缓冲区是完全分开的。 它们具有不同的名称、独立的点值、独立的缩小、独立的标记和覆盖(尽管在任一缓冲区中插入或删除文本都会重新定位两者的标记和覆盖)、独立的主要模式和独立的缓冲区局部变量绑定。

间接缓冲区不能访问文件,但其基本缓冲区可以。 如果您尝试保存间接缓冲区,那实际上会保存基本缓冲区。

杀死间接缓冲区对其基本缓冲区没有影响。 杀死基本缓冲区有效地杀死了间接缓冲区,因为它不能再次成为当前缓冲区。

Command: make-indirect-buffer base-buffer name &optional clone inhibit-buffer-hooks ¶

这将创建并返回一个名为 name 的间接缓冲区,其基本缓冲区是 base-buffer。 参数 base-buffer 可以是活动缓冲区或现有缓冲区的名称(字符串)。 如果 name 是现有缓冲区的名称,则会发出错误信号。

如果 clone 为非 nil,则间接缓冲区最初共享基本缓冲区的状态,例如主要模式、次要模式、缓冲区局部变量等。 如果省略 clone 或 nil ,则间接缓冲区的状态设置为新缓冲区的默认状态。

如果 base-buffer 是间接缓冲区,则其基本缓冲区用作新缓冲区的基础。 此外,如果 clone 不是 nil,则初始状态是从实际的基本缓冲区复制的,而不是从基本缓冲区复制的。

有关禁止缓冲区挂钩的含义,请参见创建缓冲区。

Command: clone-indirect-buffer newname display-flag &optional norecord ¶

此函数创建并返回一个新的间接缓冲区,该缓冲区共享当前缓冲区的基本缓冲区并复制当前缓冲区的其余属性。 (如果当前缓冲区不是间接的,则将其用作基本缓冲区。)

如果 display-flag 不是 nil,就像在交互式调用中一样,这意味着通过调用 pop-to-buffer 来显示新的缓冲区。 如果 norecord 为非 nil,则表示不将新缓冲区放在缓冲区列表的前面。

Function: buffer-base-buffer &optional buffer ¶

该函数返回缓冲区的基本缓冲区,默认为当前缓冲区。 如果缓冲区不是间接的,则值为 nil。 否则,该值是另一个缓冲区,它永远不是间接缓冲区。

28.12 在两个缓冲区之间交换文本

专用模式有时需要让用户从同一个缓冲区访问几种截然不同的文本。 例如,除了让用户访问文本本身之外,您可能还需要显示缓冲区文本的摘要。

这可以通过多个缓冲区(在用户编辑文本时保持同步)或缩小(参见缩小)来实现。 但是这些替代方案有时可能会变得乏味或过于昂贵,特别是如果每​​种类型的文本都需要昂贵的缓冲区全局操作以提供正确的显示和编辑命令。

Emacs 为这种模式提供了另一种工具:您可以使用 buffer-swap-text 在两个缓冲区之间快速交换缓冲区文本。 这个函数非常快,因为它不移动任何文本,它只改变缓冲区对象的内部数据结构以指向不同的文本块。 使用它,您可以假装一组两个或多个缓冲区实际上是一个虚拟缓冲区,它将所有单独缓冲区的内容保存在一起。

Function: buffer-swap-text buffer ¶

这个函数交换当前缓冲区的文本和它的参数缓冲区的文本。 如果两个缓冲区之一是间接缓冲区(请参阅间接缓冲区)或间接缓冲区的基本缓冲区,它会发出错误信号。

与缓冲区文本相关的所有缓冲区属性也被交换:点和标记的位置、所有标记、覆盖、文本属性、撤消列表、启用多字节字符标志的值(参见启用多字节字符)等。

警告:如果在 save-excursion 表单中调用此函数,则当前缓冲区将在离开表单时设置为 buffer,因为 save-excursion 用于保存位置和缓冲区的标记也将被交换。

如果您在文件访问缓冲区上使用缓冲区交换文本,您应该设置一个挂钩来保存缓冲区的原始文本,而不是它被交换的内容。 write-region-annotate-functions 用于此目的。 您可能应该在缓冲区中将 buffer-saved-size 设置为 -2,以便与之交换的文本中的更改不会干扰自动保存。

28.13 缓冲间隙

Emacs 缓冲区是使用一个不可见的间隙来实现的,以使插入和删除更快。 插入通过填充部分间隙来起作用,而删除则增加间隙。 当然,这意味着必须首先将间隙移动到插入或删除的位点。 仅当您尝试插入或删除时,Emacs 才会移动间隙。 这就是为什么你在一个大缓冲区的一个部分中的第一个编辑命令,在之前在另一个很远的部分进行编辑之后,有时会出现明显的延迟。

这种机制是不可见的,Lisp 代码永远不会受到间隙当前位置的影响,但这些函数可用于获取有关间隙状态的信息。

Function: gap-position ¶

此函数返回当前缓冲区中的当前间隙位置。

Function: gap-size ¶

此函数返回当前缓冲区的当前间隙大小。

马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/rookieagle/elisp.git
git@gitee.com:rookieagle/elisp.git
rookieagle
elisp
Elisp
main

搜索帮助