diff --git a/bin/git-forgit b/bin/git-forgit index 4a6a66d..ea064b4 100755 --- a/bin/git-forgit +++ b/bin/git-forgit @@ -441,12 +441,26 @@ _forgit_add_preview() { fi } +_forgit_unstage_preview() { + file=$(echo "$1" | _forgit_get_single_file_from_add_line) + if (git status -s -- "$file" | grep '^??') &>/dev/null; then # diff with /dev/null for untracked files + git diff --color=always --no-index -- /dev/null "$file" | _forgit_pager diff | sed '2 s/added:/untracked:/' + else + git diff --color=always -- "$file" | _forgit_pager diff + fi +} _forgit_git_add() { _forgit_add_git_opts=() _forgit_parse_array _forgit_add_git_opts "$FORGIT_ADD_GIT_OPTS" git add "${_forgit_add_git_opts[@]}" "$@" } +_forgit_git_unstage() { + _forgit_add_git_opts=() + _forgit_parse_array _forgit_add_git_opts "$FORGIT_ADD_GIT_OPTS" + git reset "${_forgit_add_git_opts[@]}" -q HEAD -- "$@" +} + _forgit_get_single_file_from_add_line() { # NOTE: paths listed by 'git status -su' mixed with quoted and unquoted style # remove indicators | remove original path for rename case | remove surrounding quotes @@ -490,6 +504,37 @@ _forgit_add() { echo 'Nothing to add.' } +# git unstage selector +_forgit_unstage() { + _forgit_inside_work_tree || return 1 + local changed unmerged untracked files opts + # Add files if passed as arguments + [[ $# -ne 0 ]] && { _forgit_git_unstage "$@" && git status -s; return $?; } + + changed=$(git config --get-color color.status.changed red) + staged=$(git config --get-color color.status.changed green) + unmerged=$(git config --get-color color.status.unmerged red) + untracked=$(git config --get-color color.status.untracked red) + opts=" + $FORGIT_FZF_DEFAULT_OPTS + -0 -m --nth 2..,.. + --preview=\"$FORGIT add_preview {}\" + --bind=\"alt-e:execute($FORGIT edit_add_file {})+refresh-preview\" + $FORGIT_ADD_FZF_OPTS + " + + files=() + while IFS='' read -r file; do + files+=("$file") + done < <(git -c color.status=always -c status.relativePaths=true -c core.quotePath=false status -s | + grep -F -e "$staged" | + sed -E 's/^(..[^[:space:]]*)[[:space:]]+(.*)$/[\1] \2/' | + FZF_DEFAULT_OPTS="$opts" fzf | + _forgit_get_single_file_from_add_line) + [[ "${#files[@]}" -gt 0 ]] && _forgit_git_unstage "${files[@]}" && git status -s && return + echo 'Nothing to unstage.' +} + _forgit_reset_head_preview() { file=$1 git diff --staged --color=always -- "$file" | _forgit_pager diff @@ -1068,7 +1113,7 @@ _forgit_ignore() { args=() while IFS='' read -r arg; do args+=("$arg") - done < <(_forgit_paths_list "$FORGIT_GI_TEMPLATES" .gitignore | + done < <(_forgit_paths_list "$FORGIT_GI_TEMPLATES" .gitignore | nl -w4 -s' ' | FZF_DEFAULT_OPTS="$opts" fzf | awk '{print $2}') fi @@ -1141,6 +1186,7 @@ _forgit_paths_list() { public_commands=( "add" "attributes" + "unstage" "blame" "branch_delete" "checkout_branch" diff --git a/completions/git-forgit.bash b/completions/git-forgit.bash index 380fc4b..9267528 100755 --- a/completions/git-forgit.bash +++ b/completions/git-forgit.bash @@ -58,6 +58,7 @@ _git_forgit() cmds=" add + unstage blame branch_delete checkout_branch @@ -87,6 +88,7 @@ _git_forgit() 3) case ${prev} in add) _git_add ;; + _git_unstage ;; branch_delete) _git_branch_delete ;; checkout_branch) _git_checkout_branch ;; checkout_commit) _git_checkout ;; @@ -122,6 +124,7 @@ then # Completion for forgit plugin shell functions __git_complete forgit::add _git_add + __git_complete forgit::unstage _git_unstage __git_complete forgit::branch::delete _git_branch_delete __git_complete forgit::checkout::branch _git_checkout_branch __git_complete forgit::checkout::commit _git_checkout @@ -143,6 +146,7 @@ then # Completion for forgit plugin shell aliases if [[ -z "$FORGIT_NO_ALIASES" ]]; then __git_complete "${forgit_add}" _git_add + __git_complete "${forgit_unstage}" _git_unstage __git_complete "${forgit_branch_delete}" _git_branch_delete __git_complete "${forgit_checkout_branch}" _git_checkout_branch __git_complete "${forgit_checkout_commit}" _git_checkout diff --git a/forgit.plugin.zsh b/forgit.plugin.zsh index 3043f1e..d676717 100755 --- a/forgit.plugin.zsh +++ b/forgit.plugin.zsh @@ -61,6 +61,10 @@ forgit::add() { "$FORGIT" add "$@" } +forgit::unstage() { + "$FORGIT" unstage "$@" +} + forgit::reset::head() { "$FORGIT" reset_head "$@" } @@ -150,6 +154,7 @@ forgit::attributes() { if [[ -z "$FORGIT_NO_ALIASES" ]]; then export forgit_add="${forgit_add:-ga}" + export forgit_unstage="${forgit_unstage:-gu}" export forgit_reset_head="${forgit_reset_head:-grh}" export forgit_log="${forgit_log:-glo}" export forgit_reflog="${forgit_reflog:-grl}" @@ -172,6 +177,7 @@ if [[ -z "$FORGIT_NO_ALIASES" ]]; then export forgit_blame="${forgit_blame:-gbl}" alias "${forgit_add}"='forgit::add' + alias "${forgit_unstage}"='forgit::unstage' alias "${forgit_reset_head}"='forgit::reset::head' alias "${forgit_log}"='forgit::log' alias "${forgit_reflog}"='forgit::reflog'