โค้ด elisp เยื้องอัตโนมัติอีกครั้งเมื่อเพิ่มหรือลบโค้ดก่อนบล็อกที่เยื้อง


18

ว่าฉันมีรหัส elisp เช่น:

(+ 2 3▮(+ 3
          4))

มีวิธีที่จะเยื้อง sexp หลังเคอร์เซอร์อีกครั้งโดยอัตโนมัติเมื่อฉันเพิ่มหรือลบสัญลักษณ์?

ดังนั้นหลังจากกดSPC 4 SPCฉันจะได้รับโดยอัตโนมัติ:

(+ 2 3 4 ▮(+ 3
             4))

ฉันจะทำคู่มือฉบับนี้โดยการโทรตามมาด้วยmark-sexp indent-regionมีวิธีที่ดีกว่าในการทำเช่นนี้?


ฉันไม่คิดว่าจะมีการผูกคีย์เริ่มต้นที่สะดวก แต่คุณสามารถสร้างเองได้อย่างง่ายดาย
shosti

ฉันรู้ แต่ฉันสงสัยโดยเฉพาะว่ามีวิธีใดที่ดีกว่าในการทำเช่นนี้ ตัวอย่างเช่นการelectric-indent-modeแมป<return>ไปยังดีกว่าnewline-and-indent
Maciej Goszczycki

คำตอบ:


14

คุณสามารถกดแทนmark-sexp+ ได้ สิ่งนี้จะเรียกว่า ไม่ใช่อัตโนมัติ แต่ดีกว่าเล็กน้อยที่ต้องเรียกใช้สองคำสั่งindent-regionC-M-qindent-pp-sexp

หรือถ้าคุณกำลังใช้กดparedit-mode M-qที่จะรวมคำจำกัดความฟังก์ชันทั้งหมดที่คุณเข้ามา


1
(add-hook 'post-self-insert-hook 'indent-pp-sexp)ทำงานได้ดีอย่างน่าประหลาดใจ
Maciej Goszczycki

ดูดี. อาจมีค่าใช้จ่ายสูงในบางโหมด แต่มันก็เป็นวิธีการที่ดี
Dmitry

สำหรับผู้ใช้ Smartparens คุณสามารถใส่ค่า defun ปัจจุบันM-x sp-indent-defunอีกครั้งได้ C-M-qผมผูกนี้
Radon Rosborough

15

โหมดการเยื้องเชิงรุก

เนื่องจากบางคนถามว่าผมหันคำตอบนี้ เป็นแพคเกจ

หากคุณมีการกำหนดค่า Melpa คุณสามารถติดตั้งได้ด้วย

M-x package-install RET aggressive-indent

ดูReadmeสำหรับตัวเลือกทั้งหมด แต่วิธีที่ง่ายที่สุดในการเปิดใช้งานคือ:

(add-hook 'emacs-lisp-mode-hook #'aggressive-indent-mode)

คำตอบเก่า ๆ

ต่อไปนี้จะทำการเยื้องอัตโนมัติกับบัฟเฟอร์ elisp เท่านั้น มันมีข้อดีของการทำงานเมื่อคุณลบหรือดึงข้อมูล (แทนที่จะพิมพ์) มันง่ายที่จะเพิ่มไปยังโหมดอื่นเช่นกัน

ฟังก์ชั่นนี้จะเยื้องสิ่งที่แสดงออกในจุดที่อยู่ภายใน คุณสามารถผูกมันไว้กับกุญแจหากคุณต้องการ แต่ดูด้านล่างก่อน

(require 'cl-lib)

(defun endless/indent-defun ()
  "Indent current defun.
Do nothing if mark is active (to avoid deactivating it), or if
buffer is not modified (to avoid creating accidental
modifications)."
  (interactive)
  (ignore-errors
    (unless (or (region-active-p)
                buffer-read-only
                (null (buffer-modified-p)))
      (let ((l (save-excursion (beginning-of-defun 1) (point)))
            (r (save-excursion (end-of-defun 1) (point))))
        (cl-letf (((symbol-function 'message) #'ignore))
          (indent-region l r))))))

เบ็ดนี้จะทำให้มันเพื่อให้ฟังก์ชั่นนี้จะทำงานหลังจากที่คุณพิมพ์อะไร แต่เฉพาะในบัฟเฟอร์ elisp สิ่งนี้ควรเก็บทุกอย่างไว้เสมอ

(add-hook
 'emacs-lisp-mode-hook
 (lambda ()
   (add-hook 'post-command-hook
             #'endless/indent-defun nil 'local)))

ลองมัน! มันใช้งานได้ดีอย่างน่าทึ่ง

นอกจากนี้การทำตามคำแนะนำของ @ holocronweaver ในความคิดเห็นคุณสามารถใช้สิ่งต่อไปนี้สำหรับภาษา c-like:

(define-key c++-mode-map ";"
  (lambda () (interactive)
    (insert ";")
    (endless/indent-defun)))

จะดีมากถ้าข้อความเยื้องอัตโนมัติที่เงียบนี้และภาษาที่จัดการได้ดีขึ้นซึ่งลงท้ายด้วยเครื่องหมายอัฒภาค
holocronweaver

@holocronweaver แน่นอนฉันสามารถลองสิ่งนั้นได้ โหมดหลักใดมีข้อความเยื้อง แล้วปัญหาอะไรกับเครื่องหมายทวิภาค (semi colons)?
Malabarba

ทุกโหมดที่ฉันลองบน Emacs trunk นั้นจะสร้างข้อความเยื้องรวมถึง Elisp เนื่องจากเครื่องหมายอัฒภาคจบบรรทัดในหลายภาษาจนกว่าคุณจะพิมพ์เครื่องหมายอัฒภาคบรรทัดต่อไปนี้จะกระโดดข้ามราวกับว่ามันเป็นส่วนหนึ่งของบรรทัดปัจจุบัน
holocronweaver

@holocronweaver ปิดเสียงข้อความแล้ว ขอบคุณที่ชี้นำ
Malabarba

ขอบคุณสำหรับการแก้ไข! วิธีหนึ่งในการแก้ปัญหาเครื่องหมายอัฒภาคคือการเยื้องในภาษาโหมด c เท่านั้นเมื่อพิมพ์เครื่องหมายอัฒภาค
holocronweaver

3

ฉันไม่รู้วิธีแก้ปัญหาที่มีอยู่แล้ว แต่คุณสามารถใช้post-self-insert-hookเพื่อทำให้สำเร็จด้วยตัวคุณเอง:

(defun my-indent-next-sexp ()
  (interactive)
  (mark-sexp)
  (indent-region))

(add-hook 'post-self-insert-hook 'my-indent-next-sexp)

ฉันจะกังวลเกี่ยวกับปัญหาประสิทธิภาพที่อาจเกิดขึ้น


โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.