fstat (2476B) - raw


      1 #!/usr/bin/env zsh
      2 
      3 0="${${ZERO:-${0:#$ZSH_ARGZERO}}:-${(%):-%N}}"
      4 0="${${(M)0:#/*}:-$PWD/$0}"
      5 
      6 # Desc: interactive git status menu; toggle stage and unstage
      7 #
      8 # @params
      9 # Globals:
     10 #   ${mydir}: current directory of where the script is running
     11 #   ${selected_files}: raw selected file (with current git status prepend)
     12 #   ${selected_filenames}: bash array of names for the selected_files
     13 #   ${stage_file}: determine if current operation should be staging file or unstage
     14 
     15 emulate -LR zsh
     16 setopt warncreateglobal noshortloops
     17 
     18 local mydir; mydir=${0:h:A}
     19 builtin source ${mydir}/fgit_helper
     20 
     21 function usage() {
     22   builtin print -P -- "\
     23 %F{1}%BUsage%f%b: %F{2}fstat%f [%F{13}-h%f] ...
     24 
     25 Display interactive git status menu.
     26 Toggle file stage/unstage interactively.
     27 
     28 %F{1}%BOptions%f%f:
     29   %F{13}-h%f, %F{13}--help%f  Show this help message and exit"
     30 }
     31 
     32 (( $# )) && {
     33   case "$1" in
     34     (-h|--help)  usage && exit 0 ;;
     35     (*)          print::error "Invalid option: $1" &&   { usage; exit 1 } ;;
     36   esac
     37 }
     38 
     39 local -a mod_files
     40 
     41 while :; do
     42   # reset all variable and arrays for each loop
     43   local -a selected_files selected_filenames
     44   local stage_file
     45   selected_files=( ${(@f)"$(get_modified_file 'select files to stage/unstage' 'all' 'raw')"} )
     46   (( $#selected_files )) || break
     47 
     48   # check if current operation should stage file or unstage file
     49   # if any file start with M but has char immediately follow it, new changes are made, stage file
     50   # if any file start with a space or tab, the file is not staged, stage file
     51   # otherwise, we unstage
     52   stage_file=$(print -lr -- "$selected_files[@]" \
     53     | command awk '{
     54       if ($0 ~ /^[[:alpha:]]{2}.*$/) {
     55         print "stage"
     56       } else if ($0 ~ /^[ \t].*$/) {
     57         print "stage"
     58       }
     59     }'
     60   )
     61 
     62   while IFS= read -r line; do
     63     selected_filenames+=("${line}")
     64     # may be a bit much to have two arrays, inside/outside loop
     65     # workaround to have a loop continuously ask
     66     # as well as display git status when finished
     67     mod_files+=("${line}")
     68   done < <(
     69     printf '%s\n' "${selected_files[@]}" \
     70       | awk -v home="${FZFGIT_TREE}" '{
     71           $1=""
     72           gsub(/^[ \t]/, "", $0)
     73           gsub(/"/, "", $0)
     74           print home "/" $0
     75         }'
     76   )
     77 
     78   if [[ -z "$stage_file" ]]; then
     79     command git reset --quiet HEAD "$selected_filenames[@]"
     80   else
     81     command git add "$selected_filenames[@]"
     82   fi
     83 done
     84 
     85 (( $#mod_files[@] )) && \
     86   command git status -sb || print -Pr -- "%F{1}Nothing to add%f"