You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让自定义Git命令git-profile的Bash补全支持部分匹配?

Git自定义命令git profile补全部分匹配失效的修复方案

问题核心

自定义git profile命令的补全逻辑已实现透传Git原生补全,但存在部分匹配失效问题:输入git profile projs r按TAB无响应,必须输入完整命令(如remote)并加空格后,才能触发下一级补全。

问题原因

  1. 补全上下文初始化缺失:重构COMP_WORDS/COMP_LINE后,未重新调用Git补全脚本的初始化函数,导致Git补全内部变量(如cur、prev)仍使用原始上下文,无法识别部分匹配输入。
  2. 光标位置计算误差:原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
}

关键修复点

  1. 修正光标位置计算:直接减去profile PROFILE_NAME 这部分的长度,确保光标在重构后的命令行中准确对应当前输入位置。
  2. 重新初始化补全状态:调用__git_init_completion函数,让Git补全脚本重新读取修改后的COMP_WORDS/COMP_LINE,生成正确的部分匹配补全结果。
  3. 优化匹配逻辑:将__git_profile_word_in的正则匹配改为循环字面匹配,避免目录名含特殊字符时的匹配错误。

验证效果

  • 输入git profile projs r按TAB,自动补全为remote
  • 输入git profile projs rem按TAB,自动补全为remote
  • 后续子命令(如remote add)的补全行为与原生Git完全一致

内容的提问来源于stack exchange,提问作者Marĉjo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 19:14:54