202 lines
7.1 KiB
Bash
202 lines
7.1 KiB
Bash
#!bash
|
|
#
|
|
###############################################################################
|
|
#
|
|
# Bash completion for homeshick (https://github.com/andsens/homeshick).
|
|
#
|
|
# To use, add this line (or equivalent) to your .bashrc:
|
|
#
|
|
# source ~/.homesick/repos/homeshick/completions/homeshick-completion.bash
|
|
#
|
|
###############################################################################
|
|
#
|
|
# Copyright (C) 2013 Jeremy Lin
|
|
#
|
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
# of this software and associated documentation files (the "Software"), to deal
|
|
# in the Software without restriction, including without limitation the rights
|
|
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
# copies of the Software, and to permit persons to whom the Software is
|
|
# furnished to do so, subject to the following conditions:
|
|
#
|
|
# The above copyright notice and this permission notice shall be included in
|
|
# all copies or substantial portions of the Software.
|
|
#
|
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
# THE SOFTWARE.
|
|
#
|
|
###############################################################################
|
|
|
|
_homeshick_basename()
|
|
{
|
|
echo "${1##*/}"
|
|
}
|
|
|
|
_homeshick_castles()
|
|
{
|
|
local repos="$HOME/.homesick/repos"
|
|
# This should be a while loop like in link.sh, leave it for now though
|
|
# shellcheck disable=SC2044
|
|
for repo in $(find -L "$repos" -mindepth 2 -maxdepth 2 -type d -name .git); do
|
|
_homeshick_basename "${repo%/.git}"
|
|
done
|
|
}
|
|
|
|
_homeshick_complete_castles()
|
|
{
|
|
COMPREPLY=($(compgen -W "$(_homeshick_castles)" -- "$1"))
|
|
}
|
|
|
|
_homeshick_complete()
|
|
{
|
|
# The comments at the bottom of the file explain what's going on here.
|
|
if $_HOMESHICK_HAS_COMPOPT; then
|
|
compopt +o default +o nospace
|
|
COMPREPLY=()
|
|
else
|
|
COMPREPLY=('')
|
|
fi
|
|
|
|
local -r cmds='
|
|
cd
|
|
clone
|
|
generate
|
|
list
|
|
check
|
|
refresh
|
|
pull
|
|
link
|
|
track
|
|
help
|
|
symlink
|
|
updates
|
|
'
|
|
local -r short_opts='-q -s -f -b -v'
|
|
local -r long_opts='--quiet --skip --force --batch --verbose'
|
|
local -r protocols='file ftp ftps git http https rsync ssh'
|
|
|
|
# Scan through the command line and find the homeshick command
|
|
# (if present), as well as its expected position.
|
|
local cmd
|
|
local cmd_index=1 # Expected index of the command token.
|
|
local i
|
|
for (( i = 1; i < ${#COMP_WORDS[@]}; i++ )); do
|
|
local word="${COMP_WORDS[i]}"
|
|
case "$word" in
|
|
-*)
|
|
((cmd_index++))
|
|
;;
|
|
*)
|
|
cmd="$word"
|
|
break
|
|
;;
|
|
esac
|
|
done
|
|
|
|
local cur="${COMP_WORDS[COMP_CWORD]}"
|
|
|
|
if (( COMP_CWORD < cmd_index )); then
|
|
# Offer option completions.
|
|
case "$cur" in
|
|
--*)
|
|
COMPREPLY=($(compgen -W "$long_opts" -- "$cur"))
|
|
;;
|
|
-*)
|
|
COMPREPLY=($(compgen -W "$short_opts" -- "$cur"))
|
|
;;
|
|
*)
|
|
# Skip completion; we should never get here.
|
|
;;
|
|
esac
|
|
elif (( COMP_CWORD == cmd_index )); then
|
|
# Offer command name completions.
|
|
COMPREPLY=($(compgen -W "$cmds" -- "$cur"))
|
|
else
|
|
# Offer command argument completions.
|
|
case "$cmd" in
|
|
check | pull | link | symlink | updates)
|
|
# Offer one or more castle name completions.
|
|
_homeshick_complete_castles "$cur"
|
|
;;
|
|
cd)
|
|
# Offer exactly one castle name completion.
|
|
if (( COMP_CWORD == cmd_index + 1 )); then
|
|
_homeshick_complete_castles "$cur"
|
|
fi
|
|
;;
|
|
refresh)
|
|
# Offer a numerical completion for DAYS (mostly as a reminder
|
|
# that this argument should be a number), then castle name
|
|
# completions after that.
|
|
if (( COMP_CWORD == cmd_index + 1 )); then
|
|
COMPREPLY=({0..9})
|
|
else
|
|
_homeshick_complete_castles "$cur"
|
|
fi
|
|
;;
|
|
track)
|
|
# Offer one castle name completion, then filename completions
|
|
# after that.
|
|
if (( COMP_CWORD == cmd_index + 1 )); then
|
|
_homeshick_complete_castles "$cur"
|
|
else
|
|
$_HOMESHICK_HAS_COMPOPT && compopt -o default
|
|
# Let the default Readline filename completion take over.
|
|
COMPREPLY=()
|
|
fi
|
|
;;
|
|
clone)
|
|
# Offer an initial protocol completion.
|
|
if (( COMP_CWORD == cmd_index + 1 )); then
|
|
$_HOMESHICK_HAS_COMPOPT && compopt -o nospace
|
|
COMPREPLY=($(compgen -W "$protocols" -S '://' -- "$cur"))
|
|
fi
|
|
;;
|
|
help)
|
|
# Offer exactly one command name completion.
|
|
if (( COMP_CWORD == cmd_index + 1 )); then
|
|
COMPREPLY=($(compgen -W "$cmds" -- "$cur"))
|
|
fi
|
|
;;
|
|
*)
|
|
# Unknown command or unknowable argument.
|
|
;;
|
|
esac
|
|
fi
|
|
}
|
|
|
|
# The behavior of 'compgen -f' is pretty bizarre, in that if there's a
|
|
# directory 'foo', then compgen simply completes 'foo' and moves on, rather
|
|
# than offering to complete names of files underneath 'foo', which is what
|
|
# Bash (or Readline, actually) usually does.
|
|
#
|
|
# You can get the usual Readline filename completion behavior by doing
|
|
# 'complete -o default -F <func>', in which case the Readline filename
|
|
# completer is called if COMPREPLY=(). But this also means that you can no
|
|
# longer deny completion with COMPREPLY=() -- now Readline will always offer
|
|
# to complete a filename, even if this is inappropriate (e.g., the command
|
|
# takes no further arguments).
|
|
#
|
|
# In Bash 4.0 and above, there's a way to work around this problem. These
|
|
# versions have a 'compopt' builtin, which allows '-o default' to be enabled
|
|
# or disabled as needed. The workaround, then, is to disable '-o default'
|
|
# at the top of the completion function, and enable it as needed later on.
|
|
#
|
|
# For older Bash releases, there's a different workaround that doesn't work
|
|
# quite as well, but is still better than nothing. This workaround is to
|
|
# always enable '-o default' (which can't be disabled later), and then to use
|
|
# COMPREPLY=('') to semi-deny completion. That is, pressing Tab will just add
|
|
# space characters to the command line, rather than generating filenames.
|
|
#
|
|
if type compopt &>/dev/null; then
|
|
_HOMESHICK_HAS_COMPOPT=true
|
|
else
|
|
_HOMESHICK_HAS_COMPOPT=false
|
|
fi
|
|
complete -o default -F _homeshick_complete homeshick
|