Đóng tất cả các dấu ngoặc đơn đang chờ xử lý


14

Khi viết mã lisp, đôi khi tôi nằm sâu trong một biểu thức lồng nhau và tất cả những gì tôi muốn là chèn tất cả dấu ngoặc đơn bị thiếu. Ngay bây giờ tôi chỉ cần chèn chúng cho đến khi tôi nhận được một paren không khớp, nhưng nó không hiệu quả lắm.
Có lệnh nào để chèn tất cả các dấu ngoặc đơn bị thiếu không?

FYI, tôi đang sử dụng smartparens để tự động chèn parens phù hợp. Tuy nhiên, đôi khi tôi chỉ cần làm điều này.


2
FWIW, Franz Lisp (trước CL) có một tính năng trong đó một ]hành động như một paren siêu phải, đóng tất cả các parens mở, như bạn yêu cầu.
vẽ

2
Tôi đã sử dụng phương pháp tương tự trong quá khứ. Kể từ đó, tôi bắt đầu sử dụng paredit , nó dừng vấn đề trước khi nó bắt đầu. Nhắc nhở duy nhất là dán mã không nhận được điều trị cân bằng tương tự.
elarson

Câu trả lời:


6

Đây là một chức năng đóng tất cả các dấu ngoặc đơn không được tiết lộ và các cặp khớp khác. Nó dựa vào phân tích giới tính của Emacs. Nó chỉ hỗ trợ các cặp đối sánh một ký tự, vì vậy một cái gì đó giống như {-sẽ được đóng lại }, không -}. Đối với Lisp, điều đó không thành vấn đề.

(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, Điều này đòi hỏi điểm đó không nằm trong bất kỳ dấu ngoặc đơn phù hợp nào. Tôi đã có ấn tượng rằng OQ cần để làm việc từ một số biểu hiện bên trong, trong đó các dấu ngoặc đơn được thực hiện sẽ không khớp nhưng những cái khác thì không.
Malabarba

@Malabarba Điều này sẽ đóng tất cả các dấu ngoặc đơn đã mở trước đó, cho dù chúng có khớp dấu ngoặc đơn đóng sau điểm hay không. Đó là cách tôi hiểu câu hỏi, nhưng nó được thừa nhận là không rõ ràng về điểm này. Theo giải thích của bạn, các dấu phân cách đóng sẽ được chèn vào đâu? Ví dụ với ([-!-foo], bạn chèn ])tại điểm, hoặc )sau foo]?
Gilles 'SO- ngừng trở nên xấu xa'

từ sự hiểu biết của tôi, nếu bạn có ([-!-foo], tôi sẽ chèn )sau foo]. Nhưng tôi có thể sai tất nhiên. Có lẽ @rlazo có thể xây dựng.
Malabarba

đối với trường hợp sử dụng của tôi, @Gilles là đúng, tôi không quan tâm nếu các dấu phân cách được đóng sau điểm, tôi muốn đóng mọi thứ trước điểm.
rlazo

3

Tôi đã phát hiện ra rằng nếu bạn đã cài đặt chất nhờn, có một lệnh để làm điều này, được gọi là slime-close-all-parens-in-sexp


Hmm ... vì vậy điều này dường như đóng trên dòng hiện tại. Có thể tốt hơn nếu có một cách tiếp cận đóng "khối hiện tại". Điều này có thể đạt được bằng cách đi đến cuối tập tin và sau đó di chuyển ngược lại cho đến khi tìm thấy một cái gì đó không đóng cửa.
Att Righ

1

Một cách rất nguyên thủy (và gần như chắc chắn sai) để làm điều đó sẽ là

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

Trong số các hạn chế khác, nó giả định rằng tất cả các dấu ngoặc cần chèn là:

  • đóng cửa
  • cần thiết ở vị trí hiện tại

Tôi đoán nó có thể vừa đủ hữu ích cho trường hợp sử dụng cụ thể của bạn


Điều này bị kẹt trong một vòng lặp vô hạn nếu bạn có quá nhiều dấu ngoặc đơn đóng.
Emil Vikström

@ EmilVikström yep, điều đó thực sự không tương thích với giới hạn được nêu đầu tiên của tôi :)
Sigma
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.