在 ZSH 中围绕项目根路径创建自定义自动完成脚本

问题描述 投票:0回答:1

我正在尝试创建一个模拟 cd 的脚本,其中我提供了一个路径,并且脚本 cd 通过将其附加到绝对现有路径来实现。这个想法是,无论我在哪里调用它,它总是会表现得好像我试图从项目的根目录进行 cd 一样。

我想添加的一个关键功能是用户键入时自动完成,例如 cd,它将提供路径选项,并且用户可以在键入时自动完成。

示例:

goto po
pointers/    positions/

goto pointers/
src/         lib/

这是我迄今为止制作的初始脚本:

#!/bin/zsh

# Find the root directory of the repository
find_repo_root() {
    local repo_root
    repo_root=$(git rev-parse --show-toplevel 2>/dev/null)
    if [ -z "$repo_root" ]; then
        return 1  # Return failure if not in a Git repository
    fi
    echo $repo_root
}

# Change directory relative to repository root
goto() {
    local repo_root=$(find_repo_root)
    if [ -z "$repo_root" ]; then
        echo "Error: Not in a Git repository." >&2  # Print error message to stderr
        return 1
    fi

    # Create an absolute path using the repo root
    local target_dir="$repo_root/$1"
    if [ -d "$target_dir" ]; then
        cd "$target_dir"
    else
        echo "Directory does not exist: $target_dir" >&2
        return 1
    fi
}

# Autocomplete function for the goto command
_goto_autocomplete() {
    local repo_root=$(find_repo_root)
    if [ -z "$repo_root" ]; then
        return 1  # If not in a Git repo, don't suggest any autocompletions
    fi

    # Dynamically generate possible matches relative to the repo root
    local current_input="${(Q)PREFIX}"

    # Find directories relative to the repository root, not the current directory
    local possible_dirs=(${(f)"$(find $repo_root -type d -not -path '*/\.*' -maxdepth 2)"})

    # Filter for directories that start with the current input
    local matches=()
    for dir in $possible_dirs; do
        # Strip the repository root from the beginning of the directory path
        local rel_dir=${dir#$repo_root/}
        if [[ $rel_dir == $current_input* ]]; then
            matches+=$rel_dir
        fi
    done

    # Provide autocomplete suggestions
    compadd $matches
}

# Register the autocomplete function for the goto command
compdef _goto_autocomplete goto

# Ensure compinit is loaded for autocompletion to work
autoload -Uz compinit && compinit

起初我以为它可以工作,因为它开始自动完成,但后来我意识到它总是在查看我所在的当前工作目录。我不明白 compadd、compdef 和 compinit 是如何工作的。我正在阅读文档以获取更多见解,但我不知道如何使自动完成功能仅查看提供的文件路径。

zsh oh-my-zsh zsh-completion
1个回答
0
投票

在为 zsh 编写补全函数时,使用现有的实用函数几乎总是比直接调用

compadd
更好。它们以更少的代码为用户提供了更加一致和可定制的体验。我推荐这个参考指南来开始使用zsh完成,因为官方文档往往过于复杂。

对于此脚本,

_files -/ -W "$repo_root"
正是您想要的:完成相对于
-/
(
$repo_root
) 的目录 (
-W
)。

_goto_autocomplete() {
    local repo_root
    if ! repo_root=$(find_repo_root); then
        _message 'not in a git repository'
        # Return 0 so no other completers are tried
        return 0
    fi

    # Using _arguments here instead of just _files so it doesn't try to
    # complete more than one argument
    _arguments ': :_files -/ -W "$repo_root"'
}
© www.soinside.com 2019 - 2024. All rights reserved.