Comment rendre le yasnippet et l'entreprise plus agréables?

22

Dans mes emacs, disons, j'utilise un "elisp"yasnippet pour étendre un bloc lisp en mode org. Mais avant de l'étendre, la société est déclenchée en premier, ce qui me donne un menu comme "1. elisp1, 2. elisp2"sans option "elisp". Maintenant, si j'utilise tabpour étendre yasnippet, il est toujours ennuyeux de "elisp1"toujours d'abord s'afficher à l'écran. Je dois donc d' "1"abord supprimer et faire l'extension de l'extrait de yasnippet.

Donc, comme solution, j'utilise toujours la touche fléchée gauche pour désactiver le menu d'achèvement de l'entreprise en premier, mais le curseur va maintenant se "elis|p"déplacer, alors j'utilise à nouveau la touche fléchée droite pour déplacer le curseur jusqu'à la fin "elisp|"et étendre l'extrait de code.

Voici ma question: comment puis-je lier la tabclé d'abord déclencher yasnippet mais pas la société pour me sauver la vie?

Leu_Grady
la source
1
J'utilise tabpour companyet C-opour yasnippet. Je peux décrire davantage si vous êtes intéressé.
abo-abo
@ abo-abo, merci de répondre. Je sais que je peux le faire comme vous, mais je lie Co à un autre commandement, et j'ai mal formé mon muscle de la main pour m'adapter tab. Je ne voudrais donc pas modifier la liaison.
Leu_Grady
C'est pourquoi j'ai demandé :) C-oInutile de faire une diatribe sur la façon dont pourraient développer les abréviations et les extraits de code et les lignes ouvertes, etc. si cela ne vous intéresse pas.
abo-abo
semble intéressant, pouvez-vous décrire plus? :)
Leu_Grady

Réponses:

22

C'est ce que j'ai créé pour moi, confronté au même problème. Il s'agit de la page Wiki Emacs en mode entreprise , mais fortement étendue:

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

Fondamentalement, cela fait <tab>faire la bonne chose la plupart du temps. Appuyez sur l'onglet

  • Mettre en retrait la ligne actuelle,
  • S'il y a un yasnippet à développer, développez-le, même si cela signifie abandonner l'achèvement d'une entreprise (je n'utilise pas beaucoup d'abréviations, donc pas encore de support d'abréviations),
  • Si l'achèvement d'une entreprise est en cours, terminer avec l'élément sélectionné,
  • Sinon, essayez d'utiliser la société pour démarrer la saisie semi-automatique,
  • S'il n'y a rien à compléter automatiquement et que nous sommes dans un espace réservé yasnippet, passez à l'espace réservé suivant.

Notez que s'il existe une possibilité de saisie semi-automatique et que vous modifiez actuellement un espace réservé d'extrait de code, la situation est ambiguë. En guise de compromis, je devais C-<tab>passer directement à l'espace réservé suivant.

Le fait que le nom de l'extrait n'apparaisse pas dans le menu de l'entreprise et que l'existence d'un extrait modifie silencieusement le comportement de la touche de tabulation n'est pas particulièrement agréable, malheureusement ... Bien qu'il soit au moins possible de taper à la <return>place pour obtenir l'achèvement à la place de l'extrait.

Kristóf Marussy
la source
Cela semble interférer avec magit. Fait monter tab dans magit Buffer is read-only: #<buffer *magit: ~/.emacs.d/*>. Une idée de comment résoudre ce problème?
zsquare
@zsquare Je n'utilise pas magit (je sais, je suis fou) donc je ne peux pas tester cela pour être sûr, mais cela ressemble à la carte de clé de magit pour TAB, qui le liemagit-section-toggle , est en conflit avec la ligne (global-set-key [tab] 'tab-indent-or-complete)ci-dessus. Une solution rapide et sale serait d'ajouter une vérification au début de la fonction tab-indent-or-completeci-dessus pour voir si nous sommes en mode magit, par exemple pour une variable globale qui est activée magit-mode-hook.
dodgethesteamroller
c'est génial, merci! :) petit point de style, whenest à peu près un if+progn
Matt Briggs
@zsquare Pour prendre en charge l'onglet en mode magit, ajoutez ceci au tab-indent-or-completecond `((mode dérivé-p 'mode magit) (bascule-section-magit (section-magit-actuelle)))`
Bae
Pour prendre en charge ido au lieu de l'achèvement du mini-tampon par défaut, remplacez le cond par `(((minibufferp) (ido-complete))`
Bae
10

Voici le code que j'utilise:

(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-linede auto-yasnippet fait plus qu'une simple open-line:

  • il essaie d'élargir les abréviations
  • il essaie de passer au champ suivant de yasnippet
  • il essaie de développer yasnippet
  • enfin, il appelle open-linesi tout le reste échoue
abo-abo
la source
merci pour votre extrait. Assez bon. Mais le problème existe toujours. Lorsque je l'utilise pour la première fois C-o, il suffit de fermer le menu de l'entreprise, j'ai donc besoin d'appuyer deux fois pour étendre yasnippet.
Leu_Grady
Je n'ai aucun problème de ce type: C-olorsque le menu de la société est actif, le menu est fermé et le fragment de code est développé.
abo-abo