Completamento delle directory false avfs in zsh


37

Come posso modificare il sistema di completamento di zsh per completare i file "falsi" in alcune circostanze?

Più precisamente, il filesystem AVFS espone gli archivi come directory creando una "directory falsa" accanto a ogni archivio. Per impostazione predefinita, replica l'intera gerarchia di directory sotto il suo punto di montaggio ~/.avfs. Inoltre, sotto ~/.avfs, per ogni file di archivio come /tmp/foo.zip, oltre al file di archivio stesso ~/.avfs/tmp/foo.zip, c'è una directory chiamata ~/.avfs/tmp/foo.zip#che espone il contenuto dell'archivio. Tuttavia questa directory extra non compare nell'elenco di ~/.avfs/tmp: esiste solo quando esplicitamente richiesto. (Questo è simile a come funzionano alcuni automounter.)

mountavfs
cd ~/.avfs/tmp/foo.zip\#

Quando digito un comando come quello sopra, foo.zip#non appare come un completamento sotto ~/.avfs/tmp/, poiché non esiste tale directory. Come posso dire a zsh che ogni volta che c'è un file il cui percorso completo $arccorrisponde ~/.avfs/**/*.(tgz|zip)¹, dovrebbe fingere che ci sia una directory chiamata ${arc}#?

(Nota che voglio che il completamento funzioni con ogni chiamata a , _fileso _dirsnon solo per il cdcomando. Preferirei non dover duplicare il codice della _filesfunzione, se possibile.)

¹ e tutto il resto delle estensioni


~ / .Avfs contiene una "copia" dell'intero file system?
ctrl-alt-delor,

@richard Sì, tutto /path/to/fooè visibile come ~/.avfs/path/to/foo.
Gilles 'SO- smetti di essere malvagio' il

Questo potrebbe essere più facile da risolvere avfs. Se presentasse la #voce di directory predefinita per tutti i file che corrispondevano alle stringhe supportate, o persino magic testasse i file in una directory per ciò che era necessario avere una #voce, il completamento avrebbe funzionato. Immagino che si verificherebbe un calo delle prestazioni per qualcosa di simile findin quanto ora si trascinerebbe tra i file compressi.
Matt,

Risposte:


1

Una risposta falsa sembra insufficiente per questa domanda falsa; il supporto incorporato zsh per le directory di montaggio automatico opera su directory ( fake-files dir:names) e non su modelli di file in esse. Questo è utile per aggiungere specifici file con nome a una directory, che può essere adatta automounto sshfso .snapshotconfigurazioni di tipo NetApp in cui la directory da montare è un nome statico noto ALAS.

autoload -U compinit
compinit
zstyle ':completion:*' fake-files $HOME/.avfs:'ALAS POOR YORICK'

zshall(1)dice che i "nomi" sono stringhe e gli esperimenti indicano che i metacaratteri (ad esempio #o \#o '*(e:"echo hi":)') "non funzionano" in vari modi, quindi non ho modo di conoscere un globo sulla porzione dei nomi dell'istruzione fake-files. (L'analisi approfondita Src/Zle/computil.cpotrebbe rivelare esattamente quali possono essere i nomi, ma sarebbe più lavoro.) (Inoltre, l'utilizzo di globi ricorsivi nella posizione della directory per denominare i file di archivio non ha funzionato, ma di nuovo ci vorrà l'immersione C per vedere quanto fake-filesconsente te ne vai via.)

Con compdef, si possono elencare i .avfscompletamenti di directory:

compdef '_files -g $HOME/.avfs/\*' -p \^
function andthehash {
  reply=($REPLY $REPLY\#)
}
compdef "_files -g $HOME/.avfs/'*(+andthehash)'" -p \^

Tranne questo fallisce, poiché mostrerà i #file solo quando non ha importanza, e quindi non può completarli. (Ci sono usi produttivi per questo modulo, anche se non per questo caso.)

L'uso zstyleti avvicina, con il seguente .zshrc:

autoload -U compinit
compinit

function UnderAVFS {
  local pdir
  [[ -z $1 ]] && return 1
  pdir=$1:a
  [[ ! -d $pdir ]] && pdir=$pdir:h
  [[ ! -d $pdir || $pdir == . ]] && return 1
  while [[ $pdir != / ]]; do
    [[ $pdir == $HOME/.avfs ]] && return 0
    pdir=$pdir:h
  done
  return 1
}

function AVFSExtras {
  if UnderAVFS $REPLY; then
    reply=($REPLY)
    # TODO embiggen list of archive suffixes
    [[ $REPLY == *.(bz2|tbz2) ]] && reply+=($REPLY\#)
  fi
}

# Try to match avfs, otherwise the default pattern. Probably could greatly
# benefit from caching, to avoid hits on UnderAVFS function.
zstyle ':completion:*' file-patterns '*(+AVFSExtras):avfs-files' '%p:all-files'

Tuttavia, può completare solo fino al \#/bit (su un debian squeeze virt con un'impostazione avfs predefinita), ma non nel filesystem virtuale per un archivio, quindi sarà necessario un ulteriore lavoro per completare il tab negli archivi. Sto indovinando via _call_program ... lso qualcosa del genere per completamenti al \#bit, a meno che non ci sia un modo più elegante per continuare a zshcredere che le directory inesistenti lo facciano.

Cattive notizie! Il completamento non supera _path_filesle false directory; Ho il sospetto che questo sia zsh globbing. Sia zsh 4.something on che zsh 5.0.8 presentano il problema. Quindi sospetto che una correzione completa richiederebbe patch _path_fileso scrivere qualcosa di diverso che altrimenti si completa su queste false directory. Una traccia di debug di completamento può essere generata digitando ls /root/.avfs/root/sometar.gz\#/e quindi alla fine di quella digitazione control-xe quindi ?, assumendo bindkey -ee che _complete_debugè vincolata a detto keycombo, se qualcuno vuole approfondire il motivo per cui questo non riesce.


0

In zsh puoi usare compctl -Kper registrare la tua funzione nelle opzioni di completamento della generazione. Per esempio:

compctl -f -c -u -r -K myAVFScompletion "*" -tn

Quindi è necessario definire la propria funzione:

myAVFScompletion () {
    read -c COMMAND ARGS

    # Decide what paths you want to suggest completion for
    # by looking inside the ~/.avfs folder.

    # Place your suggestions into an array:
    reply=( a_path b_path ... )
}

Ovviamente quanto sopra ha bisogno di un po 'più di lavoro, ma è qualcosa per cominciare.

Una funzione di completamento personalizzata simile (ma diversa) può essere registrata per bash.

Ecco un esempio con implementazioni per bash e zsh . (Offre il completamento delle opzioni della riga di comando estraendo le opzioni dalla pagina man del comando.)

E qui ci sono alcune ipotesi su cose che potrebbero funzionare all'interno della tua funzione di completamento:

if [[ -d "$ARGS#" ]]
then reply=( "$ARGS#" )
else reply=
fi

O forse questo:

reply=( $(find ~/.avfs -type f -name "*.tgz" -or -name "*.zip" | sed 's+$+#+') )

In bocca al lupo!


So come scrivere una funzione di completamento, grazie mille. Il problema è come modificare il meccanismo di completamento esistente per i file. Nota che non uso il "nuovo" meccanismo di completamento compctl, cioè voglio cambiare cosa _filesfa. La tua risposta non è affatto utile.
Gilles 'SO- smetti di essere malvagio' il

@Gilles Non avviare una guerra alla fiamma, e a rischio di sbagliare, almeno ci ha provato ... Questo è stato seduto nella "soffitta" senza risposta 2 anni più ... +1 t resettato a 0 per lo sforzo .
eyoung100,

@ eyoung100 Per favore, non dare +1 per lo sforzo (non lo sforzo è evidente qui). L'upgrade di risposte non utili è dannoso per il sito.
Gilles 'SO- smetti di essere malvagio' il
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.