Merge pull request #13 from jshort/zsh_complete

Add support for zsh completion
This commit is contained in:
Lazarus Lazaridis 2018-03-12 07:30:08 +02:00 committed by GitHub
commit 0b3b8527a9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 70 additions and 41 deletions

View File

@ -1,6 +1,6 @@
# goto # goto
`goto` is a bash utility allowing users to change faster to aliased directories supporting auto-completion :feet: `goto` is a shell utility allowing users to change faster to aliased directories supporting auto-completion :feet:
## How does it work? ## How does it work?
@ -17,7 +17,7 @@ goto dev
## goto completion ## goto completion
`goto` comes with a nice auto-completion script so that whenever you press the `tab` key after the `goto` command, bash prompts with suggestions of the available aliases: `goto` comes with a nice auto-completion script so that whenever you press the `tab` key after the `goto` command, bash or zsh prompts with suggestions of the available aliases:
```bash ```bash
$ goto <tab> $ goto <tab>
@ -28,12 +28,12 @@ rubies /home/iridakos/.rvm/rubies
## Installation ## Installation
Copy the file `goto.bash` somewhere in your filesystem and add a line in your `.bashrc` to source it. Copy the file `goto.sh` somewhere in your filesystem and add a line in your `.zshrc` or `.bashrc` to source it.
For example, if you placed the file in your home folder, all you have to do is add the following line to your `.bashrc` file: For example, if you placed the file in your home folder, all you have to do is add the following line to your `.zshrc` or `.bashrc` file:
```bash ```bash
source ~/goto.bash source ~/goto.sh
``` ```
## Usage ## Usage
@ -75,7 +75,7 @@ goto --register blog /mnt/external/projects/html/blog
goto -r last_release . goto -r last_release .
``` ```
and it will automatically be aliased to the whole path. and it will automatically be aliased to the whole path.
* Pressing the `tab` key after the alias name, you have the default directory suggestions by bash. * Pressing the `tab` key after the alias name, you have the default directory suggestions by the shell.
### Unregister an alias ### Unregister an alias
@ -148,7 +148,6 @@ goto --version
## TODO ## TODO
* ~~Test on macOS~~ extensively * ~~Test on macOS~~ extensively
* Fix `zsh` issues [[#7](https://github.com/iridakos/goto/issues/7), ...]
* Write [tests](https://github.com/iridakos/goto/issues/2) * Write [tests](https://github.com/iridakos/goto/issues/2)
## Contributing ## Contributing

View File

@ -1,4 +1,3 @@
#!/usr/bin/env bash
# MIT License # MIT License
# #
# Copyright (c) 2018 Lazarus Lazaridis # Copyright (c) 2018 Lazarus Lazaridis
@ -59,6 +58,7 @@ function goto()
_goto_directory "$subcommand" _goto_directory "$subcommand"
;; ;;
esac esac
return $?
} }
function _goto_usage() function _goto_usage()
@ -123,12 +123,12 @@ function _goto_register_alias()
{ {
if [ "$#" -ne "2" ]; then if [ "$#" -ne "2" ]; then
_goto_error "usage: goto -r|--register <alias> <directory>" _goto_error "usage: goto -r|--register <alias> <directory>"
return return 1
fi fi
if ! [[ $1 =~ ^[[:alnum:]]+[a-zA-Z0-9_-]*$ ]]; then if ! [[ $1 =~ ^[[:alnum:]]+[a-zA-Z0-9_-]*$ ]]; then
_goto_error "invalid alias - can start with letters or digits followed by letters, digits, hyphens or underscores" _goto_error "invalid alias - can start with letters or digits followed by letters, digits, hyphens or underscores"
return return 1
fi fi
local resolved local resolved
@ -136,14 +136,14 @@ function _goto_register_alias()
if [ -n "$resolved" ]; then if [ -n "$resolved" ]; then
_goto_error "alias '$1' exists" _goto_error "alias '$1' exists"
return return 1
fi fi
local directory local directory
directory=$(_goto_expand_directory "$2") directory=$(_goto_expand_directory "$2")
if [ -z "$directory" ]; then if [ -z "$directory" ]; then
_goto_error "failed to register '$1' to '$2' - can't cd to directory" _goto_error "failed to register '$1' to '$2' - can't cd to directory"
return return 1
fi fi
local duplicate local duplicate
@ -162,14 +162,14 @@ function _goto_unregister_alias
{ {
if [ "$#" -ne "1" ]; then if [ "$#" -ne "1" ]; then
_goto_error "usage: goto -u|--unregister <alias>" _goto_error "usage: goto -u|--unregister <alias>"
return return 1
fi fi
local resolved local resolved
resolved=$(_goto_find_alias_directory "$1") resolved=$(_goto_find_alias_directory "$1")
if [ -z "$resolved" ]; then if [ -z "$resolved" ]; then
_goto_error "alias '$1' does not exist" _goto_error "alias '$1' does not exist"
return return 1
fi fi
# shellcheck disable=SC2034 # shellcheck disable=SC2034
@ -186,22 +186,11 @@ function _goto_cleanup()
return return
fi fi
local IFS=$'\n' match matches al dir while IFS= read -r i && [ -n "$i" ]; do
echo "Cleaning up: $i"
read -d '' -r -a matches < "$GOTO_DB" _goto_unregister_alias "$i"
done <<< "$(awk '{al=$1; $1=""; dir=substr($0,2);
IFS=' ' system("[ ! -d \"" dir "\" ] && echo " al)}' "$GOTO_DB")"
for i in "${!matches[@]}"; do
read -r -a match <<< "${matches[$i]}"
al="${match[0]}"
dir="${match[*]:1}"
if [ -n "$al" ] && [ ! -d "$dir" ]; then
echo "Cleaning up: $al - $dir"
_goto_unregister_alias "$al"
fi
done
} }
# Changes to the given alias' directory # Changes to the given alias' directory
@ -209,11 +198,10 @@ function _goto_directory()
{ {
local target local target
target=$(_goto_resolve_alias "$1") target=$(_goto_resolve_alias "$1") || return 1
if [ -n "$target" ]; then cd "$target" 2> /dev/null || \
cd "$target" || _goto_error "Failed to goto '$target'" { _goto_error "Failed to goto '$target'" && return 1; }
fi
} }
# Fetches the alias directory. # Fetches the alias directory.
@ -261,7 +249,7 @@ function _goto_resolve_alias()
if [ -z "$resolved" ]; then if [ -z "$resolved" ]; then
_goto_error "unregistered alias $1" _goto_error "unregistered alias $1"
_goto_print_similar "$1" _goto_print_similar "$1"
echo "" return 1
else else
echo "${resolved}" echo "${resolved}"
fi fi
@ -279,7 +267,7 @@ function _complete_goto_commands()
# Completes the goto function with the available aliases # Completes the goto function with the available aliases
function _complete_goto_aliases() function _complete_goto_aliases()
{ {
local IFS=$'\n' matches al local IFS=$'\n' matches
# shellcheck disable=SC2207 # shellcheck disable=SC2207
matches=($(sed -n "/^$1/p" "$GOTO_DB" 2>/dev/null)) matches=($(sed -n "/^$1/p" "$GOTO_DB" 2>/dev/null))
@ -307,7 +295,7 @@ function _complete_goto_aliases()
} }
# Bash programmable completion for the goto function # Bash programmable completion for the goto function
function _complete_goto() function _complete_goto_bash()
{ {
local cur="${COMP_WORDS[$COMP_CWORD]}" prev local cur="${COMP_WORDS[$COMP_CWORD]}" prev
@ -342,9 +330,51 @@ function _complete_goto()
fi fi
} }
# Register the goto compspec # Zsh programmable completion for the goto function
function _complete_goto_zsh()
{
local all_aliases=()
while IFS= read -r line; do
all_aliases+=("$line")
done <<< "$(sed -e 's/ /:/g' ~/.goto 2>/dev/null)"
local state
local -a options=(
'(1)'{-r,--register}'[registers an alias]:register:->register'
'(- 1 2)'{-u,--unregister}'[unregisters an alias]:unregister:->unregister'
'(: -)'{-l,--list}'[lists aliases]'
'(*)'{-c,--cleanup}'[cleans up non existent directory aliases]'
'(: -)'{-h,--help}'[prints this help]'
'(* -)'{-v,--version}'[displays the version of the goto script]'
)
_arguments -C \
"${options[@]}" \
'1:alias:->aliases' \
'2:dir:_files' \
&& ret=0
case ${state} in
(aliases)
_describe -t aliases 'goto aliases:' all_aliases && ret=0
;;
(unregister)
_describe -t aliases 'unregister alias:' all_aliases && ret=0
;;
esac
return $ret
}
# Register the goto completions.
if [ -n "${BASH_VERSION}" ]; then
if ! [[ $(uname -s) =~ Darwin* ]]; then if ! [[ $(uname -s) =~ Darwin* ]]; then
complete -o filenames -F _complete_goto goto complete -o filenames -F _complete_goto_bash goto
else else
complete -F _complete_goto goto complete -F _complete_goto_bash goto
fi
elif [ -n "${ZSH_VERSION}" ]; then
compdef _complete_goto_zsh goto
else
echo "Unsupported shell."
exit 1
fi fi