Làm thế nào để làm cho yasnippet và công ty làm việc tốt hơn?


22

Trong emacs của tôi, giả sử, tôi sử dụng một "elisp"yasnippet để mở rộng một khối lisp trong chế độ org. Nhưng trước khi tôi mở rộng nó, công ty được kích hoạt trước, nó cho tôi một menu như "1. elisp1, 2. elisp2"không có tùy chọn "elisp". Bây giờ nếu tôi sử dụng tabđể mở rộng yasnippet, sẽ luôn khó chịu khi "elisp1"luôn xuất hiện trên màn hình. Vì vậy, tôi cần phải xóa "1"trước tiên và thực hiện mở rộng đoạn trích yasnippet.

Vì vậy, như một giải pháp, tôi luôn sử dụng phím mũi tên trái để tắt menu hoàn thành công ty trước, nhưng con trỏ bây giờ sẽ chuyển sang "elis|p", vì vậy một lần nữa tôi sử dụng phím mũi tên phải để di chuyển con trỏ đến cuối "elisp|"và mở rộng đoạn mã.

Đây là câu hỏi của tôi: làm thế nào tôi có thể liên kết tabkhóa trước tiên kích hoạt yasnippet nhưng không phải là công ty để cứu tôi?


1
Tôi đang sử dụng tabcho companyC-ocho yasnippet. Tôi có thể mô tả thêm nếu bạn quan tâm.
abo-abo

@ abo-abo, cảm ơn trả lời. Tôi biết tôi có thể làm điều đó như bạn, nhưng tôi ràng buộc Co với lệnh khác, và thật tệ là tôi đã luyện tập cơ tay để thích nghi tab. Vì vậy, tôi không muốn thay đổi ràng buộc.
Leu_Grady

Đó là lý do tại sao tôi hỏi :) Không có lý do gì để nói về việc làm thế nào C-ocó thể mở rộng các chữ viết tắt và đoạn trích và các dòng mở, vv nếu bạn không quan tâm.
abo-abo

Có vẻ thú vị, bạn có thể mô tả thêm không? :)
Leu_Grady

Câu trả lời:


22

Đây là những gì tôi tạo ra cho chính mình, đối mặt với cùng một vấn đề. Nó là từ trang Wiki Emacs của chế độ công ty , nhưng được mở rộng rất nhiều:

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

Về cơ bản, điều này làm cho <tab>điều đúng đắn hầu hết thời gian. Nhấn tab sẽ

  • Thụt dòng
  • Nếu có một yasnippet để mở rộng, hãy mở rộng nó, ngay cả khi điều này có nghĩa là hủy bỏ hoàn thành công ty (tôi không sử dụng viết tắt nhiều, vì vậy chưa có hỗ trợ viết tắt),
  • Nếu việc hoàn thành công ty đang diễn ra, hãy hoàn thành với mục đã chọn,
  • Nếu không, hãy thử sử dụng công ty để bắt đầu tự động hoàn thành,
  • Nếu không có gì để tự động hoàn tất và chúng tôi đang ở trong một trình giữ chỗ yasnippet, hãy bỏ qua trình giữ chỗ tiếp theo.

Lưu ý rằng nếu có cơ hội tự động hoàn thành và bạn hiện đang chỉnh sửa trong một trình giữ chỗ đoạn trích, tình huống này rất mơ hồ. Như một sự thỏa hiệp, tôi nhất C-<tab>định bỏ qua trực tiếp cho trình giữ chỗ tiếp theo.

Thực tế là tên của đoạn trích không xuất hiện trong menu công ty và sự tồn tại của đoạn mã âm thầm sửa đổi hành vi của phím tab không đặc biệt tốt, thật không may ... Mặc dù ít nhất có thể gõ <return>thay vào đó để hoàn thành của đoạn trích.


Điều này dường như can thiệp vào pháp sư. Nguyên nhân tab trong magit để nâng cao Buffer is read-only: #<buffer *magit: ~/.emacs.d/*>. Bất cứ ý tưởng làm thế nào tôi có thể khắc phục điều đó?
zsapes

@zsapes Tôi không sử dụng magit (tôi biết, tôi là người dở hơi) vì vậy tôi không thể kiểm tra điều này để chắc chắn, nhưng có vẻ như sơ đồ chính của magit cho TAB, liên kết với nómagit-section-toggle , đang mâu thuẫn với dòng (global-set-key [tab] 'tab-indent-or-complete)trên. Một cách khắc phục nhanh và bẩn sẽ là thêm một kiểm tra ở đầu hàm tab-indent-or-completetrên để xem liệu chúng ta có ở chế độ magit hay không, ví dụ như một biến toàn cục được đặt magit-mode-hook.
dodgethesteamler

điều này thật tuyệt vời, cảm ơn :) điểm phong cách nhỏ, whenkhá nhiều if+progn
Matt Briggs

@zsapes Để hỗ trợ tab trong chế độ magit, hãy thêm cái này vào tab-indent-or-completecond `((dẫn xuất chế độ-p 'magit-mode) (magit-part-toggle (magit-current-part)))`
Bae

Để hỗ trợ ido thay vì hoàn thành bộ thu nhỏ mặc định, hãy thay thế cond bằng `((miniufferp) (hoàn thành ido))`
Bae

10

Đây là mã tôi đang sử dụng:

(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-linetừ auto-yasnippet không chỉ đơn giản là open-line:

  • nó cố gắng mở rộng chữ viết tắt
  • nó cố gắng chuyển sang lĩnh vực tiếp theo của yasnippet
  • nó cố gắng mở rộng yasnippet
  • cuối cùng, nó gọi open-linenếu thất bại

cảm ơn vì đoạn trích của bạn Khá tốt. Nhưng vấn đề vẫn tồn tại. Khi tôi sử dụng lần đầu C-o, nó chỉ đóng menu công ty, vì vậy tôi cần nhấn hai lần để mở rộng yasnippet.
Leu_Grady

Tôi không có vấn đề như vậy: C-ovới menu công ty hoạt động sẽ đóng menu mở rộng đoạn trích.
abo-abo
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.