Elisp do zastosowania polecenia tylko do wybranego regionu

18

Powiedz, mam taki kod:

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

Czy chcę teraz some-functiondziałać tylko na wybranym regionie w buforze? Jak mogę to zrobić ? Czy mogą istnieć dwie osobne ścieżki do zrobienia czegoś, jeśli wybrałem jakiś region i zrobienia czegoś innego, jeśli nie wybrałem.

Sibi
źródło

Odpowiedzi:

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

Zastosowanie (interactive "r")oznacza, że ​​parametry beginningi endautomatycznie otrzymają wartości początku regionu i końca regionu, odpowiednio po wywołaniu funkcji. (Możesz również uzyskać te wartości w dowolnym momencie, używając odpowiednio funkcji region-beginningi region-end.)

Region jest zawsze obecny (jeśli w bieżącym buforze znajduje się znak), ale możesz nie myśleć, że tak jest. Region jest aktywny, gdy jest podświetlony (zaznaczony jest tekst). Możesz sprawdzić, czy region jest aktywny, używając predykatu region-active-p. Ale zwykle lepszy jest test use-region-p, ponieważ (domyślnie) zwraca true (nie nil) tylko wtedy, gdy region jest zarówno aktywny, jak i niepusty (punkt i znak są różne).

Pierwotnie nie było wyróżnienia regionu. I przez długi czas, mimo że podświetlanie było dostępne, nie było to zachowanie domyślne. Aby nastąpiło wyróżnienie, musisz transient-mark-modewłączyć (lub włączyć przynajmniej tymczasowo). Domyślnie transient-mark-modejest włączony w najnowszych wersjach Emacsa.

Warto przyjrzeć się definicji predykatu use-region-p:

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

use-empty-active-regionto opcja użytkownika, której wartością domyślną jest nil(prawda), co oznacza, że ​​domyślnie use-region-pnie zwróci wartości prawda, jeśli region jest pusty. W takim przypadku, aby zwrócił wartość true, koniec regionu musi być większy niż początek (zachowanie, które opisałem powyżej).

A jeśli spojrzymy na definicję region-active-p:

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

Widzimy, że zwraca true (nie nil), gdy wszystkie z nich są prawdziwe:

  • transient-mark-mode jest włączony.
  • Znak jest aktywny ( mark-active).
  • W bieżącym buforze znajduje się znak.

Aktywny znak jest naprawdę tym, na czym polega aktywny region. Gdy jest aktywny, zakładając, że transient-mark-modejest włączony i w bieżącym buforze znajduje się znak, region jest podświetlony.

Rysował
źródło
AFAICS, jeśli znacznik jest ustawiony na punkt, tzn. Region nie rozszerza się, znacznik aktywny jest zerowy. Zatem tryb mark-active i transient-mark-mode są jedynymi wartościami dodającymi wartość w tych dość redundantnych funkcjach.
Andreas Röhler
1
@ AndreasRöhler: Nie. C-SPC M-: mark-active=> t. Zdecydowanie możesz mieć pusty region, który jest jednak aktywny.
Drew
Ok, dzięki. Nadal uważam, że mark-active i region-active-p - zdefiniowane jako rozszerzenie większego zera - powinny być potrzebne.
Andreas Röhler