gcw() { # Filter specific workflows. local ADD_STATUS=$(git diff --staged --diff-filter=A --name-only) local DELETE_STATUS=$(git diff --staged --diff-filter=D --name-only) local RENAME_STATUS=$(git diff --staged --diff-filter=R --name-only) # Update status includes everything else. local UPDATE_STATUS=$(git diff --staged --diff-filter=MCTUXB --name-only) # Make sure we're using one workflow by counting up workflow changes. local STATUS_CHANGE_COUNT=0 if [ ! -z "$ADD_STATUS" ]; then STATUS_CHANGE_COUNT=$((STATUS_CHANGE_COUNT+1)) fi if [ ! -z "$DELETE_STATUS" ]; then STATUS_CHANGE_COUNT=$((STATUS_CHANGE_COUNT+1)) fi if [ ! -z "$RENAME_STATUS" ]; then STATUS_CHANGE_COUNT=$((STATUS_CHANGE_COUNT+1)) fi if [ ! -z "$UPDATE_STATUS" ]; then STATUS_CHANGE_COUNT=$((STATUS_CHANGE_COUNT+1)) fi if [ $STATUS_CHANGE_COUNT -gt 1 ]; then echo "Too many changes. Use 'git commit' directly instead." return elif [ $STATUS_CHANGE_COUNT -eq 0 ]; then echo "No changes found." return fi # Find the correct context for these changes. # Select parts of the selected source. # Example: # Selected: src/modules/nvim/nvim.sh # > [src, modules, nvim, nvim.sh] # Select option "modules" # > [nvim, nvim.sh] # Continue until exhausted or "DONE" local SELECTED_UPDATE=$(echo "$ADD_STATUS$DELETE_STATUS$RENAME_STATUS$UPDATE_STATUS" | fzf) local SELECTED_UPDATE_PARTS=($(echo $SELECTED_UPDATE | sed -e 's/\//\n/g')) __gcm_select_source_part() { local SELECTED_UPDATE_PART_OPTIONS=("${SELECTED_UPDATE_PARTS[@]}" "DONE") local SELECTED_UPDATE_PART=$(printf "%s\n" "${SELECTED_UPDATE_PART_OPTIONS[@]}" | fzf | sed 's/^src\///g') # Return "DONE". if [[ "$SELECTED_UPDATE_PART" == "DONE" ]]; then echo -1 return fi # Return selected part index. local PART_INDEX=0; for PART in "${SELECTED_UPDATE_PARTS[@]}"; do [[ $PART == "$SELECTED_UPDATE_PART" ]] && break PART_INDEX=$((PART_INDEX+1)) done echo $((PART_INDEX)) } __gcm_inside_out_select() { local NEXT_INDEX=0; while [ ! $NEXT_INDEX -eq -1 ]; do SELECTED_UPDATE_PARTS=("${SELECTED_UPDATE_PARTS[@]:$NEXT_INDEX}") if [ "${#SELECTED_UPDATE_PARTS[@]}" -le "0" ]; then break fi local SELECTED_INDEX=$(__gcm_select_source_part $NEXT_INDEX) if [ "$SELECTED_INDEX" -le "-1" ]; then # User manually exited. break fi echo "${SELECTED_UPDATE_PARTS[$SELECTED_INDEX+1]}" NEXT_INDEX=$((SELECTED_INDEX+1)) done } # Common message format. local MESSAGE_CONTEXT=$(__gcm_inside_out_select | tr '\n' '/' | sed 's/.$//') # Get additional context if any. git diff --staged echo "\n" local MESSAGE_CONTEXT_ADDITION MESSAGE_CONTEXT_ADDITION=$(bash -c 'read -e -p "Additional Context: " tmp; echo $tmp') if [ ! -z $MESSAGE_CONTEXT_ADDITION ]; then MESSAGE_CONTEXT_ADDITION=" $MESSAGE_CONTEXT_ADDITION" fi # Execute workflow. if [ ! -z "$ADD_STATUS" ]; then # Add. git commit -m "Add '$MESSAGE_CONTEXT'$MESSAGE_CONTEXT_ADDITION" elif [ ! -z "$DELETE_STATUS" ]; then # Delete. git commit -m "Delete '$MESSAGE_CONTEXT'$MESSAGE_CONTEXT_ADDITION" elif [ ! -z "$RENAME_STATUS" ]; then # Rename. git commit -m "Rename '$MESSAGE_CONTEXT'$MESSAGE_CONTEXT_ADDITION" elif [ ! -z "$UPDATE_STATUS" ]; then # Update. git commit -m "Update '$MESSAGE_CONTEXT'$MESSAGE_CONTEXT_ADDITION" fi }