Làm thế nào để chỉnh sửa elisp mà không bị mất trong ngoặc đơn


13

Tôi đang sửa đổi một số mã elisp từ linum.el:

(custom-set-variables '(linum-format 'dynamic))
(defadvice linum-update-window (around linum-dynamic activate)
   (let* ((w (length (number-to-string
      (+ (count-lines (point-min) (point-max)) 1))))
         (linum-format (concat " %" (number-to-string w) "d ")))
            ad-do-it))

Tôi đã có thể sửa chữa một lỗi nơi thụt đầu dòng là off-by-one bằng cách sửa đổi (count-lines (point-min) (point-max))để (+ (count-lines (point-min) (point-max)) 1). Điều đó thật dễ dàng.

Nhưng bây giờ tôi muốn sửa đổi nó để độ rộng tối thiểu là 2 bằng cách thêm một if-có điều kiện trong đó (concat " %" (number-to-string w) "2d ")nếu số lượng dòng là <10.

Điều này nên dễ dàng! Thêm một điều kiện và sao chép / dán concat. Miếng bánh, phải không? Ý tôi là, tôi biết những gì tôi phải làm nhưng tôi hiếm khi chạm vào elisp và tôi luôn luôn nản chí khi tôi phải sửa đổi bất cứ điều gì với nhiều dấu ngoặc đơn.

Kiểu "chính xác", theo những gì tôi hiểu, là cấu trúc mã dựa trên thụt lề và bọc dấu ngoặc đơn ở cuối dòng chứ không phải trên chính nó. Đến từ các ngôn ngữ kiểu 'C' khác, tôi phải vật lộn với cả việc đọc và viết mã theo cách này. Vì vậy, câu hỏi của tôi là: tôi đang làm gì sai? Làm thế nào tôi có thể chỉnh sửa elisp và điều hướng xung quanh mã để tôi không phải ngồi đó và đếm từng dấu ngoặc đơn?

Khi tôi làm việc với một thứ gì đó quá sâu, tôi phải đóng cửa, kéo rèm và bắt đầu định vị kiểu ngoặc đơn K & R để tôi không chỉ đọc mà sửa đổi thứ ngu ngốc mà không sợ hãi.

Rõ ràng là tôi đang làm sai tất cả. Làm thế nào tôi có thể chạm vào elisp như thế này mà không sợ hãi?

Xin lưu ý rằng câu hỏi của tôi là làm thế nào để điều hướng và chỉnh sửa elisp không phải là một câu hỏi về phong cách. Tôi đang sử dụng các hướng dẫn sau đây như một hướng dẫn về phong cách: https://github.com/bbatsov/emacs-lisp-style-guide

Cập nhật:

Làm thế nào để định dạng đúng elisp trước khi lúng túng trên emacs.stackexchange:

Đánh dấu elisp của bạn và thực hiện M-x indent-region.

Giải pháp cho vấn đề:

Đối với những người muốn biết làm thế nào để thực hiện một biện minh đúng cho linum với chiều rộng tối thiểu là hai, đây là giải pháp:

(defadvice linum-update-window (around linum-dynamic activate)
  (let* ((w (length (number-to-string
                     (+ (count-lines (point-min) (point-max)) 1))))
         (linum-format (if (> w 1)
                           (concat " %" (number-to-string w) "d ")
                         " %2d ")))
    ad-do-it))

1
Mọi người đều vật lộn với việc đọc lisp xuất phát từ C. Nó chỉ mất thời gian, nhưng cuối cùng nó trở nên vô cùng tự nhiên. Ngoài ra, bạn có thể giải quyết vấn đề của mình bằng cách thay đổi định dạng linum thành chuỗi định dạng như "% 2d".
Jordon Biondo

Tôi không thể chỉ sử dụng %2dvì một khi chiều rộng cuộn lên đến 3 ký tự trở lên thì nó sẽ chuyển từ mang sang phải hợp lý sang trái.
Zhro

Có một vài thư viện nêu bật các dấu ngoặc đơn phù hợp là vô giá (theo ý kiến ​​của tôi), vd highlight-parentheses; rainbow-delimiters; v.v ... Đây là phiên bản đơn giản hóa của riêng tôi highlight-parenthesescho phép cuộn mà không xóa các dấu ngoặc đơn được tô màu lần cuối: stackoverflow.com/a/23998965/2112361 Trong tương lai, đó là một câu hỏi cho mỗi khách hàng / chủ đề.
luật

1
Nghe có vẻ như vấn đề của bạn là đọc sách chứ không phải chỉnh sửa mã Elisp. Bạn có vẻ như bạn có vấn đề trong việc hiểu cấu trúc của Lisp và điều đó làm suy yếu việc chỉnh sửa của bạn.
PythonNut

1
Để bảo vệ bạn, đó là một đoạn mã được thụt vào khá tệ. Tôi đã đọc sai bản thân mình 3 lần đầu tiên vì điều đó. Ngoài ra, paredit .
Malabarba

Câu trả lời:


12

Có một số gói bổ trợ có thể giúp ích, chẳng hạn như paredit, smartparens và lispy. Các gói này giúp điều hướng và thao tác mã lisp dễ dàng hơn để bạn có thể suy nghĩ theo biểu thức s và để trình soạn thảo lo lắng về việc cân bằng các dấu ngoặc.

Emacs cũng có rất nhiều lệnh tích hợp để xử lý các danh sách và danh sách đáng để học hỏi và có thể giúp bạn quen với cấu trúc của mã lisp. Chúng thường được liên kết với một C-M-tiền tố, chẳng hạn như:

  • C-M-f/ C-M-bđể di chuyển tiến / lùi bởi sexp
  • C-M-n/ C-M-pđể di chuyển tiến / lùi theo danh sách
  • C-M-u/ C-M-dđể di chuyển lên / xuống một cấp
  • C-M-t để trao đổi hai giới tính xung quanh điểm
  • C-M-k giết một sexp
  • C-M-SPC để đánh dấu một sexp
  • C-M-q để thụt lại một sexp

Mã ví dụ bạn cung cấp có thể rõ ràng hơn nếu bạn sửa lỗi thụt lề: đặt điểm ở đầu (defadvice...và nhấn C-M-qđể thụt lại toàn bộ biểu thức. Để thay thế (concat...tôi sẽ bắt đầu bằng cách đặt điểm khi bắt đầu sexp đó và đánh C-M-ođể tách dòng trong khi duy trì vết lõm. Sau đó thêm của bạn (if...và sử dụng các lệnh ở trên để nhảy đến cuối danh sách để thêm một paren đóng khác, quay lại từ đầu để thụt lại, v.v.

Bạn cũng có thể muốn bật show-paren-mode, điều này sẽ làm nổi bật paren tương ứng khi điểm nằm ở đầu hoặc cuối danh sách. Bạn có thể thích làm nổi bật toàn bộ biểu thức hơn là paren phù hợp, vì vậy hãy thử tùy chỉnh show-paren-style.

Như @Tyler đã đề cập trong các nhận xét về câu trả lời khác, bạn nên xem hướng dẫn để tìm hiểu thêm về các lệnh này và các lệnh liên quan.


Lưu ý rằng C-M-qcó thể được gọi với một đối số tiền tố ( C-u C-M-q) để in đẹp biểu thức tại điểm. Điều này sẽ phá vỡ mọi thứ trên để tách các dòng và thụt lề để việc lồng nhau là rất rõ ràng. Nói chung, bạn không muốn mã lisp của mình trông giống như vậy, nhưng có thể hữu ích để hiểu một chút mã mà không cần thủ công đầy đủ K & R trên đó. (Và bạn luôn có thể C-x uhoàn tác).
glucas

6

Một cách tốt để chỉnh sửa LISP là thao tác AST, thay vì các ký tự hoặc dòng riêng lẻ. Tôi đã làm điều đó với gói của tôi lispy mà tôi đã bắt đầu 2 năm trước. Tôi nghĩ rằng thực sự có thể mất khá nhiều thực hành để học cách làm tốt điều này, nhưng ngay cả việc chỉ sử dụng những điều cơ bản cũng đã giúp bạn.

Tôi có thể giải thích làm thế nào tôi sẽ thực hiện thay đổi này:

Bước 1

Vị trí bắt đầu thường là có điểm trước khi quan hệ tình dục cấp cao nhất. Đây |là điểm.

|(defadvice linum-update-window (around linum-dynamic activate)
   (let* ((w (length (number-to-string
      (+ (count-lines (point-min) (point-max)) 1))))
         (linum-format (concat " %" (number-to-string w) "d ")))
            ad-do-it))

Bạn sẽ muốn có mã được thụt lề đúng cách, vì vậy hãy nhấn imột lần. Nó sẽ thụt lại độc đáo.

Bước 2

Bạn sẽ muốn đánh dấu "d "bằng một vùng, vì một đối tượng có thể thao tác trong đó lispylà một danh sách, không cần phải đánh dấu, hoặc một chuỗi các ký hiệu hoặc / và danh sách cần được đánh dấu bằng một vùng.

Nhấn atđể làm như vậy. Các alệnh cho phép để đánh dấu bất kỳ biểu tượng duy nhất trong danh sách phụ huynh, và tlà chỉ số của biểu tượng đặc biệt này.

Bước 3

  1. Để bọc khu vực hiện tại với (), nhấn (.
  2. Nhấn C-fđể di chuyển về phía trước một char và chèn if.
  3. Nhấn (một lần nữa để chèn ().
  4. Chèn > w 10.
  5. C-f C-m để di chuyển chuỗi sang một dòng mới.

Bước 4

Để sao chép chuỗi:

  1. Đánh dấu ký hiệu hoặc chuỗi ký tự tại điểm M-m.
  2. Nhấn c.

Nếu bạn muốn hủy kích hoạt vùng theo cách lạ mắt và đặt điểm ở ngay đầu chuỗi, bạn có thể nhấn idm:

  1. i sẽ chọn nội dung bên trong chuỗi.
  2. d sẽ trao đổi điểm và đánh dấu.
  3. m sẽ hủy kích hoạt khu vực

Hoặc bạn có thể làm m C-b C-b C-btrong trường hợp này, hoặc C-g C-b C-b C-b. Tôi nghĩ idmlà tốt hơn, vì nó giống nhau bất kể độ dài của chuỗi. Tôi nghĩ rằng C-x C-x C-f C-g cũng sẽ làm việc bất kể chiều dài chuỗi.

Cuối cùng, chèn 2để lấy mã kết thúc:

(defadvice linum-update-window (around linum-dynamic activate)
  (let* ((w (length (number-to-string
                     (+ (count-lines (point-min) (point-max)) 1))))
         (linum-format (concat " %" (number-to-string w) (if (> w 10)
                                                             "2|d "
                                                           "d "))))
    ad-do-it))

Tóm lược

Trình tự đầy đủ là: at( C-f, if, (, > w 10, C-f C-m M-m cidm, 2.

Lưu ý rằng nếu bạn tính đến việc chèn mã, các khóa duy nhất không liên quan đến thao tác AST là hai C-fvà một C-m.


3
Lispy nghe có vẻ thú vị! Đối với OP: bạn có thể phát triển các quy trình công việc tương tự với paredit: emacsrocks.com/e14.html và mở rộng vùng: github.com/magnars/Exand-region.el hoặc chỉ chơi xung quanh với các lệnh khớp ngoặc đơn tích hợp: gnu. org / software / emacs / thủ công / html_node / emacs / Parentheses.html
Tyler

Tôi chắc rằng bạn đã đoán được khi bạn buộc phải giải quyết vấn đề cho tôi; cảm ơn bạn đã cố gắng Tôi đã xoay xở để tìm cách sử dụng mã của bạn làm ví dụ. Xem cập nhật của tôi cho giải pháp chính xác.
Zhro

6

Bạn sẽ quen với nó theo thời gian, nhưng tất nhiên có rất nhiều điều bạn có thể làm để giúp tăng tốc:

Lõm

Có một phương pháp cho sự điên rồ này. Trong lisp bạn có thể làm điều này:

(a-fun (another-fun (magic-macro 1)))

Giả sử đó 1thực sự là một biểu thức lớn và bạn muốn thụt lề trên dòng riêng của nó.

(a-fun (another-fun (magic-macro 
  1)))

Điều này là sai lệch. 1được thụt lề chỉ một khe, mặc dù đó là toàn bộ ba cấp độ lồng nhau cao hơn! Tốt hơn nên đặt nó bởi cha mẹ của nó.

(a-fun (another-fun (magic-macro 
                      1)))

Nếu chúng tôi sử dụng lược đồ này trên mã của riêng bạn, chúng tôi sẽ nhận được điều này:

(custom-set-variables '(linum-format 'dynamic))
(defadvice linum-update-window (around linum-dynamic activate)
  (let* ((w (length (number-to-string
                      (+ (count-lines (point-min) (point-max)) 1))))       
          (linum-format 
            (concat " %" (number-to-string w) "d ")))
     ad-do-it))

Lưu ý mối tương quan mạnh mẽ giữa thụt đầu dòng và mức độ lồng nhau. Các dòng có mức lồng nhau lớn hơn luôn được thụt vào nhiều hơn các dòng có ít hơn.

Điều này một mình sẽ giúp rất nhiều. Bạn có thể dễ dàng nhìn thấy "hình dạng" của mã và hầu hết các ngôn ngữ khác đã huấn luyện bạn liên kết thụt lề với các khối và khối với một số hình thức lồng nhau (rõ ràng hoặc ngụ ý).

Như một bài tập, tôi đã loại bỏ các dấu ngoặc đơn không cần thiết khỏi mã. Bạn sẽ có thể vừa đọc mã vừa cung cấp các dấu ngoặc đơn bị thiếu, được cung cấp kiến ​​thức cơ bản về Elisp (cụ thể, những thứ đó là chức năng và giá trị và cấu trúc của let*).

custom-set-variables '(linum-format 'dynamic)
defadvice linum-update-window (around linum-dynamic activate)
  let* w length number-to-string
                  + 
                    count-lines (point-min) (point-max) 
                    1       
         linum-format 
           concat " %" (number-to-string w) "d "
     ad-do-it

1
Lưu ý rằng trong Emacs, tab nhấn hầu như sẽ luôn đặt thụt lề chính xác như được mô tả ở đây - bạn không bao giờ nên làm điều đó bằng cách thêm khoảng trắng bằng tay!
Tyler

Liên kết "Cm" với newline-and-indentchế độ emacs-lisp-mode và lisp-tương tác-chế độ giải quyết ví dụ đầu tiên của bạn, PythonNut. Và TAB sẽ thực hiện công việc trong thời gian còn lại.
Davor Cubranic

5

Tôi bao gồm điều này như một câu trả lời khác nhau.

Đôi khi, thụt sẽ làm bạn thất bại. Sau đó, bạn nên sử dụng một cái gì đó như rainbow-delimiters:

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

Điều này làm cho mức lồng nhau của bất kỳ paren rõ ràng và dễ dàng quét.

Có một vấn đề khá lớn: các parens bị phân tâm một cách lố bịch. Có một sự cân bằng của sự nhấn mạnh ở đây. rainbow-delimitersthông thường sẽ tập trung rất nhiều vào các parens với chi phí của phần còn lại của mã của bạn! Nhưng nếu bạn chỉnh mặt cầu vồng xuống, chúng sẽ dần dần khó quét hơn.

Nếu bạn có thể tìm thấy một bộ khuôn mặt cân bằng tốt điều này, thì bằng mọi cách hãy sử dụng nó.

Điều đó nói rằng, một giải pháp (một giải pháp khiến tôi phải cười thầm), là có hai bộ mặt và chuyển đổi giữa chúng khi đang bay. Khi bạn đang làm việc khác, khuôn mặt sẽ loãng và mờ dần vào nền:

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

Nhưng khi bạn đặt điểm trên một paren, nó sẽ đấm các parens để bạn có thể thấy các mức lồng nhau:

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

Và đây là mã để làm điều đó:

(defvar rainbow-delimiters-switch nil
  "t if rainbow-delimiters are currently punched")
(defvar rainbow-delimiters-face-cookies nil
  "a list of face-remap-add-relative cookies to reset")

(make-variable-buffer-local 'rainbow-delimiters-switch)
(make-variable-buffer-local 'rainbow-delimiters-face-cookies)

(add-hook 'prog-mode-hook #'rainbow-delimiters-mode)
(add-hook 'text-mode-hook #'rainbow-delimiters-mode)

(with-eval-after-load 'rainbow-delimiters
  (set-face-foreground 'rainbow-delimiters-depth-1-face "#889899")
  (set-face-foreground 'rainbow-delimiters-depth-2-face "#9b7b6b")
  (set-face-foreground 'rainbow-delimiters-depth-3-face "#7b88a5")
  (set-face-foreground 'rainbow-delimiters-depth-4-face "#889899")
  (set-face-foreground 'rainbow-delimiters-depth-5-face "#839564")
  (set-face-foreground 'rainbow-delimiters-depth-6-face "#6391aa")
  (set-face-foreground 'rainbow-delimiters-depth-7-face "#9d748f")
  (set-face-foreground 'rainbow-delimiters-depth-8-face "#7b88a5")
  (set-face-foreground 'rainbow-delimiters-depth-9-face "#659896")

  (defun rainbow-delimiters-focus-on ()
    "Punch the rainbow-delimiters"
    (setq rainbow-delimiters-face-cookies
      (list
        (face-remap-add-relative 'rainbow-delimiters-depth-1-face
          '((:foreground "#3B9399") rainbow-delimiters-depth-1-face))
        (face-remap-add-relative 'rainbow-delimiters-depth-2-face
          '((:foreground "#9B471D") rainbow-delimiters-depth-2-face))
        (face-remap-add-relative 'rainbow-delimiters-depth-3-face
          '((:foreground "#284FA5") rainbow-delimiters-depth-3-face))
        (face-remap-add-relative 'rainbow-delimiters-depth-4-face
          '((:foreground "#3B9399") rainbow-delimiters-depth-4-face))
            (face-remap-add-relative 'rainbow-delimiters-depth-5-face
          '((:foreground "#679519") rainbow-delimiters-depth-5-face))
        (face-remap-add-relative 'rainbow-delimiters-depth-6-face
          '((:foreground "#0E73AA") rainbow-delimiters-depth-6-face))
        (face-remap-add-relative 'rainbow-delimiters-depth-7-face
          '((:foreground "#9D2574") rainbow-delimiters-depth-7-face))
        (face-remap-add-relative 'rainbow-delimiters-depth-8-face
          '((:foreground "#284FA5") rainbow-delimiters-depth-8-face))
        (face-remap-add-relative 'rainbow-delimiters-depth-9-face
          '((:foreground "#199893") rainbow-delimiters-depth-9-face)))
      rainbow-delimiters-switch t))

  (defun rainbow-delimiters-focus-off ()
    "Reset the rainbow-delimiters faces"
    (mapc #'face-remap-remove-relative rainbow-delimiters-face-cookies)
    (setq rainbow-delimiters-switch nil))

  (defun rainbow-delimiters-focus-on-maybe ()
    "Punch the rainbow-delimiters if the point is on a paren"
    (when (looking-at "[][(){}]")
      (unless (or rainbow-delimiters-switch (minibufferp))
        (rainbow-delimiters-focus-on))))

  (defun rainbow-delimiters-focus-off-maybe ()
    "Reset the rainbow-delimiters if the point is not on a paren"
    (unless (looking-at "[][(){}]")
      (when rainbow-delimiters-switch
        (rainbow-delimiters-focus-off))))

  (run-with-idle-timer 0.6 t 'rainbow-delimiters-focus-on-maybe)
  (run-with-idle-timer 0.1 t 'rainbow-delimiters-focus-off-maybe))

Thật tuyệt! Bất kỳ lý do nào bạn chọn phân định cầu vồng trên dấu ngoặc đơn để bắt đầu?
Tyler

@Tyler không có lý do cụ thể, mặc dù bây giờ tôi vẫn gắn bó với các dấu phân cách cầu vồng (nhưng điều đó có thể là do tôi đã quen với nó). Tôi chỉ đơn giản là đã không nghe nói về dấu ngoặc đơn cho đến gần đây.
PythonNut

4

Nếu bạn thụt mã của mình, thì bạn thực sự cần phải thụt lề đúng cách. Các nhà phát triển Lisp có kỳ vọng những gì được thụt lề đúng cách sẽ trông như thế nào. Điều này không có nghĩa là mã trông giống nhau. Vẫn có nhiều cách khác nhau để định dạng mã.

  • một dòng nên dài bao nhiêu?
  • Làm thế nào để phân phối một cuộc gọi chức năng / macro qua các dòng?
  • nên có bao nhiêu chỗ lõm?
(defadvice linum-update-window (around linum-dynamic activate)
   (let* ((w (length (number-to-string
      (+ (count-lines (point-min) (point-max)) 1))))
         (linum-format (concat " %" (number-to-string w) "d ")))
            ad-do-it))

Tôi mong đợi rằng thụt lề cho thấy ngăn chặn theo một cách nào đó. Nhưng không phải trong mã của bạn.

Theo mặc định, mã của bạn có thể được thụt lề như thế này. Các câu trả lời khác mô tả cách bạn có thể làm điều đó với sự trợ giúp của Emacs:

(defadvice linum-update-window (around linum-dynamic activate)
  (let* ((w (length (number-to-string
                     (+ (count-lines (point-min) (point-max)) 1))))
         (linum-format (concat " %" (number-to-string w) "d ")))
    ad-do-it))

Tôi hy vọng rằng các letbiến ràng buộc bắt đầu trên cùng một cột dọc. Tôi cũng mong rằng cơ thể của letít bị thụt vào. Chúng ta học cách mộtlet nên được thụt lề. Khi bạn luyện tập một chút, đó là một mẫu hình ảnh dễ nhận biết.

Các khối xây dựng hình ảnh chính trong mã là defadvice, let*và một loạt các lệnh gọi hàm. Cái deftên cho tôi biết đó là một định nghĩa theo sau là tên, danh sách đối số và phần thân.

Vì vậy tôi muốn xem

defadvice name arglist
  body

Các let*sẽ là: let*, một danh sách các ràng buộc và một cơ thể.

Vì vậy, tôi muốn xem:

let*  list of bindings
  body

Chi tiết hơn:

let*   binding1
       binding2
       binding3
  body

Đối với một cuộc gọi chức năng tôi muốn xem:

FUNCTIONNAME ARG1 ARG2 ARG3

hoặc là

FUNCTIONNAME ARG1
             ARG2
             ARG3

hoặc là

FUNCTIONNAME
  ARG1
  ARG2
  ARG3

Cái nào được sử dụng phụ thuộc vào thời gian của các đối số. Chúng tôi không muốn tạo các dòng quá dài và mỗi đối số trên dòng riêng cho phép chúng tôi có nhiều cấu trúc hơn.

Vì vậy, bạn cần viết mã bằng các mẫu đó và bạn cần đảm bảo rằng người đọc có thể dễ dàng xác định các mẫu đó trong mã của bạn.

Dấu ngoặc đơn nên trực tiếp kèm theo cấu trúc của chúng.

(sin 10)

(sin
  10)

Tránh các ví dụ về khoảng trắng:

(  sin 10  )

hoặc là

(
   sin
)

hoặc là

(sin 10
)

Trong Lisp, dấu ngoặc đơn không có chức năng cú pháp ngôn ngữ, chúng là một phần của cú pháp của cấu trúc dữ liệu danh sách (biểu thức s). Do đó chúng tôi viết danh sách và định dạng danh sách. Để định dạng nội dung danh sách, chúng tôi sử dụng kiến ​​thức về ngôn ngữ lập trình Lisp. Một letbiểu thức nên được định dạng khác với một lời gọi hàm. Vẫn là cả hai danh sách và dấu ngoặc đơn nên trực tiếp kèm theo danh sách. Có một số ví dụ trong đó có ý nghĩa khi có một dấu ngoặc đơn trên một dòng, nhưng hiếm khi sử dụng nó.

Sử dụng dấu ngoặc đơn để hỗ trợ bạn tìm ranh giới biểu thức. Hãy để họ giúp bạn chuyển từ danh sách sang danh sách, chỉnh sửa danh sách, cắt và sao chép danh sách, để thay thế danh sách, vào danh sách thụt lề / định dạng, chọn danh sách, ...


2

Để được trợ giúp cơ bản với thụt đầu dòng, sử dụng TAB và "CMq" ( indent-pp-sexp); ràng buộc "Cm" newline-and-indentsẽ giúp bạn tiết kiệm phải nhấn TAB sau một dòng mới.

Bạn có thể điều hướng bằng sexp với "CM-left / right / up / down / home / end", rất hữu ích.

Nếu bạn lo lắng về việc duy trì cân bằng dấu ngoặc đơn, hãy sử dụng một cái gì đó như smartparens (sẽ dễ tha thứ hơn cho paredit đó, ban đầu có thể cảm thấy như đang mặc một chiếc váy bó). Nó cũng đi kèm với rất nhiều ràng buộc để điều hướng và chỉnh sửa ở cấp độ sexp.

Cuối cùng, để làm nổi bật các dấu ngoặc, hãy bắt đầu bằng cách bật tùy chọn (menu Tùy chọn-> Đánh dấu các dấu ngoặc phù hợp hoặc show-paren-mode.) Bạn cũng có thể sử dụng một trong các gói được đề cập bởi danh sách luật trong nhận xét của mình, như "đánh dấu dấu ngoặc đơn" hoặc "dấu phân cách cầu vồng" ".


1

Ngoài ra những gì người khác đã đưa ra làm câu trả lời, đây là 2 xu của tôi:

  • Việc thụt lề tự động được cung cấp bởi emacs-lisp-modelà rất cần thiết.
  • blink-matching-parenđược bật (không nil) theo mặc định. Để nó như vậy.
  • Tôi sử dụng show-paren-mode, để làm nổi bật paren trái tương ứng với paren phải trước con trỏ.
  • Tôi tạm thời xóa và nhập lại paren phải trước con trỏ, nếu tôi muốn xem tốt hơn vị trí của paren bên trái.

Tôi không sử dụng ghép nối điện hoặc cầu vồng bất cứ điều gì hoặc bất kỳ "trợ giúp" nào khác. Đối với tôi đó là một phiền phức, không phải là một sự trợ giúp.

Đặc biệt, electric-pair-modeđối với tôi, là một sự phiền phức bất tiện. Nhưng một số người thích nó. Và tôi tưởng tượng rằng nó có thể hữu ích trong một số bối cảnh ghép nối khác ngoài dấu ngoặc đơn Lisp (tôi tưởng tượng như vậy, nhưng tôi cũng không bị thuyết phục cho các trường hợp sử dụng như vậy).

Bạn sẽ tìm thấy những gì làm việc tốt nhất cho bạn. Những điều chính tôi muốn nói là: (1) thụt tự động là bạn của bạn, như một cách nào đó để phát hiện ra paren trái khớp với paren phải trước điểm.

Cụ thể, nhìn thấy những gì thụt tự động làm cho bạn ngay lập tức dạy cho bạn rằng bạn sẽ không bao giờ muốn đặt parens đúng trên một dòng. Phong cách mã hóa, vốn phổ biến ở các ngôn ngữ khác, chỉ là ồn ào.

Bên cạnh việc thụt lề tự động mà bạn có RETTABsử dụng thoải mái C-M-q. (Sử dụng C-h ktrong emacs-lisp-modeđể tìm hiểu những gì các phím làm.)


0

Tôi nhận thấy một số người đã đề cập đến các dấu phân cách cầu vồng, đó cũng là chế độ yêu thích của tôi khi chỉnh sửa mã lisp.

Thật ra tôi yêu dấu ngoặc đơn, điều tuyệt nhất ở Lisp là những dấu ngoặc đơn đó, thật vui khi đối phó với chúng nếu bạn biết cách:

  • cài đặt chế độ độc ác và plugin ác của nó, vì vậy bạn có thể chỉnh sửa dấu ngoặc đơn dễ dàng, ví dụ, nhấn ci( sẽ xóa mọi thứ bên trong (), va(sẽ chọn thứ được bao bọc bởi "()" và chính "()". và bạn có thể nhấn %để nhảy giữa các dấu ngoặc đơn phù hợp

  • sử dụng flycheck hoặc flymake, dấu ngoặc đơn chưa từng có sẽ được gạch chân trong thời gian thực


0

Khó khăn ở đây là bạn muốn thêm một số mã trước và sau một số nhất định sexp. Trong tình huống này là sexp (concat " %" (number-to-string w) "d "). Bạn muốn chèn câu lệnh if (if (> w 1) trước nó và câu lệnh câu lệnh khác " %2d ") sau câu lệnh .

Một phần chính của khó khăn là cô lập điều này sexp, cá nhân tôi sử dụng lệnh dưới đây để cô lập mộtsexp

(defun isolate-sexp () (interactive)
       (save-excursion (forward-sexp) (if (not (eolp-almost))
               (split-line) nil)))
(defun eolp-almost () (interactive)
(save-excursion (while (equal (char-after) ? ) (forward-char 1))
        (if (eolp) t nil )      ))

Chỉ cần đặt con trỏ ở đầu (concat " %" (number-to-string w) "d "), nghĩa là lúc đầu (, sau đó áp dụng cách trên isolate-sexp. Bạn được thông qua

(defadvice linum-update-window (around linum-dynamic activate)
   (let* ((w (length (number-to-string
      (+ (count-lines (point-min) (point-max)) 1))))
         (linum-format (concat " %" (number-to-string w) "d ")
                                  ))
            ad-do-it))

Sau đó thêm mã thích hợp trước và sau này sexp, tức là

(defadvice linum-update-window (around linum-dynamic activate)
   (let* ((w (length (number-to-string
      (+ (count-lines (point-min) (point-max)) 1))))
         (linum-format (if (> w 1) (concat " %" (number-to-string w) "d ") " %2d ")
                                  ))
            ad-do-it))

Và Voila. Mã thu được theo cách này có lẽ không đẹp nhưng cơ hội bị mất là nhỏ hơn.

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.