Zamykanie wszystkich oczekujących nawiasów

14

Podczas pisania kodów lisp czasami jestem głęboko w wyrażeniu zagnieżdżonym i wszystko, czego chcę, to wstawienie wszystkich brakujących nawiasów zamykających. W tej chwili wkładam je tylko, dopóki nie otrzymam niedopasowanego miąższu, ale nie jest to zbyt wydajne.
Czy istnieje polecenie wstawienia wszystkich brakujących nawiasów?

Do Twojej wiadomości używam smartparens do automatycznego wstawiania pasujących parens. Mimo to czasami muszę to zrobić.

rlazo
źródło
2
FWIW, Franz Lisp (przed CL) miał funkcję, w której ]działał jako super prawy paren, zamykając wszystkie otwarte pareny, zgodnie z twoją prośbą.
Drew
2
W przeszłości korzystałem z tej samej metodologii. Od tego czasu zacząłem używać paredit , który zatrzymuje problem przed jego uruchomieniem. Jedynym zastrzeżeniem jest to, że wklejanie kodu nie jest traktowane tak samo.
elarson

Odpowiedzi:

6

Oto funkcja, która zamyka wszystkie niezamknięte nawiasy i inne dopasowane pary. Opiera się na analizie seksu Emacsa. Obsługuje tylko pary dopasowanych pojedynczych znaków, więc coś takiego {-zostanie zamknięte }, a nie -}. Dla Lispa to nie ma znaczenia.

(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- przestań być zły”
źródło
IIUC, wymaga to, aby punkt nie znajdował się w żadnym zestawie dopasowanych nawiasów. Miałem wrażenie, że OQ musi pracować z niektórymi w wyrażeniach seplenienia, gdzie wykonane nawiasy będą niedopasowane, a inne nie.
Malabarba
@Malabarba Zamyka wszystkie wcześniej otwarte nawiasy, niezależnie od tego, czy miały już pasujące nawiasy zamykające po punkcie, czy nie. Tak rozumiem pytanie, ale w tej kwestii nie jest jasne. Gdzie według twojej interpretacji wstawić ograniczniki końcowe? Np. Za pomocą ([-!-foo], czy wstawiasz ])w punkcie czy )po foo]?
Gilles 'SO - przestań być zły'
z mojego zrozumienia, jeśli tak ([-!-foo], wstawiłbym )po foo]. Ale oczywiście mogę się mylić. Może @rlazo może to rozwinąć.
Malabarba
w moim przypadku @Gilles ma rację, nie dbam o to, czy ograniczniki są zamknięte po punkcie, chcę zamknąć wszystko przed punktem.
rlazo
3

Dowiedziałem się, że jeśli masz zainstalowany szlam, jest do tego polecenie zwane slime-close-all-parens-in-sexp

rlazo
źródło
Hmm ... więc wydaje się, że zamyka się na bieżącej linii. Przydałoby się podejście, które zamykało „bieżący blok”. Można to osiągnąć, przechodząc do końca pliku, a następnie przesuwając sekwencję wstecz do momentu znalezienia czegoś, co nie zostało zamknięte.
Att Righ
1

Byłby to bardzo prymitywny (i prawie na pewno zły) sposób na zrobienie tego

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

Między innymi zakłada, że ​​wszystkie nawiasy wymagające wstawienia to:

  • zamykające
  • potrzebne w bieżącej lokalizacji

Wydaje mi się, że to może być po prostu użyteczne w konkretnym przypadku użycia

Sigma
źródło
Utknie w nieskończonej pętli, jeśli masz zbyt wiele nawiasów zamykających.
Emil Vikström,
@ EmilVikström tak, to rzeczywiście nie jest zgodne z moim pierwszym ograniczeniem :)
Sigma,