Per favore perdonami se sto facendo qualcosa di stupido qui, la documentazione è enorme e la ricerca non ha ancora trovato nulla.
Sto cercando di creare completamenti di shell per il mio script personalizzato chiamato fab
. Per bash è stato facile, basta rilasciarli in /etc/bash_completion.d
e funzionano. Ma oh ragazzo, è zsh una PITA...
Ho la funzione di completamento _fab
e funziona bene se abilitato con compdef _fab fab
. L'ho messo in /usr/share/zsh/vendor-completions/_fab
che era già nel mio $fpath
. Il file inizia con #compdef fab
e termina con compdef _fab fab
. Sembra buono:
$ type _fab
_fab is an autoload shell function
Ma ogni volta che ho avviato una nuova shell, fab
i completamenti non hanno funzionato (altre funzioni da vendor-completions
, come _docker
, stiamo bene). compinit
risolto questo problema per quella shell specifica. Ho scoperto che rm ~/.zcompdump ~/.zcompdump-$(hostname)-5.1.1; compinit
fallo funzionare in modo permanente (5.1.1 =la mia versione zsh).
Domande:
- Cosa e quando legge
~/.zcompdump
impostare i completamenti iniziali? -
man zshall
dice:La successiva chiamata di compinit leggerà il file scaricato invece di eseguire un'inizializzazione completa.
In tal caso,
compinit
non risolveva i miei completamenti prima di aver eliminato~/.zcompdump
, giusto? Mi sono perso qualcosa? - Cos'è
~/.zcompdump-$(hostname)-5.1.1
e come è correlato a.zcompdump
? L'unica differenza è un completamento che si trova in~/.oh-my-zsh/completions
(perché$ZSH
punta a~/.oh-my-zsh
). È una cosa oh-my-zsh? - Se dovessi impacchettare questi completamenti in un pacchetto ridistribuibile o creare uno script di installazione, dove dovrei inserire i completamenti zsh e cos'altro dovrei fare durante l'installazione per assicurarmi che tutto funzioni correttamente?
Mi rivolgo a Ubuntu 16.04, 18.04 e 19.04, ma sono benvenute informazioni non specifiche per la distribuzione. Lo sto testando su Ubuntu 16.04 con zsh 5.1.1 e recente oh-my-zsh.
Risposta accettata:
TL,DR:Nelle normali operazioni, trascina il file nella directory appropriata. Durante il test, devi rimuovere il file della cache (.zcompdump
per impostazione predefinita, ma gli utenti possono metterlo in una posizione diversa e oh-my-zsh lo mette in una posizione diversa).
La semplice risposta è scrivere la funzione di completamento in un file in cui la prima riga è #compdef fab
. Il file deve trovarsi in una directory su $fpath
.
Il file può contenere il corpo della funzione o una definizione della funzione seguita da una chiamata alla funzione. Cioè, il file contiene qualcosa come
#compdef fab
_arguments …
o
#compdef fab
function _fab {
_arguments …
}
_fab "[email protected]"
Il file deve essere presente su $fpath
prima di compinit
corre. Ciò significa che devi prestare attenzione all'ordine delle cose in .zshrc
:prima aggiungi tutte le directory personalizzate a $fpath
, quindi chiama compinit
. Se utilizzi un framework come oh-my-zsh, assicurati di aggiungere eventuali directory personalizzate a $fpath
prima del codice oh-my-zsh.
compinit
è la funzione che inizializza il sistema di completamento. Legge tutti i file in $fpath
e controlla la loro prima riga per le direttive magiche #autoload
e #compdef
.
.zcompdump
è un file di cache utilizzato da compinit
. ~/.zcompdump
è la posizione predefinita; puoi scegliere una posizione diversa durante l'esecuzione di compinit
. Oh-my-zsh chiama compinit
con il -d
opzione per utilizzare un nome di file cache diverso dato dalla variabile ZSH_COMPDUMP
, che per impostazione predefinita è
ZSH_COMPDUMP="${ZDOTDIR:-${HOME}}/.zcompdump-${SHORT_HOST}-${ZSH_VERSION}"
Il nome host è incluso per il bene delle persone la cui home directory è condivisa tra macchine e che potrebbero avere software diverso installato su macchine diverse. La versione zsh è inclusa perché il file della cache è incompatibile tra le versioni (include codice che cambia da versione a versione).
Correlati:cosa fa CTRL+V in vim?
Penso che tutti i tuoi problemi siano dovuti a un file di cache obsoleto (e questo ti ha reso eccessivamente complicata la situazione). Sfortunatamente, l'algoritmo di zsh per determinare se il file della cache è obsoleto non è perfetto, presumibilmente nell'interesse della velocità. Non controlla il contenuto o i timestamp dei file su $fpath
, li conta. Un .zcompdump
il file inizia con una riga come
#files: 858 version: 5.1.1
Se la versione di zsh e il numero di file sono corretti, zsh carica il file della cache.
Il file della cache contiene solo le associazioni tra i nomi dei comandi, non il codice delle funzioni di completamento. Ecco alcuni scenari comuni in cui la cache funziona in modo trasparente:
- Se aggiungi un nuovo file a
$fpath
, questo invalida la cache. - Più in generale, se aggiungi e rimuovi file su
$fpath
e il numero totale di file rimossi non è uguale al numero totale di file rimossi, questo invalida la cache. - Se sposti un file in una directory diversa in
$fpath
senza cambiarne il nome, questo non influisce su nulla che sia nella cache, quindi la cache rimane corretta. - Se modifichi un file in
$fpath
senza modificare la sua prima riga, ciò non influisce su nulla che sia nella cache, quindi la cache rimane corretta.
Ecco alcuni scenari comuni in cui la cache diventa non valida, ma zsh non se ne rende conto.
- Aggiungi alcuni file a
$fpath
e rimuovi esattamente lo stesso numero di file. - Rinomini un file in
$fpath
. - Aggiungi o modifichi il
#compdef
(o#autoload
) nella parte superiore del file.
Quest'ultimo punto è ciò che tende a mordere durante i test. Se modifichi il #compdef
riga, è necessario rimuovere il .zcompdump
file e riavvia zsh (o riesegui compinit
).
Se inserisci i completamenti in un pacchetto ridistribuibile, trascina semplicemente il file di completamento in una directory che si trova nel $fpath
a livello di sistema . Per un pacchetto Ubuntu, il posto appropriato è /usr/share/zsh/vendor-completions
. Per qualcosa installato in /usr/local
, è /usr/local/share/zsh/site-functions
. Questo è tutto ciò che devi fare.
L'unica cosa che non è trasparente è se devi cambiare il #compdef
riga in un aggiornamento o se si rimuovono o si rinominano alcuni file. In questi casi, gli utenti dovranno rimuovere il loro file di cache e non è qualcosa che puoi fare da un pacchetto che viene installato su una macchina multiutente.