动态目录哈希

动态目录哈希

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

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,因此未命名。

相关内容