Qual è la differenza tra i plug-in dei frammenti di vim?


25

Esiste un gran numero di plugin di frammenti per vim: ultisnips , snipmate , xptemplate , neosnippet e molto altro.

Tutti hanno pro e contro e più o meno dipendenze. Finora ho usato ultisnips ma non ne sono mai stato completamente soddisfatto.

Dato che abbiamo una domanda molto interessante e completa sui gestori di plugin, penso che sarebbe abbastanza utile avere lo stesso tipo di spiegazioni sui plugin di frammenti.

C'è un elenco qui che potrebbe essere un buon inizio, ma alcune risposte complete, chiare e precise che la nostra community può scrivere sarebbero molto utili.


1
Hai anche questa matrice fornita sul wiki di Marc Weber: vim-wiki.mawercer.de/wiki/topic/…
Luc Hermitte,

2
IMHO questo è abbastanza generico, forse se elabori il "mai soddisfatto totalmente"? Uso "neosnippet.vim" di Shougo.
VanLaser,

dovresti aggiornare il wiki con le informazioni da qui. Grazie.
Christian Brabandt,

@ChristianBrabandt: Sì, non appena avrò del tempo (nei prossimi giorni) lo aggiornerò.
statox

Risposte:


22

Sto usando ultisnips da diverse settimane.

Penso che i principali vantaggi di questo plugin siano i seguenti:

  • È abbastanza veloce anche con un gran numero di frammenti disponibili.
  • La sintassi di base per definire un nuovo frammento è facile da capire, quindi è facile creare rapidamente un nuovo frammento facendo quello che vuoi fare. (Per frammenti più complessi può essere necessario un lavoro aggiuntivo.)
  • Funziona molto bene fuori dagli schemi; una configurazione di base consente di utilizzare gli snippet molto rapidamente.
  • È davvero configurabile. Anche se la configurazione di base funziona bene, se sei un utente esperto puoi davvero ottimizzarlo abbastanza finemente.

Innanzitutto ultisnips è un motore di snippet, il che significa che il plug-in fornisce funzionalità per utilizzare gli snippet ma non fornisce essi stessi gli snippet. Per ottenere i frammenti, l'autore consiglia vim-snippet .

Una volta installati entrambi i plugin, sarai in grado di utilizzare i tuoi frammenti.

I frammenti definizioni sono memorizzate in file denominati seguenti schemi: ft.snippets, ft_*.snippetso ft/*, se ftè il 'filetype' del documento corrente ed *è una conchiglia wildcard qualsiasi stringa compresa la stringa vuota. (Si noti che la sintassi del tipo di file punteggiato cuda.cppè supportata.)

In questo modo gli snippet specifici di un tipo di file vengono espansi solo quando è impostato il tipo di file del buffer. È disponibile un tipo di file speciale allper creare frammenti espansi su tutti i buffer.

Oltre agli snippet forniti da vim-snippet, l'utente può definire i propri snippet. La mia raccomandazione è di metterli nella directory in ~/.vim/my-snippets/Ultisnipsquesto modo Ultisnips li troverà senza ulteriore configurazione ed è facile mantenerli in un repository dotfile.

Per espandere gli snippet, Ultisnips fornisce una variabile g:UltiSnipsExpandTrigger che definisce la mappatura che attiverà l'espansione (ho scelto **quale è abbastanza conveniente per me). Si noti che un'integrazione dovrebbe essere possibile ma non l'ho testata da solo).

Per gli utenti esperti, Ultisnips offre anche alcune funzioni per personalizzare il comportamento dell'espansione o per attivarlo in modo diverso. Vedere:h UltiSnips-trigger-functions


Questo è il primo gestore di frammenti che ho usato molto ampiamente e penso che questo sia un buon inizio per la sua semplicità fuori dagli schemi e la sua possibilità di essere sintonizzato.

Infine ecco un elenco di screencast che offrono una buona introduzione al plugin:


Sai come farlo in modo che non si espanda quando si innesca a meno che non sia preceduto da spazi bianchi O a >(come nel caso della chiusura del codice HTML. Il fatto che non sappia che alla fine di un tag è fastidioso, perché se abilito l'opzione iquindi lo rende così lo espande anche se è nel mezzo di una parola che non va bene.
Tallboy

13

Uso SnipMate originale da quando ho iniziato a usare Vim.

  • Non ha dipendenze esterne.
  • Utilizza una sintassi molto semplice.
  • È molto facile da configurare.
  • È stato abbandonato dal 2009.

Non ho nulla di cui lamentarmi.


16
È la prima volta che vedo qualcuno che parla dell'abbandono come caratteristica. : D
muru,

6
Un progetto abbandonato è un progetto stabile. Non devi preoccuparti che l'istanza locale non sia aggiornata o che un aggiornamento interrompa il flusso di lavoro con una modifica dell'API. Se ha soddisfatto le tue esigenze durante l'installazione, continuerà a farlo per sempre. A meno che le tue esigenze non cambino. La stabilità è la funzione numero 1 che cerco in qualsiasi strumento.
romainl,

3
"Se ha soddisfatto le tue esigenze quando lo hai installato, continuerà a farlo per sempre. A meno che le tue esigenze non cambino." Oppure trovi un bug, a quel punto devi ripararlo da solo, trovare qualcun altro per risolverlo o cercare un'alternativa; uno che non è stato abbandonato, forse.

1
Grazie per la tua risposta @romainl! Ho una domanda: hai detto che il plugin è stato abbandonato, ma il readme reindirizza a una versione più recente che sembra piuttosto attiva e diversi commit sembrano risolvere alcune cose non è meglio usare quella nuova?
statox

1
Ci sono alcuni bug ed errori di documentazione in UltraSnips che rendono l'esperienza introduttiva tutt'altro che piacevole. Dopo averlo finalmente messo in funzione, ho deciso di dare un'occhiata a SnipMate e capire l'argomento di @ romainl per la stabilità.
CHB

7

Ecco un elenco di funzionalità da mu-template . Discl .: Sono il suo manutentore.

  • I file modello possono essere espansi:
    • automaticamente all'apertura di un nuovo buffer (a meno che non sia disattivato dal .vimrc),
    • esplicitamente attraverso i menu o la riga di comando,
    • dalla modalità INSERT in un modo simile a un frammento;
    • dalla modalità VISUAL per circondare la selezione con uno snippet - l'ambiente circostante può essere applicato a diverse zone dello snippet (ad es. zone di codice o condizione in whileun'istruzione di controllo);
  • Tutti gli snippet sono definiti nel loro file modello - tutti gli altri motori di snippet usano un file per tipo di file e vi inseriscono tutti gli snippet;
  • I file modello possono essere sovrascritti dall'utente o nel contesto di un progetto specifico;
  • Gli snippet specifici del tipo di file possono essere definiti per la modalità INSERT (possono essere ereditati, ad esempio gli snippet C possono essere utilizzati da C ++, Java, ecc.), L'elenco degli snippet corrispondenti verrà presentato con un suggerimento per ogni snippet;
  • È possibile inserire espressioni VimL calcolate;
  • Le istruzioni di VimL possono essere eseguite durante l'espansione: la utilizzo per aggiungere automaticamente inclusioni mancanti o istruzioni di importazione;
  • I file modello possono includere altri file modello in modo simile alla funzione (i parametri sono persino supportati) - AFAIK, pochissimi motori di snippet implementano questo, non sono nemmeno in grado di supportare alias di snippet, che è banale da implementare grazie a questa caratteristica ;
  • Completamente integrato con il mio sistema segnaposto;
  • Supporta il rientro (se desiderato) e il rientro di Python;
  • Funziona bene con la piegatura di Vim;
  • I18n amichevole;
  • Quando più frammenti corrispondono, viene visualizzato un menu di completamento avanzato (ispirato al menu a comparsa YouCompleteMe);
  • Opzioni di stile vengono applicate automaticamente (come preferisci i tuoi parentesi? if (...) {\n}? if (...)\n{\n}Qualcos'altro??), E, naturalmente, possono essere ottimizzate a seconda del progetto in corso, o il tipo di file corrente, o addirittura entrambi;
  • Il plug-in è VimL al 100%. Python potrebbe essere usato dal file modello però.
  • mu-template dipende da due plugin di libreria (lh-vim-lib e lh-dev) e dal mio sistema segnaposto (parentesi lh) - ecco perché raccomando di installarlo con VAM o VimFlavor mentre fornisco i file che dichiarano le dipendenze;
  • La licenza è compatibile con la generazione del codice - ciò significa che mentre il codice mu-template è sotto GPLv3, gli snippet non lo sono, puoi usarli in codice proprietario: alcuni snippet sono sotto Boost Software License;

  • L'espansione avviene dopo il caricamento di qualsiasi VIMCC locale presente, al fine di impostare variabili specifiche del progetto prima dell'espansione.

  • Grazie al plug-in StakeHolders di Tom Link, µTemplate ha legato i segnaposto (modificando un segnaposto denominato si modificano altri segnaposto con lo stesso nome). Non installare gli Stakeholder non ti impedirà di usare µTemplate.

Ad essere sinceri, la sintassi del modello è un po 'complicata e il sistema segnaposto appartiene alla prima generazione di segnaposto: mu-template è uno dei più vecchi motori di template / snippet per Vim.

Tuttavia, il fatto che consenta agli snippet di includere altri snippet (in modo condizionale e con parametri) che possono o meno essere sovrascritti è abbastanza importante. Le applicazioni tipiche sono

  • il modello di file C ++

    1. che include un'intestazione di file (di solito ottimizzata in modo diverso per ciascun progetto al fine di includere la giusta nota sul copyright)
    2. quindi carica il modello più adatto al tipo di file corrente (.h, .cpp o file di test unità)
      • nel caso del file header, verranno incluse le protezioni anti-reinclusione - il modo in cui vengono calcolate può essere ignorato (di nuovo per seguire le politiche del progetto)
      • nel caso di file .cpp, il file .h corrispondente viene automaticamente incluso se trovato
  • Ho un frammento / procedura guidata di classe generica in lh-cpp. E diversi tipi di classe specializzati che utilizzano questo modello di classe comune, ma con parametri diversi.


Grazie per la tua risposta! Ho una domanda: hai detto All snippets are defined in their own template-file -- all other snippet engines use one file per filetype and put all snippets in it qual è il vantaggio di questa architettura rispetto al solito (ovvero un file per tipo di file)?
statox

@statox Direi che questo è un problema di manutenzione degli snippet. Alcuni frammenti sono eccessivamente complessi. Dai un'occhiata a lh-cpp internals/class-skeletonper esempio. Preferirei che non si mescolasse con i frammenti delle dichiarazioni di controllo. Ma devo ammettere che avere tutte le dichiarazioni di controllo insieme non sarebbe così problematico. Inoltre, grazie a questo approccio, posso facilmente sostituire i miei frammenti, aggiornarli al volo, usarli come funzioni, ecc.
Luc Hermitte,

In effetti quando vedo il tuo link posso capire perché alcuni frammenti vivono meglio nei loro file. Grazie per i tuoi chiarimenti.
statox

1
@statox In realtà, molti frammenti che ho tendono ad essere complessi: rilevano, deducono e provano a fare il maggior numero possibile di cose intelligenti. Il più delle volte sposto il codice su funzioni caricate automaticamente, ma a volte ha più senso usare diversi frammenti che si chiamano a vicenda (e fungono da punti di variazione che possono essere regolati per le esigenze del progetto -> dichiarazioni sul copyright, ...)
Luc Hermitte,

4

SnipMate e UltiSnips sono i due motori di frammenti più popolari per Vim. Entrambi sono ispirati dalla sintassi dello snippet di TextMate. UltiSnips può eseguire tutti i frammenti di SnipMate ma ha anche una sintassi aggiuntiva per renderlo più potente.

Una buona regola empirica è che se Vim ha il supporto per Python, usa UltiSnips. In caso contrario, utilizzare SnipMate.

Nel mio .vimrc, carico (usando Plug) entrambi i plugin a seconda della disponibilità di Python.

if (has('python') || has('python3'))
    Plug 'SirVer/ultisnips'
else
    Plug 'garbas/vim-snipmate'
    Plug 'MarcWeber/vim-addon-mw-utils' "required for snipmate
    Plug 'tomtom/tlib_vim' "required for snipmate
endif

UltiSnips può anche eseguire codici Python nel suo frammento, permettendogli di fare alcuni trucchi interessanti. Questo è uno dei miei frammenti preferiti che disegna una casella attorno a un testo (da Come sono in grado di prendere appunti nelle lezioni di matematica usando LaTeX e Vim | Gilles Castel )

snippet box2 "Box"
`!p snip.rv = '┌' + '─' * (len(t[1]) + 2) + '┐'`
│ $1 │
`!p snip.rv = '└' + '─' * (len(t[1]) + 2) + '┘'`
$0
endsnippet

Con questo frammento, posso produrre qualcosa del genere:

┌─────────────────────┐
│ this is a cool box! │
└─────────────────────┘
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.