commit 54ec2aee7951013c5ecc03031a59c089bb676b71
parent 4b4455f04e03b44bded3df4be12387e461e0e158
Author: Lucas Burns <burnsac@me.com>
Date: Sun, 9 May 2021 20:04:20 -0500
added zsh plugin, added fbackup (needs work), git show after fadd and fstat, allow symlink
Diffstat:
M | Makefile | | | 4 | +++- |
M | README.md | | | 159 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------- |
M | fadd | | | 16 | ++++++++-------- |
M | fcheckout | | | 18 | +++++++++--------- |
M | fedit | | | 16 | ++++++++-------- |
M | fgit_helper.sh | | | 88 | +++++++++++++++++++++++++++++++++++++++++++++++++++---------------------------- |
M | flog | | | 20 | ++++++++++---------- |
M | freset | | | 19 | +++++++++---------- |
M | fstash | | | 21 | +++++++++++++-------- |
M | fstat | | | 14 | +++++++------- |
M | funtrack | | | 14 | +++++++------- |
A | fzfgit.plugin.zsh | | | 185 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
M | preview.sh | | | 15 | +++++++-------- |
13 files changed, 444 insertions(+), 145 deletions(-)
diff --git a/Makefile b/Makefile
@@ -8,12 +8,14 @@ DESTDIR ?= $(PREFIX)/bin
all:
@echo "To install $(PROG) scripts run \"make install\"."
@echo "The $(PROG) scripts require some other packages:"
- @echo " brew install fzf bat"
+ @echo " brew install fzf bat delta"
install:
@install -vd "$(DESTDIR)/"
@install -vm755 fadd "$(DESTDIR)/fadd"
@echo "fadd installed successfully"
+ @install -vm755 fbackup "$(DESTDIR)/fbackup"
+ @echo "fbackup installed successfully"
@install -vm755 fcheckout "$(DESTDIR)/fcheckout"
@echo "fcheckout installed successfully"
@install -vm755 fedit "$(DESTDIR)/fedit"
diff --git a/README.md b/README.md
@@ -1,10 +1,10 @@
-fzfgit scripts
-==============
+## fzfgit scripts
-These scripts come from [dotbare](https://github.com/kazhala/dotbare) and are modified to work with a regular git directory.
+This is a fork of [`dotbare`](https://github.com/kazhala/dotbare). The scripts are modified to work with a regular `git` directory.
-Installation:
-------------
+### Installation:
+
+#### Manual - use as a script
```sh
git clone https://github.com/lmburns/fzfgit.git
@@ -12,17 +12,51 @@ cd fzfgit
make install
```
-Dependencies:
-------------
-- [`fzf`](https://github.com/junegunn/fzf)
- - macOS: `brew install fzf`
-- [`bat`](https://github.com/sharkdp/bat)
- - macOS: `brew install bat`
-
-Scripts (from [dotbare](https://github.com/kazhala/dotbare))
--------
-fadd
-----
+#### zsh
+
+##### zinit
+```sh
+zinit light lmburns/fzfgit
+```
+
+##### oh-my-zsh
+```sh
+git clone https://github.com/lmburns/fzfgit.git ${ZDOTDIR:-$HOME}/.oh-my-zsh/custom/plugins/fzfgit
+
+# Add to .zshrc
+plugins=( fzfgit )
+```
+
+##### Antigen
+```sh
+antigen bundle lmburns/fzfgit
+```
+
+##### Manual - use as a `zsh` plugin
+```sh
+git clone https://github.com/lmburns/fzfgit.git ${ZDOTDIR:-$HOME}/.fzfgit
+
+# Add to .zshrc
+source "${ZDOTDIR:-$HOME}/.fzfgit"
+```
+
+### Dependencies:
+
+* [`fzf`](https://github.com/junegunn/fzf)
+* [`bat`](https://github.com/sharkdp/bat)
+* [`delta`](https://github.com/dandavison/delta)
+* Optional: [`exa`](https://github.com/ogham/exa) or `tree`
+
+```sh
+# macOS installation - linux distributions should have it in their package manager
+# if not, check the links above to download from Github
+brew install fzf bat delta exa
+```
+
+## Scripts
+
+### `fadd`
+
Select files/directories or modified files through fzf and stage the selected files/directories.
- Default: list all modified files and stage selected files. Support multi selection.
@@ -30,9 +64,8 @@ Select files/directories or modified files through fzf and stage the selected fi
- `-f, --file`: list all files in current directory and stage selected files. Support multi selection. (Used for staging new files to index).
- `-d, --dir`: list all directory under current directory and stage selected directory. Support multi selection. (Used for staging new files to index).
+### `fcheckout`
-fcheckout
----------
Checkout files/commit/branch interactively through fzf.
- Default: list all modified files and reset selected files back to HEAD. Support multi selection. (Discard all changes) **Note**: if your file is staged, you will need to unstage first before running fcheckout to make it work.
@@ -42,9 +75,8 @@ Checkout files/commit/branch interactively through fzf.
- `-c, --commit`: list all commits and checkout selected commit.
- `-y, --yes`: acknowledge all actions that will be taken and skip confirmation.
+### `fedit`
-fedit
------
Select files/commits through fzf and edit selected files/commits in `$EDITOR`. Editing commits will perform a interactive rebase.
- Default: list all tracked files and open `$EDITOR` to edit the selected files. Support multi selection.
@@ -52,9 +84,8 @@ Select files/commits through fzf and edit selected files/commits in `$EDITOR`. E
- `-m, --modified`: list all modified files and open `$EDITOR` to edit the selected files. Support multi selection.
- `-c, --commit`: list all commits and edit the selected commit through interactive rebase.
+### `flog`
-flog
-----
Interactive log viewer that will prompt you with a menu after selecting a commit. The action menu contains options including edit, reset, revert and checkout the selected commits.
- Default: list all commits and then prompt menu to select action to perform.
@@ -65,9 +96,8 @@ Interactive log viewer that will prompt you with a menu after selecting a commit
- `-c, --checkout`: checkout selected commit and skip action menu.
- `-y, --yes`: acknowledge all actions that will be taken and skip confirmation.
+### `freset`
-freset
-------
Select staged files or commits through fzf and then reset(unstage) staged files or reset HEAD back to certain commits. Also supports reset HEAD back to certain commits using either `--soft`, `--hard`, `--mixed` flags. More information on differences between flags [here](https://git-scm.com/docs/git-reset#Documentation/git-reset.txt-emgitresetemltmodegtltcommitgt).
- Default: list all staged files and unstage the selected files. Support multi selection.
@@ -77,9 +107,8 @@ Select staged files or commits through fzf and then reset(unstage) staged files
- `-H, --hard`: use --hard flag instead of --mixed flag, reset HEAD to certain commit discard all changes from the working tree.
- `-y, --yes`: acknowledge all actions that will be taken and skip confirmation.
+### `fstash`
-fstash
-------
View and manage stash interactively.
- Default: list all stashes and apply the selected stash. (Default: `apply`).
@@ -89,15 +118,14 @@ View and manage stash interactively.
- `-p, --pop`: use `pop` instead of `apply`. (`pop` would remove the stash while `apply` preserve the stash).
-fstat
------
+### `fstat`
+
Display interactive git status menu. Toggle file stage/unstage status interactively.
- `-h, --help`: show the help message of `fstat` and exit.
+### `funtrack`
-funtrack
---------
Stop tracking the selected git files. It could also be used to temporarily stop tracking changes for files and then later on resume tracking changes.
**Note**: This command has severe limitations.
@@ -112,9 +140,8 @@ By default, selected files are permanently untracked from git. Selected files wi
- `-r, --resume`: list all tracked files and resume tracking changes of the selected files.
- `-y, --yes`: acknowledge all actions that will be taken and skip confirmation.
+### `fzgrep`
-fzgrep
-------
Grep words within tracked files and select to edit them through fzf. The words are listed as lines in fzf and is separated by columns. First column is the file name, second column is the line number and the third column and beyond are the content of the lines.
- Default: start searching from 3rd column (excluding the file name and line number during search).
@@ -122,14 +149,70 @@ Grep words within tracked files and select to edit them through fzf. The words a
- `-c COL, --col COL`: specify the column number to start searching (e.g. `fgrep --col 2`).
- `-f, --full`: include all column during search, as if using `--col 1`.
+## Helper scripts
-Helper scripts
-==============
+### `fgit_helper.sh`
-fgit_helper.sh
---------------
Provides variables and functions used by some of the scripts mentioned above.
-preview.sh
-----------
+### `preview.sh`
+
Fzf preview window coloring.
+
+## Environment variables
+
+### `FZFGIT_DEFAULT_OPTS`
+
+Enable alternate options for this specific use of `fzf`. Not set by default.
+
+```sh
+export FZFGIT_DEFAULT_OPTS="--preview-window=':nohidden,right:65%:wrap'"
+```
+
+### `FZFGIT_KEY`
+
+Set default keybindings for all the `fzf` commands. See `man fzf` for a list of all possible options, or [here](https://github.com/junegunn/fzf/blob/97a725fbd0e54cbc07e4d72661ea2bd2bb7c01c1/man/man1/fzf.1#L648).
+
+```sh
+# This variable does have a default value
+export FZFGIT_KEY="
+ --bind='ctrl-a:toggle-all' # toggle all selection
+ --bind='ctrl-b:execute(bat --paging=always -f {+})' # open in a pager
+ --bind='ctrl-y:execute-silent(echo {+} | pbcopy)' # copy the file to clipboard
+ --bind='ctrl-e:execute(echo {+} | xargs -o $EDITOR)' # open file in editor
+ --bind='ctrl-k:preview-up' # move the file preview up
+ --bind='ctrl-j:preview-down' # move the file preview down
+ --bind='alt-j:jump' # label jump mode, sort of like vim-easymotion
+ --bind='ctrl-0:top' # set cursor back to top
+ --bind='ctrl-s:toggle-sort' # toggle sorting
+ --bind='?:toggle-preview' # toggle preview
+"
+```
+
+### `FZFGIT_PREVIEW`
+
+Preview command for the preview window in `fzf`. The order in which the preview is determined is: `bat`, `highlight`, `coderay`, `rougify`, `cat`. Not set by default.
+
+```sh
+# Two different ones are given as examples to display the complexity it can be
+# When specifying the command, be sure to use the {} placeholder
+export FZFGIT_PREVIEW="([[ -f {} ]] && (bat --style=numbers --color=always {})) || ([[ -d {} ]] && (tree -C {} | less)) || echo {} 2> /dev/null | head -200"
+
+export FZFGIT_PREVIEW="cat -n {}"
+```
+
+### `FZFGIT_DIFF_PAGER`
+
+Customize diff preview on commands that display diff output. The initial value is read from from `git config core.pager`. Use this to specify something different.
+
+```sh
+export FZFGIT_DIFF_PAGER="delta --diff-so-fancy --line-numbers"
+```
+
+### `FZFGIT_BACKUP`
+
+Top level directory where the current directory you are in can be backed up to. I am working on allowing specification of a path to a directory that you're currently not in.
+
+```sh
+export FZFGIT_BACKUP="$XDG_DATA_HOME/gitbackup"
+```
diff --git a/fadd b/fadd
@@ -1,23 +1,23 @@
#!/usr/bin/env bash
#
-# Stage the selected file to git bare repo
+# Desc: stage the selected file to git bare repo
#
# @params
-# Globals
+# Globals:
# ${mydir}: string, current directory of the executing script
# ${stage_type}: modified, new file, or directory to stage
# ${selected_files}: bash array of user selected files to stage
-# Arguments
+# Arguments:
# -h|--help: show help message
# -f|--file: select a file in PWD to stage
# -d|--dir: select a directory in PWD to stage
set -ef
-mydir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
+mydir="$(dirname -- "$(readlink -f -- "${BASH_SOURCE[0]}")")"
source "${mydir}"/fgit_helper.sh
-function usage() {
+usage() {
echo -e "Usage: fadd [-h] [-f] [-d] ...
Select files/directories or modified files through fzf.
@@ -40,7 +40,7 @@ Optional arguments:
stage_file() {
local -a files && files=("$@")
[[ "${#files[@]}" -eq 0 ]] && { printf "%s" "$(tput setaf 1)Nothing added$(tput sgr0)"; exit 1; }
- git add "${files[@]}"
+ git add "${files[@]}"
}
stage_type="modified"
@@ -48,8 +48,8 @@ typeset -a selected_files && selected_files=()
while [[ "$#" -gt 0 ]]; do
case "$1" in
- -f|--file) stage_type="file" shift ;;
- -d|--dir) stage_type="dir" shift ;;
+ -f|--file) stage_type="file"; shift ;;
+ -d|--dir) stage_type="dir"; shift ;;
-h|--help) usage && exit 0 ;;
*) echo "Invalid option: $1" >&2 && usage && exit 1 ;;
esac
diff --git a/fcheckout b/fcheckout
@@ -1,16 +1,16 @@
#!/usr/bin/env bash
#
-# checkout files/commit/branches using fzf
+# Desc: checkout files/commit/branches using fzf
#
# @params
-# Globals
+# Globals:
# ${mydir}: current directory of the script, used for imports
# ${action_type}: what type of git commands to use (branch|select|commit|modified)
# ${selected_branch}: selected_branch to switch
# ${selected_files}: selected_files to checkout
# ${selected_commit}: selected commit to checkout
# ${confirm}: confirm status of the user
-# Arguments
+# Arguments:
# -h|--help: show help message
# -s|--select: search all files instead of just the modified files
# -b|--branch: search branch and checkout branch
@@ -18,7 +18,7 @@
set -ef
-mydir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
+mydir="$(dirname -- "$(readlink -f -- "${BASH_SOURCE[0]}")")"
source "${mydir}"/fgit_helper.sh
usage() {
@@ -40,17 +40,17 @@ Optional arguments:
}
action_type="modified"
-typeset -a kselected_files=()
+typeset -a selected_files && selected_files=()
confirm=""
selected_commit=""
selected_branch=""
while [[ "$#" -gt 0 ]]; do
case "$1" in
- -s|--select) action_type="select" shift ;;
- -b|--branch) action_type="branch" shift ;;
- -c|--commit) action_type="commit" shift ;;
- -y|--yes) confirm="y" shift ;;
+ -s|--select) action_type="select"; shift ;;
+ -b|--branch) action_type="branch"; shift ;;
+ -c|--commit) action_type="commit"; shift ;;
+ -y|--yes) confirm="y"; shift ;;
-h|--help) usage && exit 0 ;;
*) echo "Invalid option: $1" >&2 && usage && exit 1;;
esac
diff --git a/fedit b/fedit
@@ -1,24 +1,24 @@
#!/usr/bin/env bash
#
-# interactive menu to select file/commit to edit
+# Desc: interactive menu to choose file/commit to edit
#
# @params
-# Globals
+# Globals:
# ${mydir}: current directory of the script
# ${edit_type}: which type to edit, all files, modified files, commit
# ${selected_commit}: selected commit to edit
# ${selected_files}: arrays of selected file to edit
-# Arguments
+# Arguments:
# -m|--modified: display modified file only
# -c|--commit: edit commit using interactive rebase
# -h|--help: show helpe message and exit
set -ef
-mydir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
+mydir="$(dirname -- "$(readlink -f -- "${BASH_SOURCE[0]}")")"
source "${mydir}"/fgit_helper.sh
-function usage() {
+usage() {
echo -e "Usage: fedit [-h] [-m] [-c] ...
Select files/commits through fzf and edit selected files/commits in EDITOR.
@@ -32,13 +32,13 @@ Optional arguments:
}
edit_type="all"
-selected_files=()
+typeset -a selected_files && selected_files=()
selected_commit=""
while [[ "$#" -gt 0 ]]; do
case "$1" in
- -m|--modified) edit_type="modified" shift ;;
- -c|--commit) edit_type="commit" shift ;;
+ -m|--modified) edit_type="modified"; shift ;;
+ -c|--commit) edit_type="commit"; shift ;;
-h|--help) usage && exit 0 ;;
*) echo "Invalid option: $1" >&2 && usage && exit 1 ;;
esac
diff --git a/fgit_helper.sh b/fgit_helper.sh
@@ -3,17 +3,37 @@
#######################################
########## SETTING VARIABLES ##########
#######################################
-export GTREE="$(git rev-parse --show-toplevel)"
-export G_DIFF_PAGER="$(git config core.pager || echo 'cat')"
+export FZFGIT_TREE="$(git rev-parse --show-toplevel)"
+export FZFGIT_DIFF_PAGER="${FZFGIT_DIFF_PAGER:-$(git config core.pager || echo 'cat')}"
export EDITOR="${EDITOR:-vim}"
+export FZFGIT_VERSION="v1.2"
[[ -z "${FZF_DEFAULT_OPTS}" ]] && export FZF_DEFAULT_OPTS='--cycle'
+if [[ -z "${FZFGIT_KEY}" ]]; then
+ FZFGIT_KEY="
+ --bind='ctrl-a:toggle-all'
+ --bind='ctrl-b:execute(bat --paging=always -f {+})'
+ --bind='ctrl-y:execute-silent(echo {+} | pbcopy)'
+ --bind='ctrl-e:execute(echo {+} | xargs -o $EDITOR)'
+ --bind='ctrl-k:preview-up'
+ --bind='ctrl-j:preview-down'
+ --bind='alt-j:jump'
+ --bind='alt-0:top'
+ --bind='ctrl-s:toggle-sort'
+ --bind='?:toggle-preview'
+"
+fi
+
+
FZF_DEFAULT_OPTS="
$FZF_DEFAULT_OPTS
--ansi
--cycle
- --exit-0"
+ --exit-0
+ $FZFGIT_DEFAULT_OPTS
+ $FZFGIT_KEY
+"
[[ -z "${COLUMNS}" ]] \
&& COLUMNS=$(stty size < /dev/tty | cut -d' ' -f2)
@@ -50,8 +70,8 @@ set_fzf_multi() {
get_confirmation() {
local confirm
local message="${1:-Confirm?}"
- while [ "${confirm}" != 'y' ] && [ "${confirm}" != 'n' ]; do
- read -r -p "${message}(y/n): " confirm
+ while [[ "${confirm}" != 'y' && "${confirm}" != 'n' ]]; do
+ read -r -p "${message}[y/n]: " confirm
done
echo "${confirm}"
}
@@ -78,16 +98,16 @@ get_commit() {
| awk '{print \$1}' \
| xargs -I __ git \
show --color=always __ \
- | ${G_DIFF_PAGER}" \
+ | ${FZFGIT_DIFF_PAGER}" \
| awk '{print $1}'
else
- git \
+ git \
log --oneline --color=always --decorate=short \
| fzf --header="${header}" --no-multi --preview "echo {} \
| awk '{print \$1}' \
| xargs -I __ git \
diff --color=always __ ${files[*]} \
- | ${G_DIFF_PAGER}" \
+ | ${FZFGIT_DIFF_PAGER}" \
| awk '{print $1}'
fi
}
@@ -102,7 +122,7 @@ get_commit() {
#######################################
get_branch() {
local header="${1:-select a branch}"
- git branch -a \
+ git branch -a \
| awk '{
if ($0 ~ /\*.*\(HEAD.*/) {
gsub(/\* /, "", $0)
@@ -126,7 +146,7 @@ get_branch() {
print \$0
}
}' \
- | xargs -I __ git \
+ | xargs -I __ git \
log --color=always --color=always --format='%C(auto)%h%d %s %C(black)%C(bold)%cr' __"
}
@@ -144,12 +164,12 @@ get_git_file() {
local mydir
local header="${1:-select tracked file}"
local print_opt="${2:-full}"
- mydir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
+ mydir="$(dirname -- "$(readlink -f -- "${BASH_SOURCE[0]}")")"
set_fzf_multi "$3"
- git ls-files --full-name --directory "${GTREE}" \
+ git ls-files --full-name --directory "${FZFGIT_TREE}" \
| fzf --header="${header}" \
- --preview "preview.sh ${GTREE}/{}" \
- | awk -v home="${GTREE}" -v print_opt="${print_opt}" '{
+ --preview "preview.sh ${FZFGIT_TREE}/{}" \
+ | awk -v home="${FZFGIT_TREE}" -v print_opt="${print_opt}" '{
if (print_opt == "full") {
print home "/" $0
} else {
@@ -197,11 +217,11 @@ get_modified_file() {
}
}' \
| fzf --header="${header}" --preview "echo {} \
- | awk '{sub(\$1 FS,\"\");print \$0}' \
- | xargs -I __ git \
- diff HEAD --color=always -- ${GTREE}/__ \
- | ${G_DIFF_PAGER}" \
- | awk -v home="${GTREE}" -v format="${output_format}" '{
+ | awk '{sub(\$1 FS,\"\"); print \$0}' \
+ | xargs -I __ git \
+ diff HEAD --color=always -- ${FZFGIT_TREE}/__ \
+ | ${FZFGIT_DIFF_PAGER}" \
+ | awk -v home="${FZFGIT_TREE}" -v format="${output_format}" '{
if (format == "name") {
$1=""
gsub(/^[ \t]/, "", $0)
@@ -225,16 +245,16 @@ get_modified_file() {
get_stash() {
local header="${1:-select a stash}"
set_fzf_multi "$2"
- git \
+ git \
stash list \
| fzf --header="${header}" --preview "echo {} \
| awk '{
gsub(/:/, \"\", \$1)
print \$1
}' \
- | xargs -I __ git \
+ | xargs -I __ git \
stash show -p __ --color=always \
- | ${G_DIFF_PAGER}" \
+ | ${FZFGIT_DIFF_PAGER}" \
| awk '{
gsub(/:/, "", $1)
print $1
@@ -255,14 +275,16 @@ get_stash() {
grep_words() {
local header="${1:-select matches to edit}"
local delimiter="${2:-3}"
- mydir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
+ local grep_cmd
+ command -v rg >/dev/null && grep_cmd="rg --line-number --no-heading --color=auto --smart-case --ignore='.git' -- ." \
+ || grep_cmd="git grep --line-number -- ."
+ mydir="$(dirname -- "$(readlink -f -- "${BASH_SOURCE[0]}")")"
set_fzf_multi "$2"
- cd "${GTREE}" || exit
- git \
- grep --line-number -- . \
+ cd "${FZFGIT_TREE}" || exit
+ eval "${grep_cmd}" \
| fzf --delimiter : --nth "${delimiter}".. --header="${header}" \
- --preview "${mydir}/preview.sh ${GTREE}/{}" \
- | awk -F ":" -v home="${GTREE}" '{
+ --preview "${mydir}/preview.sh ${FZFGIT_TREE}/{}" \
+ | awk -F ":" -v home="${FZFGIT_TREE}" '{
print home "/" $1 ":" $2
}'
}
@@ -276,12 +298,16 @@ grep_words() {
#######################################
search_file() {
local search_type="$1" mydir
- mydir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
+ mydir="$(dirname -- "$(readlink -f -- "${BASH_SOURCE[0]}")")"
if [[ "${search_type}" == "f" ]]; then
find . -maxdepth 1 -type f | sed "s|\./||g" | fzf --multi --preview "${mydir}/preview.sh {}"
elif [[ "${search_type}" == "d" ]]; then
- if command -v tree &>/dev/null; then
- find . -maxdepth 1 -type d | awk '{if ($0 != "." && $0 != "./.git"){gsub(/^\.\//, "", $0);print $0}}' | fzf --multi --preview "tree -L 1 -C --dirsfirst {}"
+ if command -v exa &>/dev/null; then
+ find . -maxdepth 1 -type d | awk '{if ($0 != "." && $0 != "./.git"){gsub(/^\.\//, "", $0);print $0}}' \
+ | fzf --multi --preview "exa -TL 1 --color=always --group-directories-first --icons {}"
+ elif command -v tree &>/dev/null; then
+ find . -maxdepth 1 -type d | awk '{if ($0 != "." && $0 != "./.git"){gsub(/^\.\//, "", $0);print $0}}' \
+ | fzf --multi --preview "tree -L 1 -C --dirsfirst {}"
else
find . -maxdepth 1 -type d | awk '{if ($0 != "." && $0 != "./.git"){gsub(/^\.\//, "", $0);print $0}}' | fzf --multi
fi
diff --git a/flog b/flog
@@ -1,14 +1,14 @@
#!/usr/bin/env bash
#
-# git log interactive viewer
+# Desc: git log interactive viewer
#
# @params
-# Globals
+# Globals:
# ${mydir}: current dir of the script
# ${selected_action}: action to take on the selected commit
# ${selected_commit}: user selected commit
# ${confirm}: confirm status of user
-# Arguments
+# Arguments:
# -h|--help: display help message
# -r|--revert: revert the selected commit
# -R|--reset: reset HEAD back to the selected commit
@@ -18,7 +18,7 @@
set -ef
-mydir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
+mydir="$(dirname -- "$(readlink -f -- "${BASH_SOURCE[0]}")")"
source "${mydir}"/fgit_helper.sh
usage() {
@@ -59,7 +59,7 @@ draw_menu() {
menu="${menu}checkout: checkout the selected commit\n"
menu="${menu}exit: quit flog"
message=$(
- git \
+ git \
log --format=%B -n 1 "${selected_commit}"
)
header="commit ${selected_commit}: ${message}"
@@ -79,11 +79,11 @@ confirm=""
while [[ "$#" -gt 0 ]]; do
case "$1" in
- -r|--revert) selected_action="revert" shift ;;
- -R|--reset) selected_action="reset" shift ;;
- -e|--edit) selected_action="edit" shift ;;
- -c|--checkout) selected_action="checkout" shift ;;
- -y|--yes) confirm='y' shift ;;
+ -r|--revert) selected_action="revert"; shift ;;
+ -R|--reset) selected_action="reset"; shift ;;
+ -e|--edit) selected_action="edit"; shift ;;
+ -c|--checkout) selected_action="checkout"; shift ;;
+ -y|--yes) confirm='y'; shift ;;
-h|--help) usage && exit 0 ;;
*) echo "Invalid option: $1" >&2 && usage && exit 1 ;;
esac
diff --git a/freset b/freset
@@ -1,17 +1,16 @@
#!/usr/bin/env bash
#
-# unstage the selected staged file
-# or reset the commit to certain point
+# Desc: unstage selected staged file || reset the commit to certain point
#
# @params
-# Globals
+# Globals:
# ${mydir}: current directory of the script
# ${reset_type}: reset type, modified files or commit
# ${reset_option}: git reset flag, --mixed | --soft | --hard
# ${selected_files}: selected file to reset
# ${selected_commit}: selected commit to reset
# ${confirm}: confirmation status of the user
-# Arguments
+# Arguments:
# -h|--help: show help message and quit
# -c|--commit: reset commit
# -S|--soft: use --soft flag
@@ -20,7 +19,7 @@
set -ef
-mydir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
+mydir="$(dirname -- "$(readlink -f -- "${BASH_SOURCE[0]}")")"
source "${mydir}"/fgit_helper.sh
usage() {
@@ -41,16 +40,16 @@ Optional arguments:
reset_option="--mixed"
reset_type="modified"
-typeset -a selected_files=()
+typeset -a selected_files && selected_files=()
confirm=""
selected_commit=""
while [[ "$#" -gt 0 ]]; do
case "$1" in
- -c|--commit) reset_type="commit" shift ;;
- -S|--soft) reset_option="--soft" shift ;;
- -H|--hard) reset_option="--hard" shift ;;
- -y|--yes) confirm='y' shift ;;
+ -c|--commit) reset_type="commit"; shift ;;
+ -S|--soft) reset_option="--soft"; shift ;;
+ -H|--hard) reset_option="--hard"; shift ;;
+ -y|--yes) confirm='y'; shift ;;
-h|--help) usage && exit 0 ;;
*) echo "Invalid option: $1" >&2 && usage && exit 1 ;;
esac
diff --git a/fstash b/fstash
@@ -1,18 +1,23 @@
#!/usr/bin/env bash
#
-# stash operation using fzf
+# Desc: stash operation using fzf
#
# @params
-# Globals
+# Globals:
# ${mydir}: current dir of the script, source purpose
# ${stash_command}: stash command, pop, apply or file/delete to stash file or delete stash
# ${selected_files}: selected files to stash
# ${selected_stash}: selected stash to apply
# ${confirm}: user confirm status
+# Arguments:
+# -h|--help: show help message
+# -s|--select: select individual files and stash
+# -d|--delete: delete selected stash
+# -p|--pop: use pop instead of apply on the selected stash
set -ef
-mydir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
+mydir="$(dirname -- "$(readlink -f -- "${BASH_SOURCE[0]}")")"
source "${mydir}"/fgit_helper.sh
usage() {
@@ -30,16 +35,16 @@ Optional arguments:
}
stash_command="apply"
-typeset -a selected_files=()
+typeset -a selected_files && selected_files=()
selected_stash=""
confirm=""
while [[ "$#" -gt 0 ]]; do
case "$1" in
- -p|--pop) stash_command="pop" shift ;;
- -s|--select) stash_command="select" shift ;;
- -d|--delete) stash_command="delete" shift ;;
- -y|--yes) confirm="y" shift ;;
+ -p|--pop) stash_command="pop"; shift ;;
+ -s|--select) stash_command="select"; shift ;;
+ -d|--delete) stash_command="delete"; shift ;;
+ -y|--yes) confirm="y"; shift ;;
-h|--help) usage && exit 0 ;;
*) echo "Invalid option: $1" >&2 && usage && exit 1 ;;
esac
diff --git a/fstat b/fstat
@@ -1,10 +1,9 @@
#!/usr/bin/env bash
#
-# interactive git status menu
-# toggle stage and unstage
+# Desc: interactive git status menu; toggle stage and unstage
#
# @params
-# Globals
+# Globals:
# ${mydir}: current directory of where the script is running
# ${selected_files}: raw selected file (with current git status prepend)
# ${selected_filenames}: bash array of names for the selected_files
@@ -13,6 +12,7 @@
set -ef
mydir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
+# mydir="$(dirname -- "$(readlink -f -- "${BASH_SOURCE[0]}")")"
source "${mydir}"/fgit_helper.sh
usage() {
@@ -32,12 +32,12 @@ while [[ "$#" -gt 0 ]]; do
esac
done
-typeset -a mod_files=()
+typeset -a mod_files && mod_files=()
while :; do
# reset all variable and arrays for each loop
- typeset -a selected_files=()
- typeset -a selected_filenames=()
+ typeset -a selected_files && selected_files=()
+ typeset -a selected_filenames && selected_filenames=()
stage_file=""
while IFS= read -r line; do
@@ -65,7 +65,7 @@ while :; do
mod_files+=("${line}")
done < <(
printf '%s\n' "${selected_files[@]}" \
- | awk -v home="${GTREE}" '{
+ | awk -v home="${FZFGIT_TREE}" '{
$1=""
gsub(/^[ \t]/, "", $0)
gsub(/"/, "", $0)
diff --git a/funtrack b/funtrack
@@ -1,9 +1,9 @@
#!/usr/bin/env bash
#
-# untrack selected files
+# Desc: untrack selected files
#
# @params
-# Globals
+# Globals:
# ${mydir}: current dir of the script
# ${track_type}: determine method to use for untrack, possible values: untrack, temp, resume
# ${confirm}: user confirm status
@@ -11,7 +11,7 @@
set -ef
-mydir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
+mydir="$(dirname -- "$(readlink -f -- "${BASH_SOURCE[0]}")")"
source "${mydir}"/fgit_helper.sh
usage() {
@@ -36,14 +36,14 @@ Optional arguments:
}
track_type="untrack"
-typeset -a selected_files=()
+typeset -a selected_files && selected_files=()
confirm=""
while [[ "$#" -gt 0 ]]; do
case "$1" in
- -t|--temp) track_type="temp" shift ;;
- -r|--resume) track_type="retrack" shift ;;
- -y|--yes) confirm='y' shift ;;
+ -t|--temp) track_type="temp"; shift ;;
+ -r|--resume) track_type="retrack"; shift ;;
+ -y|--yes) confirm='y'; shift ;;
-h|--help) usage && exit 0 ;;
*) echo "Invalid option: $1" >&2 && usage && exit 1 ;;
esac
diff --git a/fzfgit.plugin.zsh b/fzfgit.plugin.zsh
@@ -0,0 +1,185 @@
+0="${${ZERO:-${0:#$ZSH_ARGZERO}}:-${(%):-%N}}"
+0="${${(M)0:#/*}:-$PWD/$0}"
+_path="${0:h}"
+
+if [[ -z "${path[(r)$_path]}" ]]; then
+ path+=( "${_path}" )
+fi
+
+__fzfgit_completion() {
+ local context state state_descr line ret curcontext
+ local -A opt_args
+ ret=1
+ curcontext="${curcontext}"
+
+ _arguments -C \
+ '(- : *)'{-h,--help}'[show help information]' \
+ '(- : *)'{-v,--version}'[display fzfgit version]' \
+ '(-g --git)'{-g,--git}'[use fzfgit as a generic fuzzy git tool and operate in current git directory]' \
+ '1:cmds:->cmds' \
+ '*::options:->options' \
+ && ret=0
+
+ case "${state}" in
+ cmds)
+ local subcommands
+ subcommands=(
+ 'fadd:stage files'
+ 'fbackup:backup files'
+ 'fcheckout:checkout file/branch/commit'
+ 'fedit:edit files'
+ 'fzgrep:grep within tracked files'
+ 'flog:interactive log viewer'
+ 'freset:reset files/commit'
+ 'fstash:stage management'
+ 'fstat:toggle stage/unstage of files'
+ 'funtrack:untrack files'
+ 'fupgrade:update fzfgit'
+ )
+ _describe 'command' subcommands \
+ && ret=0
+ ;;
+ options)
+ case "${line[1]}" in
+ fadd)
+ _arguments \
+ '(- : *)'{-h,--help}'[show help information]' \
+ '(-f --file -d --dir -h --help)'{-f,--file}'[select files from PWD and stage]' \
+ '(-d --dir -f --file -h --help)'{-d,--dir}'[select directory from PWD and stage]' \
+ && ret=0
+ ;;
+ fbackup)
+ _arguments \
+ '(- : *)'{-h,--help}'[show help information]' \
+ '(-s --select -p --path -h --help)'{-s,--select}'[select tracked files to backup]' \
+ '(-p --path -s --select -h --help)'{-p,--path}'[sepcify path of files to backup]:filename:_files' \
+ '(-m --move -h --help)'{-m,--move}'[use mv cmd instead of cp cmd]' \
+ && ret=0
+ ;;
+ fcheckout)
+ _arguments \
+ '(- : *)'{-h,--help}'[show help information]' \
+ '(-s --select -b --branch -c --commit -h --help)'{-s,--select}'[select files and then checkout them in selected commits]' \
+ '(-b --branch -s --select -c --commit -h --help)'{-b,--branch}'[checkout branch]' \
+ '(-c --commit -b --branch -s --select -h --help)'{-c,--commit}'[checkout commit]' \
+ '(-y --yes -h --help)'{-y,--yes}'[acknowledge all actions and skip confirmation]' \
+ && ret=0
+ ;;
+ fedit)
+ _arguments \
+ '(- : *)'{-h,--help}'[show help information]' \
+ '(-m --modified -c --commit -h --help)'{-m,--modified}'[edit modified files]' \
+ '(-c --commit -m --modified -h --help)'{-c,--commit}'[edit commits]' \
+ && ret=0
+ ;;
+ fzgrep)
+ _arguments \
+ '(- : *)'{-h,--help}'[show help information]' \
+ '(-f --full -c --col)'{-f,--full}'[include all columns during fzf search, as if using "--col 1"]' \
+ '(-f --full -c --col)'{-c,--col}'[specify a column number to start searching in fzf]: :->cols' \
+ && ret=0
+ ;;
+ flog)
+ _arguments \
+ '(- : *)'{-h,--help}'[show help information]' \
+ '(-r --revert -R --reset -e --edit -c --checkout -h --help)'{-r,--revert}'[revert the selected commit and skip action menu]' \
+ '(-r --revert -R --reset -e --edit -c --checkout -h --help)'{-R,--reset}'[reset the selected commit and skip action menu]' \
+ '(-r --revert -R --reset -e --edit -c --checkout -h --help)'{-e,--edit}'[edit the selected commit and skip action menu]' \
+ '(-r --revert -R --reset -e --edit -c --checkout -h --help)'{-c,--checkout}'[checkout the selected commit and skip action menu]' \
+ '(-y --yes -h --help)'{-y,--yes}'[acknowledge all actions and skip confirmation]' \
+ && ret=0
+ ;;
+ freset)
+ _arguments \
+ '(- : *)'{-h,--help}'[show help information]' \
+ '(-c --commit -h --help)'{-c,--commit}'[reset HEAD to certain commit]' \
+ '(-S --soft -H --hard -h --help)'{-S,--soft}'[reset commit using --soft flag]' \
+ '(-H --hard -S --soft -h --help)'{-H,--hard}'[reset commit using --hard flag]' \
+ '(-y --yes -h --help)'{-y,--yes}'[acknowledge all actions and skip confirmation]' \
+ && ret=0
+ ;;
+ fstash)
+ _arguments \
+ '(- : *)'{-h,--help}'[show help information]' \
+ '(-s --select -d --delete -p --pop -h --help)'{-s,--select}'[list modified files and stash the selected files]' \
+ '(-s --select -d --delete -p --pop -h --help)'{-d,--delete}'[list stash and delete the selected stash]' \
+ '(-s --select -d --delete -p --pop -h --help)'{-p,--pop}'[use "stash pop" instead of "stash apply"]' \
+ && ret=0
+ ;;
+ fstat)
+ _arguments \
+ '(- : *)'{-h,--help}'[show help information]' \
+ && ret=0
+ ;;
+ funtrack)
+ _arguments \
+ '(- : *)'{-h,--help}'[show help information]' \
+ '(-t --temp -r --resume -h --help)'{-t,--temp}'[temporarily ignore changes of the selected files]' \
+ '(-t --temp -r --resume -h --help)'{-r,--resume}'[resume tracking changes of the selected files]' \
+ '(-y --yes -h --help)'{-y,--yes}'[acknowledge all actions and skip confirmation]' \
+ && ret=0
+ ;;
+ fupgrade)
+ _arguments \
+ '(- : *)'{-h,--help}'[show help information]' \
+ && ret=0
+ ;;
+ *)
+ _normal
+ ;;
+ esac
+ ;;
+ esac
+
+ return "${ret}";
+}
+
+_fzfgit_completion_cmd() {
+ local compdef_name="fzfgit"
+ compdef __fzfgit_completion "${compdef_name}"
+}
+
+_fzfgit_completion_git() {
+ local compdef_name="fzfgit"
+ compdef "${compdef_name}"=git
+}
+
+_widget_fzfgit_fadd() { fzfgit fadd; }
+_widget_fzfgit_fedit() { fzfgit fedit; }
+_widget_fzfgit_fcheckout() { fzfgit fcheckout; }
+_widget_fzfgit_freset() { fzfgit freset; }
+_widget_fzfgit_flog() { fzfgit flog; }
+_widget_fzfgit_fzgrep() { fzfgit fzgrep; }
+_widget_fzfgit_fstat() { fzfgit fstat; }
+
+zle -N fzfgit-fadd _widget_fzfgit_fadd
+zle -N fzfgit-fedit _widget_fzfgit_fedit
+zle -N fzfgit-fcheckout _widget_fzfgit_fcheckout
+zle -N fzfgit-freset _widget_fzfgit_reset
+zle -N fzfgit-flog _widget_fzfgit_flog
+zle -N fzfgit-fzgrep _widget_fzfgit_fzgrep
+zle -N fzfgit-fstat _widget_fzfgit_fstat
+
+_widget_git_transform_fzfgit() {
+ local fzfgit_cmd new_cmd
+ fzfgit_cmd=$(alias | grep fzfgit | cut -d'=' -f1 | head -n 1)
+ [[ -z "${fzfgit_cmd}" ]] && fzfgit_cmd="fzfgit"
+ fzfgit_cmd="${fzfgit_cmd} -g"
+ BUFFER=$(echo "$BUFFER" \
+ | awk -v fzfgit="${fzfgit_cmd}" '{
+ if ($1 == "git") {
+ $1=fzfgit
+ if ($2 ~ /(log|add|reset|checkout|status|stash|grep|untrack|stat)/) {
+ if ($2 == "status"){
+ $2="stat"
+ }
+ $2="f"$2
+ }
+ }
+ print $0
+ }'
+ )
+ zle end-of-line
+}
+
+zle -N fzfgit-transform _widget_git_transform_fzfgit
diff --git a/preview.sh b/preview.sh
@@ -1,11 +1,10 @@
#!/usr/bin/env bash
#
-# dynamic preview command for git
-# borrowed and modified from fzf.vim
-# can export G_PREVIEW='bat -Pf --style auto'
+# Desc: dynamic preview command; borrowed & modified from fzf.vim
+# can export FZFGIT_PREVIEW='bat -Pf --style auto'
#
# @params
-# Globals
+# Globals:
# reverse_seq: reverse highlight sequence for easier print
# reset_seq: reset highlight sequence for eaiser print
# input_option: the array containing informaiton from cmd argument
@@ -15,10 +14,10 @@
# preview_first: the first line number of the file to be printed
# preview_last: the last line number of the file to be printed
# file_mime: mime of the file, used to display information for binary file
-# Arguments
+# Arguments:
# $1: The filename and line info to be previewed
# Format: filepath[:lineno][:ignored]
-# Example
+# Example:
# preview "$HOME/.bashrc:15"
#######################################
@@ -46,14 +45,14 @@ display_preview() {
preview_cmd=${preview_cmd//{\}/$(printf %q "${preview_file}")}
if [[ -z "${preview_first}" ]] || [[ -z "${preview_center}" ]] || [[ -z "${preview_last}" ]]; then
- if [[ -z "${G_PREVIEW}" ]] && command -v bat > /dev/null; then
+ if [[ -z "${FZFGIT_PREVIEW}" ]] && command -v bat > /dev/null; then
bat --color=always --pager=never "${preview_file}"
exit $?
fi
eval "${preview_cmd}" 2> /dev/null
exit 0
else
- if [ -z "${G_PREVIEW}" ] && command -v bat > /dev/null; then
+ if [ -z "${FZFGIT_PREVIEW}" ] && command -v bat > /dev/null; then
bat --color=always --pager=never \
--line-range="${preview_first}":"${preview_last}" --highlight-line="${preview_center}" "${preview_file}"
exit $?