Concluindo os diretórios falsos do avfs no zsh


37

Como posso ajustar o sistema de conclusão do zsh para concluir arquivos "falsos" em algumas circunstâncias?

Mais precisamente, o sistema de arquivos AVFS expõe 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 ~/.avfstodo arquivo morto, como /tmp/foo.zip, além do próprio arquivo morto ~/.avfs/tmp/foo.zip, existe um diretório chamado ~/.avfs/tmp/foo.zip#que expõe o conteúdo do arquivo morto. No entanto, esse diretório extra não aparece na lista de ~/.avfs/tmp: ele existe apenas quando solicitado explicitamente. (É semelhante à maneira como alguns montadores automáticos operam.)

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

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

(Observe que desejo que a conclusão funcione com todas as chamadas _filesou _dirsnão, apenas no cdcomando. Prefiro não ter que duplicar o código da _filesfunção, se possível.)

¹ e todo o restante das extensões


~ / .Avfs contém uma "cópia" de todo o sistema de arquivos?
CTRL-ALT-DELOR

@richard Sim, tudo /path/to/fooé visível como ~/.avfs/path/to/foo.
Gilles 'SO- stop be evil'

Isso pode ser mais fácil de consertar avfs. Se ele apresentasse a #entrada de diretório padrão para qualquer arquivo que correspondesse às seqüências de caracteres suportadas, ou mesmo a mágica testasse os arquivos em um diretório quanto ao necessário para ter uma #entrada, a conclusão funcionaria. Eu acho que haveria um impacto no desempenho para algo como findagora arrastaria arquivos compactados.
Matt

Respostas:


1

Uma resposta falsa parece insuficiente para esta pergunta falsa; o suporte embutido do zsh para diretórios automount opera nos diretórios ( fake-files dir:names) e não nos padrões de arquivos nele. Isso é útil para adicionar arquivos chamados específicos para um diretório, que pode atender automountou sshfsou NetApp .snapshottipo configurações onde 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 os "nomes" são cadeias de caracteres, e as experiências indicam que os metacaracteres (por exemplo, #ou \#ou '*(e:"echo hi":)') "não funcionam" de várias maneiras; portanto, não sei como colocar uma bola na parte de nomes da fake-filesdeclaração. (Explorar Src/Zle/computil.cpode revelar exatamente quais são os nomes, mas isso seria mais trabalhoso.) (Além disso, o uso de globs recursivos na posição de diretório para nomear os arquivos não voou, mas novamente será necessário C C para ver quanto fake-filespermite você se safa.)

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

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

Exceto se isso falhar, pois apenas mostrará os #arquivos quando isso não for importante e, portanto, não poderá ser concluído neles. (Existem usos produtivos para este formulário, embora não para este caso.)

Usar zstyleo aproxima mais, 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 pode apenas completar o \#/bit (em um debian squeeze virt com uma configuração padrão do avfs), mas não no sistema de arquivos virtual de um arquivo, portanto, será necessário um trabalho adicional para tabular os arquivos. Eu estou supondo que via _call_program ... lsou algo parecido com essas conclusões \#esteja completo , a menos que haja uma maneira mais elegante de convencer- zshnos de que os diretórios que não existem existem.

Más notícias! A conclusão não passa pelos _path_filesdiretórios falsos; Eu suspeito que isso esteja relacionado ao zsh globbing. O zsh 4.something on e o zsh 5.0.8 exibem o problema. Portanto, suspeito que uma correção completa exigiria correções _path_filesou que escrevesse algo diferente que, caso contrário, seja concluído nesses diretórios falsos. Um rastreamento de depuração de conclusão pode ser gerado digitando-se ls /root/.avfs/root/sometar.gz\#/e depois no final dessa digitação control-xe ?, assumindo bindkey -ee _complete_debugvinculado ao referido keycombo, se alguém quiser investigar por que isso está falhando.


0

No zsh, você pode usar compctl -Kpara 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 que precede precisa de mais 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 na página de manual do comando.)

E aqui estão algumas dicas rápidas sobre coisas que podem funcionar na 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!


Eu sei como escrever uma função de conclusão, muito obrigado. O problema é como modificar o mecanismo de conclusão existente para arquivos. Observe que eu uso o “novo” mecanismo de conclusão, não compctl, ou seja, quero alterar o que _filesfaz. Sua resposta não é de todo útil.
Gilles 'SO- stop be evil'

@Gilles Para não iniciar uma guerra de chamas, e com o risco de sair errado, pelo menos ele tentou ... Isso está ocorrendo no "sótão" sem resposta há 2 anos mais ... +1 t redefiniu para 0 pelo esforço .
eyoung100

@ eyoung100 Por favor, não dê +1 para o esforço (o esforço não é aparente aqui). A promoção de respostas inúteis é prejudicial para o site.
Gilles 'SO- stop be evil'
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.