Mise en forme automatique des supports


9

J'essaie de créer une fonction qui place / aligne / indente les accolades selon le formatage de style Allman (pour le codage en C).

De manière générale, je suis fan de l'interface de Smartparens à la disposition des utilisateurs pour la personnalisation des fonctionnalités. J'ai écrit un tas d'autres fonctions en utilisant l'interface Smartparens, donc je préférerais fortement ne pas changer de paquet à ce stade. Cela dit, je suis ouvert aux implémentations indépendantes des packages (par exemple, pourraient defadviceêtre pertinentes ici?).

Passons au problème en cours. Quel est l'objectif final? Supposons que nous codons et que nous atteignons l'état représenté ci-dessous. Le symbole de tuyau représente le curseur; J'ai tapé l'en-tête de fonction et l'accolade ouvrante {, et Smartparens a automatiquement ajouté l'accolade fermante }. À ce stade, je voudrais que presser RET...

int main {|}

... conduit à ce qui suit:

int main
{
    |
}

J'ai pu écrire la fonction qui se traduit par ce comportement mais cela ne fonctionne que pour le premier niveau d'indentation (par exemple, pour notre fonction principale dans l'exemple ci-dessus). Je ne peux pas le faire fonctionner pour les niveaux d'indentation suivants (voir gif):

entrez la description de l'image ici

Le code correspondant est ci-dessous. La fonction n'est pas jolie mais je pense qu'elle devrait fonctionner ... La toute dernière ligne est l'interface avec Smartparens.

Aucune suggestion?


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

Réponses:


11

Emacs-24.4 electric-pair-modefait déjà une partie de ce que vous voulez (ce mode est très similaire à autopair.el, je ne sais pas comment il se compare aux smartparens). Et c-toggle-auto-newlinefait l'autre partie.

Mais malheureusement, ils ne fonctionnent pas correctement ensemble. S'il vous plaît, M-x report-emacs-bugafin que nous puissions résoudre ce problème.

Au lieu de c-toggle-auto-newline, vous pouvez également utiliser electric-layout-modeun paramètre comme (setq electric-layout-rules '((?\{ . around) (?\} . around))).


1
signalé! ce serait en effet bien que les deux puissent travailler ensemble.
iceman

7

Résolu. La séquence de mouvements du curseur de ma première version (dans le message d'origine) était géniale.

Comme référence pour les futurs lecteurs, le code suivant devrait fonctionner. Il a besoin du paquet Smartparens (que vous pouvez obtenir auprès de git-hub). J'utilise Emacs 24.4. Il fonctionne avec le mode de retrait électrique activé ou désactivé.

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

Et vous devrez également inclure les éléments suivants dans votre fichier init, quelque part après le chargement du package Smartparens:

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

2
Plutôt que d'utiliser des choses comme previous-lineavec search-forwardpour essayer de redécouvrir où vous vous trouviez, vous feriez mieux de vous souvenir de votre position dans une variable, puis de simplement l'utiliser goto-char.
Stefan

C'est probablement la voie la plus robuste. Y a-t-il des fonctions / variables / etc qui, selon vous, pourraient être utiles dans ce contexte? Je ne peux que penser, save-excursionmais je suis sûr qu'il y en a d'autres que je ne connais pas.
iceman


0

Voici le code que j'utilise, juste pour vous donner plus d'idées pour modifier votre code:

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

Je préfère le style d'attelle suspendue, car il économise de l'espace.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.