Як зробити так, щоб ясніппет і компанія працювали приємніше?


22

Скажімо, в моїх програмах emacs "elisp"ясіппет розширює блок lisp в org-режимі. Але перед тим, як продовжувати його, спочатку спрацьовує компанія, яка дає мені меню, як "1. elisp1, 2. elisp2"без варіанту "elisp". Тепер, якщо я використовую tabдля розширення yasnippet, це завжди дратує те, що "elisp1"завжди вперше виходить на екран. Тому мені потрібно видалити "1"спочатку і зробити розширення фрагмента yasnippet.

Тому в якості рішення я завжди використовую ліву клавішу зі стрілкою, щоб спочатку вимкнути меню завершення компанії, але курсор тепер перейде "elis|p", тому я знову використовую клавішу зі стрілкою праворуч для переміщення курсору до кінця "elisp|"та розширення фрагмента.

Тут виникає моє запитання: як я можу прив’язати tabклавішу спочатку до запуску yasnippet, але не компанії, щоб врятувати мені життя?


1
Я використовую tabдля companyі C-oдля yasnippet. Я можу описати далі, якщо вам цікаво.
або-або

@ abo-abo, дякую відповідь. Я знаю, що я можу це зробити, як і ти, але я прив'язую Ко до іншої команди, і я погано тренував м'язи рук для адаптації tab. Тому я не хотів би змінювати прив’язку.
Leu_Grady

Ось чому я запитав :) Немає сенсу займатися C-oрозмовою про те, як можна розширити скорочення та фрагменти, відкрити рядки тощо, якщо вас не цікавить.
або-або

здається цікавим, ви можете описати більше? :)
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>перейти до наступного заповнювача.

На жаль, те, що ім’я фрагмента не відображається в меню компанії, а наявність фрагмента мовчки модифікує поведінку клавіші вкладки, не дуже приємно, на жаль ... Хоча принаймні можна набрати <return>натомість, щоб отримати замість цього фрагмента


Це, здається, заважає магіту. Викликає підняття вкладки в 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 замість завершення мінібуфера за замовчуванням, замініть 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:

  • він намагається розширити скорочення
  • вона намагається перейти до наступного поля ясніппета
  • вона намагається розширити ясніппет
  • нарешті, він дзвонить, open-lineякщо все інше не вдається

дякую за ваш фрагмент Досить добре. Але проблема все ще існує. Коли я вперше користуюся C-o, він просто закриває фірмове меню, тому мені потрібно двічі натиснути, щоб розгорнути ясніппет.
Leu_Grady

У мене немає такої проблеми: C-oпри активному меню компанії він закриє меню та розширить фрагмент.
або-або
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.