微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何从单词中间使 zsh 函数自动完成?

如何解决如何从单词中间使 zsh 函数自动完成?

我用zsh写了一个函数来代替cd函数。在一些帮助下,我让它像我想要的那样工作(主要是)。这是 one of my other question 的后续。 该函数几乎按我的意愿工作,但我在语法突出显示自动完成方面仍然存在一些问题。

对于示例,假设您的目录如下所示:

"dependencies": {
    "@material-ui/core": "^4.9.10","@material-ui/icons": "^4.9.1","@testing-library/jest-dom": "^4.2.4","@testing-library/react": "^9.3.2","@testing-library/user-event": "^7.1.2","axios": "^0.19.2","moment": "^2.27.0","react": "^16.12.0","react-dom": "^16.12.0","react-file-base64": "^1.0.3","react-redux": "^7.1.3","react-scripts": "3.4.1","redux": "^4.0.5","redux-thunk": "^2.3.0"
  },

我还假设已获取以下代码

/
    a/
        b/
        c/
            d/
        some_dir/

问题:

在我的 zshrc 中,我有一行:

cl () {
    local first=$( echo $1 | cut -d/ -f1 )
    if [ -d $first ]; then
        pushd $1 >/dev/null # If the first argument is an existing normal directory,move there
    else
        pushd ${PWD%/$first/*}/$1 >/dev/null # Otherwise,move to a parent directory or a child of that parent directory
    fi
}
_cl() {
    _cd
    pth=${words[2]}
    opts=""
    new=${pth##*/}
    local expl
    # Generate the visual formatting and store it in `$expl`
    _description -V ancestor-directories expl 'ancestor directories'
    [[ "$pth" != *"/"*"/"* ]] && middle="" || middle="${${pth%/*}#*/}/"
    if [[ "$pth" != *"/"* ]]; then
        # If this is the start of the path
        # In this case we should also show the parent directories
        local ancestor=$PWD:h
        while (( $#ancestor > 1 )); do
            # -f: Treat this as a file (incl. dirs),so you get proper highlighting.
            # -Q: Don't quote (escape) any of the characters.
            # -W: Specify the parent of the dir we're adding.
            # ${ancestor:h}: The parent ("head") of $ancestor.
            # ${ancestor:t}: The short name ("tail") of $ancestor.
            compadd "$expl[@]" -fQ -W "${ancestor:h}/" - "${ancestor:t}"
            # Move on to the next parent.
            ancestor=$ancestor:h
        done
    else
        # $first is the first part of the path the user typed in.
        # it it is part of the current direoctory,we kNow the user is trying to go back to a directory
        first=${pth%%/*}
        # $middle is the rest of the provided path
        if [ ! -d $first ]; then
            # path starts with parent directory
            dir=${PWD%/$first/*}/$first
            first=$first/
            # List all sub directories of the $dir/$middle directory
            if [ -d "$dir/$middle" ]; then
                for d in $(ls -a $dir/$middle); do
                    if [ -d $dir/$middle/$d ] && [[ "$d" != "." ]] && [[ "$d" != ".." ]]; then
                        compadd "$expl[@]" -fQ -W $dir/ - $first$middle$d
                    fi
                done
            fi
        fi
    fi
}
compdef _cl cl

这应该使自动完成不区分大小写,并确保我可以开始输入目录名称的最后一部分,并且仍然会输入全名

示例:

zstyle ':completion:*' matcher-list 'm:{a-z}={A-Za-z}' '+l:|=* r:|=*'

当我输入“di”时如何让它提示“some_dir”?

解决方法

您的 matcher-list 中的第二个匹配器永远不会被调用,因为即使 _cl() 没有添加任何匹配项,它也会返回“true”(实际上是退出状态 0)。返回“true”会导致 _main_complete() 假设我们已经完成,因此它不会尝试列表中的下一个匹配器。

要解决此问题,请将以下内容添加到 _cl() 的开头:

local -i nmatches=$compstate[nmatches]

直到_cl()结束:

(( compstate[nmatches] > nmatches ))

这样,_cl() 只会在成功添加补全时返回“true”。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。