Come rendere yasnippet e la compagnia più belli?


22

Nel mio emacs, diciamo, uso un "elisp"yasnippet per estendere un blocco lisp in modalità org. Ma prima di estenderlo, la società viene innescata per prima, il che mi dà un menu come "1. elisp1, 2. elisp2"senza un'opzione "elisp". Ora, se uso tabper estendere yasnippet, è sempre fastidioso che venga sempre "elisp1"visualizzato sullo schermo. Quindi devo "1"prima cancellare e fare l'estensione del frammento di yasnippet.

Quindi, come soluzione, utilizzo sempre il tasto freccia sinistra per disattivare prima il menu di completamento dell'azienda, ma ora il cursore si "elis|p"sposta su , quindi utilizzo nuovamente il tasto freccia destra per spostare il cursore alla fine "elisp|"ed estendere lo snippet.

Ecco la mia domanda: come posso in tabprimo luogo legare chiave innescare yasnippet ma non società per salvarmi la vita?


1
Sto usando tabper companye C-oper yasnippet. Posso descrivere ulteriormente se sei interessato.
abo-ABO

@ abo-abo, grazie risposta. So di poterlo fare come fai tu, ma lego Co ad altri comandi e ho mal addestrato il muscolo della mia mano ad adattarsi tab. Quindi non vorrei cambiare l'associazione.
Leu_Grady,

Questo è il motivo per cui ho chiesto :) C-oInutile pensare a come espandere abbrevs e snippet e linee aperte ecc. Se non ti interessa.
abo-ABO

sembra interessante, puoi descriverne di più? :)
Leu_Grady,

Risposte:


22

Questo è ciò che ho creato per me stesso, affrontando lo stesso problema. È dalla pagina Wiki Emacs in modalità azienda , ma fortemente estesa:

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

Fondamentalmente, questo fa <tab>fare la cosa giusta il più delle volte. Premendo tab sarà

  • Rientra la riga corrente,
  • Se c'è un yasnippet da espandere, espanderlo, anche se questo significa interrompere il completamento di un'azienda (non uso molto le abbreviazioni, quindi non ho ancora supporto per le abbreviazioni),
  • Se è in corso il completamento di un'azienda, completare con l'elemento selezionato,
  • Altrimenti prova a usare la compagnia per avviare il completamento automatico,
  • Se non c'è nulla da completare automaticamente e ci troviamo in un segnaposto yasnippet, passa al segnaposto successivo.

Tieni presente che se esiste un'opportunità per il completamento automatico e stai attualmente modificando in un segnaposto di frammenti, la situazione è ambigua. Come compromesso, sono obbligato C-<tab>a saltare direttamente al prossimo segnaposto.

Il fatto che il nome dello snippet non appaia nel menu dell'azienda e che l'esistenza di uno snippet modifichi silenziosamente il comportamento del tasto tab non è particolarmente bello, sfortunatamente ... Anche se almeno è possibile digitare <return>invece per ottenere il completamento dello snippet.


Questo sembra interferire con Magit. Fa alzare la linguetta in magit Buffer is read-only: #<buffer *magit: ~/.emacs.d/*>. Qualche idea su come posso risolverlo?
zsquare,

@zsquare Non uso magit (lo so, sono pazzo), quindi non posso provarlo per sicurezza, ma sembra che la mappa dei tasti di magit per TAB, alla quale si legamagit-section-toggle , sia in conflitto con la riga (global-set-key [tab] 'tab-indent-or-complete)sopra. Una soluzione rapida e sporca sarebbe quella di aggiungere un segno di spunta all'inizio della funzione tab-indent-or-completesopra per vedere se siamo in modalità magit, ad esempio per una variabile globale che viene attivata magit-mode-hook.
dodgethesteamroller,

è fantastico, grazie! :) piccolo punto di stile, whenè praticamente un if+progn
Matt Briggs

@zsquare Per supportare la scheda in modalità magit aggiungi questo al tab-indent-or-completecond `((deriv-mode-p 'magit-mode) (magit-section-toggle (magit-current-section)))`
Bae

Per supportare ido invece del completamento predefinito del minibuffer, sostituisci il cond con `((minibufferp) (ido-complete))`
Bae

10

Ecco il codice che sto usando:

(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-lineda auto-yasnippet fa più di una semplice open-line:

  • cerca di espandere abbrevs
  • tenta di passare al campo successivo di yasnippet
  • tenta di espandere yasnippet
  • infine, chiama open-linese tutto il resto fallisce

grazie per il tuo frammento. Piuttosto buono. Ma il problema esiste ancora. Quando lo uso per la prima volta C-o, chiudo semplicemente il menu dell'azienda, quindi ho bisogno di premere due volte per estendere yasnippet.
Leu_Grady,

Non ho questo problema: C-ocon il menu aziendale attivo chiuderà il menu ed espanderà lo snippet.
abo-ABO
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.