Jak zdefiniować dodatkowe pary specyficzne dla trybu dla trybu pary elektrycznej

13

electric-pair-modeto tryb wbudowany do automatycznego wstawiania pasujących par ograniczników (nawiasów, nawiasów kwadratowych itp.) w oparciu o bieżący tryb główny.

Wiem, że mogę zdefiniować dodatkowe pary (które będą globalne ) w następujący sposób:

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

Moje pytanie brzmi : jak mogę zdefiniować pary specyficzne dla trybu (np. //, ==Dla org-mode)?

itsjeyd
źródło

Odpowiedzi:

7

Prostym sposobem na to jest poprzez electric-pair-pairsi electric-pair-text-pairsbufor-local i dostosowując je do haków do odpowiednich trybów.

Przykład roboczy dla 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)

Zauważ, że to podejście można uogólnić na inne sytuacje, w których chcesz zmodyfikować wartość zmiennej globalnej dla określonych trybów.


Dodatkowe informacje: setq-local

Z Tworzenie i usuwanie Buffer-Local Wiązania sekcji obsługi Elisp :

Makro: setq-local variable value

To makro tworzy lokalne powiązanie bufora w bieżącym buforze dla VARIABLEi nadaje mu wartość lokalnego bufora VALUE. Jest to odpowiednik połączenia, make-local-variablepo którym następuje setq. VARIABLEpowinien być niecytowanym symbolem.

itsjeyd
źródło
7

Prawidłowy sposób: wypełnij zgłoszenie błędu odpowiednim kanałem swojego projektu, np. org-submit-bug-reportLub report-emacs-bugargumentuj, dlaczego należy zmienić klasę składni ulubionej postaci.

Alternatywnie możesz zmodyfikować odpowiednią tabelę składni (info "(elisp) Syntax Tables")w swoim init.el.

Spróbujmy 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))

Alternatywnie możesz użyć zmiennych rezerwowych. Oto defun, który powinien zadziałać, ale możesz sprawić, że będzie ładniejszy:

(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
źródło
Dziękujemy za opublikowanie odpowiedzi, która pokazuje, jak zmodyfikować tabelę składni. Spośród dwóch sugestii zawartych w Twojej odpowiedzi wolę takie podejście. W / r / t przy użyciu zmiennych rezerwowych wymyśliłem inne rozwiązanie, które jest nieco krótsze niż defunw twojej odpowiedzi.
itsjeyd
2

Ta odpowiedź nie odpowiada na pytanie dotyczące konfiguracji electric-pair-mode. Ale może prowadzić do pożądanych rezultatów.

wrap-regionPakiet dostępny na Melpa może być odpowiedź na swój problem. Oto jego krótki opis z github:

Zawijaj region to niewielki tryb dla Emacsa, który owija region interpunkcjami. W trybach znaczników „tagowanych”, takich jak HTML i XML, jest on zawijany znacznikami.

Oto jak ustawiłem go do pracy w wybranych trybach. Fragment obejmuje również punkty, które poruszyłeś w swoim pytaniu; o org-modeznacznikach właściwości czcionek.

(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

Chciałbym dodać, że ten pakiet działa naprawdę dobrze z expand-regionpakietem (dostępnym również w Melpa).

Z tymi 2 pakietami, kiedy jestem w org-modeśrodku, robię: MY-EXPAND-REGION-BINDING *jednym słowem rozjaśni to.

Kaushal Modi
źródło
Dziękuję za odpowiedź. Byłem świadomy wrap-regionpaczki; to całkiem przydatne. Obecnie próbuję zmniejszyć liczbę pakietów innych firm, na których polegam, więc nie będę korzystać z tego rozwiązania, ale zdecydowanie warto o tym wspomnieć! :)
itsjeyd
2

Opierając się na odpowiedzi 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
źródło
Musiałem uciec od postaci, aby to zadziałało(?\= . ?\=)
phoxd