Merge pull request #21 from kazhala/dev

pull/25/head
Kevin Zhuang 4 years ago committed by GitHub
commit 42fe532769
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -2,6 +2,9 @@ name: CI
on: [push, pull_request]
env:
COLUMNS: 80
defaults:
run:
shell: bash

@ -2,6 +2,31 @@
Noteble changes are documentated in this file.
## dev
### Added
- hide preview window on small window (when \$COLUMNS less than 80)
- If using default keybinds, use `alt-t` to re-open the preview
- verbose flag completion for bash
- `dotbare` can now be used as a generic fuzzy git tool, using `-g` or `--git flag`
- Sort of like a replacement for `forgit`, bascially just dynamiclly switching
`DOTBARE_DIR` and `DOTBARE_TREE` to the current git directory.
- Seems kind of wierd to make `dotbare` also a fuzzy git client, but since it's literally
like a few lines of changes, I figured why not ..
- options for `fgrep` to configure search behavior in fzf
- `-c, --col`: pass in argument to specify which column to start searching in fzf (`dotbare fgrep --col 2`), by default `fgrep` starts the search from column 3, column 1 is the file name, column2 is the line number and starting from column 3 is the actual content.
- `-f, --full`: configure the fzf search to include all columns, same as using `dotbare fgrep --col 1` which includes the file name, line number and the actual content.
- dedicated completion file to use for package installation
### CHANGED
- update the fzf header to make more sense, some wording issues
### Fixed
- bash completion raising unexpected git error
## 1.2.3 (17/07/2020)
### Added
@ -10,11 +35,11 @@ Noteble changes are documentated in this file.
- zsh completion for git commands
- bash completion for git commands
- fgrep: grep words within tracked dotfiles and edit them through EDITOR
More info is documented in wiki.
- More info is documented in wiki
### Changed
- Changed how help messages are printed to reduce some calls
- adjusted how help messages are printed to reduce some calls
### Fixed
@ -24,20 +49,20 @@ Noteble changes are documentated in this file.
### Fixed
- Fixed the dotbare crash when migrating a dotfile repo with over 100 files [#12](https://github.com/kazhala/dotbare/issues/12)
- Fixed dotbare fbackup crash when using cp command on symlink
- dotbare crash when migrating a dotfile repo with over 100 files [#12](https://github.com/kazhala/dotbare/issues/12)
- dotbare fbackup crash when using cp command on symlink
## 1.2.1 (09/07/2020)
### Added
- dynamic preview function, detect bats, hightlight etc to provide syntax hightlighting when previewing files.
- Custom preview ENV variable (DOTBARE_PREVIEW)
Note: has to be this format `export DOTBARE_PREVIEW='cat -n {}'`, the `{}` is
used in preview functions to subsitute for the filepath.
- Added support for fancy diff tools like "diff-so-fancy" or "delta"
This is optional, only takes effect if installed and set as `git config core.pager`
Also configurable through DOTBARE_DIFF_PAGER, these are documentated in the README.
- custom preview ENV variable (DOTBARE_PREVIEW)
- Note: has to be this format `export DOTBARE_PREVIEW='cat -n {}'`, the `{}` is
used in preview functions to subsitute for the filepath.
- support for fancy diff tools like "diff-so-fancy" or "delta"
- This is optional, only takes effect if installed and set as `git config core.pager`
- Also configurable through DOTBARE_DIFF_PAGER, these are documentated in the README.
## 1.2.0 (01/07/2020)
@ -45,10 +70,10 @@ Noteble changes are documentated in this file.
- `dotbare` now accept verbose type of argument e.g. `dotbare fadd --file` `dotbare fcheckout --branch`.
More information please refer to each commands help manual
- Added support for handling files with spaces
- Improved unittest with mocking
- A more reliable `dotbare fupgrade` behavior
- Added version flag for `dotbare`, `dotbare --version` or `dotbare -v`
- support for handling files with spaces
- improved unittest with mocking
- more reliable `dotbare fupgrade` behavior
- version flag for `dotbare`, `dotbare --version` or `dotbare -v`
### Changed
@ -60,7 +85,7 @@ Noteble changes are documentated in this file.
### Removed
- Removed `-a` flag of `dotbare freset`. It's not working as intended because I misunderstand it, the intended
- removed `-a` flag of `dotbare freset`. It's not working as intended because I misunderstand it, the intended
behavior is actually achieved by `dotbare fcheckout -a`, use `dotbare fcheckout -a` instead.
(Edit: `dotbare fcheckout -a` is now `dotbare fcheckout -s` or `dotbare fcheckout --select`)
@ -68,20 +93,20 @@ Noteble changes are documentated in this file.
### Added
- Added zsh plugin [#4](https://github.com/kazhala/dotbare/pull/4)
- Added bash plugin
- Added drop-in functionality [#6](https://github.com/kazhala/dotbare/pull/6)
- zsh plugin [#4](https://github.com/kazhala/dotbare/pull/4)
- bash plugin
- drop-in functionality [#6](https://github.com/kazhala/dotbare/pull/6)
- User can now place custom fzf scripts into scripts folder
- Added bash completion capabilities [#7](https://github.com/kazhala/dotbare/pull/7)
- Added option to clone submodule [#8](https://github.com/kazhala/dotbare/issues/8)
- bash completion capabilities [#7](https://github.com/kazhala/dotbare/pull/7)
- option to clone submodule [#8](https://github.com/kazhala/dotbare/issues/8)
### Fixed
- Fixed ambiguous argument error [#3](https://github.com/kazhala/dotbare/pull/3)
- ambiguous argument error [#3](https://github.com/kazhala/dotbare/pull/3)
### Removed
- Removed global .gitignore manipulation during migration, not needed. Added .gitignore tips to README and
- removed global .gitignore manipulation during migration, not needed. Added .gitignore tips to README and
let user handle it
## 1.0.0 (20/05/2020)

@ -7,27 +7,21 @@
## Introduction
`dotbare` is a command line utility to help manage dotfiles. It wraps around git bare
repository and heavily utilises [fzf](https://github.com/junegunn/fzf) for an interactive experience.
It is inspired by [forgit](https://github.com/wfxr/forgit), a git wrapper using fzf.
`dotbare` uses a different implementation approach and focuses on managing and interacting with system dotfiles.
Don't worry about migration if you have a symlink/GNU stow setup, you can easily integrate `dotbare` with them.
Pros:
- No symlink
- Simple setup/remove
- Customizable
- Easy migration
- Flat learning curve
- Manage dotfiles anywhere in your system
- Integration with symlink/GNU stow setup
`dotbare` is a command line utility to help manage dotfiles and or as a generic fuzzy git client. As a dotfile management tool,
it wraps around git bare repository, query git information from it and display them through [fzf](https://github.com/junegunn/fzf) for an
interactive experience. It is originally inspired by [forgit](https://github.com/wfxr/forgit), a git wrapper using fzf.
`dotbare` uses a different implementation approach and focuses on managing and interacting with system dotfiles. Because
of the flexible implementation of `dotbare`, it can easily integrate with symlink/GNU stow setup or even as a generic
fuzzy git client to use in any git repository.
As a generic fuzzy git client (usign `--git` flag), `dotbare` dynamically determine the top level `.git` folder and process git information
and perform git operation in the current working tree.
You could find out how git bare repository could be used for managing dotfiles [here](https://www.atlassian.com/git/tutorials/dotfiles).
Or a [video](https://www.youtube.com/watch?v=tBoLDpTWVOM&t=288s) explanation that helped me to get started. If you are currently
using a symlink/GNU stow setup, checkout how to integrate `dotbare` with them [here](#migrating-from-a-generic-symlink-setup-or-gnu-stow).
Select and edit tracked dotfiles.
Select and edit dotfiles.
![fedit](https://user-images.githubusercontent.com/43941510/87669391-37f28180-c7b1-11ea-907d-3b26f363a279.png)
Stage and unstage dotfiles.
![fstat](https://user-images.githubusercontent.com/43941510/87669408-43de4380-c7b1-11ea-8a31-fc702eb69804.png)
@ -51,7 +45,8 @@ to another system as you will have to manually resolve all the git checkout issu
all the git information and display it through fzf. In addition, `dotbare` also comes with command line completion
that you could choose to either to complete `git` commands or `dotbare` commands.
`dotbare` also comes with the ability to integrate with GNU stow or any symlink set up as long as you are using git.
It is easy to migrate to any system with minimal set up required.
It is easy to migrate to any system with minimal set up required. In addition, with a simple flag `--git`, you can
now also use `dotbare` as a generic fuzzy git client to manage any git repository.
## Install
@ -405,7 +400,7 @@ All usage and commands are documented in **[wiki](https://github.com/kazhala/dot
## Changes
Latest changes are documented in CHANGELOG.md. View the upcoming changes in the [CHANGELOG](https://github.com/kazhala/dotbare/blob/dev/CHANGELOG.md) of dev branch.
Latest changes are documented in [CHANGELOG](https://github.com/kazhala/dotbare/blob/master/CHANGELOG.md).
## Testing

@ -4,6 +4,8 @@ env:
parameter-store:
LOGIN_PASSWORD: /dotbare/dockerpassword
LOGIN_USERNAME: /dotbare/dockerusername
exported-variables:
COLUMNS: 80
phases:
install:
@ -17,7 +19,7 @@ phases:
- 'echo $LOGIN_PASSWORD | docker login --username $LOGIN_USERNAME --password-stdin'
build:
commands:
- echo Checking script compliance
- echo Checking script compliance ...
- ./tests/shellcheck.sh
- echo Building docker url image ...
- docker image build --build-arg MIGRATE=url -t kazhala/dotbare:testurl -f tests/Dockerfile .
@ -28,8 +30,10 @@ phases:
- echo Running bats unittest ...
- docker container run -i --rm --name dotbare kazhala/dotbare:testbare
- echo Building docker image ...
- docker image build -t kazhala/dotbare:latest .
- DOTBARE_VERSION=$(./dotbare --version | awk -F ": v" '{print $2}')
- docker image build -t kazhala/dotbare:latest -t kazhala/fzfaws:$DOTBARE_VERSION .
post_build:
commands:
- echo Deploying docker image ...
- docker image push kazhala/dotbare:latest
- docker image push kazhala/dotbare:$DOTBARE_VERSION

@ -24,6 +24,7 @@ To see all dotbare specific COMMANDS, run dotbare without any arguments.
Optional arguments:
-h, --help\t\tshow this help message and exit.
-v, --version\t\tshow dotbare current version.
-g, --git\t\tuse dotbare as a generic fuzzy git tool and operate in current git directory.
Available commands:
All git commands are available, treat dotbare as git.
@ -41,12 +42,25 @@ Available commands:
fupgrade \t\tupdate dotbare to the latest master."
}
# if no argument, display all possible actions
if [[ "$#" -eq 0 ]]; then
find "${mydir}"/scripts/* -type f -print0 \
| xargs -I __ -0 basename __ \
function list_dotbare_commands() {
find "${mydir}"/scripts/* -type f -exec basename {} + \
| fzf --no-multi --header='Available commands' --preview="${mydir}/dotbare {} -h" \
| xargs -I __ "${mydir}"/dotbare __ -h
}
function execute_dotbare() {
[[ "$#" -eq 0 ]] \
&& list_dotbare_commands \
&& exit 0
if [[ -x "${mydir}/scripts/$1" ]]; then
exec "${mydir}/scripts/$1" "${@:2}"
fi
}
# if no argument, display all possible actions
if [[ "$#" -eq 0 ]]; then
list_dotbare_commands
exit 0
fi
@ -64,11 +78,28 @@ case "$1" in
echo "Current dotbare version: ${DOTBARE_VERSION}"
exit 0
;;
*)
if [[ -x "${mydir}/scripts/$1" ]]; then
exec "${mydir}/scripts/$1" "${@:2}"
-g|--git)
if git rev-parse --is-inside-work-tree &>/dev/null; then
DOTBARE_TREE=$(git rev-parse --show-toplevel)
DOTBARE_DIR="${DOTBARE_TREE}/.git"
shift
case "$1" in
fbackup|finit|fupgrade)
echo "dotbare $1 is not supported when using dotbare as a generic fuzzy git tool"
exit 1
;;
*)
execute_dotbare "$@"
;;
esac
else
echo "Not in a git directory"
exit 1
fi
;;
*)
execute_dotbare "$@"
;;
esac
git --git-dir="${DOTBARE_DIR}" --work-tree="${DOTBARE_TREE}" "$@"

@ -5,7 +5,7 @@ mydir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
__dotbare_completion()
{
local IFS=$'\n' subcommands curr prev options suggestions
local IFS=$'\n' subcommands curr prev options verbose_options suggestions
curr="${COMP_WORDS[$COMP_CWORD]}"
prev="${COMP_WORDS[$COMP_CWORD-1]}"
@ -20,7 +20,6 @@ __dotbare_completion()
}
}'
)
options=$(
"${mydir}"/dotbare -h \
| awk '{
@ -33,22 +32,92 @@ __dotbare_completion()
}
}'
)
if [[ "${curr}" == -* ]]; then
verbose_options=$("${mydir}"/dotbare -h | awk '$0 ~ /^ -.*/ {print $2}')
if [[ "${curr}" == --* ]]; then
suggestions=($(compgen -W "${verbose_options}" -- "${curr}"))
elif [[ "${curr}" == -* ]]; then
suggestions=($(compgen -W "${options}" -- "${curr}"))
else
suggestions=($(compgen -W "${subcommands}" -- "${curr}"))
fi
elif [[ "${COMP_WORDS[1]}" == "fbackup" && "${prev}" == "-p" ]]; then
elif [[ "${COMP_CWORD}" -eq 2 && "${prev}" == "-g" || "${prev}" == "--git" ]]; then
subcommands=$(
"${mydir}"/dotbare -h \
| awk '{
if ($0 ~ /^ f.*/) {
if ($0 ~ /^ f(backup|init|upgrade).*/) {
next
}
gsub(/^ /, "", $0)
gsub(/\t\t/, " ", $0)
print $0
}
}'
)
suggestions=($(compgen -W "${subcommands}" -- "${curr}"))
elif [[ "${COMP_WORDS[1]}" == "-g" || "${COMP_WORDS[1]}" == "--git" ]] && [[ "${COMP_CWORD}" -gt 2 ]]; then
if [[ "${curr}" == --* && "${prev}" != "-h" && "${prev}" != "--help" ]]; then
verbose_options=$(
"${mydir}"/dotbare "${COMP_WORDS[2]}" -h 2> /dev/null \
| awk '{
if ($0 ~ /^ -p PATH/) {
next
} else if ($0 ~ /^ -u URL/) {
next
} else if ($0 ~ /^ -*/) {
print $2
}
}'
)
suggestions=($(compgen -W "${verbose_options}" -- "${curr}"))
elif [[ "${prev}" != "-h" && "${prev}" != "--help" ]]; then
options=$(
"${mydir}"/dotbare "${COMP_WORDS[2]}" -h 2> /dev/null \
| awk '{
gsub(/,/, " ", $0)
if ($0 ~ /^ -p PATH/) {
next
} else if ($0 ~ /^ -u URL/) {
next
} else if ($0 ~ /^ -*/) {
gsub(/^ /, "", $0)
gsub(/\t/, " ", $0)
$2=""
print $0
}
}'
)
suggestions=($(compgen -W "${options}" -- "${curr}"))
else
return
fi
elif [[ "${COMP_WORDS[1]}" == "fbackup" ]] && [[ "${prev}" == "-p" || "${prev}" == "--path" ]]; then
COMPREPLY=($(compgen -d -- "${curr}"))
return
elif [[ "${COMP_WORDS[1]}" == "finit" && "${prev}" == "-u" ]]; then
elif [[ "${COMP_WORDS[1]}" == "finit" ]] && [[ "${prev}" == "-u" || "${prev}" == "--url" ]]; then
return
elif [[ "${curr}" == --* && "${prev}" != "-h" && "${prev}" != "--help" ]]; then
verbose_options=$(
"${mydir}"/dotbare "${COMP_WORDS[1]}" -h 2> /dev/null \
| awk '{
if ($0 ~ /^ -p PATH/) {
print "--path"
} else if ($0 ~ /^ -u URL/) {
print "--url"
} else if ($0 ~ /^ -c COL/) {
print "--col"
} else if ($0 ~ /^ -*/) {
print $2
}
}'
)
suggestions=($(compgen -W "${verbose_options}" -- "${curr}"))
elif [[ "${prev}" != "-h" && "${prev}" != "--help" ]]; then
options=$(
"${mydir}"/dotbare "${COMP_WORDS[1]}" -h \
"${mydir}"/dotbare "${COMP_WORDS[1]}" -h 2> /dev/null \
| awk '{
gsub(/,/, " ", $0)
if ($0 ~ /^ -p PATH/) {
@ -59,6 +128,10 @@ __dotbare_completion()
gsub(/^ -u URL --url URL/, "-u", $0)
gsub(/\t/, " ", $0)
print $0
} else if ($0 ~ /^ -c COL/) {
gsub(/^ -c COL --col COL/, "-c", $0)
gsub(/\t/, " ", $0)
print $0
} else if ($0 ~ /^ -*/) {
gsub(/^ /, "", $0)
gsub(/\t/, " ", $0)

@ -14,6 +14,7 @@ __dotbare_completion() {
_arguments -C \
'(- : *)'{-h,--help}'[show help information]' \
'(- : *)'{-v,--version}'[display dotbare version]' \
'(-g --git)'{-g,--git}'[use dotbare as a generic fuzzy git tool and operate in current git directory]' \
'1:cmds:->cmds' \
'*::options:->options' \
&& ret=0
@ -74,6 +75,8 @@ __dotbare_completion() {
fgrep)
_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
;;
finit)

@ -195,18 +195,20 @@ function get_stash() {
# all tracked files in the bare repo.
# Arguments:
# $1: the help message to display in header
# $2: if exists, don't do multi select, only allow single selection
# $2: the fzf delimiter to start searching, default is 3
# $3: if exists, don't do multi select, only allow single selection
# Outputs:
# the selected file name with it's line number and line, seperated by ":"
# e.g. .bash_profile:1:echo hello
#######################################
function grep_lines() {
local header="${1:-select lines to edit}"
function grep_words() {
local header="${1:-select matches to edit}"
local delimiter="${2:-3}"
set_fzf_multi "$2"
cd "${DOTBARE_TREE}" || exit
git --git-dir="${DOTBARE_DIR}" --work-tree="${DOTBARE_TREE}" \
grep --line-number -- . \
| fzf --delimiter : --nth 3.. --header="${header}" \
| fzf --delimiter : --nth "${delimiter}".. --header="${header}" \
--preview "${mydir}/../helper/preview.sh ${DOTBARE_TREE}/{}" \
| awk -F ":" -v home="${DOTBARE_TREE}" '{
print home "/" $1 ":" $2

@ -15,7 +15,7 @@ function search_file() {
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 tree --version &>/dev/null; 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 {}"
else
find . -maxdepth 1 -type d | awk '{if ($0 != "." && $0 != "./.git"){gsub(/^\.\//, "", $0);print $0}}' | fzf --multi

@ -21,7 +21,7 @@ export DOTBARE_DIFF_PAGER="${DOTBARE_DIFF_PAGER:-$(git config core.pager || echo
export EDITOR="${EDITOR:-vim}"
if [[ -z "${DOTBARE_KEY}" ]]; then
export DOTBARE_KEY="
DOTBARE_KEY="
--bind=alt-a:toggle-all
--bind=alt-w:jump
--bind=alt-0:top
@ -32,7 +32,7 @@ fi
[[ -z "${FZF_DEFAULT_OPTS}" ]] && export FZF_DEFAULT_OPTS='--cycle'
export FZF_DEFAULT_OPTS="
FZF_DEFAULT_OPTS="
$FZF_DEFAULT_OPTS
--ansi
--cycle
@ -41,6 +41,11 @@ export FZF_DEFAULT_OPTS="
$DOTBARE_KEY
"
[[ -z "${COLUMNS}" ]] \
&& COLUMNS=$(stty size < /dev/tty | cut -d' ' -f2)
[[ "${COLUMNS}" -lt 80 ]] \
&& FZF_DEFAULT_OPTS="$FZF_DEFAULT_OPTS --preview-window=hidden"
#######################################
# determine to set multi selection or not
# Globals:

@ -0,0 +1,153 @@
# shellcheck disable=SC2207
_dotbare_completion()
{
local IFS=$'\n' subcommands curr prev options verbose_options suggestions
curr="${COMP_WORDS[$COMP_CWORD]}"
prev="${COMP_WORDS[$COMP_CWORD-1]}"
if [[ "$COMP_CWORD" -eq "1" ]]; then
subcommands=$(
dotbare -h \
| awk '{
if ($0 ~ /^ f.*/) {
gsub(/^ /, "", $0)
gsub(/\t\t/, " ", $0)
print $0
}
}'
)
options=$(
dotbare -h \
| awk '{
if ($0 ~ /^ -.*/) {
gsub(/,/, " ", $0)
gsub(/^ /, "", $0)
gsub(/\t\t/, " ", $0)
$2=""
print $0
}
}'
)
verbose_options=$(dotbare -h | awk '$0 ~ /^ -.*/ {print $2}')
if [[ "${curr}" == --* ]]; then
suggestions=($(compgen -W "${verbose_options}" -- "${curr}"))
elif [[ "${curr}" == -* ]]; then
suggestions=($(compgen -W "${options}" -- "${curr}"))
else
suggestions=($(compgen -W "${subcommands}" -- "${curr}"))
fi
elif [[ "${COMP_CWORD}" -eq 2 && "${prev}" == "-g" || "${prev}" == "--git" ]]; then
subcommands=$(
dotbare -h \
| awk '{
if ($0 ~ /^ f.*/) {
if ($0 ~ /^ f(backup|init|upgrade).*/) {
next
}
gsub(/^ /, "", $0)
gsub(/\t\t/, " ", $0)
print $0
}
}'
)
suggestions=($(compgen -W "${subcommands}" -- "${curr}"))
elif [[ "${COMP_WORDS[1]}" == "-g" || "${COMP_WORDS[1]}" == "--git" ]] && [[ "${COMP_CWORD}" -gt 2 ]]; then
if [[ "${curr}" == --* && "${prev}" != "-h" && "${prev}" != "--help" ]]; then
verbose_options=$(
dotbare "${COMP_WORDS[2]}" -h 2> /dev/null \
| awk '{
if ($0 ~ /^ -p PATH/) {
next
} else if ($0 ~ /^ -u URL/) {
next
} else if ($0 ~ /^ -*/) {
print $2
}
}'
)
suggestions=($(compgen -W "${verbose_options}" -- "${curr}"))
elif [[ "${prev}" != "-h" && "${prev}" != "--help" ]]; then
options=$(
dotbare "${COMP_WORDS[2]}" -h 2> /dev/null \
| awk '{
gsub(/,/, " ", $0)
if ($0 ~ /^ -p PATH/) {
next
} else if ($0 ~ /^ -u URL/) {
next
} else if ($0 ~ /^ -*/) {
gsub(/^ /, "", $0)
gsub(/\t/, " ", $0)
$2=""
print $0
}
}'
)
suggestions=($(compgen -W "${options}" -- "${curr}"))
else
return
fi
elif [[ "${COMP_WORDS[1]}" == "fbackup" ]] && [[ "${prev}" == "-p" || "${prev}" == "--path" ]]; then
COMPREPLY=($(compgen -d -- "${curr}"))
return
elif [[ "${COMP_WORDS[1]}" == "finit" ]] && [[ "${prev}" == "-u" || "${prev}" == "--url" ]]; then
return
elif [[ "${curr}" == --* && "${prev}" != "-h" && "${prev}" != "--help" ]]; then
verbose_options=$(
dotbare "${COMP_WORDS[1]}" -h 2> /dev/null \
| awk '{
if ($0 ~ /^ -p PATH/) {
print "--path"
} else if ($0 ~ /^ -u URL/) {
print "--url"
} else if ($0 ~ /^ -c COL/) {
print "--col"
} else if ($0 ~ /^ -*/) {
print $2
}
}'
)
suggestions=($(compgen -W "${verbose_options}" -- "${curr}"))
elif [[ "${prev}" != "-h" && "${prev}" != "--help" ]]; then
options=$(
dotbare "${COMP_WORDS[1]}" -h 2> /dev/null \
| awk '{
gsub(/,/, " ", $0)
if ($0 ~ /^ -p PATH/) {
gsub(/^ -p PATH --path PATH/, "-p", $0)
gsub(/\t/, " ", $0)
print $0
} else if ($0 ~ /^ -u URL/) {
gsub(/^ -u URL --url URL/, "-u", $0)
gsub(/\t/, " ", $0)
print $0
} else if ($0 ~ /^ -c COL/) {
gsub(/^ -c COL --col COL/, "-c", $0)
gsub(/\t/, " ", $0)
print $0
} else if ($0 ~ /^ -*/) {
gsub(/^ /, "", $0)
gsub(/\t/, " ", $0)
$2=""
print $0
}
}'
)
suggestions=($(compgen -W "${options}" -- "${curr}"))
fi
if [[ "${#suggestions[*]}" -eq 1 ]]; then
COMPREPLY=("${suggestions[@]%% *}")
else
for i in "${!suggestions[@]}"; do
suggestions[$i]="$(printf '%*s' "-$COLUMNS" "${suggestions[$i]}")"
done
COMPREPLY=("${suggestions[@]}")
fi
}
complete -F _dotbare_completion dotbare

@ -0,0 +1,137 @@
#compdef dotbare
_dotbare() {
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 dotbare version]' \
'(-g --git)'{-g,--git}'[use dotbare 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'
'fgrep:grep within tracked files'
'finit:init/migrate dotbare'
'flog:interactive log viewer'
'freset:reset files/commit'
'fstash:stage management'
'fstat:toggle stage/unstage of files'
'funtrack:untrack files'
'fupgrade:update dotbare'
)
_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
;;
fgrep)
_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
;;
finit)
_arguments \
'(- : *)'{-h,--help}'[show help information]' \
'(-u --url -h --help)'{-u,--url}'[migrate remote dotfiles to current system]: :->url' \
'(-s --submodule -h --help)'{-s,--submodule}'[clone submodules during migration]' \
'(-y --yes -h --help)'{-y,--yes}'[acknowledge all actions and skip confirmation]' \
&& 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
;;
esac
;;
esac
return "${ret}";
}
_dotbare "$@"

@ -0,0 +1,4 @@
#!/usr/bin/env bash
SCRIPT_DIR=/opt/dotbare
${SCRIPT_DIR}/dotbare "$@"

@ -0,0 +1,4 @@
#!/usr/bin/env bash
SCRIPT_DIR=/usr/local/Cellar/dotbare/1.3.0
${SCRIPT_DIR}/dotbare "$@"

@ -92,7 +92,7 @@ elif [[ "${action_type}" == "modified" ]]; then
# checkout modified file back to version in HEAD
while IFS= read -r line; do
selected_files+=("${line}")
done < <(get_modified_file 'select a file to checkout version in HEAD')
done < <(get_modified_file 'select files to checkout version in HEAD')
[[ "${#selected_files[@]}" -eq 0 ]] && exit 1
[[ -z "${confirm}" ]] && echo "(dryrun) dotbare checkout --" "${selected_files[@]}"
[[ -z "${confirm}" ]] && confirm=$(get_confirmation "Confirm?")
@ -102,7 +102,7 @@ elif [[ "${action_type}" == "select" ]]; then
# checkout selected files to a selected commit
while IFS= read -r line; do
selected_files+=("${line}")
done < <(get_git_file 'select a file to checkout')
done < <(get_git_file 'select files to checkout to previous commit')
[[ "${#selected_files[@]}" -eq 0 ]] && exit 1
# continue select a commit and then checkout the file back to the selected commit
selected_commit=$(get_commit 'select the target commit' "${selected_files[@]}")

@ -60,7 +60,7 @@ while [[ "$#" -gt 0 ]]; do
done
if [[ "${edit_type}" == "commit" ]]; then
selected_commit=$(get_commit "select a commit to rename")
selected_commit=$(get_commit "select a commit to edit")
[[ -z "${selected_commit}" ]] && exit 1
git --git-dir="${DOTBARE_DIR}" --work-tree="${DOTBARE_TREE}" rebase -i "${selected_commit}"~
else
@ -68,9 +68,9 @@ else
selected_files+=("${line}")
done < <(
if [[ "${edit_type}" == "modified" ]]; then
get_modified_file "select modified files to edit"
get_modified_file "select files to edit"
else
get_git_file "select tracked files to edit"
get_git_file "select files to edit"
fi
)
[[ "${#selected_files[@]}" -eq 0 ]] && exit 1

@ -6,8 +6,11 @@
# Globals
# mydir: path to this current script
# selected_lines: selected lines to edit
# fzf_search_delimiter: the col to start searching in fzf
# Arguments
# -h|--help: show help message and exit
# -c COL| --col COL: use a different delimiter in fzf search
# -f|--full: include file name in fzf searching, as if using --col 1
set -e
set -f
@ -17,18 +20,32 @@ source "${mydir}"/../helper/set_variable.sh
source "${mydir}"/../helper/git_query.sh
function usage() {
echo -e "Usage: dotbare fgrep [-h] ...
echo -e "Usage: dotbare fgrep [-h] [-c] [-f] ...
Grep words within tracked files and select to edit them through fzf.
Grep words within tracked files and select to edit matches.
Default: start searching from 3rd column (excluding the file name during search).
Optional arguments:
-h, --help\t\tshow this help message and exit."
-h, --help\t\tshow this help message and exit.
-c COL, --col COL\tspecify the column number to start searching.
-f, --full\t\tinclude all column during search, as if using '--col 1'."
}
selected_lines=()
fzf_search_delimiter=3
while [[ "$#" -gt 0 ]]; do
case "$1" in
-c|--col)
fzf_search_delimiter="$2"
shift
shift
;;
-f|--full)
fzf_search_delimiter=1
shift
;;
-h|--help)
usage
exit 0
@ -52,7 +69,7 @@ while IFS= read -r line; do
selected_lines+=("${line}")
;;
esac
done < <(grep_lines)
done < <(grep_words "select matches to edit" "${fzf_search_delimiter}")
[[ "${#selected_lines[@]}" -eq 0 ]] && exit 1

@ -79,7 +79,7 @@ while [[ "$#" -gt 0 ]]; do
done
if [[ "${reset_type}" == "commit" ]]; then
selected_commit=$(get_commit "select the target commit for HEAD")
selected_commit=$(get_commit "select the target commit")
[[ -z "${selected_commit}" ]] && exit 1
[[ -z "${confirm}" ]] && confirm=$(get_confirmation "Reset HEAD to ${selected_commit} ${reset_option}?")
[[ "${confirm}" != 'y' ]] && exit 1

@ -34,6 +34,60 @@ no_argument() {
"${BATS_TEST_DIRNAME}"/../dotbare
}
generic_git_operation_block_finit() {
"${BATS_TEST_DIRNAME}"/../dotbare --git finit
}
generic_git_operation_block_fbackup() {
"${BATS_TEST_DIRNAME}"/../dotbare --git fbackup
}
generic_git_operation_block_fupgrade() {
"${BATS_TEST_DIRNAME}"/../dotbare --git fupgrade
}
generic_git_operation_init() {
export PATH="${BATS_TEST_DIRNAME}:$PATH"
"${BATS_TEST_DIRNAME}"/../dotbare --git init
}
generic_git_operation_fadd() {
export PATH="${BATS_TEST_DIRNAME}:$PATH"
"${BATS_TEST_DIRNAME}"/../dotbare --git fadd
}
@test "main generic git fadd" {
run generic_git_operation_fadd
[ "${status}" -eq 0 ]
[[ "${output}" =~ "--git-dir=rev-parse --show-toplevel/.git --work-tree=rev-parse --show-toplevel" ]]
[[ "${output}" =~ "fadd_stage_modified" ]]
}
@test "main generic git commands" {
run generic_git_operation_init
[ "${status}" -eq 0 ]
[[ "${output}" =~ "--git-dir=rev-parse --show-toplevel/.git --work-tree=rev-parse --show-toplevel" ]]
[[ "${output}" =~ "init" ]]
}
@test "main generic git flag block finit" {
run generic_git_operation_block_finit
[ "${status}" -eq 1 ]
[ "${output}" = "dotbare finit is not supported when using dotbare as a generic fuzzy git tool" ]
}
@test "main generic git flag block fbackup" {
run generic_git_operation_block_fbackup
[ "${status}" -eq 1 ]
[ "${output}" = "dotbare fbackup is not supported when using dotbare as a generic fuzzy git tool" ]
}
@test "main generic git flag block fupgrade" {
run generic_git_operation_block_fupgrade
[ "${status}" -eq 1 ]
[ "${output}" = "dotbare fupgrade is not supported when using dotbare as a generic fuzzy git tool" ]
}
@test "main help" {
run help
[ "${status}" -eq 0 ]

@ -14,10 +14,32 @@ edit_lines() {
bash "${BATS_TEST_DIRNAME}"/../dotbare fgrep
}
full_deli() {
export PATH="${BATS_TEST_DIRNAME}:$PATH"
export EDITOR="echo"
bash "${BATS_TEST_DIRNAME}"/../dotbare fgrep --full
}
option_deli() {
export PATH="${BATS_TEST_DIRNAME}:$PATH"
export EDITOR="echo"
bash "${BATS_TEST_DIRNAME}"/../dotbare fgrep --col 2
}
@test "fgrep option delimiter" {
run option_deli
[[ "${output}" =~ "--nth 2.. --header=select matches to edit" ]]
}
@test "fgrep full delimiter" {
run full_deli
[[ "${output}" =~ "--nth 1.. --header=select matches to edit" ]]
}
@test "fgrep help" {
run help
[ "${status}" -eq 0 ]
[ "${lines[0]}" = "Usage: dotbare fgrep [-h] ..." ]
[ "${lines[0]}" = "Usage: dotbare fgrep [-h] [-c] [-f] ..." ]
}
@test "fgrep invalid option" {
@ -28,5 +50,5 @@ edit_lines() {
@test "fgrep edit lines" {
run edit_lines
[[ "${output}" =~ "fgrep_lines" ]]
[[ "${output}" =~ "--nth 3.. --header=select matches to edit" ]]
}

@ -21,22 +21,22 @@ elif [[ "$*" =~ "--no-multi --header=select a branch to checkout" ]]; then
elif [[ "$*" =~ "--header=select a commit to checkout" ]] && [[ "$*" =~ "show --color" ]]; then
# dotbare fcheckout --c -- "./fcheckout.bats" @test "fcheckout commit"
echo "fcheckout_commit"
elif [[ "$*" =~ "--header=select a file to checkout version in HEAD" ]] && [[ "$*" =~ "diff HEAD --color=always" ]]; then
elif [[ "$*" =~ "--header=select files to checkout version in HEAD" ]] && [[ "$*" =~ "diff HEAD --color=always" ]]; then
# dotbare fcheckout -y -- "./fcheckout.bats" @test "fcheckout modified"
echo "-- fcheckout_modified"
elif [[ "$*" =~ '--header=select the target commit' ]] && [[ "$*" =~ "diff --color" ]]; then
# dotbare fcheckout --yes -s -- "./fcheckout.bats" @test "fcheckout select"
echo "fcheckout_select_commitdiff"
elif [[ "$*" =~ '--header=select a file to checkout' ]] && [[ "$*" =~ "preview.sh ${DOTBARE_TREE}/{}" ]]; then
elif [[ "$*" =~ '--header=select files to checkout' ]] && [[ "$*" =~ "preview.sh ${DOTBARE_TREE}/{}" ]]; then
# dotbare fcheckout --yes -s -- "./fcheckout.bats" @test "fcheckout select"
echo "fcheckout_select_gitfile"
elif [[ "$*" =~ "--header=select a commit to rename --no-multi" ]] && [[ "$*" =~ "show --color=always" ]]; then
elif [[ "$*" =~ "--header=select a commit to edit --no-multi" ]] && [[ "$*" =~ "show --color=always" ]]; then
# dotbare fedit --commit -- "./fedit.bats" @test "fedit edit commits"
echo "fedit_commits"
elif [[ "$*" =~ "--header=select tracked files to edit" ]]; then
elif [[ "$*" =~ "--header=select files to edit" ]]; then
# dotbare fedit -- "./fedit.bats" @test "fedit edit files"
echo "fedit_files"
elif [[ "$*" =~ '--header=select the target commit for HEAD --no-multi' ]] && [[ "$*" =~ "show --color" ]]; then
elif [[ "$*" =~ '--header=select the target commit --no-multi' ]] && [[ "$*" =~ "show --color" ]]; then
# dotbare freset --commit -y -- "./freset.bats" @test "freset select commit"
echo "freset_commit"
elif [[ "$*" =~ "--header=select files to unstage" ]] && [[ "$*" =~ "diff HEAD --color=always" ]]; then
@ -60,9 +60,6 @@ elif [[ "$*" =~ '--header=select stash to delete' ]] && [[ "$*" =~ "show -p __ -
elif [[ "$*" =~ '--header=select stash to apply' ]] && [[ "$*" =~ "show -p __ --color=always" ]]; then
# dotbare fstash -- "./fstash.bats" @test "fstash apply stash"
echo "fstash_apply"
elif [[ "$*" =~ '--delimiter : --nth 3..' ]]; then
# dotbare fgrep -- "./fgrep.bats" @test "fgrep edit lines"
echo "fgrep_lines"
else
echo "$@"
fi

@ -22,7 +22,9 @@ done < <(
shellcheck -e SC1090 "${scripts[@]}"
shellcheck -e SC1090 --shell=bash "dotbare.plugin.bash"
shellcheck --shell=bash "pkg/completion/bash/dotbare"
# \shellcheck does not have zsh support yet, hence using bash for now
shellcheck -e SC2034 --shell=bash "dotbare.plugin.zsh"
shellcheck -e SC2034 --shell=bash "pkg/completion/zsh/_dotbare"
exit $?

Loading…
Cancel
Save