Skip to content

Instantly share code, notes, and snippets.

@ijse
Created October 13, 2025 13:06
Show Gist options
  • Select an option

  • Save ijse/a66c16a9e85d85f4362ee8916071048f to your computer and use it in GitHub Desktop.

Select an option

Save ijse/a66c16a9e85d85f4362ee8916071048f to your computer and use it in GitHub Desktop.
修改当前终端提示PS1, 使展示当前Git分支所关联的飞书项目任务信息,每次切换分支时更新
#!/usr/bin/env bash
set -e
# ==================== 配置项 ====================
# 缓存过期时间(秒)
CACHE_TTL=300
# 分支匹配规则(正则表达式)
BRANCH_PATTERN="^(story|issue)-([0-9]+)$"
# API 接口地址模板({type} 和 {id} 会被替换)
API_URL_TEMPLATE="https://****/fsp/{type}/{id}/doc"
# jq 提取字段路径
JQ_EXTRACT_PATH=".name"
# 缓存目录名
CACHE_DIR_NAME=".task_prompt_cache"
# ==================== Git Hook 脚本 ====================
HOOK_CONTENT='#!/usr/bin/env bash
# 配置项(从主脚本注入)
CACHE_TTL='"$CACHE_TTL"'
BRANCH_PATTERN="'"$BRANCH_PATTERN"'"
API_URL_TEMPLATE="'"$API_URL_TEMPLATE"'"
JQ_EXTRACT_PATH="'"$JQ_EXTRACT_PATH"'"
CACHE_DIR_NAME="'"$CACHE_DIR_NAME"'"
# ==================== 主逻辑 ====================
CACHE_DIR=".git/$CACHE_DIR_NAME"
branch=$(git symbolic-ref --short HEAD 2>/dev/null)
now=$(date +%s)
# 创建缓存目录
mkdir -p "$CACHE_DIR"
# 对分支名进行安全编码,用于文件名
branch_encoded=$(echo "$branch" | sed "s/\//_/g")
CACHE_FILE="$CACHE_DIR/$branch_encoded"
# 检查该分支的缓存是否有效
if [[ -f "$CACHE_FILE" ]]; then
source "$CACHE_FILE"
# 验证缓存的分支名与当前分支匹配,且未过期
if [[ "$branch_cached" == "$branch" && $((now - timestamp)) -lt CACHE_TTL ]]; then
exit 0
fi
fi
# 请求接口
if [[ $branch =~ $BRANCH_PATTERN ]]; then
type=${BASH_REMATCH[1]}
id=${BASH_REMATCH[2]}
# 替换 URL 模板中的占位符
url="${API_URL_TEMPLATE//\{type\}/$type}"
url="${url//\{id\}/$id}"
# 使用 jq 提取任务名称
name=$(curl -s "$url" | jq -r "$JQ_EXTRACT_PATH // empty")
else
name=""
fi
# 更新该分支的缓存
cat > "$CACHE_FILE" <<EOF
branch_cached=$branch
name=$name
timestamp=$now
EOF
'
# ==================== Shell 提示符配置 ====================
SHELL_SNIPPET='
# >>> git-task-prompt start >>>
setopt prompt_subst 2>/dev/null || true
# 配置项
CACHE_DIR_NAME="'"$CACHE_DIR_NAME"'"
task_prompt_display() {
local cache_dir=".git/$CACHE_DIR_NAME"
local branch=$(git symbolic-ref --short HEAD 2>/dev/null)
[[ -z "$branch" ]] && return
# 对分支名进行安全编码
local branch_encoded=$(echo "$branch" | sed "s/\//_/g")
local cache_file="$cache_dir/$branch_encoded"
[[ -f "$cache_file" ]] || return
source "$cache_file"
# 验证缓存的分支名与当前分支匹配
[[ "$branch_cached" == "$branch" && -n "$name" ]] && echo "%{$fg[green]%}[$name]\n %{$reset_color%}"
}
# 动态多行提示符
PROMPT="$(task_prompt_display) %{$fg[cyan]%}%c%{$reset_color%} $(git_prompt_info)"
# <<< git-task-prompt end <<<
'
# ==================== 安装函数 ====================
# ==================== 安装函数 ====================
install_hooks() {
local hook_dir
hook_dir="$(git rev-parse --git-dir)/hooks"
echo "Installing git hooks to: $hook_dir"
echo "$HOOK_CONTENT" > "$hook_dir/post-checkout"
echo "$HOOK_CONTENT" > "$hook_dir/post-switch"
chmod +x "$hook_dir/post-checkout" "$hook_dir/post-switch"
echo "✅ Git hooks installed."
}
inject_shell_snippet() {
local installed=false
for rcfile in ~/.bashrc ~/.zshrc; do
[[ -f "$rcfile" ]] || continue
if grep -q ">>> git-task-prompt start >>>" "$rcfile"; then
echo "⏭ $rcfile already contains configuration, skipping."
else
echo "📝 Injecting shell config into $rcfile"
echo "$SHELL_SNIPPET" >> "$rcfile"
installed=true
fi
done
[[ "$installed" == true ]] && echo "✅ Shell snippet injected."
}
# ==================== 卸载函数 ====================
remove_hooks() {
local hook_dir
hook_dir="$(git rev-parse --git-dir)/hooks"
local removed=false
for file in post-checkout post-switch; do
if [[ -f "$hook_dir/$file" ]]; then
rm -f "$hook_dir/$file"
echo "🗑 Removed $hook_dir/$file"
removed=true
fi
done
# 清理缓存目录
local cache_dir="$(git rev-parse --git-dir)/$CACHE_DIR_NAME"
if [[ -d "$cache_dir" ]]; then
rm -rf "$cache_dir"
echo "🗑 Removed cache directory: $cache_dir"
removed=true
fi
[[ "$removed" == true ]] && echo "✅ Git hooks and cache removed."
}
remove_shell_snippet() {
local removed=false
for rcfile in ~/.bashrc ~/.zshrc; do
[[ -f "$rcfile" ]] || continue
if grep -q ">>> git-task-prompt start >>>" "$rcfile"; then
sed -i.bak '/>>> git-task-prompt start >>>/,/<<< git-task-prompt end <<</d' "$rcfile"
echo "🗑 Removed git-task-prompt snippet from $rcfile"
removed=true
fi
done
[[ "$removed" == true ]] && echo "✅ Shell snippet removed."
}
# ==================== 主程序 ====================
case "$1" in
install)
echo "🚀 Installing git-task-prompt..."
install_hooks
inject_shell_snippet
echo ""
echo "✅ git-task-prompt installed successfully!"
echo "💡 Please restart your terminal or run: source ~/.zshrc"
;;
uninstall)
echo "🧹 Uninstalling git-task-prompt..."
remove_hooks
remove_shell_snippet
echo ""
echo "✅ git-task-prompt uninstalled."
;;
*)
echo "Usage: $0 {install|uninstall}"
echo ""
echo "Commands:"
echo " install - Install git hooks and shell prompt configuration"
echo " uninstall - Remove all git-task-prompt files and configurations"
exit 1
;;
esac
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment