Como definir pares específicos de modo adicionais para o modo de par elétrico

13

electric-pair-modeé um embutido modo para inserir automaticamente pares de delimitadores (parênteses, colchetes, etc.) com base no modo de corrente principal.

Eu sei que posso definir pares adicionais (que serão globais ) assim:

(push '(?\' . ?\') electric-pair-pairs)      ; Automatically pair single-quotes
(push '(?\' . ?\') electric-pair-text-pairs) ; ... in comments

Minha pergunta é : como posso definir pares específicos de modo (por exemplo //, ==para org-mode)?

itsjeyd
fonte

Respostas:

7

Uma maneira fácil de fazer isso é fazendo electric-pair-pairse electric-pair-text-pairstampão-local e personalizando-os em ganchos para modos relevantes.

Exemplo de trabalho para org-mode:

(defvar org-electric-pairs '((?/ . ?/) (?= . ?=)) "Electric pairs for org-mode.")

(defun org-add-electric-pairs ()
  (setq-local electric-pair-pairs (append electric-pair-pairs org-electric-pairs))
  (setq-local electric-pair-text-pairs electric-pair-pairs))

(add-hook 'org-mode-hook 'org-add-electric-pairs)

Observe que essa abordagem é generalizável para outras situações nas quais você deseja modificar o valor de uma variável global para modos específicos.


Informação adicional: setq-local

Na seção Criando e excluindo ligações de buffer-local do manual Elisp :

Macro: setq-local variable value

Essa macro cria uma ligação local do buffer no buffer atual para VARIABLEe fornece o valor local do buffer VALUE. É equivalente a chamar make-local-variableseguido por setq. VARIABLEdeve ser um símbolo sem aspas.

itsjeyd
fonte
7

A maneira correta: preencha um relatório de erro através do canal apropriado do seu projeto, por exemplo, org-submit-bug-reportou report-emacs-buge discuta por que a classe de sintaxe do seu personagem favorito deve ser alterada.

Como alternativa, você pode modificar a tabela de sintaxe adequada (info "(elisp) Syntax Tables"), em sua init.el.

Vamos tentar a Org:

(with-eval-after-load 'org
  (modify-syntax-entry ?/ "(/" org-mode-syntax-table)
  (modify-syntax-entry ?= "(=" org-mode-syntax-table)
  (add-hook 'org-mode-hook 'electric-pair-mode))

Como alternativa, você pode usar as variáveis ​​de fallback. Aqui está um resumo que deve funcionar, mas que você pode querer tornar mais bonito:

(defun rasmus/electric-pairs-with-local-pairs (pairs)
  "Start electric pair with buffer-local PAIRS.

  PAIRS is a list of strings and/or cons of strings."
  (require 'elec-pair)
  (let ((ec-lists '(electric-pair-pairs electric-pair-text-pairs)))
    (mapc 'make-local-variable ec-lists)        
    (mapc (lambda (L)
            (mapc (lambda (elm) (add-to-list L elm))
                  (mapcar (lambda (x)
                            (if (consp x)
                                (cons (string-to-char (car x))
                                      (string-to-char (cdr x)))
                              (cons (string-to-char x)
                                    (string-to-char x))))
                          pairs)))
          ec-lists))
  (electric-pair-mode t))

(with-eval-after-load 'org
  (add-hook 'org-mode-hook
            (lambda ()
              (rasmus/electric-pairs-with-local-pairs
               '("/" "=" ("`" . "'"))))))
rasmus
fonte
Obrigado por postar uma resposta que mostra como modificar a tabela de sintaxe. Das duas sugestões em sua resposta, essa é a abordagem que eu preferiria. W / r / t usando as variáveis ​​de fallback, eu vim com outra solução que é um pouco menor que a defunda sua resposta.
itsjeyd
2

Esta resposta não responde à sua pergunta sobre como configurar electric-pair-mode. Mas isso pode levar você aos resultados desejados.

O wrap-regionpacote disponível no Melpa pode ser a resposta para o seu problema. Aqui está uma breve descrição do seu github:

Região de quebra automática é um modo secundário para o Emacs que envolve uma região com pontuações. Para os modos de marcação "etiquetados", como HTML e XML, ele envolve etiquetas.

Aqui está como eu o configurei para funcionar nos meus modos selecionados. O snippet também cobre os pontos que você levantou na sua pergunta; sobre org-modemarcadores de propriedade de fonte.

(require 'wrap-region)

;; Enable wrap-region in the following major modes
(dolist (hook '(emacs-lisp-mode-hook
                org-mode-hook))
  (add-hook hook 'wrap-region-mode))

(wrap-region-add-wrapper "`" "'") ; select region, hit ` then region -> `region'

(wrap-region-add-wrapper "=" "=" nil 'org-mode) ; select region, hit = then region -> =region= in org-mode
(wrap-region-add-wrapper "*" "*" nil 'org-mode) ; select region, hit * then region -> *region* in org-mode
(wrap-region-add-wrapper "/" "/" nil 'org-mode) ; select region, hit / then region -> /region/ in org-mode
(wrap-region-add-wrapper "_" "_" nil 'org-mode) ; select region, hit _ then region -> _region_ in org-mode
(wrap-region-add-wrapper "+" "+" nil 'org-mode))) ; select region, hit + then region -> +region+ in org-mode

Gostaria de acrescentar que este pacote funciona muito bem com o expand-regionpacote (também disponível no Melpa).

Com estes 2 pacotes, quando eu estou org-mode, fazendo: MY-EXPAND-REGION-BINDING *em uma palavra vai torná-lo em negrito.

Kaushal Modi
fonte
Obrigado pela sua resposta. Eu estava ciente do wrap-regionpacote; é bastante útil. Atualmente, estou tentando reduzir o número de pacotes de terceiros dos quais dependo, por isso não usarei esta solução, mas ela definitivamente merece uma menção aqui! :)
itsjeyd
2

Com base na resposta de itsjeyd:

(defmacro spw/add-mode-pairs (hook pairs)
  `(add-hook ,hook
             (lambda ()
               (setq-local electric-pair-pairs (append electric-pair-pairs ,pairs))
               (setq-local electric-pair-text-pairs electric-pair-pairs))))

(spw/add-mode-pairs 'emacs-lisp-mode-hook '((?` . ?')))
Sean Whitton
fonte
Eu tive que escapar caracteres, a fim de fazê-lo funcionar(?\= . ?\=)
phoxd