2

В zsh есть хороший метод с именем hash -d с примером использования:

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

Тогда я могу cd ~magic/deeper . Можно ли достичь того же результата, но чтобы ~magic зависела от результата какого-либо сценария? (это динамично) Вот так:

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

Это не работает для меня, потому что это вычисление выполняется один раз, а не каждый раз, когда используется магия.

Существует обходной путь для создания некоторой команды для выполнения этого mycd который анализирует аргументы и проверяет, начинается ли первый аргумент с ~magic а затем выполняет фактический cd . Я не удовлетворен этим, потому что он не будет работать с vim ~magic/something или другими командами.

1 ответ1

2

zsh действительно поддерживает «динамические хеши каталогов», они называются динамическими именованными каталогами (подробнее см. zshexpn(1) ). Имя динамического каталога указывается в квадратных скобках без кавычек: ~[name] .

Они настраиваются путем определения функции zsh_directory_name или путем создания массива с именем zsh_directory_name_functions содержащего имена функций. Эти функции используются тремя способами, которые определяются первым параметром:

  1. проверка, является ли текущий каталог именованным каталогом (d)
  2. сопоставить имя с каталогом (n)
  3. предоставить список имен для завершения (c)

Не каждый режим должен быть реализован, но должен возвращать ненулевой статус.

Вот пример, который динамически называет любое /very/long/name/$USER/even/more с помощью ~[magic:$USER] (на основе примера из 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
}

Использование:

% 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

Каталог /very/long/name/baz не содержит подкаталога even/more и поэтому не имеет имени.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .