简体   繁体   English

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

[英]How to make region transient in elisp when in transient-mark-mode

I wrote an elisp macro that preserves the region when in transient-mark-mode : 我写了一个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)

This preserves the region for commands that are advised using the keep-region macro; 这为使用keep-region宏建议的命令保留了区域; very helpful when you want to make multiple replacements in a selected block. 想要在选定的块中进行多次替换时非常有用。

The problem is that after running a command that has been advised using this macro, the region loses its transient nature; 问题是在运行使用此宏建议的命令后,该区域会失去其瞬态特性; subsequent movement commands extend the region, rather than deselecting it. 后续的移动命令扩展了区域,而不是取消选择它。

How can I programmatically re-enable the transience of the marked region? 如何以编程方式重新启用标记区域的短暂性?

From Ch f transient-mark-mode : Ch f transient-mark-mode

Transient Mark mode is a global minor mode. 瞬态标记模式是一种全局次要模式。 When enabled, the region is highlighted whenever the mark is active . 启用后, 只要标记处于活动状态 ,区域就会突出显示。 The mark is "deactivated" by changing the buffer, and after certain other operations that set the mark but whose main purpose is something else--for example, incremental search, <, and >. 通过更改缓冲区以及在设置标记但其主要目的是其他内容的某些其他操作(例如,增量搜索,<和>)之后,标记被“停用”。

Hence, activate-mark after exchange-point-and-mark should restore the transient nature of the mark. 因此, exchange-point-and-mark activate-mark后的activate-mark exchange-point-and-mark应该恢复exchange-point-and-mark的瞬态特性。

I am not sure, though, why you are using exchange-point-and-mark here, and why you are calling it twice. 不过,我不确定你为什么在这里使用exchange-point-and-mark ,以及为什么你要两次调用它。 In my opinion, just saving (point) and (mark) in a let -binding and restoring them after ad-do-it would be easier. 在我看来,只需在let -binding中保存(point)(mark)并在ad-do-it之后恢复它们会更容易。 push-mark and pop-mark might help as well, since the latter automatically reactivates the mark anyway. push-markpop-mark也可能有所帮助,因为后者自动重新激活标记。

Just remove your calls to exchange-point-and-mark . 只需删除您对exchange-point-and-mark调用。 The preservation is done by the deactive-mark let-binding anyway. 无论如何,通过deactive-mark let-binding完成保存。

The problem is that after running a command that has been advised using this macro, the region loses its transient nature; 问题是在运行使用此宏建议的命令后,该区域会失去其瞬态特性; subsequent movement commands extend the region, rather than deselecting it. 后续的移动命令扩展了区域,而不是取消选择它。

You should rather talk about "shift-selected nature": movement commands extending the region is what happens when the mark is activated in the "normal" way. 你应该谈论“移位选择的性质”:扩展区域的移动命令是当以“正常”方式激活标记时发生的。

The shift-select status is stored inside the transient-mark-mode variable, and is modified by someone ( handle-shift-selection ?) who doesn't care about the value of deactivate-mark . shift-select状态存储在transient-mark-mode变量中,并由不关心deactivate-mark值的某人( handle-shift-selection ?)修改。 We can get around this by saving the value of transient-mark-mode : 我们可以通过保存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 is a variable defined in `buffer.c'. transient-mark-mode是`buffer.c'中定义的变量。

... ...

Lisp programs may give this variable certain special values: Lisp程序可能会为此变量赋予某些特殊值:

... ...

  • A value of (only . OLDVAL) enables Transient Mark mode temporarily. (only . OLDVAL)暂时启用瞬态标记模式。 After any subsequent point motion command that is not shift-translated, or any other action that would normally deactivate the mark (eg buffer modification), the value of 在没有换档的任何后续点运动命令之后,或者通常会停用标记的任何其他动作(例如缓冲区修改)之后,
    `transient-mark-mode' is set to OLDVAL. `transient-mark-mode'设置为OLDVAL。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM