Fermeture de toutes les parenthèses en attente

14

Lors de l'écriture de codes lisp, je suis parfois plongé dans une expression imbriquée et tout ce que je veux, c'est insérer toutes les parenthèses fermantes manquantes. Pour le moment, je ne fais que les insérer jusqu'à ce que j'obtienne un paren dépareillé, mais ce n'est pas très efficace.
Existe-t-il une commande pour insérer toutes les parenthèses manquantes?

Pour info, j'utilise des smartparens pour insérer automatiquement des parens correspondants. Pourtant, parfois j'ai juste besoin de faire ça.

rlazo
la source
2
FWIW, Franz Lisp (avant CL) avait une fonctionnalité où a ]agi comme une paren super droite, fermant toutes les parens ouvertes, comme vous le demandez.
Drew
2
J'ai utilisé la même méthodologie dans le passé. Depuis lors, j'ai commencé à utiliser Paredit , ce qui arrête le problème avant qu'il ne démarre. La seule mise en garde est que le collage de code n'obtient pas le même traitement d'équilibrage.
elarson

Réponses:

6

Voici une fonction qui ferme toutes les parenthèses non fermées et autres paires correspondantes. Il repose sur l'analyse sexp d'Emacs. Il ne supporte que les paires d'un seul caractère, donc quelque chose comme {-sera fermé avec }, non -}. Pour Lisp, cela n'a pas d'importance.

(defun close-all-parentheses ()
  (interactive "*")
  (let ((closing nil))
    (save-excursion
      (while (condition-case nil
         (progn
           (backward-up-list)
           (let ((syntax (syntax-after (point))))
             (case (car syntax)
               ((4) (setq closing (cons (cdr syntax) closing)))
               ((7 8) (setq closing (cons (char-after (point)) closing)))))
           t)
           ((scan-error) nil))))
    (apply #'insert (nreverse closing))))
Gilles 'SO- arrête d'être méchant'
la source
IIUC, Cela nécessite que le point ne se trouve dans aucun ensemble de parenthèses appariées. J'avais l'impression que l'OQ devait fonctionner à partir de certains à l'intérieur d'une expression lisp, où les parenthèses terminées seront incompatibles mais d'autres non.
Malabarba
@Malabarba Cela ferme toutes les parenthèses précédemment ouvertes, qu'elles aient déjà ou non des parenthèses fermantes correspondantes après le point. C'est ainsi que je comprends la question, mais il n'est certes pas clair sur ce point. Selon votre interprétation, où les délimiteurs de fermeture seraient-ils insérés? Par exemple avec ([-!-foo], insérez-vous ])au point ou )après foo]?
Gilles 'SO- arrête d'être méchant'
d'après ma compréhension, si vous l'avez ([-!-foo], je voudrais insérer )après foo]. Mais je peux me tromper bien sûr. Peut-être que @rlazo peut élaborer.
Malabarba
pour mon cas d'utilisation, @ Gilles a raison, je me fiche que les délimiteurs soient fermés après le point, je veux tout fermer avant le point.
rlazo
3

J'ai découvert que si vous avez installé slime, il existe une commande pour ce faire, appelée slime-close-all-parens-in-sexp

rlazo
la source
Hmm ... donc cela semble se fermer sur la ligne actuelle. Ce serait bien s'il y avait une approche qui fermait "le bloc actuel". Cela pourrait être réalisé en allant à la fin du fichier, puis en reculant sexp jusqu'à ce que quelque chose de non fermé ne soit trouvé.
Att Righ
1

Une façon très primitive (et presque certainement erronée) de le faire serait

(defun buffer-needs-parens-fixing ()
  (save-excursion
    (condition-case nil
        (check-parens)
      (error (point)))))

(defun buffer-fix-parens ()
  (interactive)
  (while (buffer-needs-parens-fixing)
    (insert ")")))

Entre autres limitations, il suppose que toutes les parenthèses à insérer sont:

  • les derniers
  • nécessaire à l'emplacement actuel

Je suppose que cela pourrait être juste assez pour être utile pour votre cas d'utilisation spécifique

Sigma
la source
Cela se coince dans une boucle infinie si vous avez trop de parenthèses fermantes.
Emil Vikström
@ EmilVikström yep, ce n'est en effet pas compatible avec ma première limitation indiquée :)
Sigma