วิธีที่จะทำให้ yasnippet และ บริษัท ทำงานได้ดีกว่า?


22

ใน emacs ของฉันสมมติว่าฉันใช้"elisp"yasnippet เพื่อขยายบล็อกเสียงกระเพื่อมในโหมดองค์กร แต่ก่อนที่จะขยายไป บริษัท จะถูกเรียกครั้งแรกที่ทำให้ผมมีเมนูเหมือนโดยไม่ต้องมีตัวเลือก"1. elisp1, 2. elisp2" "elisp"ตอนนี้ถ้าฉันใช้tabเพื่อขยาย yasnippet มันน่ารำคาญ"elisp1"อยู่เสมอที่จะปรากฏบนหน้าจอเป็นครั้งแรก ดังนั้นฉันต้องลบ"1"ก่อนและทำส่วนขยายของตัวอย่าง yasnippet

ดังนั้นวิธีการแก้ไขฉันมักจะใช้ปุ่มลูกศรซ้ายเพื่อปิดเมนูเสร็จสิ้นของ บริษัท ก่อน แต่เคอร์เซอร์จะไปที่"elis|p"ดังนั้นฉันจึงใช้ปุ่มลูกศรขวาอีกครั้งเพื่อเลื่อนเคอร์เซอร์ไปที่จุดสิ้นสุด"elisp|"และขยายส่วนย่อย

ที่นี่คำถามของฉันมา: ฉันจะผูกtabกุญแจแรกเรียก yasnippet แต่ไม่ใช่ บริษัท ที่จะช่วยชีวิตฉันได้อย่างไร


1
ฉันใช้tabสำหรับcompanyและสำหรับC-o yasnippetฉันสามารถอธิบายเพิ่มเติมหากคุณสนใจ
abo-abo

@ abo-abo ขอบคุณคำตอบ ฉันรู้ว่าฉันสามารถทำมันได้ในขณะที่คุณทำ แต่ผมผูกร่วมกับคำสั่งอื่น ๆ tabและไม่ดีที่ฉันได้รับการฝึกฝนกล้ามเนื้อมือของฉันที่จะปรับตัว ดังนั้นฉันไม่ต้องการเปลี่ยนการเชื่อมโยง
Leu_Grady

นั่นเป็นเหตุผลที่ฉันถาม :) ไม่มีจุดพูดจาโผงผางว่าC-oจะขยายตัวย่อและตัวอย่างและบรรทัดเปิดเป็นต้นหากคุณไม่สนใจ
abo-abo

ดูเหมือนจะน่าสนใจคุณสามารถอธิบายเพิ่มเติมได้หรือไม่ :)
Leu_Grady

คำตอบ:


22

นี่คือสิ่งที่ฉันสร้างขึ้นสำหรับตัวฉันเองเผชิญกับปัญหาเดียวกัน มันมาจากหน้า Emacs Wiki ของโหมด บริษัทแต่ได้ขยายออกไปอย่างมาก:

(defun check-expansion ()
  (save-excursion
    (if (looking-at "\\_>") t
      (backward-char 1)
      (if (looking-at "\\.") t
    (backward-char 1)
    (if (looking-at "->") t nil)))))

(defun do-yas-expand ()
  (let ((yas/fallback-behavior 'return-nil))
    (yas/expand)))

(defun tab-indent-or-complete ()
  (interactive)
  (cond
   ((minibufferp)
    (minibuffer-complete))
   (t
    (indent-for-tab-command)
    (if (or (not yas/minor-mode)
        (null (do-yas-expand)))
    (if (check-expansion)
        (progn
          (company-manual-begin)
          (if (null company-candidates)
          (progn
            (company-abort)
            (indent-for-tab-command)))))))))

(defun tab-complete-or-next-field ()
  (interactive)
  (if (or (not yas/minor-mode)
      (null (do-yas-expand)))
      (if company-candidates
      (company-complete-selection)
    (if (check-expansion)
      (progn
        (company-manual-begin)
        (if (null company-candidates)
        (progn
          (company-abort)
          (yas-next-field))))
      (yas-next-field)))))

(defun expand-snippet-or-complete-selection ()
  (interactive)
  (if (or (not yas/minor-mode)
      (null (do-yas-expand))
      (company-abort))
      (company-complete-selection)))

(defun abort-company-or-yas ()
  (interactive)
  (if (null company-candidates)
      (yas-abort-snippet)
    (company-abort)))

(global-set-key [tab] 'tab-indent-or-complete)
(global-set-key (kbd "TAB") 'tab-indent-or-complete)
(global-set-key [(control return)] 'company-complete-common)

(define-key company-active-map [tab] 'expand-snippet-or-complete-selection)
(define-key company-active-map (kbd "TAB") 'expand-snippet-or-complete-selection)

(define-key yas-minor-mode-map [tab] nil)
(define-key yas-minor-mode-map (kbd "TAB") nil)

(define-key yas-keymap [tab] 'tab-complete-or-next-field)
(define-key yas-keymap (kbd "TAB") 'tab-complete-or-next-field)
(define-key yas-keymap [(control tab)] 'yas-next-field)
(define-key yas-keymap (kbd "C-g") 'abort-company-or-yas)

โดยทั่วไปทำให้นี้<tab>ทำสิ่งที่ถูกต้องมากที่สุดของเวลา กดแท็บจะ

  • เยื้องบรรทัดปัจจุบัน
  • หากมี yasnippet ที่จะขยายให้ขยายแม้ว่านี่จะหมายถึงการยกเลิกความสำเร็จของ บริษัท (ฉันไม่ได้ใช้ตัวย่อมากนักดังนั้นจึงไม่มีการสนับสนุนตัวย่อ)
  • หากความสมบูรณ์ของ บริษัท ดำเนินต่อไปให้ทำตามรายการที่เลือก
  • มิฉะนั้นลองใช้ บริษัท เพื่อเริ่มการเติมข้อความอัตโนมัติ
  • หากไม่มีการเติมข้อความอัตโนมัติและเราอยู่ในตัวยึดตำแหน่ง yasnippet ให้ข้ามไปที่ตัวยึดตำแหน่งถัดไป

โปรดทราบว่าหากมีโอกาสที่จะเติมข้อความอัตโนมัติและคุณกำลังแก้ไขตัวยึดตัวอย่างข้อมูลสถานการณ์จะคลุมเครือ ในฐานะที่เป็นผู้ประนีประนอมฉันจึงต้องC-<tab>ข้ามไปที่ตัวยึดตำแหน่งถัดไปโดยตรง

ความจริงที่ว่าชื่อของตัวอย่างไม่ปรากฏในเมนู บริษัท และการมีอยู่ของตัวอย่างการปรับเปลี่ยนพฤติกรรมของแท็บคีย์ไม่ดีโดยเฉพาะอย่างยิ่งน่าเสียดายที่ ... แม้ว่าอย่างน้อยก็เป็นไปได้ที่จะพิมพ์<return>แทนเพื่อให้เสร็จสมบูรณ์แทน ของตัวอย่าง


ดูเหมือนว่ามันจะรบกวน magit เป็นสาเหตุที่ทำให้แท็บใน magit Buffer is read-only: #<buffer *magit: ~/.emacs.d/*>ที่จะยกระดับ ความคิดใดที่ฉันสามารถแก้ไขได้
zsquare

@zsquare ฉันไม่ได้ใช้ magit (ฉันรู้ว่าฉันเป็นถั่ว) ดังนั้นฉันไม่สามารถทดสอบสิ่งนี้ได้อย่างแน่นอน แต่ดูเหมือนว่าแผนที่สำคัญของ magit สำหรับ TAB ซึ่งผูกกับมันmagit-section-toggleขัดแย้งกับบรรทัด(global-set-key [tab] 'tab-indent-or-complete)ด้านบน การแก้ไขอย่างรวดเร็วและสกปรกจะเพิ่มการตรวจสอบที่จุดเริ่มต้นของการทำงานtab-indent-or-completeด้านบนเพื่อดูว่าเรากำลังอยู่ในโหมด magit magit-mode-hookเช่นสำหรับตัวแปรทั่วโลกที่ได้รับการตั้งอยู่บน
dodgethesteamroller

มันยอดเยี่ยมมากขอบคุณ! :) จุดเล็ก ๆ สไตล์whenสวยมากif+progn
แมตต์บริกส์

@zsquare เพื่อสนับสนุนแท็บในโหมด magit เพิ่มสิ่งนี้ลงในtab-indent-or-completecond `((โหมดที่ได้รับ -p 'โหมด magit) (magit-section-toggle (magit-current-section)))
Bae

เพื่อรองรับ ido แทนที่จะใช้ minibuffer ที่เป็นค่าเริ่มต้นให้แทนที่ cond ด้วย `((minibufferp) (ido-complete)) '
Bae

10

นี่คือรหัสที่ฉันใช้:

(global-set-key "\C-o" 'aya-open-line)

(defun aya-open-line ()
  "Call `open-line', unless there are abbrevs or snippets at point.
In that case expand them.  If there's a snippet expansion in progress,
move to the next field. Call `open-line' if nothing else applies."
  (interactive)
  (cond ((expand-abbrev))

        ((yas--snippets-at-point)
         (yas-next-field-or-maybe-expand))

        ((ignore-errors
           (yas-expand)))

        (t
         (open-line 1))))

aya-open-lineจากauto-yasnippetทำมากกว่าธรรมดาopen-line:

  • มันพยายามที่จะขยายตัวย่อ
  • พยายามย้ายไปยังฟิลด์ถัดไปของ yasnippet
  • มันพยายามขยาย yasnippet
  • ในที่สุดมันก็โทรopen-lineถ้าทุกอย่างล้มเหลว

ขอบคุณสำหรับตัวอย่างของคุณ ใช้ได้ดีทีเดียว. แต่ปัญหายังคงมีอยู่ เมื่อฉันใช้งานครั้งแรกC-oมันแค่ปิดเมนู บริษัท ดังนั้นฉันจึงต้องกดสองครั้งเพื่อขยาย yasnippet
Leu_Grady

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