Jak sprawić, by yasnippet i firma działały ładniej?

22

W emacs, powiedzmy, używam "elisp"yasnippet, aby rozszerzyć blok lisp w trybie org. Ale zanim go przedłużę, najpierw uruchamiane jest towarzystwo, co daje mi menu jak "1. elisp1, 2. elisp2"bez opcji "elisp". Teraz, jeśli tabużyję rozszerzenia yasnippet, zawsze denerwuje mnie to, że "elisp1"zawsze najpierw pojawia się na ekranie. "1"Najpierw muszę usunąć i zrobić rozszerzenie fragmentu yasnippet.

Jako rozwiązanie zawsze używam lewego klawisza strzałki, aby najpierw wyłączyć menu ukończenia firmy, ale teraz kursor przejdzie do "elis|p", więc ponownie używam klawisza strzałki w prawo, aby przesunąć kursor na koniec "elisp|"i rozszerzyć fragment kodu.

Oto moje pytanie: w jaki sposób mogę powiązać tabklucz, aby najpierw uruchomić yasnippet, ale nie firmę, aby uratować mi życie?

Leu_Grady
źródło
1
Używam tabdla companyi C-odla yasnippet. Mogę opisać dalej, jeśli jesteś zainteresowany.
abo-abo
@ abo-abo, dzięki, odpowiedz. Wiem, że mogę to zrobić tak jak ty, ale wiążę Co z innym dowództwem i źle wyszkoliłem mięśnie ręki do przystosowania się tab. Więc nie chciałbym zmieniać wiązania.
Leu_Grady
Dlatego zapytałem :) Nie ma sensu zastanawiać się, jak C-orozwinąć skróty, fragmenty i otwarte wiersze itp., Jeśli nie jesteś zainteresowany.
abo-abo
wydaje się interesujące, czy możesz opisać więcej? :)
Leu_Grady

Odpowiedzi:

22

To właśnie stworzyłem dla siebie, mając do czynienia z tym samym problemem. Pochodzi ze strony Wiki Emacsa w trybie firmowym , ale mocno rozbudowana:

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

Zasadniczo <tab>przez większość czasu robi to dobrze . Naciśnięcie przycisku spowoduje

  • Wcięcie bieżącej linii,
  • Jeśli istnieje yasnippet do rozwinięcia, rozwiń go, nawet jeśli oznacza to przerwanie ukończenia firmy (nie używam dużo skrótów, więc nie obsługuję jeszcze skrótów),
  • Jeśli trwa ukończenie firmy, uzupełnij wybrany element,
  • W przeciwnym razie spróbuj użyć firmy, aby rozpocząć autouzupełnianie,
  • Jeśli nie ma nic do autouzupełniania, a my jesteśmy w symbolu zastępczym yasnippet, przejdź do następnego symbolu zastępczego.

Pamiętaj, że jeśli istnieje możliwość autouzupełniania i obecnie edytujesz w miejscu symbolu zastępczego fragmentu, sytuacja jest niejednoznaczna. Jako kompromis musiałem C-<tab>przejść bezpośrednio do następnego symbolu zastępczego.

Fakt, że nazwa fragmentu nie pojawia się w menu firmy, a istnienie fragmentu cicho modyfikuje zachowanie klawisza Tab, nie jest szczególnie miłe, niestety ... Chociaż <return>zamiast tego można zamiast tego wpisać fragmentu kodu.

Kristóf Marussy
źródło
To wydaje się kolidować z magitem. Powoduje podniesienie karty w magit Buffer is read-only: #<buffer *magit: ~/.emacs.d/*>. Masz pomysł, jak to naprawić?
zsquare,
@zsquare Nie używam magit (wiem, jestem szalony), więc nie mogę tego przetestować, ale to brzmi jak mapa klawiszy magit dla TAB, z którą jest związanamagit-section-toggle , jest w konflikcie z linią (global-set-key [tab] 'tab-indent-or-complete)powyżej. Szybką i brudną poprawką byłoby dodanie sprawdzenia na początku tab-indent-or-completepowyższej funkcji, aby sprawdzić, czy jesteśmy w trybie magit, np. Dla zmiennej globalnej, która jest włączana magit-mode-hook.
dodgethesteamroller
to jest niesamowite, dzięki! :) mały punkt stylu, whenjest prawie if+progn
Matt Briggs
@zsquare Aby obsługiwać zakładkę w trybie magit, dodaj to do tab-indent-or-completecond '(( mag -tryb-p-magit-mode) (magit-sekcja-przełączanie (magit-prąd-sekcja)))
Bae
Aby wesprzeć ido zamiast domyślnego uzupełniania minibuforów, zamień cond na `((minibufferp) (ido-complete))`
Bae
10

Oto kod, którego używam:

(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-linez auto-yasnippet robi więcej niż zwykły open-line:

  • próbuje rozwinąć skróty
  • próbuje przejść do następnego pola yasnippet
  • próbuje rozwinąć yasnippet
  • wreszcie wywołuje, open-linejeśli wszystko inne zawiedzie
abo-abo
źródło
dziękuję za Twój fragment. Całkiem dobre. Ale problem nadal istnieje. Przy pierwszym użyciu C-opo prostu zamyka menu firmowe, więc muszę dwukrotnie nacisnąć, aby przedłużyć yasnippet.
Leu_Grady
Nie mam takiego problemu: C-oprzy aktywnym menu firmowym zamyka menu i rozwija fragment kodu.
abo-abo