如何在瞬态标记模式下使elisp中的区域瞬态

时间:2014-06-30 11:09:18

标签: emacs elisp

我写了一个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宏建议的命令的区域;想要在选定的块中进行多次替换时非常有用。

问题是在运行使用此宏建议的命令后,该区域会失去其瞬态特性;后续的移动命令扩展了区域,而不是取消选择它。

如何以编程方式重新启用标记区域的短暂性?

3 个答案:

答案 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-markpop-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。
  •