Elisp para aplicar o comando apenas à região selecionada

18

Digamos, eu tenho um código como este:

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

Agora eu quero some-functionoperar apenas na região selecionada no buffer? Como eu posso fazer isso ? Além disso, pode haver dois caminhos de código separados para fazer algo se eu tiver selecionado alguma região e fazer outra coisa se não tiver selecionado.

Sibi
fonte

Respostas:

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

O uso de (interactive "r")significa que os parâmetros beginninge endreceberão automaticamente os valores da região inicial e final da região, respectivamente, quando a função for chamada. (Você também pode obter esses valores a qualquer momento usando as funções region-beginninge region-end, respectivamente.)

A região está sempre presente (se houver uma marca no buffer atual), mas você pode achar que não. A região está ativa quando é destacada (o texto é selecionado). Você pode testar se a região está ativa usando o predicado region-active-p. Mas o melhor teste geralmente é use-region-pporque (por padrão) ele retorna verdadeiro (não nil) somente quando a região está ativa e não vazia (ponto e marca são diferentes).

Originalmente, não havia destaque na região. E por um longo tempo, embora o destaque estivesse disponível, esse não era o comportamento padrão. Para que ocorra o realce, você deve ter transient-mark-modeativado (ou pelo menos temporariamente). Por padrão, transient-mark-modeestá ativado nas versões recentes do Emacs.

É útil examinar a definição 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-regioné uma opção do usuário, cujo valor padrão é nil(true), o que significa que, por padrão use-region-p, não retornará true se a região estiver vazia. Nesse caso, para retornar verdadeiro, o final da região deve ser maior que o início (o comportamento que descrevi acima).

E se olharmos para a definição de region-active-p:

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

Vemos que ele retorna verdadeiro (não nil) quando tudo isso é verdadeiro:

  • transient-mark-mode está ligado.
  • A marca está ativa ( mark-active).
  • Há uma marca no buffer atual.

A marca de estar ativo é realmente o objetivo da região. Quando está ativo, assumindo que está ativado transient-mark-modee há uma marca no buffer atual, a região é destacada.

Desenhou
fonte
AFAICS se a marca estiver definida para apontar, ou seja, a região não se estender, a marca ativa será nula. Portanto, os modos de marcação ativa e transitória são as únicas coisas que agregam valor nessas funções bastante redundantes.
Andreas Röhler
1
@ AndreasRöhler: Não. C-SPC M-: mark-active=> t. Você pode definitivamente ter uma região vazia que, no entanto, está ativa.
Tirou
Ok obrigado. Ainda acho que mark-active e region-active-p - definidos como estender um zero maior - devem ser todos necessários.
Andreas Röhler