2 Star 13 Fork 3

advanceflow/Elisp

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

32 标记

标记是一个 Lisp 对象,用于指定缓冲区中相对于周围文本的位置。 每当插入或删除文本时,标记会自动更改其与缓冲区开头的偏移量,以便它与两侧的两个字符保持一致。

32.1 标记概述

标记指定缓冲区和该缓冲区中的位置。 标记可用于表示需要标记的函数中的位置,就像可以使用整数一样。 在这种情况下,标记的缓冲区通常会被忽略。 当然,以这种方式使用的标记通常指向缓冲区中函数操作的位置,但这完全是程序员的责任。 有关职位的完整描述,请参阅职位。

标记具有三个属性:标记位置、标记缓冲区和插入类型。 标记位置是一个整数,相当于(在给定时间)作为该缓冲区中位置的标记。 但是标记的位置值可能会在标记的生命周期内发生变化,而且经常会发生变化。 在缓冲区中插入和删除文本会重新定位标记。 这个想法是,尽管在缓冲区中的其他地方插入和删除,位于两个字符之间的标记仍保留在这两个字符之间。 重定位会更改标记的整数等效值。

删除标记位置周围的文本会将标记留在已删除文本之前和之后的字符之间。 在标记位置插入文本通常会将标记留在新文本之前或之后,具体取决于标记的插入类型(请参阅标记插入类型)——除非插入是使用 insert-before-markers 完成的(请参阅插入文本)。

缓冲区中的插入和删除必须检查所有标记并在必要时重新定位它们。 这会减慢具有大量标记的缓冲区中的处理速度。 出于这个原因,如果您确定不再需要它,最好不要在任何地方做一个标记点​​。 无法再访问的标记最终会被删除(请参阅垃圾收集)。

因为对标记位置执行算术运算很常见,所以大多数这些操作(包括 + 和 -)都接受标记作为参数。 在这种情况下,标记代表其当前位置。

以下是创建标记、设置标记和将点移动到标记的示例:

;; Make a new marker that initially does not point anywhere:
(setq m1 (make-marker))
     ⇒ #<marker in no buffer>


;; Set m1 to point between the 99th and 100th characters
;;   in the current buffer:
(set-marker m1 100)
     ⇒ #<marker at 100 in markers.texi>


;; Now insert one character at the beginning of the buffer:
(goto-char (point-min))
     ⇒ 1
(insert "Q")
     ⇒ nil


;; m1 is updated appropriately.
m1
     ⇒ #<marker at 101 in markers.texi>


;; Two markers that point to the same position
;;   are not eq, but they are equal.
(setq m2 (copy-marker m1))
     ⇒ #<marker at 101 in markers.texi>
(eq m1 m2)
     ⇒ nil
(equal m1 m2)
     ⇒ t


;; When you are finished using a marker, make it point nowhere.
(set-marker m1 nil)
     ⇒ #<marker in no buffer>

32.2 关于标记的谓词

您可以测试一个对象以查看它是否是标记,或者它是整数还是标记。 后一个测试对于同时使用标记和整数的算术函数很有用。

Function: markerp object ¶

如果 object 是标记,此函数返回 t,否则返回 nil。 请注意,整数不是标记,即使许多函数将接受标记或整数。

Function: integer-or-marker-p object ¶

如果 object 是整数或标记,此函数返回 t,否则返回 nil。

Function: number-or-marker-p object ¶

如果 object 是数字(整数或浮点数)或标记,则此函数返回 t,否则返回 nil。

32.3 创建标记的函数

当你创建一个新的标记时,你可以让它不指向任何地方,或者指向点的当前位置,或者指向缓冲区可访问部分的开始或结束,或者指向与另一个给定标记相同的位置。

接下来的四个函数都返回插入类型为 nil 的标记。 请参阅标记插入类型。

Function: make-marker ¶

此函数返回一个新创建的不指向任何地方的标记。

  (make-marker)
	   ⇒ #<marker in no buffer>
Function: point-marker ¶

此函数返回一个新标记,该标记指向当前缓冲区中点的当前位置。 见点。 例如,请参阅下面的复制标记。

Function: point-min-marker ¶

此函数返回一个新标记,该标记指向缓冲区可访问部分的开头。 除非收窄生效,否则这将是缓冲区的开始。 请参阅收窄。

Function: point-max-marker ¶

此函数返回一个新标记,该标记指向缓冲区可访问部分的末尾。 除非收窄生效,否则这将是缓冲区的结尾。 请参阅收窄。

下面是这个函数和 point-min-marker 的示例,显示在包含本章文本源文件版本的缓冲区中。

  (point-min-marker)
	   ⇒ #<marker at 1 in markers.texi>
  (point-max-marker)
	   ⇒ #<marker at 24080 in markers.texi>


  (narrow-to-region 100 200)
	   ⇒ nil

  (point-min-marker)
	   ⇒ #<marker at 100 in markers.texi>

  (point-max-marker)
	   ⇒ #<marker at 200 in markers.texi>
Function: copy-marker &optional marker-or-integer insertion-type ¶

如果将标记作为其参数传递,则复制标记返回一个新标记,该标记指向与标记或整数相同的位置和相同的缓冲区。 如果传递一个整数作为其参数,则复制标记返回一个新标记,该标记指向当前缓冲区中的位置标记或整数。

新标记的插入类型由参数插入类型指定。 请参阅标记插入类型。

  (copy-marker 0)
	   ⇒ #<marker at 1 in markers.texi>


  (copy-marker 90000)
	   ⇒ #<marker at 24080 in markers.texi>

如果标记既不是标记也不是整数,则会发出错误信号。

如果两个不同的标记具有相同的位置和缓冲区,或者它们都没有指向任何地方,则认为它们彼此相等(即使不是 eq)。

(setq p (point-marker))
     ⇒ #<marker at 2139 in markers.texi>


(setq q (copy-marker p))
     ⇒ #<marker at 2139 in markers.texi>


(eq p q)
     ⇒ nil


(equal p q)
     ⇒ t

32.4 来自标记的信息

本节介绍用于访问标记对象的组件的函数。

Function: marker-position marker ¶

此函数返回标记指向的位置,如果它不指向任何地方,则返回 nil。

Function: marker-buffer marker ¶

此函数返回标记指向的缓冲区,如果它不指向任何地方,则返回 nil。

  (setq m (make-marker))
	   ⇒ #<marker in no buffer>

  (marker-position m)
	   ⇒ nil

  (marker-buffer m)
	   ⇒ nil


  (set-marker m 3770 (current-buffer))
	   ⇒ #<marker at 3770 in markers.texi>

  (marker-buffer m)
	   ⇒ #<buffer markers.texi>

  (marker-position m)
	   ⇒ 3770

32.5 标记插入类型

当您直接在标记指向的位置插入文本时,有两种可能的方法来重新定位该标记:它可以指向插入的文本之前,也可以指向它之后。 您可以通过设置其插入类型来指定给定标记应该执行的操作。 请注意,使用 insert-before-markers 会忽略标记的插入类型,总是将标记重新定位到插入文本之后。

Function: set-marker-insertion-type marker type ¶

该函数将marker标记的插入类型设置为type。 如果 type 为 t,则在其位置插入文本时,标记将前进。 如果 type 为 nil,则在此处插入文本时标记不会前进。

Function: marker-insertion-type marker ¶

此函数报告当前插入类型的标记。

所有创建标记而不接受指定插入类型的参数的函数,都使用插入类型 nil 创建它们(请参阅创建标记的函数)。 此外,默认情况下,该标记的插入类型为 nil。

32.6 移动标记位置

本节介绍如何更改现有标记的位置。 当你这样做时,确保你知道标记是否在你的程序之外使用,如果是,移动它会产生什么效果——否则,在 Emacs 的其他部分可能会发生令人困惑的事情。

Function: set-marker marker position &optional buffer ¶

此函数将标记移动到缓冲区中的位置。 如果未提供缓冲区,则默认为当前缓冲区。

如果 position 为 nil 或标记不指向任何地方,则标记设置为不指向任何地方。

返回的值是标记。



  (setq m (point-marker))
	   ⇒ #<marker at 4714 in markers.texi>

  (set-marker m 55)
	   ⇒ #<marker at 55 in markers.texi>

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

  (set-marker m 0 b)
	   ⇒ #<marker at 1 in foo>
Function: move-marker marker position &optional buffer ¶

这是设置标记的另一个名称。

32.7 标记

每个缓冲区都有一个特殊的标记,称为标记。 新建缓冲区时,该标记存在但不指向任何地方; 这意味着该缓冲区中尚不存在该标记。 后续命令可以设置标记。

该标记指定了为许多命令(例如 kill-region 和 indent-rigidly)绑定文本范围的位置。 这些命令通常作用于点和标记之间的文本,称为区域。 如果您正在编写对区域进行操作的命令,请不要直接检查标记; 相反,使用带有“r”规范的交互。 这提供了 point 和 mark 的值作为交互式调用中命令的参数,但允许其他 Lisp 程序显式指定参数。 请参阅代码字符以进行交互。

一些命令将标记设置为副作用。 只有当命令对用户有潜在用途时,命令才应该这样做,而不是为了他们自己的内部目的。 例如,replace-regexp 命令在进行任何替换之前将标记设置为点的值,因为这使用户可以在替换完成后方便地返回那里。

一旦标记存在于缓冲区中,它通常永远不会停止存在。 但是,如果启用了瞬态标记模式,它可能会变为非活动状态。 缓冲区局部变量mark-active,如果非零,则表示该标记是活动的。 命令可以调用函数 deactivate-mark 来直接取消激活标记,也可以在返回到编辑器命令循环时通过将变量 deactivate-mark 设置为非零值来请求取消激活标记。

如果启用了瞬态标记模式,则通常应用于点附近文本的某些编辑命令会在标记处于活动状态时应用于该区域。 这是使用瞬态标记模式的主要动机。 (另一个是,当标记处于活动状态时,这可以突出显示该区域。请参阅 Emacs 显示。)

除了标记之外,每个缓冲区都有一个标记环,它是一个标记列表,其中包含标记的先前值。 编辑命令更改标记时,通常应将标记的旧值保存在标记环上。 变量 mark-ring-max 指定了标记环中的最大条目数; 一旦列表变得这么长,添加一个新元素会删除最后一个元素。

还有一个单独的全局标记环,但仅用于少数特定的用户级命令,与 Lisp 编程无关。 所以我们不在这里描述它。

Function: mark &optional force ¶

此函数以整数形式返回当前缓冲区的标记位置,如果此缓冲区中没有设置标记,则返回 nil。

如果启用了 Transient Mark 模式,并且 mark-even-if-inactive 为 nil,则如果 mark 处于非活动状态,则 mark 会发出错误信号。 但是,如果 force 不为零,则标记忽略标记的不活动,并返回标记位置(或零)。

Function: mark-marker ¶

此函数返回代表当前缓冲区标记的标记。 它不是副本,它是内部使用的标记。 因此,改变这个标记的位置会直接影响缓冲区的标记。 不要那样做,除非那是你想要的效果。



  (setq m (mark-marker))
	   ⇒ #<marker at 3420 in markers.texi>

  (set-marker m 100)
	   ⇒ #<marker at 100 in markers.texi>

  (mark-marker)
	   ⇒ #<marker at 100 in markers.texi>

像任何标记一样,此标记可以设置为指向您喜欢的任何缓冲区。 如果你让它指向除它作为标记的缓冲区之外的任何缓冲区,它将产生完全一致但相当奇怪的结果。 我们建议您不要这样做!

Function: set-mark position ¶

此函数将标记设置为位置,并激活标记。 标记的旧值不会被推送到标记环上。

请注意:仅当您希望用户看到标记已移动,并且您希望之前的标记位置丢失时,才使用此功能。 通常,当设置新标记时,旧标记应该在标记环上。 出于这个原因,大多数应用程序应该使用 push-mark 和 pop-mark,而不是 set-mark。

新手 Emacs Lisp 程序员经常尝试将标记用于错误的目的。 为了方便用户,该标记保存了一个位置。 除非更改标记是命令的用户级功能的一部分,否则编辑命令不应更改标记。 (并且,在这种情况下,应该记录这种效果。)要记住 Lisp 程序内部使用的位置,请将其存储在 Lisp 变量中。 例如:

     (let ((beg (point)))
	(forward-line 1)
	(delete-region beg (point))).
Function: push-mark &optional position nomsg activate ¶

此函数将当前缓冲区的标记设置为位置,并将前一个标记的副本推送到标记环上。 如果 position 为 nil,则使用 point 的值。

按钮标记功能通常不会激活标记。 为此,请为参数激活指定 t。

除非 nomsg 为非零,否则将显示“标记集”消息。

Function: pop-mark ¶

此函数弹出标记环的顶部元素并使该标记成为缓冲区的实际标记。 这不会移动缓冲区中的点,如果标记环为空,它什么也不做。 它使标记失效。

User Option: transient-mark-mode ¶

此变量,如果非零,启用瞬态标记模式。 在 Transient Mark 模式下,每个缓冲区修改原语都设置 deactivate-mark。 因此,大多数修改缓冲区的命令也会停用该标记。

当启用瞬态标记模式并且标记处于活动状态时,通常应用于文本附近点的许多命令改为应用于该区域。 这样的命令应该使用函数 use-region-p 来测试它们是否应该在区域上操作。 见地区。

Lisp 程序可以将瞬态标记模式设置为非零、非 t 值以临时启用瞬态标记模式。 如果值为 lambda,则瞬态标记模式会在任何操作(例如缓冲区修改)后自动关闭,这通常会停用标记。 如果该值为(仅 .oldval),则在任何移动点且未移位转换的后续命令之后,或在任何其他通常会正常执行的操作之后,将瞬态标记模式设置为值 oldval停用标记。 (用鼠标标记一个区域会以这种方式临时启用瞬态标记模式。)

User Option: mark-even-if-inactive ¶

如果它不是 nil,Lisp 程序和 Emacs 用户可以使用该标记,即使它处于非活动状态。 此选项影响瞬态标记模式的行为。 当该选项为非 nil 时,标记的停用会关闭区域突出显示,但使用该标记的命令的行为就像该标记仍处于活动状态一样。

Variable: deactivate-mark ¶

如果编辑器命令将此变量设置为非零,则编辑器命令循环会在命令返回后停用标记(如果启用了瞬态标记模式)。 所有更改缓冲区的原语都设置了 deactivate-mark,以在命令完成时停用该标记。 设置此变量使其成为缓冲区本地。

要编写修改缓冲区而不导致在命令末尾停用标记的 Lisp 代码,请将 deactivate-mark 绑定到执行修改的代码周围的 nil 。 例如:

     (let (deactivate-mark)
	(insert " "))
Function: deactivate-mark &optional force ¶

如果启用了 Transient Mark 模式或 force 为非 nil,则此函数停用标记并运行正常的钩子 deactivate-mark-hook。 否则,它什么也不做。

Variable: mark-active ¶

当此变量为非零时,该标记处于活动状态。 此变量在每个缓冲区中始终是缓冲区本地的。 不要使用此变量的值来决定通常对文本近点操作的命令是否应该改为对区域进行操作。 为此使用函数 use-region-p(请参阅 The Region)。

Variable: activate-mark-hook ¶
Variable: deactivate-mark-hook ¶

这些正常的钩子分别在标记变为活动和不活动时运行。 当区域被重新激活时,钩子 activate-mark-hook 也会运行,例如在使用切换回具有活动标记的缓冲区的命令之后。

Function: handle-shift-selection ¶

此函数实现点运动命令的移位选择行为。 请参阅 GNU Emacs 手册中的 Shift 选择。 每当在其交互规范中调用带有 ‘^’ 字符的命令时,在命令本身执行之前,它就会被 Emacs 命令循环自动调用(参见 ^)。

如果 shift-select-mode 不是 nil 并且当前命令是通过 shift 转换调用的(请参阅 shift-translation),则此函数设置标记并临时激活该区域,除非该区域已经以这种方式临时激活。 否则,如果该区域已被临时激活,它会停用标记并将变量瞬态标记模式恢复为其早期值。

Variable: mark-ring ¶

这个缓冲区局部变量的值是当前缓冲区保存的以前标记的列表,最近的在前。

   mark-ring
   ⇒ (#<marker at 11050 in markers.texi>
	  #<marker at 10832 in markers.texi>
	  …)
User Option: mark-ring-max ¶

该变量的值是标记环的最大尺寸。 如果更多的标记被推送到标记环上,push-mark 在添加新标记时会丢弃旧标记。

当启用删除选择模式(参见 GNU Emacs 手册中的删除选择)时​​,在活动区域​​(也称为“选择”)上操作的命令的行为会略有不同。 这通过将函数 delete-selection-pre-hook 添加到 pre-command-hook 来工作(请参阅命令循环概述)。 该函数调用 delete-selection-helper 以根据命令删除选择。 如果要使命令适应删除选择模式,请将 delete-selection 属性放在函数的符号上(请参阅访问符号属性); 符号上没有此属性的命令不会删除选择。 此属性可以具有几个值之一,以根据命令应该执行的操作来调整行为; 有关详细信息,请参阅 delete-selection-pre-hook 和 delete-selection-helper 的文档字符串。

32.8 区域

点和标记之间的文本称为区域。 各种功能对由点和标记分隔的文本进行操作,但这里只描述与区域本身特别相关的那些功能。

如果标记没有指向任何地方,则接下来的两个函数会发出错误信号。 如果启用了 Transient Mark 模式并且 mark-even-if-inactive 为 nil,则如果标记处于非活动状态,它们也会发出错误信号。

Function: region-beginning ¶

此函数返回区域开始的位置(作为整数)。 这是点或标记的位置,以较小者为准。

Function: region-end ¶

此函数返回区域结束的位置(作为整数)。 这是点或标记的位置,以较大者为准。

而不是使用 region-beginning 和 region-end ,设计用于在区域上操作的命令通常应该使用与 ‘r’ 规范交互来查找区域的开始和结束。 这让其他 Lisp 程序可以明确指定边界作为参数。 请参阅代码字符以进行交互。

Function: use-region-p ¶

如果启用了瞬态标记模式、标记处于活动状态并且缓冲区中有有效区域,则此函数返回 t。 当标记处于活动状态时,此功能旨在由在区域上操作的命令使用,而不是在点附近的文本上。

如果区域的大小不为零,或者用户选项 use-empty-active-region 为非 nil(默认情况下为 nil),则该区域是有效的。 功能 region-active-p 类似于 use-region-p,但认为所有区域都是有效的。 在大多数情况下,您不应该使用 region-active-p,因为如果区域为空,则通常更适合在点上操作。

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

搜索帮助