Completando diretórios falsos do avfs no zsh

37

Como posso ajustar o sistema de completação do zsh para completar arquivos “falsos” em algumas circunstâncias?

Mais precisamente, o sistema de arquivos AVFS expõe os arquivos como diretórios, criando um “diretório falso” ao lado de cada arquivo. Por padrão, ele replica toda a hierarquia de diretórios sob seu ponto de montagem ~/.avfs . Além disso, em ~/.avfs , para cada arquivo, como /tmp/foo.zip , além do próprio arquivo archive ~/.avfs/tmp/foo.zip , existe um diretório chamado ~/.avfs/tmp/foo.zip# que expõe o conteúdo do arquivo. No entanto, esse diretório extra não aparece na listagem de ~/.avfs/tmp : ele existe somente quando explicitamente solicitado. (Isso é semelhante a como alguns automounters operam.)

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

Quando eu digito um comando como o acima, foo.zip# não aparece como uma conclusão em ~/.avfs/tmp/ , já que não existe tal diretório. Como posso dizer ao zsh que sempre que houver um arquivo cujo caminho completo $arc corresponda a ~/.avfs/**/*.(tgz|zip) ¹, ele deve fingir que existe um diretório chamado ${arc}# ?

(Observe que quero que a conclusão funcione com todas as chamadas para _files ou _dirs , não apenas para o comando cd . Prefiro não ter que duplicar o código da função _files , se possível.)

¹ e todo o resto das extensões

    
por Gilles 25.07.2012 / 03:16

2 respostas

1

Uma resposta falsa parece insuficiente para essa pergunta falsa; o suporte interno ao zsh para diretórios automontados opera em diretórios ( fake-files dir:names ) e não em padrões de arquivo. Isso é útil para adicionar arquivos nomeados específicos a um diretório, o que pode ser adequado para automount ou sshfs ou NetApp .snapshot type setups em que o diretório a ser montado é um nome estático conhecido, ALAS .

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

zshall(1) diz que "nomes" são strings e experimentos indicam metacaracteres (por exemplo, # ou \# ou '*(e:"echo hi":)' ) "não funcionam" de várias maneiras, então não há como saber coloque um glob na porção de nomes da instrução fake-files . (Descobrir Src/Zle/computil.c pode revelar exatamente o que os nomes podem ser, mas isso seria mais trabalho.) (Além disso, usar globs recursivos na posição do diretório para nomear os arquivos archive não voou, mas, novamente, será necessário o mergulho C para ver quanto fake-files permite que você se dê bem.)

Com compdef , pode-se listar as conclusões do diretório .avfs :

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

Exceto que isso falhará, pois só mostrará os arquivos # quando isso não for relevante e, portanto, não poderá ser concluído neles. (Há usos produtivos para este formulário, embora não para este caso.)

Usar zstyle aproxima você, com o seguinte .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'

No entanto, ele só pode completar até o \#/ bit (em um squeeze debian virt com uma configuração avfs padrão), mas não no sistema de arquivos virtual para um archive, portanto será necessário um trabalho adicional para aba completa no arquivos. Eu estou supondo via _call_program ... ls ou algo ao longo dessas linhas para conclusões no \# bit, a menos que haja uma maneira mais elegante de con zsh em acreditar que diretórios que não existem fazem.

Más notícias! A conclusão não passa de _path_files para os diretórios falsos; Eu suspeito que isso seja relacionado a globalização de zsh. Tanto o zsh 4.something on quanto o zsh 5.0.8 exibem o problema. Portanto, suspeito que uma correção completa exigiria patches para _path_files ou para escrever algo diferente que, de outra forma, seria concluído nesses diretórios falsos. Um rastreamento de depuração de conclusão pode ser gerado digitando ls /root/.avfs/root/sometar.gz\#/ e, em seguida, no final dessa digitação, control-x e, em seguida, ? , assumindo bindkey -e e _complete_debug vinculado ao dito keycombo, se alguém quiser se aprofundar por que isso está falhando.

    
por 23.09.2015 / 02:41
0

No zsh, você pode usar compctl -K para registrar sua própria função nas opções de conclusão da geração. Por exemplo:

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

Então você precisa definir sua própria função:

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, o item acima precisa de mais algum trabalho, mas é algo para começar.

Uma função de conclusão personalizada semelhante (mas diferente) pode ser registrada para o bash.

Aqui está um exemplo com implementações para bash e zsh . (Ele oferece a conclusão de opções de linha de comando, pegando as opções fora da página man do comando).

E aqui estão algumas suposições rápidas sobre as coisas que podem funcionar dentro da sua função de conclusão:

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

Ou talvez isso:

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

Boa sorte!

    
por 05.06.2015 / 14:30