Wie macht man yasnippet und die Firma schöner?

22

In meinem Emacs verwende ich beispielsweise ein "elisp"Yasnippet, um einen Lisp-Block im Org-Modus zu erweitern. Aber bevor ich es erweitere, wird zuerst eine Firma ausgelöst, die mir ein Menü wie "1. elisp1, 2. elisp2"ohne eine Option gibt "elisp". Wenn ich tabnun yasnippet erweitere, ist es immer ärgerlich, dass "elisp1"immer zuerst der Bildschirm erscheint. Also muss ich "1"erstens löschen und die Erweiterung von yasnippet snippet machen.

Als Lösung verwende ich immer die linke Pfeiltaste, um zuerst das Firmenabschlussmenü zu deaktivieren, aber der Cursor wechselt jetzt zu "elis|p". Wieder verwende ich die rechte Pfeiltaste, um den Cursor zum Ende des "elisp|"Snippets zu bewegen und das Snippet zu erweitern.

Hier kommt meine Frage: Wie kann ich tabSchlüssel erstens binden, aber nicht Firma yasnippet auslösen, um mir das Leben zu retten?

Leu_Grady
quelle
1
Ich benutze tabfür companyund C-ofür yasnippet. Ich kann weiter beschreiben, wenn Sie interessiert sind.
abo-abo
@abo-abo, danke Antwort. Ich weiß, dass ich es genauso machen kann wie Sie, aber ich binde Co an einen anderen Befehl und habe meinen Handmuskel schlecht trainiert, um mich anzupassen tab. Daher möchte ich die Bindung nicht ändern.
Leu_Grady
Das ist der Grund, warum ich gefragt habe :) Es macht keinen Sinn C-o, darüber nachzudenken, wie man Abkürzungen und Ausschnitte, offene Zeilen usw. erweitern kann, wenn Sie nicht interessiert sind.
abo-abo
scheint interessant, können Sie mehr beschreiben? :)
Leu_Grady

Antworten:

22

Dies ist, was ich für mich selbst geschaffen habe, vor dem gleichen Problem. Es stammt aus der Emacs-Wiki-Seite von company-mode , wurde jedoch stark erweitert:

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

Grundsätzlich macht <tab>dies die meiste Zeit das Richtige . Drücken Sie die Tabulatortaste

  • Die aktuelle Zeile einrücken,
  • Wenn ein yasnippet zum Erweitern vorhanden ist, erweitern Sie es, auch wenn dies bedeutet, dass eine Unternehmensvervollständigung abgebrochen wird (ich verwende noch nicht viele Abkürzungen, also noch keine Abkürzungsunterstützung).
  • Wenn die Fertigstellung eines Unternehmens noch nicht abgeschlossen ist, geben Sie den ausgewählten Artikel ein.
  • Versuchen Sie andernfalls, mit company die Autovervollständigung zu starten.
  • Wenn es nichts zu vervollständigen gibt und wir uns in einem yasnippet-Platzhalter befinden, fahren Sie mit dem nächsten Platzhalter fort.

Beachten Sie, dass die Situation zwiespältig ist, wenn die Möglichkeit zur automatischen Vervollständigung besteht und Sie gerade einen Snippet-Platzhalter bearbeiten. Als Kompromiss musste ich C-<tab>direkt zum nächsten Platzhalter springen.

Die Tatsache, dass der Name des Snippets nicht im Firmenmenü angezeigt wird und das Vorhandensein eines Snippets das Verhalten der Tabulatortaste stillschweigend ändert, ist leider nicht besonders schön ... Obwohl es zumindest möglich ist, <return>stattdessen zu tippen , um stattdessen die Vervollständigung zu erhalten des Schnipsel.

Kristóf Marussy
quelle
Dies scheint magit zu stören. Bewirkt, dass der Tab in Magit erhöht wird Buffer is read-only: #<buffer *magit: ~/.emacs.d/*>. Irgendeine Idee, wie ich das beheben kann?
Zsquare
@zsquare Ich verwende kein Magit (ich weiß, ich bin verrückt), daher kann ich das nicht testen, aber es klingt so, als ob Magits Keymap für TAB, an das esmagit-section-toggle gebunden ist, mit der (global-set-key [tab] 'tab-indent-or-complete)obigen Zeile in Konflikt steht . Eine schnelle und fehlerhafte Lösung wäre, zu Beginn der tab-indent-or-completeobigen Funktion eine Prüfung hinzuzufügen, um festzustellen, ob wir uns im Magit-Modus befinden, z. B. für eine globale Variable, die aktiviert wird magit-mode-hook.
Dodgethesteamroller
Das ist großartig, danke! :) kleinen Stil Punkt, whenist so ziemlich ein if+progn
Matt Briggs
@zsquare Um Stützlasche in magit Modus hinzuzufügen dies den tab-indent-or-completecond `((abgeleitet-mode-p‚magit-Modus) (magit schnittsKnebel (magit Stromschnitt))) `
Bae
Um Ido anstelle der Standard-Minibuffer-Vervollständigung zu unterstützen, ersetzen Sie die Bedingung durch `((Minibufferp) (Ido-Vervollständigung))`
Bae
10

Hier ist der Code, den ich verwende:

(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-linevon auto-yasnippet macht mehr als eine Ebene open-line:

  • es wird versucht, Abkürzungen zu erweitern
  • es wird versucht, zum nächsten Feld von yasnippet zu gelangen
  • es versucht, yasnippet zu erweitern
  • Schließlich ruft es auf, open-linewenn alles andere fehlschlägt
abo-abo
quelle
danke für deinen schnipsel. Ziemlich gut. Aber das Problem besteht immer noch. Wenn ich es zum ersten Mal benutze C-o, schließe ich einfach das Firmenmenü, sodass ich zweimal drücken muss, um yasnippet zu erweitern.
Leu_Grady
Ich habe kein solches Problem: C-oWenn das Firmenmenü aktiv ist, wird das Menü geschlossen und das Snippet erweitert.
abo-abo