Tự động định dạng dấu ngoặc


9

Tôi đang cố gắng tạo một hàm đặt / căn chỉnh / thụt lề dấu ngoặc nhọn theo định dạng kiểu Allman (để mã hóa bằng C).

Nói chung, tôi là người hâm mộ giao diện của Smartparens dành cho người dùng để tùy chỉnh chức năng. Tôi đã viết một loạt các chức năng khác bằng giao diện Smartparens vì vậy sẽ có một ưu tiên mạnh mẽ là không chuyển đổi các gói tại thời điểm này. Điều đó nói rằng, tôi mở cho việc triển khai gói bất khả tri (ví dụ, có thể defadvicecó liên quan ở đây không?).

Về vấn đề trong tầm tay. Mục tiêu cuối cùng là gì? Giả sử chúng ta đang mã hóa và chúng ta đạt đến trạng thái được trình bày dưới đây. Biểu tượng ống đại diện cho con trỏ; Tôi đã gõ tiêu đề chức năng và dấu ngoặc mở {và Smartparens đã tự động thêm dấu ngoặc đóng }. Tại thời điểm này, tôi muốn nó đến mức nhấn RET...

int main {|}

... dẫn đến những điều sau đây:

int main
{
    |
}

Tôi đã có thể viết hàm dẫn đến hành vi này nhưng nó chỉ hoạt động ở cấp độ thụt đầu tiên (ví dụ: đối với chức năng chính của chúng tôi trong ví dụ trên). Tôi không thể làm cho nó hoạt động cho các mức thụt tiếp theo (xem gif):

nhập mô tả hình ảnh ở đây

Các mã có liên quan dưới đây. Chức năng này không đẹp nhưng tôi nghĩ nó sẽ hoạt động ... Dòng cuối cùng là giao diện cho Smartparens.

Bất kỳ đề xuất?


(defun my-create-newline-and-enter-sexp (&rest _ignored)
  "Open a new brace or bracket expression, with relevant newlines and indent. "
  (interactive)
  (progn
    (backward-char 2) (newline) (forward-char) (newline)     
    (indent-according-to-mode)                               
    (previous-line 2) (indent-according-to-mode)         
    (next-line) (next-line) (indent-according-to-mode)))      

(sp-local-pair 'c-mode "{" nil :post-handlers '((my-create-newline-and-enter-sexp "RET")))

Câu trả lời:


11

Emacs-24.4 electric-pair-modethực hiện một phần của những gì bạn muốn (chế độ này rất giống với autopair.el, không chắc nó so sánh với smartparens như thế nào). Và c-toggle-auto-newlinelàm phần khác.

Nhưng buồn thay, họ không làm việc đúng với nhau. Xin vui lòng M-x report-emacs-bugđể chúng tôi có thể khắc phục điều đó.

Thay vì c-toggle-auto-newline, bạn cũng có thể sử dụng electric-layout-modevới một cài đặt như thế nào (setq electric-layout-rules '((?\{ . around) (?\} . around))).


1
báo cáo! Thật tuyệt nếu hai người có thể làm việc cùng nhau.
iceman

7

Giải quyết. Chuỗi các chuyển động con trỏ từ phiên bản đầu tiên của tôi (trong bài viết gốc) thật thú vị.

Để tham khảo cho các độc giả trong tương lai, mã sau đây sẽ hoạt động. Nó obv cần gói Smartparens (mà bạn có thể nhận được từ git-hub). Tôi đang chạy Emacs 24.4. Nó hoạt động với chế độ thụt điện được bật hoặc tắt.

(defun my-create-newline-and-allman-format (&rest _ignored)
"Allman-style formatting for C."
  (interactive)
  (progn
    (newline-and-indent)
    (previous-line) (previous-line) (search-forward "{") (backward-char) (newline-and-indent)
    (next-line) (indent-according-to-mode)))

Và bạn cũng cần bao gồm các mục sau trong tệp init của mình, ở đâu đó sau khi tải gói Smartparens:

(sp-local-pair '(c-mode) "{" nil :post-handlers '((my-create-newline-and-allman-format "RET")))

2
Thay vì sử dụng những thứ như previous-linevới search-forwardcố gắng và tái khám phá nơi bạn được, bạn tốt hơn off nhớ vị trí của bạn trong một biến và sau đó chỉ cần sử dụng goto-char.
Stefan

Đó có lẽ là con đường mạnh mẽ hơn. Có bất kỳ chức năng / biến / vv mà bạn nghĩ có thể hữu ích trong bối cảnh này không? Tôi chỉ có thể nghĩ đến save-excursionnhưng chắc chắn có những người khác mà tôi không biết.
iceman


0

Đây là mã mà tôi sử dụng, chỉ để cung cấp cho bạn thêm ý tưởng để sửa đổi mã của bạn:

(defun ins-c++-curly ()
  "Insert {}.
Threat is as function body when from endline before )"
  (interactive)
  (cond ((eq major-mode 'term-mode)
         (term-send-raw-string "{}")
         (term-send-raw-string "^B"))
        ((looking-back "\\()\\|try\\|else\\|const\\|:\\)$")
         (insert " {\n\n}")
         (indent-according-to-mode)
         (forward-line -1)
         (indent-according-to-mode))
        ((region-active-p)
         (let ((beg (region-beginning))
               (end (region-end)))
           (deactivate-mark)
           (goto-char beg)
           (insert "{")
           (goto-char (1+ end))
           (insert "}")))
        (t
         (insert "{}")
         (indent-according-to-mode)
         (backward-char))))

Tôi thích kiểu treo nẹp, vì nó tiết kiệm không gian.

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.