From 10f0af9bb866dfe4ecdf953ffd6f0ce01ccee904 Mon Sep 17 00:00:00 2001 From: Christopher Apple Date: Sun, 3 Nov 2019 12:32:11 -0700 Subject: [PATCH] First draft of fish forgit completed :) --- forgit.plugin.fish | 230 +++++++++++++++++++++++++++++---------------- 1 file changed, 151 insertions(+), 79 deletions(-) diff --git a/forgit.plugin.fish b/forgit.plugin.fish index b1e2db7..db36a0f 100755 --- a/forgit.plugin.fish +++ b/forgit.plugin.fish @@ -1,5 +1,10 @@ #!/usr/local/bin/fish -# MIT (c) Wenxuan Zhang +# MIT (c) Chris Apple + +if not hash fzf > /dev/null 2>&1 + echo "FZF not found and is requried for forgit" + exit 1 +end function forgit::warn printf "%b[Warn]%b %s\n" '\e[0;33m' '\e[0m' "$argv" >&2; @@ -23,16 +28,22 @@ hash emojify >/dev/null 2>&1 && set forgit_emojify '|emojify' function forgit::log forgit::inside_work_tree || return 1 set cmd "echo {} |grep -Eo '[a-f0-9]+' |head -1 |xargs -I% git show --color=always % $argv $forgit_fancy" + + if test -n "$FORGIT_COPY_CMD" + set copy_cmd $FORGIT_COPY_CMD + else + set copy_cmd pbcopy + end + set opts " $FORGIT_FZF_DEFAULT_OPTS +s +m --tiebreak=index --preview=\"$cmd\" --bind=\"enter:execute($cmd |env LESS='-R' less)\" - --bind=\"ctrl-y:execute-silent(echo {} |grep -Eo '[a-f0-9]+' | head -1 | tr -d '\n' | pbcopy)\" + --bind=\"ctrl-y:execute-silent(echo {} |grep -Eo '[a-f0-9]+' | head -1 | tr -d '\n' | $copy_cmd)\" $FORGIT_LOG_FZF_OPTS " - #TODO: removed option for another pbcopy above eval "git log --graph --color=always --format='%C(auto)%h%d %s %C(black)%C(bold)%cr' $argv $forgit_emojify" | - env FZF_DEFAULT_OPTS "$opts" fzf + env FZF_DEFAULT_OPTS="$opts" fzf end ## git diff viewer @@ -79,7 +90,7 @@ function forgit::add env FZF_DEFAULT_OPTS="$opts" fzf | cut -d] -f2 | sed 's/.* -> //') # for rename case - if test -n $files + if test -n "$files" echo "$files" |xargs -I{} git add {} && git status --short && return end echo 'Nothing to add.' @@ -94,8 +105,9 @@ function forgit::reset::head -m -0 --preview=\"$cmd\" $FORGIT_RESET_HEAD_FZF_OPTS " - set files "(git diff --cached --name-only --relative | env FZF_DEFAULT_OPTS="$opts" fzf)" - if test -n $files + set files (git diff --cached --name-only --relative | env FZF_DEFAULT_OPTS="$opts" fzf) + if test -n "$files" + echo herer echo "$files" |xargs -I{} git reset -q HEAD {} && git status --short && return end echo 'Nothing to unstage.' @@ -113,7 +125,7 @@ function forgit::restore " set git_rev_parse (git rev-parse --show-toplevel) set files (git ls-files --modified "$git_rev_parse" | env FZF_DEFAULT_OPTS="$opts" fzf) - if test -n $files + if test -n "$files" echo "$files" |xargs -I{} git checkout {} && git status --short && return end echo 'Nothing to restore.' @@ -131,7 +143,6 @@ function forgit::stash::show git stash list | env FZF_DEFAULT_OPTS="$opts" fzf end - # git clean selector function forgit::clean forgit::inside_work_tree || return 1 @@ -141,92 +152,153 @@ function forgit::clean -m -0 $FORGIT_CLEAN_FZF_OPTS " - # Note: Postfix '/' in directory path should be removed. Otherwise the directory itself will not be removed. - # TODO removed $argv here - set files (git clean -xdfn | awk '{print $3}' | env FZF_DEFAULT_OPTS="$opts" fzf | sed 's#/$##') - if test -n $files + set files (git clean -xdfn $argv| awk '{print $3}'| env FZF_DEFAULT_OPTS="$opts" fzf |sed 's#/$##') + + if test -n "$files" echo "$files" |xargs -I% git clean -xdf % && return end echo 'Nothing to clean.' end # git ignore generator -set -x FORGIT_GI_REPO_REMOTE ${FORGIT_GI_REPO_REMOTE:-https://github.com/dvcs/gitignore} -set -x FORGIT_GI_REPO_LOCAL ${FORGIT_GI_REPO_LOCAL:-~/.forgit/gi/repos/dvcs/gitignore} -set -x FORGIT_GI_TEMPLATES ${FORGIT_GI_TEMPLATES:-$FORGIT_GI_REPO_LOCAL/templates} +if test -z "$FORGIT_GI_REPO_REMOTE" + set -x FORGIT_GI_REPO_REMOTE https://github.com/dvcs/gitignore +end + +if test -z "$FORGIT_GI_REPO_LOCAL" + set -x FORGIT_GI_REPO_LOCAL ~/.forgit/gi/repos/dvcs/gitignore +end + +if test -z "$FORGIT_GI_TEMPLATES" + set -x FORGIT_GI_TEMPLATES $FORGIT_GI_REPO_LOCAL/templates +end function forgit::ignore - [ -d "$FORGIT_GI_REPO_LOCAL" ] || forgit::ignore::update + if test -d "$FORGIT_GI_REPO_LOCAL" + forgit::ignore::update + end + # https://github.com/sharkdp/bat.git - hash bat > /dev/null 2>&1 && cat='bat -l gitignore --color=always' || cat="cat" + hash bat > /dev/null 2>&1 && set cat 'bat -l gitignore --color=always' || set cat "cat" set cmd "$cat $FORGIT_GI_TEMPLATES/{2}{,.gitignore} 2>/dev/null" set opts " $FORGIT_FZF_DEFAULT_OPTS -m --preview=\"$cmd\" --preview-window='right:70%' $FORGIT_IGNORE_FZF_OPTS " - # shellcheck disable=SC2206,2207 - IFS=$'\n' args=($argv) && [[ $# -eq 0 ]] && args=((forgit::ignore::list | nl -nrn -w4 -s' ' | - env FZF_DEFAULT_OPTS="$opts" fzf |awk '{print $2}')) - [ ${#args[@]} -eq 0 ] && return 1 - # shellcheck disable=SC2068 - if hash bat > /dev/null 2>&1; then - forgit::ignore::get ${args[@]} | bat -l gitignore + set IFS '\n' + + set args $argv + if not count $argv > /dev/null + set args (forgit::ignore::list | nl -nrn -w4 -s' ' | + env FZF_DEFAULT_OPTS="$opts" fzf |awk '{print $2}') + end + + if not count $args > /dev/null + return 1 + end + + if hash bat > /dev/null 2>&1 + forgit::ignore::get $args | bat -l gitignore else - forgit::ignore::get ${args[@]} - fi + forgit::ignore::get $args + end end -#function forgit::ignore::update -# if [[ -d "$FORGIT_GI_REPO_LOCAL" ]]; then -# forgit::info 'Updating gitignore repo...' -# (cd "$FORGIT_GI_REPO_LOCAL" && git pull --no-rebase --ff) || return 1 -# else -# forgit::info 'Initializing gitignore repo...' -# git clone --depth=1 "$FORGIT_GI_REPO_REMOTE" "$FORGIT_GI_REPO_LOCAL" -# fi -#end -#function forgit::ignore::get -# for item in "$argv"; do -# if filename=(find -L "$FORGIT_GI_TEMPLATES" -type f \( -iname "${item}.gitignore" -o -iname "${item}" \) -print -quit); then -# [[ -z "$filename" ]] && forgit::warn "No gitignore template found for '$item'." && continue -# header="${filename##*/}" && header="${header%.gitignore}" -# echo "### $header" && cat "$filename" && echo -# fi -# done -#end -#function forgit::ignore::list -# find "$FORGIT_GI_TEMPLATES" -print |sed -e 's#.gitignore$##' -e 's#.*/##' | sort -fu -#end -#function forgit::ignore::clean -# setopt localoptions rmstarsilent -# [[ -d "$FORGIT_GI_REPO_LOCAL" ]] && rm -rf "$FORGIT_GI_REPO_LOCAL" -#end -# -#FORGIT_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' -#--bind='alt-w:toggle-preview-wrap' -#--preview-window='right:60%' -#$FORGIT_FZF_DEFAULT_OPTS -#" -# -## register aliases -## shellcheck disable=SC2139 -#if test -z "$FORGIT_NO_ALIASES" -# alias "${forgit_add:-ga}"='forgit::add' -# alias "${forgit_reset_head:-grh}"='forgit::reset::head' -# 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' -# alias "${forgit_stash_show:-gss}"='forgit::stash::show' -#end +function forgit::ignore::update + if test -d "$FORGIT_GI_REPO_LOCAL" + forgit::info 'Updating gitignore repo...' + set pull_result (git -C "$FORGIT_GI_REPO_LOCAL" pull --no-rebase --ff) + test -n "$pull_result" || return 1 + else + forgit::info 'Initializing gitignore repo...' + git clone --depth=1 "$FORGIT_GI_REPO_REMOTE" "$FORGIT_GI_REPO_LOCAL" + end +end + +function forgit::ignore::get + for item in $argv + set filename (find -L "$FORGIT_GI_TEMPLATES" -type f \( -iname "$item.gitignore" -o -iname "$item}" \) -print -quit) + if test -n "$filename" + set header $filename && set header (echo $filename | sed 's/.*\.//') + echo "### $header" && cat "$filename" && echo + else + forgit::warn "No gitignore template found for '$item'." && continue + end + end +end + +function forgit::ignore::list + find "$FORGIT_GI_TEMPLATES" -print |sed -e 's#.gitignore$##' -e 's#.*/##' | sort -fu +end + +function forgit::ignore::clean + setopt localoptions rmstarsilent + [[ -d "$FORGIT_GI_REPO_LOCAL" ]] && rm -rf "$FORGIT_GI_REPO_LOCAL" +end + +set FORGIT_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' +--bind='alt-w:toggle-preview-wrap' +--preview-window='right:60%' +$FORGIT_FZF_DEFAULT_OPTS +" + +# register aliases +if test -z "$FORGIT_NO_ALIASES" + if test -n "$forgit_add" + alias $forgit_add 'forgit::add' + else + alias ga 'forgit::add' + end + + if test -n "$forgit_reset_head" + alias $forgit_reset_head 'forgit::reset::head' + else + alias grh 'forgit::reset::head' + end + + if test -n "$forgit_log" + alias $forgit_log 'forgit::log' + else + alias glo 'forgit::log' + end + + if test -n "$forgit_diff" + alias $forgit_diff 'forgit::diff' + else + alias gd 'forgit::diff' + end + + if test -n "$forgit_ignore" + alias $forgit_ignore 'forgit::ignore' + else + alias gi 'forgit::ignore' + end + + if test -n "$forgit_restore" + alias $forgit_restore 'forgit::restore' + else + alias gcf 'forgit::restore' + end + + if test -n "$forgit_clean" + alias $forgit_clean 'forgit::clean' + else + alias gclean 'forgit::clean' + end + + if test -n "$forgit_stash_show" + alias $forgit_stash_show 'forgit::stash::show' + else + alias gss 'forgit::stash::show' + end +end