Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added bash completion and fzf support #33

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,6 @@
*~

# DVM
darts
darts/
cache/
environments/
72 changes: 72 additions & 0 deletions scripts/bash-completion.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# Setup bash completion
_dvm_completions() {
local CURRENT_WORD="${COMP_WORDS[COMP_CWORD]}"

if [[ "$COMP_CWORD" == 0 ]]; then
COMPREPLY=($(compgen -W "dvm" -- "$CURRENT_WORD"))
return
fi
if [[ "$COMP_CWORD" == 1 ]]; then
COMPREPLY=($(compgen -W "alias implode install list listall upgrade use version" -- "$CURRENT_WORD"))
return
fi

case "${COMP_WORDS[1]}" in
# dvm alias
alias)
if [[ "$COMP_CWORD" == 2 ]]; then
COMPREPLY=($(compgen -W "create update delete list" -- "$CURRENT_WORD"))
fi
;;

# dvm implode
implode)
;;

# dvm install
install)
if [[ "$COMP_CWORD" == 2 ]]; then
COMPREPLY=($(compgen -W "$(dvm listall)" -- "$CURRENT_WORD"))
fi
;;

# dvm list
list)
;;

# dvm listall
listall)
if [[ "$COMP_CWORD" == 2 ]]; then
COMPREPLY=($(compgen -W "--dev --beta" -- "$CURRENT_WORD"))
fi
;;

# dvm upgrade
upgrade)
;;

# dvm use
use)
if [[ "$COMP_CWORD" == 2 ]]; then
COMPREPLY=($(compgen -W "$(dvm list) --default" -- "$CURRENT_WORD"))
fi
if [[ "$COMP_CWORD" == 3 ]]; then
if [[ "${COMP_WORDS[2]}" == '--default' ]]; then
COMPREPLY=($(compgen -W "$(dvm list)" -- "$CURRENT_WORD"))
else
COMPREPLY=($(compgen -W "--default" -- "$CURRENT_WORD"))
fi
fi
;;

# dvm version
version)
;;

# Others don't work!
*)
;;
esac
} && complete -F _dvm_completions dvm


107 changes: 76 additions & 31 deletions scripts/dvm
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ _dvm_usage() {
_dvm_create_dirs() {
mkdir -p "$DVM_ROOT/darts" > /dev/null 2>&1
mkdir -p "$DVM_ROOT/environments" > /dev/null 2>&1
mkdir -p "$DVM_ROOT/cache" > /dev/null 2>&1
}

# Removes $1 from PATH.
Expand All @@ -50,6 +51,22 @@ _dvm_doctor() {
echo " RedHat/Fedora: sudo dnf install unzip"
echo " OpenSUSE: sudo zypper install unzip"
echo " Arch/Manjaro: sudo pacman -S unzip"
echo " Mac OS: brew install unzip"
return 1
fi
}

_dvm_check_fzf() {
if [[ ! -x "$(which fzf)" ]]; then
echo "ERROR: dvm requires the 'fzf' tool, which was not found."
echo "To install fzf:"
echo " Debian/Ubuntu: sudo apt install fzf"
echo " RedHat/Fedora: sudo dnf install fzf"
echo " OpenSUSE: sudo zypper install fzf"
echo " Arch/Manjaro: sudo pacman -S fzf"
echo " Mac OS: brew install fzf"
echo ""
echo "See: https://github.com/junegunn/fzf#installation"
Comment on lines +54 to +69
Copy link
Owner

@cbracken cbracken Jun 15, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it'd be nice to use fzf if it's installed, but not require it. I actually hadn't heard of it till today, but it looks pretty nice!

That raises the question of how we advertise to the user that dvm makes use of fzf if available. Perhaps we could break out a dvm doctor command and have it list all dependencies (required and optional) with their install status. We'd show a scary red X if a required dependency is missing (currently just unzip), a yellow warning sign or something if fzf is missing, otherwise a green check.

That would entail breaking out _dvm_check_required_deps and _dvm_check_optional_deps functions and then pull the two together in _dvm_doctor. We'd then run _dvm_check_required_deps on line 497 below instead of _dvm_doctor.

What do you think?

Copy link
Contributor Author

@jonasfj jonasfj Jun 16, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We only call _dvm_check_fzf if we are about to use fzf.

So if you do: dart use <version> you'll never notice... If you do dart use it'll error saying that you need fzf.

I did consider improving the error message to say that dart use <version> works without fzf, but looking at how widely fzf is available I think most users will just install it.


In either case, we could explicitly support --help for all commands, but I think that's a separate issue :D

return 1
fi
}
Expand All @@ -58,7 +75,7 @@ _dvm_alias_usage() {
echo "usage: dvm alias <create|update|delete|list> [<args>]"
}

dvm_alias_list() {
_dvm_alias_list() {
find "$DVM_ROOT/darts" -maxdepth 1 ! -path "$DVM_ROOT/darts" -type l -exec basename "{}" \; | sort
}

Expand All @@ -85,7 +102,7 @@ _dvm_alias_set() {
fi
}

dvm_alias_update() {
_dvm_alias_update() {
if [[ $# < 2 || "$2" == "--path" && $# < 3 ]]; then
echo "usage: dvm alias update <alias> [--path] <version>"
return 1
Expand All @@ -100,7 +117,7 @@ dvm_alias_update() {
_dvm_alias_set "$@"
}

dvm_alias_create() {
_dvm_alias_create() {
if [[ $# < 2 || "$2" == "--path" && $# < 3 ]]; then
echo "usage: dvm alias create <alias> [--path] <version>"
return 1
Expand All @@ -118,7 +135,7 @@ dvm_alias_create() {
_dvm_alias_set "$@"
}

dvm_alias_delete() {
_dvm_alias_delete() {
if [[ $# < 1 ]]; then
echo "usage: dvm alias delete <alias>"
return 1
Expand All @@ -130,7 +147,7 @@ dvm_alias_delete() {
rm -f -- "$DVM_ROOT/darts/$1"
}

dvm_alias() {
_dvm_alias() {
if [[ $# < 1 ]]; then
_dvm_alias_usage
return 1
Expand All @@ -139,16 +156,16 @@ dvm_alias() {
shift
case $cmd in
create)
dvm_alias_create "$@"
_dvm_alias_create "$@"
;;
delete)
dvm_alias_delete "$@"
_dvm_alias_delete "$@"
;;
list)
dvm_alias_list "$@"
_dvm_alias_list "$@"
;;
update)
dvm_alias_update "$@"
_dvm_alias_update "$@"
;;
*)
_dvm_alias_usage
Expand All @@ -157,14 +174,27 @@ dvm_alias() {
esac
}

dvm_use() {
_dvm_use() {
if [[ $# < 1 ]]; then
_dvm_check_fzf || return 1

local version=$(_dvm_list | fzf --no-multi --tac)
local default=''
elif [[ $# == 1 ]] && [[ "$1" == "--default" ]]; then
_dvm_check_fzf || exit 1;

local version=$(_dvm_list | fzf --no-multi --tac)
local default="--default"
elif [[ $# == 2 ]] && [[ "$1" == "--default" ]]; then
local version="$2"
local default="$1"
elif [[ $# > 2 ]]; then
echo "usage: dvm use <version> [--default]"
return 1
else
local version="$1"
local default="$2"
fi

local version=$1
local default=$2
shift

if [[ ! -e "$DVM_ROOT/darts/$version" ]]; then
Expand All @@ -183,23 +213,29 @@ dvm_use() {
_dvm_path_prepend "$DVM_ROOT/darts/$version/bin"
}

dvm_list() {
_dvm_list() {
find "$DVM_ROOT/darts" -maxdepth 1 ! -path "$DVM_ROOT/darts" -type d \
-exec basename "{}" \; | sort -V
}

_dvm_list_repo() {
local channel=$1
local channel="$1"
local api_uri="https://www.googleapis.com/storage/v1/b/dart-archive/o"
local query="prefix=channels/$channel/release/&delimiter=/"
curl -s "$api_uri?$query" | \
local cache_file="$DVM_ROOT/cache/versions-$channel"
if [ ! -f "$cache_file" ] || [[ $(($(date +%s) - $(date -r "$cache_file" +%s))) -gt 300 ]]; then
curl -s "$api_uri?$query" | \
grep "channels/$channel/release/" | \
sed -e "s@.*/$channel/release/@@;s@/.*@@" | \
grep -v "^[0-9]*$" | \
sort -V
sort -V | \
tee "$cache_file"
else
cat "$cache_file"
fi
}

dvm_listall() {
_dvm_listall() {
if [[ "$1" == "--dev" ]]; then
_dvm_list_repo "dev"
elif [[ "$1" == "--beta" ]]; then
Expand Down Expand Up @@ -254,10 +290,16 @@ _dvm_dartium_arch() {
fi
}

dvm_install() {
_dvm_install() {
if [[ $# < 1 ]]; then
_dvm_check_fzf || return 1

local version=$(_dvm_listall | fzf --no-multi --tac)
elif [[ $# > 1 ]]; then
echo "usage: dvm install <version>"
return 1
else
local version="$1"
fi

curl=$(which curl)
Expand All @@ -266,7 +308,6 @@ dvm_install() {
return 1
fi

local version=$1
shift

if [[ -d "$DVM_ROOT/darts/$version" ]]; then
Expand Down Expand Up @@ -398,7 +439,7 @@ _dvm_needsupgrade() {
return 1
}

dvm_upgrade() {
_dvm_upgrade() {
# Abort if there are local diffs that aren't checked in.
local diffs="$(git -C "$DVM_ROOT" status --porcelain=v1 2>/dev/null)"
if [[ -n "$diffs" ]]; then
Expand Down Expand Up @@ -426,11 +467,11 @@ dvm_upgrade() {
return 0
}

dvm_version() {
_dvm_version() {
echo "Dart Version Manager version $DVM_VERSION installed at $DVM_ROOT"
}

dvm_implode() {
_dvm_implode() {
echo "This will delete dvm and all installed versions."
echo -n "Are you sure? "
read yn
Expand Down Expand Up @@ -469,35 +510,39 @@ dvm() {
shift
case $cmd in
alias)
dvm_alias "$@"
_dvm_alias "$@"
;;
implode)
dvm_implode "$@"
_dvm_implode "$@"
;;
install)
dvm_install "$@"
_dvm_install "$@"
;;
list)
dvm_list "$@"
_dvm_list "$@"
;;
listall)
dvm_listall "$@"
_dvm_listall "$@"
;;
upgrade)
dvm_upgrade "$@"
_dvm_upgrade "$@"
;;
use)
dvm_use "$@"
_dvm_use "$@"
;;
version)
dvm_version "$@"
_dvm_version "$@"
;;
*)
_dvm_usage
;;
esac
}

if [ -n "${BASH_VERSION}" ]; then
. "$DVM_ROOT/scripts/bash-completion.sh"
fi

if [[ -e "$DVM_ROOT/environments/default" ]]; then
. "$DVM_ROOT/environments/default"
fi