Completar directorios falsos avfs en zsh

37

¿Cómo puedo modificar el sistema de finalización de zsh para completar archivos "falsos" en algunas circunstancias?

Más precisamente, el sistema de archivos AVFS expone los archivos como directorios al crear un "directorio falso" al lado de cada archivo. Por defecto, replica toda la jerarquía de directorios bajo su punto de montaje ~/.avfs. Además, debajo de ~/.avfs, para cada archivo de archivado, como /tmp/foo.zip, además del archivo de archivado ~/.avfs/tmp/foo.zip, hay un directorio llamado ~/.avfs/tmp/foo.zip#que expone el contenido del archivo. Sin embargo, este directorio adicional no aparece en la lista de ~/.avfs/tmp: solo existe cuando se solicita explícitamente. (Esto es similar a cómo funcionan algunos montadores automáticos).

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

Cuando escribo un comando como el anterior, foo.zip#no aparece como una finalización en ~/.avfs/tmp/, ya que no existe ese directorio. ¿Cómo puedo decirle a zsh que siempre que haya un archivo cuya ruta completa $arccoincida con ~/.avfs/**/*.(tgz|zip)¹, debería pretender que hay un directorio llamado ${arc}#?

(Tenga en cuenta que quiero que la finalización funcione con cada llamada _fileso _dirs, no solo para el cdcomando. Preferiría no tener que duplicar el código de la _filesfunción, si es posible).

¹ y todo el resto de las extensiones

Gilles 'SO- deja de ser malvado'
fuente
¿~ / .Avfs contiene una "copia" de todo el sistema de archivos?
ctrl-alt-delor
@richard Sí, todos /path/to/fooson visibles como ~/.avfs/path/to/foo.
Gilles 'SO- deja de ser malvado'
Esto podría ser más fácil arreglado avfs. Si presentara la #entrada de directorio predeterminada para cualquier archivo que coincida con las cadenas que admite, o incluso probó mágicamente los archivos en un directorio para lo que necesitaba tener una #entrada, entonces la finalización simplemente funcionaría. Supongo que habría un éxito en el rendimiento de algo como, findya que ahora rastrearía a través de archivos comprimidos.
Matt

Respuestas:

1

Una respuesta falsa parece insuficiente para esta pregunta falsa; El soporte incorporado de zsh para directorios de montaje automático opera en directorios ( fake-files dir:names), y no en patrones de archivo en ellos. Esto es útil para agregar archivos llamados específicos a un directorio, que puede adaptarse automounto sshfso NetApp .snapshottipo configuraciones donde el directorio-a-ser-montar es un nombre estático conocido, ALAS.

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

zshall(1)dice que los "nombres" son cadenas, y los experimentos indican meta-caracteres (por ejemplo, #o \#o '*(e:"echo hi":)') "no hacer el trabajo" de varias maneras, por lo que no hay manera que conozco para echar un pegote sobre la parte de los nombres de la fake-filesdeclaración. (Profundizar Src/Zle/computil.cpodría revelar exactamente cuáles pueden ser los nombres, pero eso sería más trabajo). (Además, el uso de globos recursivos en la posición del directorio para nombrar los archivos de almacenamiento no voló, pero nuevamente tomará C zambullirse para ver cuánto fake-filespermite te saldrás con la tuya)

Con compdef, uno puede enumerar las .avfsterminaciones de directorio:

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

Excepto que esto falla, ya que solo mostrará los #archivos cuando no importa y, por lo tanto, no se puede completar en ellos. (Hay usos productivos para este formulario, aunque no para este caso).

Usar zstylete acerca, con lo siguiente .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'

Sin embargo, solo puede completarse hasta el \#/bit (en un debian squeeze virt con una configuración avfs predeterminada), pero no en el sistema de archivos virtual para un archivo, por lo que será necesario un trabajo adicional para completar la pestaña en los archivos. Estoy adivinando a través de _call_program ... lso algo por el estilo para completar en el momento \#, a menos que haya una forma más elegante de zshcreer que los directorios que no existen sí lo hacen.

¡Malas noticias! La finalización no llega _path_filesa los directorios falsos; Sospecho que esto está relacionado con zsh globbing. Tanto zsh 4.something on como zsh 5.0.8 presentan el problema. Por lo tanto, sospecho que una solución completa requeriría parches _path_fileso escribir algo diferente que de lo contrario se completa en estos directorios falsos. Se puede generar una traza de depuración completada escribiendo ls /root/.avfs/root/sometar.gz\#/y luego al final de esa escritura control-xy luego ?, suponiendo bindkey -ey que _complete_debugestá vinculado a dicho combo de teclas, si alguien quiere profundizar en por qué esto está fallando.

thrig
fuente
0

En zsh puede usar compctl -Kpara registrar su propia función en las opciones de finalización de generación. Por ejemplo:

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

Entonces necesitas definir tu propia función:

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

Obviamente, lo anterior necesita algo más de trabajo, pero es algo para comenzar.

Se puede registrar una función de finalización personalizada similar (pero diferente) para bash.

Aquí hay un ejemplo con implementaciones para bash y zsh . (Ofrece la finalización de las opciones de la línea de comandos al extraer las opciones de la página del comando man.)

Y aquí hay algunas conjeturas rápidas sobre cosas que podrían funcionar dentro de su función de finalización:

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

O tal vez esto:

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

¡Buena suerte!

joeytwiddle
fuente
Sé cómo escribir una función de finalización, muchas gracias. El problema es cómo modificar el mecanismo de finalización existente para los archivos. Tenga en cuenta que uso el "nuevo" mecanismo de finalización, no compctl, es decir, quiero cambiar lo que _fileshace. Tu respuesta no es útil en absoluto.
Gilles 'SO- deja de ser malvado'
@Gilles Para no comenzar una guerra de llamas, y con el riesgo de salir mal, al menos lo intentó ... Esto ha estado sentado en el "ático" sin respuesta 2 años más ... +1 t restablecer a 0 por el esfuerzo .
eyoung100
@ eyoung100 Por favor, no le des +1 al esfuerzo (no ese esfuerzo es evidente aquí). Votar respuestas inútiles es perjudicial para el sitio.
Gilles 'SO- deja de ser malvado'