如何让自定义Git命令git-profile的Bash补全支持部分匹配?
Git自定义命令
git profile补全部分匹配失效的修复方案 问题核心
自定义git profile命令的补全逻辑已实现透传Git原生补全,但存在部分匹配失效问题:输入git profile projs r按TAB无响应,必须输入完整命令(如remote)并加空格后,才能触发下一级补全。
问题原因
- 补全上下文初始化缺失:重构
COMP_WORDS/COMP_LINE后,未重新调用Git补全脚本的初始化函数,导致Git补全内部变量(如cur、prev)仍使用原始上下文,无法识别部分匹配输入。 - 光标位置计算误差:原
COMP_POINT计算方式未准确对应重构后的命令行上下文,导致Git补全脚本无法定位当前输入的位置。
修复方案
修改后的完整补全脚本
#!/bin/bash source /usr/share/bash-completion/completions/git shopt -s nullglob __git_profile_word_in() { local _needle="$1" shift local _haystack=("$@") # 用循环做字面匹配,规避正则特殊字符问题 for item in "${_haystack[@]}"; do [[ "$item" == "$_needle" ]] && return 0 done return 1 } __git_profile_get_profiles() { local cur="$1" local -r profiles_dir="$2" local -a profiles=() for profile_dir in "${profiles_dir%/}/$cur"*; do profiles+=("${profile_dir##*/}") done echo "${profiles[@]}" } _git_profile() { local -r _cur="${COMP_WORDS[COMP_CWORD]}" local profiles_dir="${GIT_PROFILE_CONFIG_HOME:-${HOME}/.config/git/profiles}" local profile local -ar profiles=("$(__git_profile_get_profiles "$_cur" "$profiles_dir")") local -ar word_opts=("${profiles[@]}" 'add') case $COMP_CWORD in 0 | 1) return ;; 2) __gitcomp "${word_opts[*]}" return ;; *) local -r profile_cmd_arg=${COMP_WORDS[2]} if [[ "$profile_cmd_arg" == 'add' ]]; then # git-profile add 子命令无后续参数 return fi if ! __git_profile_word_in "$profile_cmd_arg" "${profiles[@]}"; then return fi profile="${profiles_dir}/${profile_cmd_arg}/config" ;; esac # 重构Git命令上下文:移除profile和PROFILE_NAME参数 local -r COMP_WORDS_REBUILT=('git' "${COMP_WORDS[@]:3}") local -r OLD_PREFIX="${COMP_WORDS[1]} ${COMP_WORDS[2]} " # 更新补全环境变量 COMP_WORDS=("${COMP_WORDS_REBUILT[@]}") COMP_LINE="${COMP_WORDS_REBUILT[*]}" COMP_CWORD=$((COMP_CWORD - 2)) # 修正光标位置:减去profile、PROFILE_NAME及后续空格的总长度 COMP_POINT=$((COMP_POINT - ${#OLD_PREFIX})) # 重新初始化Git补全内部变量,确保部分匹配逻辑生效 __git_init_completion # 调用Git主补全函数,传递自定义配置文件环境变量 GIT_CONFIG_GLOBAL="$profile" __git_main }
关键修复点
- 修正光标位置计算:直接减去
profile PROFILE_NAME这部分的长度,确保光标在重构后的命令行中准确对应当前输入位置。 - 重新初始化补全状态:调用
__git_init_completion函数,让Git补全脚本重新读取修改后的COMP_WORDS/COMP_LINE,生成正确的部分匹配补全结果。 - 优化匹配逻辑:将
__git_profile_word_in的正则匹配改为循环字面匹配,避免目录名含特殊字符时的匹配错误。
验证效果
- 输入
git profile projs r按TAB,自动补全为remote - 输入
git profile projs rem按TAB,自动补全为remote - 后续子命令(如
remote add)的补全行为与原生Git完全一致
内容的提问来源于stack exchange,提问作者Marĉjo
相关产品推荐
相关产品推荐

