Elisp per applicare il comando solo alla regione selezionata


18

Dì, ho un codice come questo:

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

Ora voglio some-functionoperare solo sulla regione selezionata nel buffer? Come posso fare ciò ? Inoltre, possono esserci due percorsi di codice separati per fare qualcosa se ho selezionato una regione e fare qualcos'altro se non ho selezionato.

Risposte:


22
(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)))

L'uso di (interactive "r")significa che i parametri beginninge endriceveranno automaticamente i valori dell'inizio e della fine della regione, rispettivamente, quando viene invocata la funzione. (Puoi anche ottenere quei valori in qualsiasi momento usando le funzioni region-beginninge region-end, rispettivamente.)

La regione è sempre presente (se è presente un segno nel buffer corrente), ma potresti non pensare che lo sia. La regione è attiva quando è evidenziata (il testo è selezionato). È possibile verificare se la regione è attiva utilizzando predicato region-active-p. Ma il test migliore è di solito use-region-p, perché (per impostazione predefinita) restituisce true (non- nil) solo quando la regione è attiva e non vuota (punto e segno sono diversi).

Inizialmente, non vi era alcun evidenziamento della regione. E per molto tempo, anche se l'evidenziazione era disponibile, non era il comportamento predefinito. Perché si verifichi l'evidenziazione, è necessario aver transient-mark-modeattivato (o attivato almeno temporaneamente). Per impostazione predefinita, transient-mark-modeè attivato nelle versioni recenti di Emacs.

È utile esaminare la definizione di predicato use-region-p:

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

use-empty-active-regionè un'opzione utente, il cui valore predefinito è nil(true), il che significa che per impostazione predefinita use-region-pnon restituirà true se l'area è vuota. In tal caso, affinché ritorni vero, la fine della regione deve essere maggiore dell'inizio (il comportamento che ho descritto sopra).

E se guardiamo alla definizione di region-active-p:

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

Vediamo che restituisce true (non- nil) quando tutti questi sono true:

  • transient-mark-mode è acceso.
  • Il segno è attivo ( mark-active).
  • C'è un segno nel buffer corrente.

Il marchio attivo è proprio ciò che riguarda la regione attiva. Quando è attivo, supponendo che sia attivo e che transient-mark-modesia presente un segno nel buffer corrente, l'area viene evidenziata.


AFAICS se mark è impostato su point, ovvero la regione non si è estesa, mark-active è zero. Quindi mark-active e transient-mark-mode sono le uniche cose che aggiungono valore in queste funzioni abbastanza ridondanti.
Andreas Röhler,

1
@ AndreasRöhler: No. C-SPC M-: mark-active=> t. Puoi sicuramente avere una regione vuota che è comunque attiva.
Disegnò

Va bene, grazie. Continuo a pensare che mark-active e region-active-p - definito come extender zero maggiore - dovrebbero essere tutti necessari.
Andreas Röhler,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.