Закрытие всех ожидающих скобок


14

При написании кодов LISP иногда я глубоко погружен во вложенное выражение, и все, что я хочу, это вставить все отсутствующие закрывающие скобки. Прямо сейчас я просто вставляю их до тех пор, пока не получу неподходящую парен, но это не очень эффективно.
Есть ли команда для вставки всех пропущенных скобок?

К вашему сведению, я использую smartparens для автоматической вставки совпадающих символов. Тем не менее, иногда мне просто нужно сделать это.


2
FWIW, у Франца Лиспа (до CL) была особенность, в которой он ]выступал в роли суперправого парена, закрывая все открытые парены по вашему желанию.
Дрю

2
Я использовал ту же методологию в прошлом. С тех пор я начал использовать paredit , который останавливает проблему до ее запуска. Единственное предостережение в том, что вставка в коде не обеспечивает такой же балансировки.
Эларсон

Ответы:


6

Вот функция, которая закрывает все незамкнутые скобки и другие совпадающие пары. Это зависит от синтаксического разбора Emacs. Он поддерживает только односимвольные пары, поэтому что-то вроде {-будет закрыто }, а не -}. Для Лиспа это не имеет значения.

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

IIUC, это требует, чтобы точка не находилась внутри любого набора соответствующих скобок. У меня сложилось впечатление, что OQ нужно работать с некоторыми внутри выражения lisp, где выполненные скобки будут не соответствовать, а другие - нет.
Малабарба

@Malabarba Это закрывает все ранее открытые скобки, независимо от того, имели ли они соответствующие закрывающие скобки после точки или нет. Вот как я понимаю вопрос, но он, по общему признанию, не ясен в этом вопросе. Как вы понимаете, где будут вставлены закрывающие разделители? Например ([-!-foo], вы вставляете ])в точку или )после foo]?
Жиль "ТАК - перестать быть злым"

из моего понимания, если бы у вас было ([-!-foo], я бы вставил )после foo]. Но я могу ошибаться, конечно. Может быть, @rlazo может уточнить.
Малабарба

для моего случая использования @Gilles - это правильно, мне все равно, закрываются ли разделители после точки, я хочу закрыть все до точки.
rlazo

3

Я обнаружил, что если у вас установлена ​​слизь, есть команда для этого, называемая slime-close-all-parens-in-sexp


Хм ... так что это похоже на текущую строку. Было бы хорошо, если бы был подход, который закрыл «текущий блок». Этого можно достичь, перейдя в конец файла и затем переместив его назад, пока не будет найдено что-то закрытое.
Att Righ

1

Очень примитивный (и почти наверняка неправильный) способ сделать это

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

Среди прочих ограничений предполагается, что все круглые скобки, которые нужно вставить:

  • закрывающие
  • необходимо в текущем местоположении

Я думаю, это может быть достаточно, чтобы быть полезным для вашего конкретного случая использования


Это застревает в бесконечном цикле, если у вас слишком много закрывающих скобок.
Эмиль Викстрем

@ EmilVikström Да, это действительно не совместимо с моим первым заявленным ограничением :)
Sigma
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.