Cerrar todos los paréntesis pendientes

14

Al escribir códigos lisp, a veces estoy profundamente en una expresión anidada y todo lo que quiero es insertar todos los paréntesis de cierre que faltan. En este momento solo los estoy insertando hasta que obtengo un par no coincidente, pero no es muy eficiente.
¿Hay algún comando para insertar todos los paréntesis faltantes?

FYI, estoy usando smartparens para insertar automáticamente parens coincidentes. Aún así, a veces solo necesito hacer esto.

rlazo
fuente
2
FWIW, Franz Lisp (antes de CL) tenía una función en la que ]actuaba como un padre súper correcto, cerrando todos los padres abiertos, según lo solicite.
Dibujó
2
He usado la misma metodología en el pasado. Desde entonces, comencé a usar el crédito , lo que detiene el problema antes de que comience. La única advertencia es que pegar el código no recibe el mismo tratamiento de equilibrio.
Elarson

Respuestas:

6

Aquí hay una función que cierra todos los paréntesis no cerrados y otros pares coincidentes. Se basa en el análisis sexp de Emacs. Solo admite pares coincidentes de un solo carácter, por lo {-que se cerrará algo así }, no -}. Para Lisp, eso no importa.

(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- deja de ser malvado'
fuente
IIUC, esto requiere que ese punto no esté dentro de ningún conjunto de paréntesis coincidentes. Tenía la impresión de que el OQ necesitaba funcionar desde algunos dentro de una expresión lisp, donde los paréntesis hechos no coincidirán, pero otros no.
Malabarba
@Malabarba Esto cierra todos los paréntesis abiertos previamente, ya sea que tengan paréntesis de cierre coincidentes después del punto o no. Así es como entiendo la pregunta, pero ciertamente no está claro en este punto. Según su interpretación, ¿dónde se insertarían los delimitadores de cierre? Por ejemplo ([-!-foo], ¿inserta ])en el punto o )después foo]?
Gilles 'SO- deja de ser malvado'
desde mi punto de vista, si es así ([-!-foo], lo insertaría )después foo]. Pero podría estar equivocado, por supuesto. Quizás @rlazo pueda dar más detalles.
Malabarba
para mi caso de uso, @Gilles tiene razón, no me importa si los delimitadores están cerrados después del punto, quiero cerrar todo antes del punto.
rlazo
3

Descubrí que si tienes slime instalado, hay un comando para hacer esto, llamado slime-close-all-parens-in-sexp

rlazo
fuente
Hmm ... así que esto parece cerrarse en la línea actual. Sería bueno si hubiera un enfoque que cerrara "el bloque actual". Esto podría lograrse yendo al final del archivo y luego retrocediendo sexp hasta que se encuentre algo que no se haya cerrado.
Att Righ
1

Una forma muy primitiva (y casi ciertamente incorrecta) de hacerlo sería

(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 otras limitaciones, se supone que todos los paréntesis que deben insertarse son:

  • los de cierre
  • necesario en la ubicación actual

Supongo que podría ser suficiente para ser útil para su caso de uso específico

Sigma
fuente
Esto se atasca en un bucle infinito si tiene demasiados paréntesis de cierre.
Emil Vikström
@ EmilVikström sí, eso de hecho no es compatible con mi primera limitación declarada :)
Sigma