Elisp zum Anwenden des Befehls nur auf die ausgewählte Region

17

Angenommen, ich habe einen Code wie diesen:

(defun some-function ()
  (interactive)
  ;; do something
  )

Jetzt möchte ich some-functionnur die ausgewählte Region im Puffer bearbeiten? Wie kann ich das machen ? Kann es auch zwei separate Codepfade geben, um etwas zu tun, wenn ich eine Region ausgewählt habe, und um etwas anderes zu tun, wenn ich nichts ausgewählt habe?

Sibi
quelle

Antworten:

21
(defun some-function (beginning end)
  (interactive "r")
  (if (use-region-p)
      (message "The region is active, and is from %d to %d" beginning end)
    (message "The region is still there (from % d to %d), but it is inactive" 
             beginning end)))

Die Verwendung von (interactive "r")bedeutet, dass die Parameter beginningund endautomatisch die Werte des Bereichsanfangs und des Bereichsendes empfangen, wenn die Funktion aufgerufen wird. (Sie können diese Werte auch jederzeit über die Funktionen region-beginningbzw. region-endabrufen.)

Die Region ist immer vorhanden (wenn sich eine Markierung im aktuellen Puffer befindet), aber Sie glauben möglicherweise nicht, dass dies der Fall ist. Die Region ist aktiv, wenn sie markiert ist (Text ist ausgewählt). Sie können mithilfe eines Prädikats testen, ob die Region aktiv ist region-active-p. Der bessere Test ist jedoch in der Regel use-region-p, da er (standardmäßig) nilnur dann true (non- ) zurückgibt, wenn die Region sowohl aktiv als auch nicht leer ist (Punkt und Marke sind unterschiedlich).

Ursprünglich gab es keine Hervorhebung der Region. Und lange Zeit war die Hervorhebung zwar verfügbar, aber nicht das Standardverhalten. Damit die Hervorhebung erfolgt, müssen Sie sie aktiviert haben transient-mark-mode(oder zumindest vorübergehend aktivieren). Standardmäßig transient-mark-modeist in neueren Emacs-Versionen aktiviert .

Es ist hilfreich, sich die Definition des Prädikats anzuschauen use-region-p:

(defun use-region-p ()
  (and (region-active-p)
       (or use-empty-active-region
           (> (region-end) (region-beginning)))))

use-empty-active-regionist eine Benutzeroption, deren Standardwert nil(true) ist . Dies bedeutet, dass standardmäßig use-region-pkein true zurückgegeben wird, wenn die Region leer ist. In diesem Fall muss das Ende der Region größer als der Anfang sein (das oben beschriebene Verhalten), damit true zurückgegeben wird.

Und wenn wir uns die Definition von region-active-p:

(defun region-active-p ()
  (and transient-mark-mode
       mark-active
       (mark)))

Wir sehen, dass es true (non- nil) zurückgibt, wenn all dies wahr ist:

  • transient-mark-mode Ist eingeschaltet.
  • Die Markierung ist aktiv ( mark-active).
  • Im aktuellen Puffer befindet sich eine Markierung.

Die Markierung, die aktiv ist, ist wirklich das, worum es in der Region geht, in der sie aktiv ist. Wenn es aktiv ist, transient-mark-modewird die Region hervorgehoben , sofern es eingeschaltet ist und sich eine Markierung im aktuellen Puffer befindet.

Drew
quelle
AFAICS Wenn mark auf point gesetzt ist, dh die Region nicht erweitert wurde, ist mark-active gleich null. Mark-Active- und Transient-Mark-Mode sind also die einzigen Dinge, die diesen ziemlich redundanten Funktionen einen Mehrwert verleihen.
Andreas Röhler
1
@ AndreasRöhler: Nein. C-SPC M-: mark-active=> t. Sie können definitiv eine leere Region haben, die dennoch aktiv ist.
Drew
Okay danke. Denken Sie immer noch, dass mark-active und region-active-p - definiert als Extend größer Null - alle benötigt werden sollten.
Andreas Röhler