Elisp для применения команды только к выбранному региону

18

Скажем, у меня есть такой код:

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

Теперь я хочу some-functionработать только с выбранным регионом в буфере? Как я могу это сделать ? Кроме того, могут ли быть два отдельных пути кода, чтобы сделать что-то, если я выбрал какой-то регион, и сделать что-то еще, если я не выбрал.

Сиби
источник

Ответы:

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

Использование (interactive "r")означает, что параметры beginningи endавтоматически получат значения начала области и конца области соответственно при вызове функции. (Вы также можете получить эти значения в любое время, используя функции region-beginningи region-end, соответственно.)

Регион всегда присутствует (если в текущем буфере есть метка), но вы можете об этом не думать. Регион активен, когда он выделен (выделен текст). Вы можете проверить, активен ли регион, используя предикат region-active-p. Но лучшим тестом обычно является то use-region-p, что (по умолчанию) он возвращает значение true (не nil) только тогда, когда область является активной и непустой (точка и метка различаются).

Первоначально не было никакого выделения региона. И в течение долгого времени, хотя выделение было доступно, это не было поведением по умолчанию. Чтобы подсветка произошла, вы должны были transient-mark-modeвключить (или включить хотя бы временно). По умолчанию transient-mark-modeвключен в последних версиях Emacs.

Полезно взглянуть на определение предиката use-region-p:

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

use-empty-active-regionэто пользовательский параметр, значение по умолчанию nil(true), означающее, что по умолчанию use-region-pне будет возвращать true, если область пуста. В этом случае, чтобы он возвращал значение true, конец области должен быть больше начала (поведение, которое я описал выше).

И если мы посмотрим на определение region-active-p:

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

Мы видим, что он возвращает true (не nil), когда все они верны:

  • transient-mark-mode включен
  • Знак активен ( mark-active).
  • В текущем буфере есть отметка.

Активный знак - это действительно то, что представляет собой активный регион. Когда он активен, при условии, что transient-mark-modeон включен и в текущем буфере есть метка, область подсвечивается.

Нарисовалась
источник
AFAICS, если метка установлена ​​в точку, то есть область не расширяется, mark-active равен нулю. Таким образом, mark-active и transient-mark-mode - единственное, что добавляет ценность этим довольно избыточным функциям.
Андреас Рёлер
1
@ AndreasRöhler: Нет. C-SPC M-: mark-active=> т. Вы можете определенно иметь пустой регион, который, тем не менее, активен.
Дрю
Хорошо спасибо. Все еще думайте, что mark-active и region-active-p - определены как расширение больше нуля - должны быть все необходимы.
Андреас Рёлер