flog (4117B) - raw
1 #!/usr/bin/env zsh 2 3 0="${${ZERO:-${0:#$ZSH_ARGZERO}}:-${(%):-%N}}" 4 0="${${(M)0:#/*}:-$PWD/$0}" 5 6 # Desc: git log interactive viewer 7 # 8 # @params 9 # Globals: 10 # ${mydir}: current dir of the script 11 # ${selected_action}: action to take on the selected commit 12 # ${selected_commit}: user selected commit 13 # ${confirm}: confirm status of user 14 # Arguments: 15 # -h|--help: display help message 16 # -r|--revert: revert the selected commit 17 # -R|--reset: reset HEAD back to the selected commit 18 # -e|--edit: edit commmit (interactive rebase) 19 # -c|--checkout: checkout selected commmit 20 # -y|--yes: confirm action by default and skip confirmation 21 22 emulate -LR zsh 23 setopt warncreateglobal noshortloops 24 25 local mydir; mydir=${0:h:A} 26 builtin source ${mydir}/fgit_helper 27 28 function usage() { 29 builtin print -P -- "\ 30 %F{1}%BUsage%b%f: 31 %F{2}flog%f [%F{13}-h%f] [%F{13}-r%f] [%F{13}-R%f] [%F{13}-e%f] [%F{13}-c%f] [%F{13}-y%f] ... 32 33 Interactive log viewer with action menu. 34 Action menu contains options including revert|reset|edit|checkout|exit. 35 36 %F{4}Default%f: list all commits and prompt a menu to select action to perform. 37 38 %F{1}%BOptions%f%b: 39 %F{13}-h%f, %F{13}--help%f Show this help message and exit 40 %F{13}-r%f, %F{13}--revert%f Revert the selected commit and skip action menu 41 %F{13}-R%f, %F{13}--reset%f Reset HEAD back to selected commit and skip action menu 42 %F{13}-e%f, %F{13}--edit%f Edit selected commit through interactive rebase and skip action menu 43 %F{13}-c%f, %F{13}--checkout%f Checkout selected commit and skip action menu 44 %F{13}-y%f, %F{13}--yes%f Acknowledge all actions that will be taken and skip confirmation" 45 } 46 47 ####################################### 48 # draw action menu for selected commit 49 # Arguments: 50 # $1: selected commit hash, used to display commit message in fzf header 51 # $2: selected action, if selected, skip menu, return action 52 # Outputs: 53 # ${selected_action}: user selected action 54 ####################################### 55 function draw_menu() { 56 local selected_commit="$1" 57 local selected_action="$2" 58 local menu header message 59 [[ -n "$selected_action" ]] && { 60 builtin print -r -- "$selected_action" 61 } || { 62 menu="revert: revert the selected commit\n" 63 menu="${menu}reset: reset HEAD to the selected commit using --mixed flag\n" 64 menu="${menu}edit: edit selected commit through interactive rebase\n" 65 menu="${menu}checkout: checkout the selected commit\n" 66 menu="${menu}exit: quit flog" 67 message=$( 68 command git log \ 69 --format=%B -n 1 "$selected_commit" 70 ) 71 header="commit $selected_commit: $message" 72 selected_action=$(print -- "$menu" \ 73 | fzf --no-multi --header="$header" \ 74 | command awk -F ":" '{ 75 print $1 76 }' 77 ) 78 builtin print -r -- "$selected_action" 79 } 80 } 81 82 while (( $# )) { 83 case "$1" in 84 (-r|--revert) selected_action="revert"; shift ;; 85 (-R|--reset) selected_action="reset"; shift ;; 86 (-e|--edit) selected_action="edit"; shift ;; 87 (-c|--checkout) selected_action="checkout"; shift ;; 88 (-y|--yes) confirm='y'; shift ;; 89 (-h|--help) usage && exit 0 ;; 90 (*) print::error "Invalid option: $1" && { usage; exit 1 } ;; 91 esac 92 } 93 94 while :; do 95 selected_commit=$(get_commit) 96 [[ -z "$selected_commit" ]] && exit 1 97 selected_action=$(draw_menu "${selected_commit}" "${selected_action}") 98 [[ -n "$selected_action" ]] && break 99 done 100 101 if [[ "${selected_action}" != 'exit' ]]; then 102 if [[ "${selected_action}" == "reset" ]] && [[ -z "${confirm}" ]]; then 103 print -P -- "(%F{3}dryrun%f) reset HEAD to $selected_commit" 104 elif [[ -z "$confirm" ]]; then 105 print -P -- "(%F{3}dryrun%f) ${selected_action} ${selected_commit}" 106 fi 107 108 [[ -z "$confirm" ]] && confirm=$(get_confirmation) 109 [[ "$confirm" != y ]] && exit 1 110 notify-send 'past' 111 fi 112 113 case "$selected_action" { 114 (revert) git revert "${selected_commit}" ;; 115 (reset) git reset "${selected_commit}" ;; 116 (edit) git rebase -i "${selected_commit}"~ ;; 117 (checkout) git checkout "${selected_commit}" ;; 118 (exit) exit 0 ;; 119 (*) exit 1 ;; 120 }