From 7b984f5542f95919abbaf6d09579c932246450a1 Mon Sep 17 00:00:00 2001 From: j Date: Sun, 1 Mar 2026 21:54:00 +1300 Subject: [PATCH] Update gp --- gp | 85 ++++++++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 64 insertions(+), 21 deletions(-) diff --git a/gp b/gp index 004494b..cbed3ac 100755 --- a/gp +++ b/gp @@ -49,14 +49,45 @@ EXAMPLES: EOF } -# Function to generate commit message based on changes -generate_commit_message() { +# Function to generate commit message using Claude AI +generate_commit_message_ai() { + # Stage files first so we can get a proper diff + if [ "$ADD_ALL" = true ]; then + git add -A + fi + + local diff + diff=$(git diff --cached) + if [ -z "$diff" ]; then + return 1 + fi + + local msg + msg=$(echo "$diff" | claude --print \ + "Write a short git commit message (max 72 chars subject line) summarising these changes. Output ONLY the message, no quotes or prefixes." \ + 2>/dev/null) || return 1 + + # Validate: non-empty, single line, reasonable length + if [ -z "$msg" ]; then + return 1 + fi + # Take only the first line + msg=$(echo "$msg" | head -1) + if [ ${#msg} -gt 120 ]; then + return 1 + fi + + echo "$msg" +} + +# Function to generate commit message based on heuristics (fallback) +generate_commit_message_fallback() { # First check if we have staged changes local has_staged_changes=false if ! git diff --cached --quiet; then has_staged_changes=true fi - + # Determine which changes to analyze based on staging status and ADD_ALL setting local status_command="" if [ "$has_staged_changes" = true ]; then @@ -64,11 +95,11 @@ generate_commit_message() { else status_command="git diff --name-status" fi - + # Get all changes (staged or unstaged depending on context) local all_changes all_changes=$($status_command) - + # If no changes from diff, check for untracked files when add-all is enabled if [ -z "$all_changes" ] && [ "$ADD_ALL" = true ]; then local untracked_files @@ -78,27 +109,27 @@ generate_commit_message() { all_changes=$(echo "$untracked_files" | sed 's/^/A\t/') fi fi - + if [ -z "$all_changes" ]; then echo "No changes to commit" return 1 fi - + # Count total files local files_count files_count=$(echo "$all_changes" | wc -l) - + # Generate smart commit message based on file types and changes local has_source_files=false local has_config_files=false local has_docs=false local has_tests=false local message="" - + # Extract just the filenames for type detection while IFS=$'\t' read -r status file; do [ -z "$file" ] && continue - + case "$file" in *.cpp|*.hpp|*.c|*.h|*.js|*.ts|*.py|*.go|*.rs|*.java) has_source_files=true @@ -114,7 +145,7 @@ generate_commit_message() { ;; esac done <<< "$all_changes" - + # Create descriptive commit message if [ "$files_count" -eq 1 ]; then local change_line @@ -123,7 +154,7 @@ generate_commit_message() { local single_file status=$(echo "$change_line" | cut -f1) single_file=$(echo "$change_line" | cut -f2) - + case "${status:0:1}" in A) message="Add $single_file" ;; M) message="Update $single_file" ;; @@ -137,9 +168,9 @@ generate_commit_message() { local modified_count=0 local deleted_count=0 local renamed_count=0 - + # Use the all_changes variable we already have - + # Count different types of changes while IFS=$'\t' read -r status file; do [ -z "$status" ] && continue @@ -150,7 +181,7 @@ generate_commit_message() { R) ((renamed_count++)) ;; esac done <<< "$all_changes" - + # Also count untracked files if add-all is enabled if [ "$ADD_ALL" = true ]; then local untracked_files @@ -161,14 +192,14 @@ generate_commit_message() { ((added_count += untracked_count)) fi fi - + # Generate message based on change types local change_parts=() [ $added_count -gt 0 ] && change_parts+=("add $added_count") [ $modified_count -gt 0 ] && change_parts+=("update $modified_count") [ $deleted_count -gt 0 ] && change_parts+=("remove $deleted_count") [ $renamed_count -gt 0 ] && change_parts+=("rename $renamed_count") - + local change_desc="" if [ ${#change_parts[@]} -eq 1 ]; then change_desc="${change_parts[0]}" @@ -183,7 +214,7 @@ generate_commit_message() { done change_desc+=" and ${change_parts[last_idx]}" fi - + local prefix="" if $has_tests; then prefix="test: " @@ -194,16 +225,28 @@ generate_commit_message() { elif $has_source_files; then prefix="feat: " fi - + # Capitalize first letter of change description change_desc="$(echo "${change_desc:0:1}" | tr '[:lower:]' '[:upper:]')${change_desc:1}" - + message="${prefix}${change_desc} files" fi - + echo "$message" } +# Function to generate commit message — tries Claude AI first, falls back to heuristics +generate_commit_message() { + if command -v claude &>/dev/null; then + local ai_msg + if ai_msg=$(generate_commit_message_ai); then + echo "$ai_msg" + return 0 + fi + fi + generate_commit_message_fallback +} + # Function to check if we're in a git repository and change to repo root check_git_repo() { if ! git rev-parse --git-dir >/dev/null 2>&1; then