So definieren Sie zusätzliche modenspezifische Paare für den elektrischen Paarmodus

13

electric-pair-modeist ein integrierter Modus zum automatischen Einfügen übereinstimmender Trennzeichenpaare (Klammern, eckige Klammern usw.) basierend auf dem aktuellen Hauptmodus.

Ich weiß, dass ich zusätzliche Paare (die global sein werden ) wie folgt definieren kann :

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

Meine Frage ist , wie kann ich definieren Modus spezifische Paare (zB //, ==für org-mode)?

itsjeyd
quelle

Antworten:

7

Eine einfache Möglichkeit , dies zu tun ist , indem sie electric-pair-pairsund electric-pair-text-pairsPuffer-lokale und sie in Haken für die relevanten Modi anpassen.

Arbeitsbeispiel für 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)

Beachten Sie, dass dieser Ansatz auf andere Situationen verallgemeinerbar ist, in denen Sie den Wert einer globalen Variablen für bestimmte Modi ändern möchten.


Zusätzliche Information: setq-local

Aus dem Abschnitt Erstellen und Löschen von pufferlokalen Bindungen im Elisp-Handbuch :

Makro: setq-local variable value

Dieses Makro erstellt eine pufferlokale Bindung im aktuellen Puffer für VARIABLEund gibt ihm den pufferlokalen Wert VALUE. Dies entspricht einem Anruf make-local-variablegefolgt von setq. VARIABLEsollte ein nicht zitiertes Symbol sein.

itsjeyd
quelle
7

Der richtige Weg: Füllen Sie einen Fehlerbericht über den richtigen Kanal Ihres Projekts aus, z. B. org-submit-bug-reportoder report-emacs-bugund argumentieren Sie, warum die Syntaxklasse Ihres Lieblingscharakters geändert werden sollte.

Alternativ können Sie die richtige Syntaxtabelle (info "(elisp) Syntax Tables")in Ihrem ändern init.el.

Versuchen wir es mit 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))

Alternativ können Sie die Fallback-Variablen verwenden. Hier ist ein Defun, der funktionieren sollte, den Sie aber vielleicht schöner machen möchten:

(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
quelle
Vielen Dank, dass Sie eine Antwort veröffentlicht haben, die zeigt, wie Sie die Syntaxtabelle ändern können. Von den beiden Vorschlägen in Ihrer Antwort ist dies der Ansatz, den ich bevorzugen würde. W / r / t unter Verwendung der Fallback-Variablen habe ich eine andere Lösung gefunden , die etwas kürzer ist als die defunin Ihrer Antwort.
Itsjeyd
2

Diese Antwort beantwortet Ihre Frage zur Konfiguration nicht electric-pair-mode. Aber es könnte Sie zu den gewünschten Ergebnissen führen.

Das wrap-regionauf Melpa verfügbare Paket könnte die Antwort auf Ihr Problem sein. Hier ist seine kurze Beschreibung von seinem Github:

Wrap Region ist ein Nebenmodus für Emacs, der eine Region mit Interpunktionen umschließt. Bei "markierten" Markup-Modi wie HTML und XML werden Tags verwendet.

Hier ist, wie ich es so eingestellt habe, dass es in meinen ausgewählten Modi funktioniert. Das Snippet behandelt auch die Punkte, die Sie in Ihrer Frage angesprochen haben. org-modeInformationen zu Markierungen für Schrifteigenschaften.

(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

Ich möchte hinzufügen, dass dieses Paket sehr gut mit dem expand-regionPaket funktioniert (auch auf Melpa verfügbar).

Wenn ich mit diesen 2 Paketen dabei bin org-mode, macht es MY-EXPAND-REGION-BINDING *ein Wort fett.

Kaushal Modi
quelle
Danke für deine Antwort. Mir war das wrap-regionPaket bekannt; es ist ziemlich nützlich. Ich versuche derzeit, die Anzahl der Pakete von Drittanbietern zu reduzieren, von denen ich abhängig bin. Daher werde ich diese Lösung nicht verwenden, aber sie verdient hier definitiv eine Erwähnung! :)
itsjeyd
2

Aufbauend auf der Antwort von 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
quelle
Ich musste den Charakteren entkommen, damit es funktionierte(?\= . ?\=)
phoxd