Hash do diretório dinâmico

2

Há um método legal em zsh chamado hash -d com o uso de exemplo:

hash -d magic=/very/long/name/$USER/even/more

Então eu posso cd ~magic/deeper . É possível obter o mesmo resultado, mas que ~magic depende do resultado de algum script? (é dinâmico) Assim:

hash -d magic=/very/long/name/$(compute the subdirectory here)/even/more

Isso não funciona para mim porque o cálculo é feito uma vez e não toda vez que a mágica é usada.

Há uma solução alternativa para criar algum comando para fazer isso mycd , que analisa os argumentos e verifica se os primeiros argumentos começam com ~magic e, em seguida, o cd real. Eu não estou satisfeito com isso porque não funcionaria com vim ~magic/something ou outros comandos.

    
por neo 09.05.2014 / 07:54

1 resposta

2

O zsh de fato suporta 'hashes do diretório dynamic', eles são chamados diretórios nomeados dinâmicos (veja zshexpn(1) para detalhes). O nome de um diretório dinâmico é fornecido entre colchetes sem aspas: ~[name] .

Eles são configurados definindo a função zsh_directory_name ou criando uma matriz chamada zsh_directory_name_functions contendo nomes de função. Essas funções são usadas de três maneiras, definidas pelo primeiro parâmetro:

  1. verificar se o diretório atual é um diretório nomeado ( d )
  2. mapeia um nome para um diretório ( n )
  3. forneça uma lista de nomes para conclusão ( c )

Nem todos os modos precisam ser implementados, mas devem retornar um status diferente de zero.

Este é um exemplo que nomeia dinamicamente qualquer /very/long/name/$USER/even/more com ~[magic:$USER] (com base no exemplo de zshexpn(1) )

zsh_directory_name() {
    emulate -L zsh
    setopt extendedglob
    local -a match mbegin mend
    local pp1=/very/long/name
    local pp2=even/more
    if [[ $1 = d ]]; then
        if [[ $2 = (#b)($pp1/)([^/]##)(/$pp2)* ]]; then
            typeset -ga reply
            reply=(magic:$match[2] $(( ${#match[1]} + ${#match[2]} + ${#match[3]} )) )
        else
            return 1
        fi
    elif [[ $1 = n ]]; then
        [[ $2 != (#b)magic:(?*) ]] && return 1
        typeset -ga reply
        reply=($pp1/$match[1]/$pp2)
    elif [[ $1 = c ]]; then
        local expl
        local -a dirs
        dirs=($pp1/*/$pp2)
        for (( i=1; i<=$#dirs; i++ )); do
            dirs[$i]=magic:${${dirs[$i]#$pp1/}%/$pp2}
        done
        _wanted dynamic-dirs expl 'user specific directory' compadd -S\] -a dirs
        return
    else
        return 1
    fi
    return 0
}

Uso:

% ls /very/long/name
bar baz foo
% ls -d /very/long/name/*/even/more
/very/long/name/bar/even/more /very/long/name/foo/even/more
% cd ~[magic:foo]
% pwd
/very/long/name/foo/even/more
% cd ~[mag  #TAB
user specific directory:
magic:bar magic:foo
% cd ~[magic:baz]
cd: no such file or directory: /very/long/name/baz/even/more

O diretório /very/long/name/baz não contém o subdiretório even/more e, portanto, não é nomeado.

    
por 09.05.2014 / 15:16

Tags