Elisp para aplicar el comando solo a la región seleccionada

18

Digamos que tengo un código como este:

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

¿Ahora quiero some-functionoperar solo en la región seleccionada en el búfer? Cómo puedo hacer eso ? Además, ¿puede haber dos rutas de código separadas para hacer algo si he seleccionado alguna región y hacer otra si no la he seleccionado?

Sibi
fuente

Respuestas:

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

El uso de (interactive "r")significa que los parámetros beginningy endrecibirán automáticamente los valores del comienzo de la región y el final de la región, respectivamente, cuando se invoca la función. (También puede obtener esos valores en cualquier momento utilizando las funciones region-beginningy region-end, respectivamente).

La región siempre está presente (si hay una marca en el búfer actual), pero es posible que no piense que es así. La región está activa cuando está resaltada (el texto está seleccionado). Puede probar si la región está activa utilizando predicado region-active-p. Pero la mejor prueba suele ser use-region-p, porque (por defecto) devuelve verdadero (no nil) solo cuando la región está activa y no vacía (el punto y la marca son diferentes).

Originalmente, no se destacaba la región. Y durante mucho tiempo, aunque el resaltado estaba disponible, no era el comportamiento predeterminado. Para que se resalte, debe haber transient-mark-modeactivado (o activado al menos temporalmente). Por defecto, transient-mark-modeestá activado en versiones recientes de Emacs.

Es útil mirar la definición de predicado use-region-p:

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

use-empty-active-regiones una opción de usuario, cuyo valor predeterminado es nil(verdadero), lo que significa que, por defecto use-region-p, no devolverá verdadero si la región está vacía. En ese caso, para que regrese verdadero, el final de la región debe ser mayor que el principio (el comportamiento que describí anteriormente).

Y si miramos la definición de region-active-p:

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

Vemos que devuelve verdadero (no nil) cuando todos estos son verdaderos:

  • transient-mark-mode está prendido.
  • La marca está activa ( mark-active).
  • Hay una marca en el búfer actual.

La marca de estar activo es realmente de lo que se trata la región de estar activo. Cuando está activo, suponiendo que está activado transient-mark-modey hay una marca en el búfer actual, la región se resalta.

Dibujó
fuente
AFAICS si la marca se establece en punto, es decir, la región no se ha extendido, la marca activa es nula. Por lo tanto, Mark-active y transient-mark-mode son las únicas cosas que agregan valor en estas funciones bastante redundantes.
Andreas Röhler
1
@ AndreasRöhler: No. C-SPC M-: mark-active=> t. Definitivamente puede tener una región vacía que, sin embargo, está activa.
Dibujó
Bien gracias. Todavía creo que mark-active y region-active-p --definido como extender mayor cero-- debería ser todo lo necesario.
Andreas Röhler