From 866f6c0f2b674999272f5acb50f0dac5800a0a57 Mon Sep 17 00:00:00 2001 From: Ido Abramovich Date: Tue, 31 Jul 2018 16:47:45 +0300 Subject: [PATCH 01/12] basic bash script; add 'ga' --- forgit.plugin.bash | 86 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100755 forgit.plugin.bash diff --git a/forgit.plugin.bash b/forgit.plugin.bash new file mode 100755 index 0000000..345fb89 --- /dev/null +++ b/forgit.plugin.bash @@ -0,0 +1,86 @@ +#!/usr/bin/env bash + +__forgit_fzf() { + FZF_DEFAULT_OPTS=" + $FZF_DEFAULT_OPTS + --ansi + --height '80%' + --bind='alt-k:preview-up,alt-p:preview-up' + --bind='alt-j:preview-down,alt-n:preview-down' + --bind='ctrl-r:toggle-all' + --bind='ctrl-s:toggle-sort' + --bind='?:toggle-preview' + --preview-window='right:60%' + --bind='alt-w:toggle-preview-wrap' + $FORGIT_FZF_DEFAULT_OPTS + " fzf "$@" +} + +__forgit_color_to_grep_code() { + case "$1" in + black) + echo -E '\[30m' + ;; + red) + echo -E '\[31m' + ;; + green) + echo -E '\[32m' + ;; + yellow) + echo -E '\[33m' + ;; + blue) + echo -E '\[34m' + ;; + magenta) + echo -E '\[35m' + ;; + cyan) + echo -E '\[36m' + ;; + white) + echo -E '\[97m' + ;; + esac +} + +command -v diff-so-fancy >/dev/null 2>&1 && forgit_fancy='|diff-so-fancy' +command -v emojify >/dev/null 2>&1 && forgit_emojify='|emojify' + +__forgit_inside_work_tree() { + git rev-parse --is-inside-work-tree >/dev/null 2>&1 +} + +__forgit_get_git_color() { + local color=$(git config $1); + color=${color:-$2} + echo $(__forgit_color_to_grep_code $color) +} + +__forgit_add() { + if [[ __forgit_inside_work_tree -ne 0 ]]; then + return 1 + fi + added=$(__forgit_get_git_color "color.status.untracked" "red") + changed=$(__forgit_get_git_color "color.status.changed" "red") + unmerged=$(__forgit_get_git_color "color.status.unmerged" "red") + + local files=$(git -c color.status=always status --short | + grep -e "$added" -e "$changed" -e "$unmerged" | + awk '{printf "[%10s] ", $1; $1=""; print $0}' | + __forgit_fzf -0 -m --nth 2..,.. \ + --preview="git diff --no-ext-diff --color=always -- {-1} $forgit_emojify $forgit_fancy" | + cut -d] -f2 | + sed 's/.* -> //' | # for rename case + tr '\n' ' ' | tr -s ' ' | sed -e 's/^[[:space:]]*//') + if [[ -n "$files" ]]; then + cmd="git add $files" + bind '"\e[0n": "'"$cmd"'"'; + printf '\e[5n' + else + echo 'Nothing to add.' + fi +} + +alias ${forgit_add:-ga}=__forgit_add From 32636f56c43acc24f0c418b112836c283da71598 Mon Sep 17 00:00:00 2001 From: Ido Abramovich Date: Tue, 31 Jul 2018 16:57:50 +0300 Subject: [PATCH 02/12] add git commit browser --- forgit.plugin.bash | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/forgit.plugin.bash b/forgit.plugin.bash index 345fb89..6da3dbd 100755 --- a/forgit.plugin.bash +++ b/forgit.plugin.bash @@ -45,6 +45,7 @@ __forgit_color_to_grep_code() { esac } +# diff is fancy with diff-so-fancy! command -v diff-so-fancy >/dev/null 2>&1 && forgit_fancy='|diff-so-fancy' command -v emojify >/dev/null 2>&1 && forgit_emojify='|emojify' @@ -58,6 +59,19 @@ __forgit_get_git_color() { echo $(__forgit_color_to_grep_code $color) } +# git commit browser +__forgit_log() { + if [[ __forgit_inside_work_tree -ne 0 ]]; then + return 1 + fi + local cmd="echo {} |grep -o '[a-f0-9]\{7\}' |head -1 |xargs -I% git show --color=always % $forgit_emojify $forgit_fancy" + eval "git log --graph --color=always --format='%C(auto)%h%d %s %C(black)%C(bold)%cr' $@ $forgit_emojify" | + __forgit_fzf +s +m --tiebreak=index \ + --bind="enter:execute($cmd |LESS='-R' less)" \ + --bind="ctrl-y:execute-silent(echo {} |grep -o '[a-f0-9]\{7\}' |pbcopy)+abort" \ + --preview="$cmd" +} + __forgit_add() { if [[ __forgit_inside_work_tree -ne 0 ]]; then return 1 @@ -84,3 +98,4 @@ __forgit_add() { } alias ${forgit_add:-ga}=__forgit_add +alias ${forgit_log:-glo}=__forgit_log From ce240ac9f75b47ce91fca167255516313fbd72f6 Mon Sep 17 00:00:00 2001 From: Ido Abramovich Date: Tue, 31 Jul 2018 17:14:18 +0300 Subject: [PATCH 03/12] add diff and ignore commands --- forgit.plugin.bash | 57 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/forgit.plugin.bash b/forgit.plugin.bash index 6da3dbd..df7dd1c 100755 --- a/forgit.plugin.bash +++ b/forgit.plugin.bash @@ -72,6 +72,18 @@ __forgit_log() { --preview="$cmd" } +__forgit_diff() { + if [[ __forgit_inside_work_tree -ne 0 ]]; then + return 1 + fi + local cmd="git diff --no-ext-diff --color=always -- {} $forgit_emojify $forgit_fancy" + [[ $# -eq 0 ]] && local files=$(git rev-parse --show-toplevel) || local files="$@" + git ls-files --modified "$files"| + __forgit_fzf +m -0 \ + --bind="enter:execute($cmd |LESS='-R' less)" \ + --preview="$cmd" +} + __forgit_add() { if [[ __forgit_inside_work_tree -ne 0 ]]; then return 1 @@ -97,5 +109,50 @@ __forgit_add() { fi } +# git ignore generator +export FORGIT_GI_CACHE=~/.gicache +export FORGIT_GI_INDEX=${FORGIT_GI_CACHE}/.index +__forgit_ignore() { + [ -f $FORGIT_GI_INDEX ] || __forgit_ignore_update + local preview="echo {} |awk '{print \$2}' |xargs -I% bash -c 'cat $FORGIT_GI_CACHE/% 2>/dev/null || (curl -sL https://www.gitignore.io/api/% |tee $FORGIT_GI_CACHE/%)'" + OLDIFS=$IFS + IFS=$'\n' + [[ $# -gt 0 ]] && args=($@) || args=($(cat $FORGIT_GI_INDEX |nl -nrn -w4 -s' ' |__forgit_fzf -m --preview="$preview" --preview-window="right:70%" |awk '{print $2}')) + test -z "$args" && return 1 + local options=( + '(1) Output to stdout' + '(2) Append to .gitignore' + '(3) Overwrite .gitignore') + opt=$(printf '%s\n' "${options[@]}" |__forgit_fzf +m |awk '{print $1}') + case "$opt" in + '(1)' ) + __forgit_ignore_get ${args[@]} + ;; + '(2)' ) + __forgit_ignore_get ${args[@]} >> .gitignore + ;; + '(3)' ) + __forgit_ignore_get ${args[@]} > .gitignore + ;; + esac + IFS=$OLDIFS +} + +__forgit_ignore_update() { + mkdir -p $FORGIT_GI_CACHE + curl -sL https://www.gitignore.io/api/list |tr ',' '\n' > $FORGIT_GI_INDEX +} +__forgit_ignore_get() { + mkdir -p $FORGIT_GI_CACHE + echo $@ |xargs -I{} bash -c "cat $FORGIT_GI_CACHE/{} 2>/dev/null || (curl -sL https://www.gitignore.io/api/{} |tee $FORGIT_GI_CACHE/{})" +} +__forgit_ignore_clean() { + setopt localoptions rmstarsilent + [[ -d $FORGIT_GI_CACHE ]] && rm -rf $FORGIT_GI_CACHE/* +} + + alias ${forgit_add:-ga}=__forgit_add alias ${forgit_log:-glo}=__forgit_log +alias ${forgit_diff:-gd}=__forgit_diff +alias ${forgit_ignore:-gi}=__forgit_ignore From 24a38b00f3500ac9ffcc80eb3f53b0648af86409 Mon Sep 17 00:00:00 2001 From: Ido Abramovich Date: Tue, 31 Jul 2018 17:20:59 +0300 Subject: [PATCH 04/12] add forgit restore --- forgit.plugin.bash | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/forgit.plugin.bash b/forgit.plugin.bash index df7dd1c..41ed91f 100755 --- a/forgit.plugin.bash +++ b/forgit.plugin.bash @@ -109,6 +109,18 @@ __forgit_add() { fi } + +__forgit_restore() { + if [[ __forgit_inside_work_tree -ne 0 ]]; then + return 1 + fi + local cmd="git diff --no-ext-diff --color=always -- {} $forgit_emojify $forgit_fancy" + local files=$(git ls-files --modified $(git rev-parse --show-toplevel)| + __forgit_fzf -m -0 --preview="$cmd") + [[ -n "$files" ]] && echo "$files" |xargs -I{} git checkout {} && git status --short && return + echo 'Nothing to restore.' +} + # git ignore generator export FORGIT_GI_CACHE=~/.gicache export FORGIT_GI_INDEX=${FORGIT_GI_CACHE}/.index @@ -156,3 +168,4 @@ alias ${forgit_add:-ga}=__forgit_add alias ${forgit_log:-glo}=__forgit_log alias ${forgit_diff:-gd}=__forgit_diff alias ${forgit_ignore:-gi}=__forgit_ignore +alias ${forgit_restore:-gcf}=__forgit_restore From 4eefa62936b10e0530a59e638ef23d646378ba5e Mon Sep 17 00:00:00 2001 From: Ido Abramovich Date: Tue, 31 Jul 2018 17:29:54 +0300 Subject: [PATCH 05/12] add gclean --- forgit.plugin.bash | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/forgit.plugin.bash b/forgit.plugin.bash index 41ed91f..a36a88a 100755 --- a/forgit.plugin.bash +++ b/forgit.plugin.bash @@ -121,6 +121,16 @@ __forgit_restore() { echo 'Nothing to restore.' } +__forgit_clean() { + if [[ __forgit_inside_work_tree -ne 0 ]]; then + return 1 + fi + # Note: Postfix '/' in directory path should be removed. Otherwise the directory itself will not be removed. + local files=$(git clean -xdfn "$@"| awk '{print $3}'| __forgit_fzf -m -0 |sed 's#/$##') + [[ -n "$files" ]] && echo "$files" |xargs -I{} git clean -xdf {} && return + echo 'Nothing to clean.' +} + # git ignore generator export FORGIT_GI_CACHE=~/.gicache export FORGIT_GI_INDEX=${FORGIT_GI_CACHE}/.index @@ -169,3 +179,4 @@ alias ${forgit_log:-glo}=__forgit_log alias ${forgit_diff:-gd}=__forgit_diff alias ${forgit_ignore:-gi}=__forgit_ignore alias ${forgit_restore:-gcf}=__forgit_restore +alias ${forgit_clean:-gclean}=__forgit_clean From f5c0ed1679da5420188aca76c211259b301a36eb Mon Sep 17 00:00:00 2001 From: Ido Abramovich Date: Tue, 31 Jul 2018 17:30:11 +0300 Subject: [PATCH 06/12] remove zsh setopt --- forgit.plugin.bash | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/forgit.plugin.bash b/forgit.plugin.bash index a36a88a..936d305 100755 --- a/forgit.plugin.bash +++ b/forgit.plugin.bash @@ -169,8 +169,7 @@ __forgit_ignore_get() { echo $@ |xargs -I{} bash -c "cat $FORGIT_GI_CACHE/{} 2>/dev/null || (curl -sL https://www.gitignore.io/api/{} |tee $FORGIT_GI_CACHE/{})" } __forgit_ignore_clean() { - setopt localoptions rmstarsilent - [[ -d $FORGIT_GI_CACHE ]] && rm -rf $FORGIT_GI_CACHE/* + [[ -d $FORGIT_GI_CACHE ]] && rm -rf $FORGIT_GI_CACHE } From c1757163d0118202e1a80ee06f62688c54e174fc Mon Sep 17 00:00:00 2001 From: Ido Abramovich Date: Tue, 31 Jul 2018 17:43:23 +0300 Subject: [PATCH 07/12] back to default forgit::add functionality --- forgit.plugin.bash | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/forgit.plugin.bash b/forgit.plugin.bash index 936d305..30f6ea6 100755 --- a/forgit.plugin.bash +++ b/forgit.plugin.bash @@ -98,15 +98,9 @@ __forgit_add() { __forgit_fzf -0 -m --nth 2..,.. \ --preview="git diff --no-ext-diff --color=always -- {-1} $forgit_emojify $forgit_fancy" | cut -d] -f2 | - sed 's/.* -> //' | # for rename case - tr '\n' ' ' | tr -s ' ' | sed -e 's/^[[:space:]]*//') - if [[ -n "$files" ]]; then - cmd="git add $files" - bind '"\e[0n": "'"$cmd"'"'; - printf '\e[5n' - else - echo 'Nothing to add.' - fi + sed 's/.* -> //') # for rename case + [[ -n "$files" ]] && echo "$files" |xargs -I{} git add {} && git status --short && return + echo 'Nothing to add.' } From 742d9303639b96e24dc3bd0fcb02f93f674c99a0 Mon Sep 17 00:00:00 2001 From: Ido Abramovich Date: Thu, 2 Aug 2018 14:13:23 +0300 Subject: [PATCH 08/12] rename to use .sh --- forgit.plugin.bash => forgit.plugin.sh | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename forgit.plugin.bash => forgit.plugin.sh (100%) diff --git a/forgit.plugin.bash b/forgit.plugin.sh similarity index 100% rename from forgit.plugin.bash rename to forgit.plugin.sh From 8faab30e94a957f556b4daae5356e3ce7d8b16e1 Mon Sep 17 00:00:00 2001 From: Ido Abramovich Date: Thu, 2 Aug 2018 14:13:37 +0300 Subject: [PATCH 09/12] update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index dab95cb..0509ddb 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ antigen bundle wfxr/forgit ### Manually -Clone this repo somewhere and source the `forgit.plugin.zsh` at ~/.zshrc. +Clone this repo somewhere and source the `forgit.plugin.zsh` at ~/.zshrc or source `forgit.plugin.sh` in ~/.bashrc. ## Commands From ebeae219bcc4221600ffcf9b21db78d2b2f19736 Mon Sep 17 00:00:00 2001 From: Ido Abramovich Date: Thu, 2 Aug 2018 14:25:19 +0300 Subject: [PATCH 10/12] reset IFS --- forgit.plugin.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/forgit.plugin.sh b/forgit.plugin.sh index 30f6ea6..c023e7a 100755 --- a/forgit.plugin.sh +++ b/forgit.plugin.sh @@ -131,9 +131,10 @@ export FORGIT_GI_INDEX=${FORGIT_GI_CACHE}/.index __forgit_ignore() { [ -f $FORGIT_GI_INDEX ] || __forgit_ignore_update local preview="echo {} |awk '{print \$2}' |xargs -I% bash -c 'cat $FORGIT_GI_CACHE/% 2>/dev/null || (curl -sL https://www.gitignore.io/api/% |tee $FORGIT_GI_CACHE/%)'" - OLDIFS=$IFS + ${IFS+"false"} && unset oldifs || oldifs="$IFS" #store IFS IFS=$'\n' [[ $# -gt 0 ]] && args=($@) || args=($(cat $FORGIT_GI_INDEX |nl -nrn -w4 -s' ' |__forgit_fzf -m --preview="$preview" --preview-window="right:70%" |awk '{print $2}')) + ${oldifs+"false"} && unset IFS || IFS="$oldifs" # restore IFS test -z "$args" && return 1 local options=( '(1) Output to stdout' @@ -151,7 +152,6 @@ __forgit_ignore() { __forgit_ignore_get ${args[@]} > .gitignore ;; esac - IFS=$OLDIFS } __forgit_ignore_update() { From e6e88991b4e0459d972238bd4c504d5d37732443 Mon Sep 17 00:00:00 2001 From: Ido Abramovich Date: Thu, 2 Aug 2018 14:45:29 +0300 Subject: [PATCH 11/12] simplify return check --- forgit.plugin.sh | 20 +++++--------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/forgit.plugin.sh b/forgit.plugin.sh index c023e7a..f047eb4 100755 --- a/forgit.plugin.sh +++ b/forgit.plugin.sh @@ -61,9 +61,7 @@ __forgit_get_git_color() { # git commit browser __forgit_log() { - if [[ __forgit_inside_work_tree -ne 0 ]]; then - return 1 - fi + __forgit_inside_work_tree || return local cmd="echo {} |grep -o '[a-f0-9]\{7\}' |head -1 |xargs -I% git show --color=always % $forgit_emojify $forgit_fancy" eval "git log --graph --color=always --format='%C(auto)%h%d %s %C(black)%C(bold)%cr' $@ $forgit_emojify" | __forgit_fzf +s +m --tiebreak=index \ @@ -73,9 +71,7 @@ __forgit_log() { } __forgit_diff() { - if [[ __forgit_inside_work_tree -ne 0 ]]; then - return 1 - fi + __forgit_inside_work_tree || return local cmd="git diff --no-ext-diff --color=always -- {} $forgit_emojify $forgit_fancy" [[ $# -eq 0 ]] && local files=$(git rev-parse --show-toplevel) || local files="$@" git ls-files --modified "$files"| @@ -85,9 +81,7 @@ __forgit_diff() { } __forgit_add() { - if [[ __forgit_inside_work_tree -ne 0 ]]; then - return 1 - fi + __forgit_inside_work_tree || return added=$(__forgit_get_git_color "color.status.untracked" "red") changed=$(__forgit_get_git_color "color.status.changed" "red") unmerged=$(__forgit_get_git_color "color.status.unmerged" "red") @@ -105,9 +99,7 @@ __forgit_add() { __forgit_restore() { - if [[ __forgit_inside_work_tree -ne 0 ]]; then - return 1 - fi + __forgit_inside_work_tree || return local cmd="git diff --no-ext-diff --color=always -- {} $forgit_emojify $forgit_fancy" local files=$(git ls-files --modified $(git rev-parse --show-toplevel)| __forgit_fzf -m -0 --preview="$cmd") @@ -116,9 +108,7 @@ __forgit_restore() { } __forgit_clean() { - if [[ __forgit_inside_work_tree -ne 0 ]]; then - return 1 - fi + __forgit_inside_work_tree || return # Note: Postfix '/' in directory path should be removed. Otherwise the directory itself will not be removed. local files=$(git clean -xdfn "$@"| awk '{print $3}'| __forgit_fzf -m -0 |sed 's#/$##') [[ -n "$files" ]] && echo "$files" |xargs -I{} git clean -xdf {} && return From 9d4e17e7b4e5481d50a1f4b29d742bfe8565439e Mon Sep 17 00:00:00 2001 From: Ido Abramovich Date: Thu, 2 Aug 2018 14:47:30 +0300 Subject: [PATCH 12/12] return 1 when return like in zsh --- forgit.plugin.sh | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/forgit.plugin.sh b/forgit.plugin.sh index f047eb4..e3bab0a 100755 --- a/forgit.plugin.sh +++ b/forgit.plugin.sh @@ -61,7 +61,7 @@ __forgit_get_git_color() { # git commit browser __forgit_log() { - __forgit_inside_work_tree || return + __forgit_inside_work_tree || return 1 local cmd="echo {} |grep -o '[a-f0-9]\{7\}' |head -1 |xargs -I% git show --color=always % $forgit_emojify $forgit_fancy" eval "git log --graph --color=always --format='%C(auto)%h%d %s %C(black)%C(bold)%cr' $@ $forgit_emojify" | __forgit_fzf +s +m --tiebreak=index \ @@ -71,7 +71,7 @@ __forgit_log() { } __forgit_diff() { - __forgit_inside_work_tree || return + __forgit_inside_work_tree || return 1 local cmd="git diff --no-ext-diff --color=always -- {} $forgit_emojify $forgit_fancy" [[ $# -eq 0 ]] && local files=$(git rev-parse --show-toplevel) || local files="$@" git ls-files --modified "$files"| @@ -81,7 +81,7 @@ __forgit_diff() { } __forgit_add() { - __forgit_inside_work_tree || return + __forgit_inside_work_tree || return 1 added=$(__forgit_get_git_color "color.status.untracked" "red") changed=$(__forgit_get_git_color "color.status.changed" "red") unmerged=$(__forgit_get_git_color "color.status.unmerged" "red") @@ -99,7 +99,7 @@ __forgit_add() { __forgit_restore() { - __forgit_inside_work_tree || return + __forgit_inside_work_tree || return 1 local cmd="git diff --no-ext-diff --color=always -- {} $forgit_emojify $forgit_fancy" local files=$(git ls-files --modified $(git rev-parse --show-toplevel)| __forgit_fzf -m -0 --preview="$cmd") @@ -108,7 +108,7 @@ __forgit_restore() { } __forgit_clean() { - __forgit_inside_work_tree || return + __forgit_inside_work_tree || return 1 # Note: Postfix '/' in directory path should be removed. Otherwise the directory itself will not be removed. local files=$(git clean -xdfn "$@"| awk '{print $3}'| __forgit_fzf -m -0 |sed 's#/$##') [[ -n "$files" ]] && echo "$files" |xargs -I{} git clean -xdf {} && return