Parentesi di formattazione automatica


9

Sto cercando di creare una funzione che posiziona / allinea / indenta parentesi graffe secondo la formattazione in stile Allman (per la codifica in C).

In generale, sono un fan dell'interfaccia di Smartparens disponibile per gli utenti per la personalizzazione della funzionalità. Ho scritto un sacco di altre funzioni usando l'interfaccia di Smartparens, quindi avrei una forte preferenza a non cambiare pacchetto a questo punto. Detto questo, sono aperto a implementazioni indipendenti dal pacchetto (ad esempio, potrebbe defadviceessere rilevante qui?).

Sul problema in questione. Qual è l'obiettivo finale? Supponiamo che stiamo codificando e raggiungiamo lo stato rappresentato di seguito. Il simbolo della pipa rappresenta il cursore; Ho digitato l'intestazione della funzione e la parentesi graffa di apertura {e Smartparens ha aggiunto automaticamente la parentesi graffa di chiusura }. A questo punto, mi piacerebbe che premendo RET...

int main {|}

... porta a quanto segue:

int main
{
    |
}

Sono stato in grado di scrivere la funzione che risulta in questo comportamento, ma funziona solo per il primo livello di rientro (ad esempio, per la nostra funzione principale nell'esempio sopra). Non riesco a farlo funzionare per i successivi livelli di rientro (vedi GIF):

inserisci qui la descrizione dell'immagine

Il codice pertinente è di seguito. La funzione non è carina ma penso che dovrebbe funzionare ... L'ultima riga è l'interfaccia di Smartparens.

Eventuali suggerimenti?


(defun my-create-newline-and-enter-sexp (&rest _ignored)
  "Open a new brace or bracket expression, with relevant newlines and indent. "
  (interactive)
  (progn
    (backward-char 2) (newline) (forward-char) (newline)     
    (indent-according-to-mode)                               
    (previous-line 2) (indent-according-to-mode)         
    (next-line) (next-line) (indent-according-to-mode)))      

(sp-local-pair 'c-mode "{" nil :post-handlers '((my-create-newline-and-enter-sexp "RET")))

Risposte:


11

Emacs-24.4 electric-pair-modefa già una parte di ciò che desideri (questa modalità è molto simile a autopair.el, non sono sicuro di come si paragona agli smartparens). E c-toggle-auto-newlinefa l'altra parte.

Ma purtroppo non funzionano insieme. Per favore, M-x report-emacs-bugcosì possiamo sistemarlo.

Invece di c-toggle-auto-newline, puoi anche usare electric-layout-modecon un'impostazione simile (setq electric-layout-rules '((?\{ . around) (?\} . around))).


1
riportato! sarebbe davvero bello se i due potessero lavorare insieme.
Iceman,

7

Risolto. La sequenza di movimenti del cursore dalla mia prima versione (nel post originale) era funky.

Come riferimento per i futuri lettori, dovrebbe funzionare il seguente codice. È necessario il pacchetto Smartparens (che puoi ottenere da git-hub). Sto eseguendo Emacs 24.4. Funziona con la modalità di rientro elettrico abilitata o disabilitata.

(defun my-create-newline-and-allman-format (&rest _ignored)
"Allman-style formatting for C."
  (interactive)
  (progn
    (newline-and-indent)
    (previous-line) (previous-line) (search-forward "{") (backward-char) (newline-and-indent)
    (next-line) (indent-according-to-mode)))

E dovrai includere anche quanto segue nel tuo file init, da qualche parte dopo aver caricato il pacchetto Smartparens:

(sp-local-pair '(c-mode) "{" nil :post-handlers '((my-create-newline-and-allman-format "RET")))

2
Invece di usare cose come previous-linecon search-forwardper provare a riscoprire dove ti trovavi, stai molto meglio ricordare la tua posizione in una variabile e poi semplicemente usare goto-char.
Stefan,

Questa è probabilmente la strada più solida. Ci sono funzioni / variabili / etc che ritieni possano essere utili in questo contesto? Posso solo pensare save-excursionma sono sicuro che ce ne sono altri che non conosco.
Iceman,


0

Ecco il codice che uso, solo per darti altre idee per modificare il tuo codice:

(defun ins-c++-curly ()
  "Insert {}.
Threat is as function body when from endline before )"
  (interactive)
  (cond ((eq major-mode 'term-mode)
         (term-send-raw-string "{}")
         (term-send-raw-string "^B"))
        ((looking-back "\\()\\|try\\|else\\|const\\|:\\)$")
         (insert " {\n\n}")
         (indent-according-to-mode)
         (forward-line -1)
         (indent-according-to-mode))
        ((region-active-p)
         (let ((beg (region-beginning))
               (end (region-end)))
           (deactivate-mark)
           (goto-char beg)
           (insert "{")
           (goto-char (1+ end))
           (insert "}")))
        (t
         (insert "{}")
         (indent-according-to-mode)
         (backward-char))))

Preferisco lo stile del gancio sospeso, in quanto consente di risparmiare spazio.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.