yasnippetと会社をより良くする方法は?


22

私のemacsでは"elisp"、orgモードでlispブロックを拡張するためにyasnippet を使用するとしましょう。しかし、拡張する前に、会社が最初にトリガーされ"1. elisp1, 2. elisp2"、オプションなしのようなメニューが表示されます"elisp"tabyasnippetを拡張するために使用する場合、"elisp1"常に最初に画面に表示されるのは常に迷惑です。だから私は"1"最初に削除する必要があり、yasnippetスニペットの拡張を行います。

したがって、解決策として、私は常に左矢印キーを使用して最初に会社の完了メニューをオフにしますが、カーソルはに移動する"elis|p"ので、再び右矢印キーを使用してカーソルをの終わりに移動し"elisp|"、スニペットを拡張します。

ここで私の質問があります:どうすればtabキーをバインドしてyasnippetをトリガーできますか?


1
tabfor companyC-ofor を使用していyasnippetます。あなたが興味を持っているなら、私はさらに説明することができます。
abo-abo

@ abo-abo、ありがとう。私はあなたのようにそれを行うことができることを知っていますが、私はCoを他のコマンドにバインドし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プレースホルダーにいる場合は、次のプレースホルダーにスキップします。

オートコンプリートの機会があり、現在スニペットプレースホルダーで編集している場合、状況はあいまいであることに注意してください。妥協案としてC-<tab>、次のプレースホルダーに直接スキップすることにしました。

少なくとも、入力することは可能ですが、スニペットの名前が会社メニューとの存在に表示されていないという事実は、... [Tab]キーの動作は、残念ながら、特に素敵ではない黙って修正をスニペット<return>補完を代わりに取得する代わりに、スニペットの。


これはmagitに干渉するようです。magitのタブを上げBuffer is read-only: #<buffer *magit: ~/.emacs.d/*>ます。どのようにそれを修正することができますか?
-zsquare

@zsquare私はmagitを使用していないので(確かに私はナッツです)、これをテストすることはできませんが、TABのmagitのキーマップは、それをバインドしmagit-section-toggle(global-set-key [tab] 'tab-indent-or-complete)上の行と競合しているようです。手っ取り早い解決tab-indent-or-complete策は、上記の関数の先頭にチェックを追加して、たとえばに設定されたグローバル変数などのmagitモードになっているかどうかを確認することですmagit-mode-hook
dodgethesteamroller

これは素晴らしい、ありがとう!:)小さなスタイルポイント、whenほぼif+progn
マットブリッグス

magitモードのサポート]タブに@zsquareは、これを追加tab-indent-or-complete指揮`((派生モード-P「magitモード)(magit-セクショントグル(magit電流セクション)))`
ペ・

デフォルトのミニバッファ補完の代わりにidoをサポートするには、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-lineauto-yasnippetからは、単なるプレーン以上のことが行われますopen-line

  • 略語を展開しようとします
  • yasnippetの次のフィールドに移動しようとします
  • yasnippetを展開しようとします
  • 最後に、open-line他のすべてが失敗した場合に呼び出します

スニペットをありがとう。かなり良い。しかし、問題は依然として存在します。を初めて使用するときはC-o、会社のメニューを閉じるだけなので、yasnippetを拡張するには2回押す必要があります。
Leu_Grady

私はそのような問題を持っていない:C-oアクティブな会社メニューで、メニューを閉じますし、スニペットを展開します。
abo-abo
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.