Remplir de faux répertoires avfs dans zsh

37

Comment puis-je modifier le système d'achèvement de zsh pour terminer les «faux» fichiers dans certaines circonstances?

Plus précisément, le système de fichiers AVFS expose les archives en tant que répertoires en créant un «répertoire factice» à côté de chaque archive. Par défaut, il réplique la totalité de la hiérarchie des répertoires sous son point de montage ~/.avfs. En outre, sous ~/.avfs, pour chaque fichier d'archive tel que /tmp/foo.zip, outre le fichier d'archive lui ~/.avfs/tmp/foo.zip- même , il existe un répertoire appelé ~/.avfs/tmp/foo.zip#qui expose le contenu de l'archive. Cependant, ce répertoire supplémentaire n'apparaît pas dans la liste de ~/.avfs/tmp: il n'existe que sur demande explicite. (Ceci est similaire à la façon dont certains monteurs automatiques fonctionnent.)

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

Lorsque je tape une commande comme celle ci-dessus, foo.zip#n'apparaît pas comme une complétion sous ~/.avfs/tmp/, car il n'y a pas de tel répertoire. Comment puis-je dire à zsh que chaque fois qu'il y a un fichier dont le chemin complet $arccorrespond ~/.avfs/**/*.(tgz|zip)¹, il doit prétendre qu'il existe un répertoire appelé ${arc}#?

(Notez que je souhaite que l'achèvement fonctionne avec chaque appel de, _filesou _dirspas uniquement pour la cdcommande. Je préférerais ne pas avoir à dupliquer le code de la _filesfonction, si possible.)

¹ et tout le reste des extensions

Gilles, arrête de faire le mal
la source
~ / .Avfs contient-il une "copie" de tout le système de fichiers?
ctrl-alt-delor
@richard Oui, tout /path/to/fooest visible en tant que ~/.avfs/path/to/foo.
Gilles 'SO- arrête d'être méchant'
Cela pourrait être plus facile à réparer avfs. Si elle présentait l' #entrée de répertoire par défaut pour tous les fichiers correspondant aux chaînes prises en charge, ou même si Magic testait les fichiers d'un répertoire pour déterminer #s'il était nécessaire d'avoir une entrée, la finalisation fonctionnerait simplement. J'imagine que les performances pourraient être affectées de la même manière findque les fichiers compressés.
Matt

Réponses:

1

Une fausse réponse semble insuffisante pour cette fausse question; la prise en charge intégrée de zsh pour les répertoires automount fonctionne sur les répertoires ( fake-files dir:names) et non sur les modèles de fichiers qu'ils contiennent. Ceci est pratique pour ajouter des fichiers nommés spécifiques à un répertoire, ce qui peut convenir à automountou aux configurations de type sshfsNetApp .snapshotoù le répertoire à monter est un nom statique connu ALAS.

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

zshall(1)dit que les "noms" sont des chaînes, et que les expériences indiquent des métacaractères (par exemple, #ou \#ou '*(e:"echo hi":)') "ne fonctionnent pas" de différentes manières, donc il m'est impossible de glisser un glob sur la partie des noms de la fake-filesdéclaration. (Fouiller à travers Src/Zle/computil.cpourrait révéler exactement ce que les noms peuvent être, mais ce serait plus de travail.) (Aussi, en utilisant globs récursifs dans la position de répertoire pour nommer les fichiers d' archive n'a pas volé, mais encore une fois , il prendra la plongée C pour voir combien fake-fileslets vous vous en sortez.)

Avec compdef, on peut lister les .avfsachèvements de répertoires:

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

Sauf que cela échoue, car il ne montrera que les #fichiers sans importance, et ne pourra donc pas être complété. (Il existe des utilisations productives pour ce formulaire, mais pas pour ce cas.)

Utiliser zstylevous rapproche, avec ce qui suit .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'

Cependant, il ne peut se terminer que jusqu'au \#/bout (sur un serveur Debian squeeze virt avec une configuration avfs par défaut), mais pas dans le système de fichiers virtuel pour une archive; un travail supplémentaire sera donc nécessaire pour compléter l’archive. Je devine par la voie via _call_program ... lsou quelque chose du genre pour les achèvements \#, à moins qu’il n’y ait un moyen plus élégant de zshcroire que des répertoires qui n’existent pas existent.

Mauvaises nouvelles! La finalisation ne réussit pas _path_filespour les faux répertoires; Je soupçonne que cela est lié au zsh globbing. Zsh 4.something on et zsh 5.0.8 présentent tous deux le problème. Donc, je soupçonne qu'un correctif complet nécessiterait des correctifs _path_files, ou d'écrire quelque chose de différent qui se termine autrement sur ces faux répertoires. Une trace de débogage d'achèvement peut être générée en tapant ls /root/.avfs/root/sometar.gz\#/puis à la fin de ce typage control-x, puis ?, en supposant bindkey -eet _complete_debuglié à keycombo, si quelqu'un veut approfondir la raison de son échec.

thrig
la source
0

En zsh, vous pouvez utiliser compctl -Kvotre propre fonction pour générer des options de complétion. Par exemple:

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

Ensuite, vous devez définir votre propre fonction:

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 ... )
}

De toute évidence, ce qui précède nécessite un peu plus de travail, mais il faut commencer par là.

Une fonction d'achèvement personnalisée similaire (mais différente) peut être enregistrée pour bash.

Voici un exemple avec des implémentations pour bash et zsh . (Il permet de compléter les options de ligne de commande en les extrayant de la page de manuel de la commande.)

Et voici quelques hypothèses sur ce qui pourrait fonctionner dans votre fonction d'achèvement:

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

Ou peut-être ceci:

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

Bonne chance!

Joeytwiddle
la source
Je sais comment écrire une fonction d'achèvement, merci beaucoup. Le problème est de savoir comment modifier le mécanisme d’achèvement existant pour les fichiers. Notez que je n’utilise pas le «nouveau» mécanisme d’achèvement compctl, c’est-à-dire que je veux changer ce qui le _filesfait. Votre réponse n'est pas utile du tout.
Gilles 'SO- arrête d'être méchant'
@Gilles Ne pas déclencher une guerre de flammes, et au risque de se tromper, au moins il a essayé ... Cela fait 2 ans qu'il est assis dans le "grenier" sans réponse plus ... +1 t remis à 0 pour l'effort .
eyoung100
@ eyoung100 S'il vous plaît ne donnez pas +1 pour l'effort (cet effort n'est pas apparent ici). Faire voter des réponses inutiles est préjudiciable au site.
Gilles, arrête de faire le mal '24