我写了一个elisp宏,在transient-mark-mode
:
(defmacro keep-region (command)
"Wrap command in code that saves and restores the region"
(letrec ((command-name (symbol-name command))
(advice-name (concat command-name "-keep-region")))
`(progn
(defadvice ,command (around ,(intern advice-name))
(let (deactivate-mark)
(save-excursion
ad-do-it)))
(ad-activate (quote ,command)))))
(keep-region replace-string)
(keep-region replace-regexp)
这会保留使用keep-region
宏建议的命令的区域;想要在选定的块中进行多次替换时非常有用。
问题是在运行使用此宏建议的命令后,该区域会失去其瞬态特性;后续的移动命令扩展了区域,而不是取消选择它。
如何以编程方式重新启用标记区域的短暂性?
答案 0 :(得分:2)
来自C-h f transient-mark-mode
:
瞬态标记模式是一种全局次要模式。启用时, 只要标记处于活动状态,区域就会突出显示。标记是 "去激活"通过改变缓冲区,以及其他一些 设定商标但其主要目的是什么的操作 否则 - 例如,增量搜索,<和>。
因此,activate-mark
之后exchange-point-and-mark
应恢复商标的瞬态性质。
我不确定你为什么在这里使用exchange-point-and-mark
,以及为什么要两次使用它。在我看来,只需将(point)
和(mark)
保存在let
- 绑定中,并在ad-do-it
之后恢复它们会更容易。 push-mark
和pop-mark
也可能会有所帮助,因为后者会自动重新激活该标记。
答案 1 :(得分:1)
只需移除您对exchange-point-and-mark
的来电即可。无论如何,保存都是由deactive-mark
let-binding完成的。
答案 2 :(得分:1)
问题是在运行使用此宏建议的命令后,该区域会失去其瞬态特性;后续的移动命令扩展了区域,而不是取消选择它。
你应该谈论“移动选择的性质”:扩展区域的移动命令是以“正常”方式激活标记时发生的。
转换选择状态存储在transient-mark-mode
变量中,并由不关心handle-shift-selection
值的某人(deactivate-mark
?)修改。我们可以通过保存transient-mark-mode
:
(defmacro keep-region (command)
"Wrap command in code that saves and restores the region"
(letrec ((command-name (symbol-name command))
(advice-name (concat command-name "-keep-region")))
`(progn
(defadvice ,command (around ,(intern advice-name))
(let ((deactivate-mark nil)
(transient-mark-mode transient-mark-mode))
(save-excursion
ad-do-it)))
(ad-activate (quote ,command)))))
transient-mark-mode是`buffer.c'中定义的变量。
...
Lisp程序可能会为此变量赋予某些特殊值:
...
- 值
(only . OLDVAL)
暂时启用瞬态标记模式。之后的任何后续点运动命令都没有 转换,或任何其他通常会停用的操作 标记(例如缓冲区修改),
的值 `transient-mark-mode'设置为OLDVAL。