|
Packit |
8462d6 |
# -*- shell-script -*-
|
|
Packit |
8462d6 |
#
|
|
Packit |
8462d6 |
# bash_completion - programmable completion functions for bash 4.1+
|
|
Packit |
8462d6 |
#
|
|
Packit |
8462d6 |
# Copyright © 2006-2008, Ian Macdonald <ian@caliban.org>
|
|
Packit |
8462d6 |
# © 2009-2017, Bash Completion Maintainers
|
|
Packit |
8462d6 |
#
|
|
Packit |
8462d6 |
# This program is free software; you can redistribute it and/or modify
|
|
Packit |
8462d6 |
# it under the terms of the GNU General Public License as published by
|
|
Packit |
8462d6 |
# the Free Software Foundation; either version 2, or (at your option)
|
|
Packit |
8462d6 |
# any later version.
|
|
Packit |
8462d6 |
#
|
|
Packit |
8462d6 |
# This program is distributed in the hope that it will be useful,
|
|
Packit |
8462d6 |
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
8462d6 |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
Packit |
8462d6 |
# GNU General Public License for more details.
|
|
Packit |
8462d6 |
#
|
|
Packit |
8462d6 |
# You should have received a copy of the GNU General Public License
|
|
Packit |
8462d6 |
# along with this program; if not, write to the Free Software Foundation,
|
|
Packit |
8462d6 |
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
Packit |
8462d6 |
#
|
|
Packit |
8462d6 |
# The latest version of this software can be obtained here:
|
|
Packit |
8462d6 |
#
|
|
Packit |
8462d6 |
# https://github.com/scop/bash-completion
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
BASH_COMPLETION_VERSINFO=(2 7)
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
if [[ $- == *v* ]]; then
|
|
Packit |
8462d6 |
BASH_COMPLETION_ORIGINAL_V_VALUE="-v"
|
|
Packit |
8462d6 |
else
|
|
Packit |
8462d6 |
BASH_COMPLETION_ORIGINAL_V_VALUE="+v"
|
|
Packit |
8462d6 |
fi
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
if [[ ${BASH_COMPLETION_DEBUG-} ]]; then
|
|
Packit |
8462d6 |
set -v
|
|
Packit |
8462d6 |
else
|
|
Packit |
8462d6 |
set +v
|
|
Packit |
8462d6 |
fi
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# Blacklisted completions, causing problems with our code.
|
|
Packit |
8462d6 |
#
|
|
Packit |
8462d6 |
_blacklist_glob='@(acroread.sh)'
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# Turn on extended globbing and programmable completion
|
|
Packit |
8462d6 |
shopt -s extglob progcomp
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# A lot of the following one-liners were taken directly from the
|
|
Packit |
8462d6 |
# completion examples provided with the bash 2.04 source distribution
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# start of section containing compspecs that can be handled within bash
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# user commands see only users
|
|
Packit |
8462d6 |
complete -u groups slay w sux
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# bg completes with stopped jobs
|
|
Packit |
8462d6 |
complete -A stopped -P '"%' -S '"' bg
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# other job commands
|
|
Packit |
8462d6 |
complete -j -P '"%' -S '"' fg jobs disown
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# readonly and unset complete with shell variables
|
|
Packit |
8462d6 |
complete -v readonly unset
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# set completes with set options
|
|
Packit |
8462d6 |
complete -A setopt set
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# shopt completes with shopt options
|
|
Packit |
8462d6 |
complete -A shopt shopt
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# helptopics
|
|
Packit |
8462d6 |
complete -A helptopic help
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# unalias completes with aliases
|
|
Packit |
8462d6 |
complete -a unalias
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# type and which complete on commands
|
|
Packit |
8462d6 |
complete -c command type which
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# builtin completes on builtins
|
|
Packit |
8462d6 |
complete -b builtin
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# start of section containing completion functions called by other functions
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# Check if we're running on the given userland
|
|
Packit |
8462d6 |
# @param $1 userland to check for
|
|
Packit |
8462d6 |
_userland()
|
|
Packit |
8462d6 |
{
|
|
Packit |
8462d6 |
local userland=$( uname -s )
|
|
Packit |
8462d6 |
[[ $userland == @(Linux|GNU/*) ]] && userland=GNU
|
|
Packit |
8462d6 |
[[ $userland == $1 ]]
|
|
Packit |
8462d6 |
}
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# This function sets correct SysV init directories
|
|
Packit |
8462d6 |
#
|
|
Packit |
8462d6 |
_sysvdirs()
|
|
Packit |
8462d6 |
{
|
|
Packit |
8462d6 |
sysvdirs=( )
|
|
Packit |
8462d6 |
[[ -d /etc/rc.d/init.d ]] && sysvdirs+=( /etc/rc.d/init.d )
|
|
Packit |
8462d6 |
[[ -d /etc/init.d ]] && sysvdirs+=( /etc/init.d )
|
|
Packit |
8462d6 |
# Slackware uses /etc/rc.d
|
|
Packit |
8462d6 |
[[ -f /etc/slackware-version ]] && sysvdirs=( /etc/rc.d )
|
|
Packit |
8462d6 |
}
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# This function checks whether we have a given program on the system.
|
|
Packit |
8462d6 |
#
|
|
Packit |
8462d6 |
_have()
|
|
Packit |
8462d6 |
{
|
|
Packit |
8462d6 |
# Completions for system administrator commands are installed as well in
|
|
Packit |
8462d6 |
# case completion is attempted via `sudo command ...'.
|
|
Packit |
8462d6 |
PATH=$PATH:/usr/sbin:/sbin:/usr/local/sbin type $1 &>/dev/null
|
|
Packit |
8462d6 |
}
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# Backwards compatibility for compat completions that use have().
|
|
Packit |
8462d6 |
# @deprecated should no longer be used; generally not needed with dynamically
|
|
Packit |
8462d6 |
# loaded completions, and _have is suitable for runtime use.
|
|
Packit |
8462d6 |
have()
|
|
Packit |
8462d6 |
{
|
|
Packit |
8462d6 |
unset -v have
|
|
Packit |
8462d6 |
_have $1 && have=yes
|
|
Packit |
8462d6 |
}
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# This function checks whether a given readline variable
|
|
Packit |
8462d6 |
# is `on'.
|
|
Packit |
8462d6 |
#
|
|
Packit |
8462d6 |
_rl_enabled()
|
|
Packit |
8462d6 |
{
|
|
Packit |
8462d6 |
[[ "$( bind -v )" == *$1+([[:space:]])on* ]]
|
|
Packit |
8462d6 |
}
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# This function shell-quotes the argument
|
|
Packit |
8462d6 |
quote()
|
|
Packit |
8462d6 |
{
|
|
Packit |
8462d6 |
local quoted=${1//\'/\'\\\'\'}
|
|
Packit |
8462d6 |
printf "'%s'" "$quoted"
|
|
Packit |
8462d6 |
}
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# @see _quote_readline_by_ref()
|
|
Packit |
8462d6 |
quote_readline()
|
|
Packit |
8462d6 |
{
|
|
Packit |
8462d6 |
local quoted
|
|
Packit |
8462d6 |
_quote_readline_by_ref "$1" ret
|
|
Packit |
8462d6 |
printf %s "$ret"
|
|
Packit |
8462d6 |
} # quote_readline()
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# This function shell-dequotes the argument
|
|
Packit |
8462d6 |
dequote()
|
|
Packit |
8462d6 |
{
|
|
Packit |
8462d6 |
eval printf %s "$1" 2> /dev/null
|
|
Packit |
8462d6 |
}
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# Assign variable one scope above the caller
|
|
Packit |
8462d6 |
# Usage: local "$1" && _upvar $1 "value(s)"
|
|
Packit |
8462d6 |
# Param: $1 Variable name to assign value to
|
|
Packit |
8462d6 |
# Param: $* Value(s) to assign. If multiple values, an array is
|
|
Packit |
8462d6 |
# assigned, otherwise a single value is assigned.
|
|
Packit |
8462d6 |
# NOTE: For assigning multiple variables, use '_upvars'. Do NOT
|
|
Packit |
8462d6 |
# use multiple '_upvar' calls, since one '_upvar' call might
|
|
Packit |
8462d6 |
# reassign a variable to be used by another '_upvar' call.
|
|
Packit |
8462d6 |
# See: http://fvue.nl/wiki/Bash:_Passing_variables_by_reference
|
|
Packit |
8462d6 |
_upvar()
|
|
Packit |
8462d6 |
{
|
|
Packit |
8462d6 |
if unset -v "$1"; then # Unset & validate varname
|
|
Packit |
8462d6 |
if (( $# == 2 )); then
|
|
Packit |
8462d6 |
eval $1=\"\$2\" # Return single value
|
|
Packit |
8462d6 |
else
|
|
Packit |
8462d6 |
eval $1=\(\"\${@:2}\"\) # Return array
|
|
Packit |
8462d6 |
fi
|
|
Packit |
8462d6 |
fi
|
|
Packit |
8462d6 |
}
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# Assign variables one scope above the caller
|
|
Packit |
8462d6 |
# Usage: local varname [varname ...] &&
|
|
Packit |
8462d6 |
# _upvars [-v varname value] | [-aN varname [value ...]] ...
|
|
Packit |
8462d6 |
# Available OPTIONS:
|
|
Packit |
8462d6 |
# -aN Assign next N values to varname as array
|
|
Packit |
8462d6 |
# -v Assign single value to varname
|
|
Packit |
8462d6 |
# Return: 1 if error occurs
|
|
Packit |
8462d6 |
# See: http://fvue.nl/wiki/Bash:_Passing_variables_by_reference
|
|
Packit |
8462d6 |
_upvars()
|
|
Packit |
8462d6 |
{
|
|
Packit |
8462d6 |
if ! (( $# )); then
|
|
Packit |
8462d6 |
echo "${FUNCNAME[0]}: usage: ${FUNCNAME[0]} [-v varname"\
|
|
Packit |
8462d6 |
"value] | [-aN varname [value ...]] ..." 1>&2
|
|
Packit |
8462d6 |
return 2
|
|
Packit |
8462d6 |
fi
|
|
Packit |
8462d6 |
while (( $# )); do
|
|
Packit |
8462d6 |
case $1 in
|
|
Packit |
8462d6 |
-a*)
|
|
Packit |
8462d6 |
# Error checking
|
|
Packit |
8462d6 |
[[ ${1#-a} ]] || { echo "bash: ${FUNCNAME[0]}: \`$1': missing"\
|
|
Packit |
8462d6 |
"number specifier" 1>&2; return 1; }
|
|
Packit |
8462d6 |
printf %d "${1#-a}" &> /dev/null || { echo "bash:"\
|
|
Packit |
8462d6 |
"${FUNCNAME[0]}: \`$1': invalid number specifier" 1>&2
|
|
Packit |
8462d6 |
return 1; }
|
|
Packit |
8462d6 |
# Assign array of -aN elements
|
|
Packit |
8462d6 |
[[ "$2" ]] && unset -v "$2" && eval $2=\(\"\${@:3:${1#-a}}\"\) &&
|
|
Packit |
8462d6 |
shift $((${1#-a} + 2)) || { echo "bash: ${FUNCNAME[0]}:"\
|
|
Packit |
8462d6 |
"\`$1${2+ }$2': missing argument(s)" 1>&2; return 1; }
|
|
Packit |
8462d6 |
;;
|
|
Packit |
8462d6 |
-v)
|
|
Packit |
8462d6 |
# Assign single value
|
|
Packit |
8462d6 |
[[ "$2" ]] && unset -v "$2" && eval $2=\"\$3\" &&
|
|
Packit |
8462d6 |
shift 3 || { echo "bash: ${FUNCNAME[0]}: $1: missing"\
|
|
Packit |
8462d6 |
"argument(s)" 1>&2; return 1; }
|
|
Packit |
8462d6 |
;;
|
|
Packit |
8462d6 |
*)
|
|
Packit |
8462d6 |
echo "bash: ${FUNCNAME[0]}: $1: invalid option" 1>&2
|
|
Packit |
8462d6 |
return 1 ;;
|
|
Packit |
8462d6 |
esac
|
|
Packit |
8462d6 |
done
|
|
Packit |
8462d6 |
}
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# Reassemble command line words, excluding specified characters from the
|
|
Packit |
8462d6 |
# list of word completion separators (COMP_WORDBREAKS).
|
|
Packit |
8462d6 |
# @param $1 chars Characters out of $COMP_WORDBREAKS which should
|
|
Packit |
8462d6 |
# NOT be considered word breaks. This is useful for things like scp where
|
|
Packit |
8462d6 |
# we want to return host:path and not only path, so we would pass the
|
|
Packit |
8462d6 |
# colon (:) as $1 here.
|
|
Packit |
8462d6 |
# @param $2 words Name of variable to return words to
|
|
Packit |
8462d6 |
# @param $3 cword Name of variable to return cword to
|
|
Packit |
8462d6 |
#
|
|
Packit |
8462d6 |
__reassemble_comp_words_by_ref()
|
|
Packit |
8462d6 |
{
|
|
Packit |
8462d6 |
local exclude i j line ref
|
|
Packit |
8462d6 |
# Exclude word separator characters?
|
|
Packit |
8462d6 |
if [[ $1 ]]; then
|
|
Packit |
8462d6 |
# Yes, exclude word separator characters;
|
|
Packit |
8462d6 |
# Exclude only those characters, which were really included
|
|
Packit |
8462d6 |
exclude="${1//[^$COMP_WORDBREAKS]}"
|
|
Packit |
8462d6 |
fi
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# Default to cword unchanged
|
|
Packit |
8462d6 |
printf -v "$3" %s "$COMP_CWORD"
|
|
Packit |
8462d6 |
# Are characters excluded which were former included?
|
|
Packit |
8462d6 |
if [[ $exclude ]]; then
|
|
Packit |
8462d6 |
# Yes, list of word completion separators has shrunk;
|
|
Packit |
8462d6 |
line=$COMP_LINE
|
|
Packit |
8462d6 |
# Re-assemble words to complete
|
|
Packit |
8462d6 |
for (( i=0, j=0; i < ${#COMP_WORDS[@]}; i++, j++)); do
|
|
Packit |
8462d6 |
# Is current word not word 0 (the command itself) and is word not
|
|
Packit |
8462d6 |
# empty and is word made up of just word separator characters to
|
|
Packit |
8462d6 |
# be excluded and is current word not preceded by whitespace in
|
|
Packit |
8462d6 |
# original line?
|
|
Packit |
8462d6 |
while [[ $i -gt 0 && ${COMP_WORDS[$i]} == +([$exclude]) ]]; do
|
|
Packit |
8462d6 |
# Is word separator not preceded by whitespace in original line
|
|
Packit |
8462d6 |
# and are we not going to append to word 0 (the command
|
|
Packit |
8462d6 |
# itself), then append to current word.
|
|
Packit |
8462d6 |
[[ $line != [[:blank:]]* ]] && (( j >= 2 )) && ((j--))
|
|
Packit |
8462d6 |
# Append word separator to current or new word
|
|
Packit |
8462d6 |
ref="$2[$j]"
|
|
Packit |
8462d6 |
printf -v "$ref" %s "${!ref}${COMP_WORDS[i]}"
|
|
Packit |
8462d6 |
# Indicate new cword
|
|
Packit |
8462d6 |
[[ $i == $COMP_CWORD ]] && printf -v "$3" %s "$j"
|
|
Packit |
8462d6 |
# Remove optional whitespace + word separator from line copy
|
|
Packit |
8462d6 |
line=${line#*"${COMP_WORDS[$i]}"}
|
|
Packit |
8462d6 |
# Start new word if word separator in original line is
|
|
Packit |
8462d6 |
# followed by whitespace.
|
|
Packit |
8462d6 |
[[ $line == [[:blank:]]* ]] && ((j++))
|
|
Packit |
8462d6 |
# Indicate next word if available, else end *both* while and
|
|
Packit |
8462d6 |
# for loop
|
|
Packit |
8462d6 |
(( $i < ${#COMP_WORDS[@]} - 1)) && ((i++)) || break 2
|
|
Packit |
8462d6 |
done
|
|
Packit |
8462d6 |
# Append word to current word
|
|
Packit |
8462d6 |
ref="$2[$j]"
|
|
Packit |
8462d6 |
printf -v "$ref" %s "${!ref}${COMP_WORDS[i]}"
|
|
Packit |
8462d6 |
# Remove optional whitespace + word from line copy
|
|
Packit |
8462d6 |
line=${line#*"${COMP_WORDS[i]}"}
|
|
Packit |
8462d6 |
# Indicate new cword
|
|
Packit |
8462d6 |
[[ $i == $COMP_CWORD ]] && printf -v "$3" %s "$j"
|
|
Packit |
8462d6 |
done
|
|
Packit |
8462d6 |
[[ $i == $COMP_CWORD ]] && printf -v "$3" %s "$j"
|
|
Packit |
8462d6 |
else
|
|
Packit |
8462d6 |
# No, list of word completions separators hasn't changed;
|
|
Packit |
8462d6 |
for i in ${!COMP_WORDS[@]}; do
|
|
Packit |
8462d6 |
printf -v "$2[i]" %s "${COMP_WORDS[i]}"
|
|
Packit |
8462d6 |
done
|
|
Packit |
8462d6 |
fi
|
|
Packit |
8462d6 |
} # __reassemble_comp_words_by_ref()
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# @param $1 exclude Characters out of $COMP_WORDBREAKS which should NOT be
|
|
Packit |
8462d6 |
# considered word breaks. This is useful for things like scp where
|
|
Packit |
8462d6 |
# we want to return host:path and not only path, so we would pass the
|
|
Packit |
8462d6 |
# colon (:) as $1 in this case.
|
|
Packit |
8462d6 |
# @param $2 words Name of variable to return words to
|
|
Packit |
8462d6 |
# @param $3 cword Name of variable to return cword to
|
|
Packit |
8462d6 |
# @param $4 cur Name of variable to return current word to complete to
|
|
Packit |
8462d6 |
# @see __reassemble_comp_words_by_ref()
|
|
Packit |
8462d6 |
__get_cword_at_cursor_by_ref()
|
|
Packit |
8462d6 |
{
|
|
Packit |
8462d6 |
local cword words=()
|
|
Packit |
8462d6 |
__reassemble_comp_words_by_ref "$1" words cword
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
local i cur index=$COMP_POINT lead=${COMP_LINE:0:$COMP_POINT}
|
|
Packit |
8462d6 |
# Cursor not at position 0 and not leaded by just space(s)?
|
|
Packit |
8462d6 |
if [[ $index -gt 0 && ( $lead && ${lead//[[:space:]]} ) ]]; then
|
|
Packit |
8462d6 |
cur=$COMP_LINE
|
|
Packit |
8462d6 |
for (( i = 0; i <= cword; ++i )); do
|
|
Packit |
8462d6 |
while [[
|
|
Packit |
8462d6 |
# Current word fits in $cur?
|
|
Packit |
8462d6 |
${#cur} -ge ${#words[i]} &&
|
|
Packit |
8462d6 |
# $cur doesn't match cword?
|
|
Packit |
8462d6 |
"${cur:0:${#words[i]}}" != "${words[i]}"
|
|
Packit |
8462d6 |
]]; do
|
|
Packit |
8462d6 |
# Strip first character
|
|
Packit |
8462d6 |
cur="${cur:1}"
|
|
Packit |
8462d6 |
# Decrease cursor position, staying >= 0
|
|
Packit |
8462d6 |
[[ $index -gt 0 ]] && ((index--))
|
|
Packit |
8462d6 |
done
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# Does found word match cword?
|
|
Packit |
8462d6 |
if [[ $i -lt $cword ]]; then
|
|
Packit |
8462d6 |
# No, cword lies further;
|
|
Packit |
8462d6 |
local old_size=${#cur}
|
|
Packit |
8462d6 |
cur="${cur#"${words[i]}"}"
|
|
Packit |
8462d6 |
local new_size=${#cur}
|
|
Packit |
8462d6 |
index=$(( index - old_size + new_size ))
|
|
Packit |
8462d6 |
fi
|
|
Packit |
8462d6 |
done
|
|
Packit |
8462d6 |
# Clear $cur if just space(s)
|
|
Packit |
8462d6 |
[[ $cur && ! ${cur//[[:space:]]} ]] && cur=
|
|
Packit |
8462d6 |
# Zero $index if negative
|
|
Packit |
8462d6 |
[[ $index -lt 0 ]] && index=0
|
|
Packit |
8462d6 |
fi
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
local "$2" "$3" "$4" && _upvars -a${#words[@]} $2 "${words[@]}" \
|
|
Packit |
8462d6 |
-v $3 "$cword" -v $4 "${cur:0:$index}"
|
|
Packit |
8462d6 |
}
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# Get the word to complete and optional previous words.
|
|
Packit |
8462d6 |
# This is nicer than ${COMP_WORDS[$COMP_CWORD]}, since it handles cases
|
|
Packit |
8462d6 |
# where the user is completing in the middle of a word.
|
|
Packit |
8462d6 |
# (For example, if the line is "ls foobar",
|
|
Packit |
8462d6 |
# and the cursor is here --------> ^
|
|
Packit |
8462d6 |
# Also one is able to cross over possible wordbreak characters.
|
|
Packit |
8462d6 |
# Usage: _get_comp_words_by_ref [OPTIONS] [VARNAMES]
|
|
Packit |
8462d6 |
# Available VARNAMES:
|
|
Packit |
8462d6 |
# cur Return cur via $cur
|
|
Packit |
8462d6 |
# prev Return prev via $prev
|
|
Packit |
8462d6 |
# words Return words via $words
|
|
Packit |
8462d6 |
# cword Return cword via $cword
|
|
Packit |
8462d6 |
#
|
|
Packit |
8462d6 |
# Available OPTIONS:
|
|
Packit |
8462d6 |
# -n EXCLUDE Characters out of $COMP_WORDBREAKS which should NOT be
|
|
Packit |
8462d6 |
# considered word breaks. This is useful for things like scp
|
|
Packit |
8462d6 |
# where we want to return host:path and not only path, so we
|
|
Packit |
8462d6 |
# would pass the colon (:) as -n option in this case.
|
|
Packit |
8462d6 |
# -c VARNAME Return cur via $VARNAME
|
|
Packit |
8462d6 |
# -p VARNAME Return prev via $VARNAME
|
|
Packit |
8462d6 |
# -w VARNAME Return words via $VARNAME
|
|
Packit |
8462d6 |
# -i VARNAME Return cword via $VARNAME
|
|
Packit |
8462d6 |
#
|
|
Packit |
8462d6 |
# Example usage:
|
|
Packit |
8462d6 |
#
|
|
Packit |
8462d6 |
# $ _get_comp_words_by_ref -n : cur prev
|
|
Packit |
8462d6 |
#
|
|
Packit |
8462d6 |
_get_comp_words_by_ref()
|
|
Packit |
8462d6 |
{
|
|
Packit |
8462d6 |
local exclude flag i OPTIND=1
|
|
Packit |
8462d6 |
local cur cword words=()
|
|
Packit |
8462d6 |
local upargs=() upvars=() vcur vcword vprev vwords
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
while getopts "c:i:n:p:w:" flag "$@"; do
|
|
Packit |
8462d6 |
case $flag in
|
|
Packit |
8462d6 |
c) vcur=$OPTARG ;;
|
|
Packit |
8462d6 |
i) vcword=$OPTARG ;;
|
|
Packit |
8462d6 |
n) exclude=$OPTARG ;;
|
|
Packit |
8462d6 |
p) vprev=$OPTARG ;;
|
|
Packit |
8462d6 |
w) vwords=$OPTARG ;;
|
|
Packit |
8462d6 |
esac
|
|
Packit |
8462d6 |
done
|
|
Packit |
8462d6 |
while [[ $# -ge $OPTIND ]]; do
|
|
Packit |
8462d6 |
case ${!OPTIND} in
|
|
Packit |
8462d6 |
cur) vcur=cur ;;
|
|
Packit |
8462d6 |
prev) vprev=prev ;;
|
|
Packit |
8462d6 |
cword) vcword=cword ;;
|
|
Packit |
8462d6 |
words) vwords=words ;;
|
|
Packit |
8462d6 |
*) echo "bash: $FUNCNAME(): \`${!OPTIND}': unknown argument" \
|
|
Packit |
8462d6 |
1>&2; return 1
|
|
Packit |
8462d6 |
esac
|
|
Packit |
8462d6 |
let "OPTIND += 1"
|
|
Packit |
8462d6 |
done
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
__get_cword_at_cursor_by_ref "$exclude" words cword cur
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
[[ $vcur ]] && { upvars+=("$vcur" ); upargs+=(-v $vcur "$cur" ); }
|
|
Packit |
8462d6 |
[[ $vcword ]] && { upvars+=("$vcword"); upargs+=(-v $vcword "$cword"); }
|
|
Packit |
8462d6 |
[[ $vprev && $cword -ge 1 ]] && { upvars+=("$vprev" ); upargs+=(-v $vprev
|
|
Packit |
8462d6 |
"${words[cword - 1]}"); }
|
|
Packit |
8462d6 |
[[ $vwords ]] && { upvars+=("$vwords"); upargs+=(-a${#words[@]} $vwords
|
|
Packit |
8462d6 |
"${words[@]}"); }
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
(( ${#upvars[@]} )) && local "${upvars[@]}" && _upvars "${upargs[@]}"
|
|
Packit |
8462d6 |
}
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# Get the word to complete.
|
|
Packit |
8462d6 |
# This is nicer than ${COMP_WORDS[$COMP_CWORD]}, since it handles cases
|
|
Packit |
8462d6 |
# where the user is completing in the middle of a word.
|
|
Packit |
8462d6 |
# (For example, if the line is "ls foobar",
|
|
Packit |
8462d6 |
# and the cursor is here --------> ^
|
|
Packit |
8462d6 |
# @param $1 string Characters out of $COMP_WORDBREAKS which should NOT be
|
|
Packit |
8462d6 |
# considered word breaks. This is useful for things like scp where
|
|
Packit |
8462d6 |
# we want to return host:path and not only path, so we would pass the
|
|
Packit |
8462d6 |
# colon (:) as $1 in this case.
|
|
Packit |
8462d6 |
# @param $2 integer Index number of word to return, negatively offset to the
|
|
Packit |
8462d6 |
# current word (default is 0, previous is 1), respecting the exclusions
|
|
Packit |
8462d6 |
# given at $1. For example, `_get_cword "=:" 1' returns the word left of
|
|
Packit |
8462d6 |
# the current word, respecting the exclusions "=:".
|
|
Packit |
8462d6 |
# @deprecated Use `_get_comp_words_by_ref cur' instead
|
|
Packit |
8462d6 |
# @see _get_comp_words_by_ref()
|
|
Packit |
8462d6 |
_get_cword()
|
|
Packit |
8462d6 |
{
|
|
Packit |
8462d6 |
local LC_CTYPE=C
|
|
Packit |
8462d6 |
local cword words
|
|
Packit |
8462d6 |
__reassemble_comp_words_by_ref "$1" words cword
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# return previous word offset by $2
|
|
Packit |
8462d6 |
if [[ ${2//[^0-9]/} ]]; then
|
|
Packit |
8462d6 |
printf "%s" "${words[cword-$2]}"
|
|
Packit |
8462d6 |
elif [[ "${#words[cword]}" -eq 0 || "$COMP_POINT" == "${#COMP_LINE}" ]]; then
|
|
Packit |
8462d6 |
printf "%s" "${words[cword]}"
|
|
Packit |
8462d6 |
else
|
|
Packit |
8462d6 |
local i
|
|
Packit |
8462d6 |
local cur="$COMP_LINE"
|
|
Packit |
8462d6 |
local index="$COMP_POINT"
|
|
Packit |
8462d6 |
for (( i = 0; i <= cword; ++i )); do
|
|
Packit |
8462d6 |
while [[
|
|
Packit |
8462d6 |
# Current word fits in $cur?
|
|
Packit |
8462d6 |
"${#cur}" -ge ${#words[i]} &&
|
|
Packit |
8462d6 |
# $cur doesn't match cword?
|
|
Packit |
8462d6 |
"${cur:0:${#words[i]}}" != "${words[i]}"
|
|
Packit |
8462d6 |
]]; do
|
|
Packit |
8462d6 |
# Strip first character
|
|
Packit |
8462d6 |
cur="${cur:1}"
|
|
Packit |
8462d6 |
# Decrease cursor position, staying >= 0
|
|
Packit |
8462d6 |
[[ $index -gt 0 ]] && ((index--))
|
|
Packit |
8462d6 |
done
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# Does found word matches cword?
|
|
Packit |
8462d6 |
if [[ "$i" -lt "$cword" ]]; then
|
|
Packit |
8462d6 |
# No, cword lies further;
|
|
Packit |
8462d6 |
local old_size="${#cur}"
|
|
Packit |
8462d6 |
cur="${cur#${words[i]}}"
|
|
Packit |
8462d6 |
local new_size="${#cur}"
|
|
Packit |
8462d6 |
index=$(( index - old_size + new_size ))
|
|
Packit |
8462d6 |
fi
|
|
Packit |
8462d6 |
done
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
if [[ "${words[cword]:0:${#cur}}" != "$cur" ]]; then
|
|
Packit |
8462d6 |
# We messed up! At least return the whole word so things
|
|
Packit |
8462d6 |
# keep working
|
|
Packit |
8462d6 |
printf "%s" "${words[cword]}"
|
|
Packit |
8462d6 |
else
|
|
Packit |
8462d6 |
printf "%s" "${cur:0:$index}"
|
|
Packit |
8462d6 |
fi
|
|
Packit |
8462d6 |
fi
|
|
Packit |
8462d6 |
} # _get_cword()
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# Get word previous to the current word.
|
|
Packit |
8462d6 |
# This is a good alternative to `prev=${COMP_WORDS[COMP_CWORD-1]}' because bash4
|
|
Packit |
8462d6 |
# will properly return the previous word with respect to any given exclusions to
|
|
Packit |
8462d6 |
# COMP_WORDBREAKS.
|
|
Packit |
8462d6 |
# @deprecated Use `_get_comp_words_by_ref cur prev' instead
|
|
Packit |
8462d6 |
# @see _get_comp_words_by_ref()
|
|
Packit |
8462d6 |
#
|
|
Packit |
8462d6 |
_get_pword()
|
|
Packit |
8462d6 |
{
|
|
Packit |
8462d6 |
if [[ $COMP_CWORD -ge 1 ]]; then
|
|
Packit |
8462d6 |
_get_cword "${@:-}" 1
|
|
Packit |
8462d6 |
fi
|
|
Packit |
8462d6 |
}
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# If the word-to-complete contains a colon (:), left-trim COMPREPLY items with
|
|
Packit |
8462d6 |
# word-to-complete.
|
|
Packit |
8462d6 |
# With a colon in COMP_WORDBREAKS, words containing
|
|
Packit |
8462d6 |
# colons are always completed as entire words if the word to complete contains
|
|
Packit |
8462d6 |
# a colon. This function fixes this, by removing the colon-containing-prefix
|
|
Packit |
8462d6 |
# from COMPREPLY items.
|
|
Packit |
8462d6 |
# The preferred solution is to remove the colon (:) from COMP_WORDBREAKS in
|
|
Packit |
8462d6 |
# your .bashrc:
|
|
Packit |
8462d6 |
#
|
|
Packit |
8462d6 |
# # Remove colon (:) from list of word completion separators
|
|
Packit |
8462d6 |
# COMP_WORDBREAKS=${COMP_WORDBREAKS//:}
|
|
Packit |
8462d6 |
#
|
|
Packit |
8462d6 |
# See also: Bash FAQ - E13) Why does filename completion misbehave if a colon
|
|
Packit |
8462d6 |
# appears in the filename? - http://tiswww.case.edu/php/chet/bash/FAQ
|
|
Packit |
8462d6 |
# @param $1 current word to complete (cur)
|
|
Packit |
8462d6 |
# @modifies global array $COMPREPLY
|
|
Packit |
8462d6 |
#
|
|
Packit |
8462d6 |
__ltrim_colon_completions()
|
|
Packit |
8462d6 |
{
|
|
Packit |
8462d6 |
if [[ "$1" == *:* && "$COMP_WORDBREAKS" == *:* ]]; then
|
|
Packit |
8462d6 |
# Remove colon-word prefix from COMPREPLY items
|
|
Packit |
8462d6 |
local colon_word=${1%"${1##*:}"}
|
|
Packit |
8462d6 |
local i=${#COMPREPLY[*]}
|
|
Packit |
8462d6 |
while [[ $((--i)) -ge 0 ]]; do
|
|
Packit |
8462d6 |
COMPREPLY[$i]=${COMPREPLY[$i]#"$colon_word"}
|
|
Packit |
8462d6 |
done
|
|
Packit |
8462d6 |
fi
|
|
Packit |
8462d6 |
} # __ltrim_colon_completions()
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# This function quotes the argument in a way so that readline dequoting
|
|
Packit |
8462d6 |
# results in the original argument. This is necessary for at least
|
|
Packit |
8462d6 |
# `compgen' which requires its arguments quoted/escaped:
|
|
Packit |
8462d6 |
#
|
|
Packit |
8462d6 |
# $ ls "a'b/"
|
|
Packit |
8462d6 |
# c
|
|
Packit |
8462d6 |
# $ compgen -f "a'b/" # Wrong, doesn't return output
|
|
Packit |
8462d6 |
# $ compgen -f "a\'b/" # Good
|
|
Packit |
8462d6 |
# a\'b/c
|
|
Packit |
8462d6 |
#
|
|
Packit |
8462d6 |
# See also:
|
|
Packit |
8462d6 |
# - http://lists.gnu.org/archive/html/bug-bash/2009-03/msg00155.html
|
|
Packit |
8462d6 |
# - http://www.mail-archive.com/bash-completion-devel@lists.alioth.\
|
|
Packit |
8462d6 |
# debian.org/msg01944.html
|
|
Packit |
8462d6 |
# @param $1 Argument to quote
|
|
Packit |
8462d6 |
# @param $2 Name of variable to return result to
|
|
Packit |
8462d6 |
_quote_readline_by_ref()
|
|
Packit |
8462d6 |
{
|
|
Packit |
8462d6 |
if [[ $1 == \'* ]]; then
|
|
Packit |
8462d6 |
# Leave out first character
|
|
Packit |
8462d6 |
printf -v $2 %s "${1:1}"
|
|
Packit |
8462d6 |
else
|
|
Packit |
8462d6 |
printf -v $2 %q "$1"
|
|
Packit |
8462d6 |
fi
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# If result becomes quoted like this: $'string', re-evaluate in order to
|
|
Packit |
8462d6 |
# drop the additional quoting. See also: http://www.mail-archive.com/
|
|
Packit |
8462d6 |
# bash-completion-devel@lists.alioth.debian.org/msg01942.html
|
|
Packit |
8462d6 |
[[ ${!2} == \$* ]] && eval $2=${!2}
|
|
Packit |
8462d6 |
} # _quote_readline_by_ref()
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# This function performs file and directory completion. It's better than
|
|
Packit |
8462d6 |
# simply using 'compgen -f', because it honours spaces in filenames.
|
|
Packit |
8462d6 |
# @param $1 If `-d', complete only on directories. Otherwise filter/pick only
|
|
Packit |
8462d6 |
# completions with `.$1' and the uppercase version of it as file
|
|
Packit |
8462d6 |
# extension.
|
|
Packit |
8462d6 |
#
|
|
Packit |
8462d6 |
_filedir()
|
|
Packit |
8462d6 |
{
|
|
Packit |
8462d6 |
local IFS=$'\n'
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
_tilde "$cur" || return
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
local -a toks
|
|
Packit |
8462d6 |
local x tmp
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
x=$( compgen -d -- "$cur" ) &&
|
|
Packit |
8462d6 |
while read -r tmp; do
|
|
Packit |
8462d6 |
toks+=( "$tmp" )
|
|
Packit |
8462d6 |
done <<< "$x"
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
if [[ "$1" != -d ]]; then
|
|
Packit |
8462d6 |
local quoted
|
|
Packit |
8462d6 |
_quote_readline_by_ref "$cur" quoted
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# Munge xspec to contain uppercase version too
|
|
Packit |
8462d6 |
# http://thread.gmane.org/gmane.comp.shells.bash.bugs/15294/focus=15306
|
|
Packit |
8462d6 |
local xspec=${1:+"!*.@($1|${1^^})"}
|
|
Packit |
8462d6 |
x=$( compgen -f -X "$xspec" -- $quoted ) &&
|
|
Packit |
8462d6 |
while read -r tmp; do
|
|
Packit |
8462d6 |
toks+=( "$tmp" )
|
|
Packit |
8462d6 |
done <<< "$x"
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# Try without filter if it failed to produce anything and configured to
|
|
Packit |
8462d6 |
[[ -n ${COMP_FILEDIR_FALLBACK:-} && -n "$1" && ${#toks[@]} -lt 1 ]] && \
|
|
Packit |
8462d6 |
x=$( compgen -f -- $quoted ) &&
|
|
Packit |
8462d6 |
while read -r tmp; do
|
|
Packit |
8462d6 |
toks+=( "$tmp" )
|
|
Packit |
8462d6 |
done <<< "$x"
|
|
Packit |
8462d6 |
fi
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
if [[ ${#toks[@]} -ne 0 ]]; then
|
|
Packit |
8462d6 |
# 2>/dev/null for direct invocation, e.g. in the _filedir unit test
|
|
Packit |
8462d6 |
compopt -o filenames 2>/dev/null
|
|
Packit |
8462d6 |
COMPREPLY+=( "${toks[@]}" )
|
|
Packit |
8462d6 |
fi
|
|
Packit |
8462d6 |
} # _filedir()
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# This function splits $cur=--foo=bar into $prev=--foo, $cur=bar, making it
|
|
Packit |
8462d6 |
# easier to support both "--foo bar" and "--foo=bar" style completions.
|
|
Packit |
8462d6 |
# `=' should have been removed from COMP_WORDBREAKS when setting $cur for
|
|
Packit |
8462d6 |
# this to be useful.
|
|
Packit |
8462d6 |
# Returns 0 if current option was split, 1 otherwise.
|
|
Packit |
8462d6 |
#
|
|
Packit |
8462d6 |
_split_longopt()
|
|
Packit |
8462d6 |
{
|
|
Packit |
8462d6 |
if [[ "$cur" == --?*=* ]]; then
|
|
Packit |
8462d6 |
# Cut also backslash before '=' in case it ended up there
|
|
Packit |
8462d6 |
# for some reason.
|
|
Packit |
8462d6 |
prev="${cur%%?(\\)=*}"
|
|
Packit |
8462d6 |
cur="${cur#*=}"
|
|
Packit |
8462d6 |
return 0
|
|
Packit |
8462d6 |
fi
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
return 1
|
|
Packit |
8462d6 |
}
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# Complete variables.
|
|
Packit |
8462d6 |
# @return True (0) if variables were completed,
|
|
Packit |
8462d6 |
# False (> 0) if not.
|
|
Packit |
8462d6 |
_variables()
|
|
Packit |
8462d6 |
{
|
|
Packit |
8462d6 |
if [[ $cur =~ ^(\$(\{[!#]?)?)([A-Za-z0-9_]*)$ ]]; then
|
|
Packit |
8462d6 |
# Completing $var / ${var / ${!var / ${#var
|
|
Packit |
8462d6 |
if [[ $cur == \${* ]]; then
|
|
Packit |
8462d6 |
local arrs vars
|
|
Packit |
8462d6 |
vars=( $( compgen -A variable -P ${BASH_REMATCH[1]} -S '}' -- ${BASH_REMATCH[3]} ) ) && \
|
|
Packit |
8462d6 |
arrs=( $( compgen -A arrayvar -P ${BASH_REMATCH[1]} -S '[' -- ${BASH_REMATCH[3]} ) )
|
|
Packit |
8462d6 |
if [[ ${#vars[@]} -eq 1 && $arrs ]]; then
|
|
Packit |
8462d6 |
# Complete ${arr with ${array[ if there is only one match, and that match is an array variable
|
|
Packit |
8462d6 |
compopt -o nospace
|
|
Packit |
8462d6 |
COMPREPLY+=( ${arrs[*]} )
|
|
Packit |
8462d6 |
else
|
|
Packit |
8462d6 |
# Complete ${var with ${variable}
|
|
Packit |
8462d6 |
COMPREPLY+=( ${vars[*]} )
|
|
Packit |
8462d6 |
fi
|
|
Packit |
8462d6 |
else
|
|
Packit |
8462d6 |
# Complete $var with $variable
|
|
Packit |
8462d6 |
COMPREPLY+=( $( compgen -A variable -P '$' -- "${BASH_REMATCH[3]}" ) )
|
|
Packit |
8462d6 |
fi
|
|
Packit |
8462d6 |
return 0
|
|
Packit |
8462d6 |
elif [[ $cur =~ ^(\$\{[#!]?)([A-Za-z0-9_]*)\[([^]]*)$ ]]; then
|
|
Packit |
8462d6 |
# Complete ${array[i with ${array[idx]}
|
|
Packit |
8462d6 |
local IFS=$'\n'
|
|
Packit |
8462d6 |
COMPREPLY+=( $( compgen -W '$(printf %s\\n "${!'${BASH_REMATCH[2]}'[@]}")' \
|
|
Packit |
8462d6 |
-P "${BASH_REMATCH[1]}${BASH_REMATCH[2]}[" -S ']}' -- "${BASH_REMATCH[3]}" ) )
|
|
Packit |
8462d6 |
# Complete ${arr[@ and ${arr[*
|
|
Packit |
8462d6 |
if [[ ${BASH_REMATCH[3]} == [@*] ]]; then
|
|
Packit |
8462d6 |
COMPREPLY+=( "${BASH_REMATCH[1]}${BASH_REMATCH[2]}[${BASH_REMATCH[3]}]}" )
|
|
Packit |
8462d6 |
fi
|
|
Packit |
8462d6 |
__ltrim_colon_completions "$cur" # array indexes may have colons
|
|
Packit |
8462d6 |
return 0
|
|
Packit |
8462d6 |
elif [[ $cur =~ ^\$\{[#!]?[A-Za-z0-9_]*\[.*\]$ ]]; then
|
|
Packit |
8462d6 |
# Complete ${array[idx] with ${array[idx]}
|
|
Packit |
8462d6 |
COMPREPLY+=( "$cur}" )
|
|
Packit |
8462d6 |
__ltrim_colon_completions "$cur"
|
|
Packit |
8462d6 |
return 0
|
|
Packit |
8462d6 |
else
|
|
Packit |
8462d6 |
case $prev in
|
|
Packit |
8462d6 |
TZ)
|
|
Packit |
8462d6 |
cur=/usr/share/zoneinfo/$cur
|
|
Packit |
8462d6 |
_filedir
|
|
Packit |
8462d6 |
for i in ${!COMPREPLY[@]}; do
|
|
Packit |
8462d6 |
if [[ ${COMPREPLY[i]} == *.tab ]]; then
|
|
Packit |
8462d6 |
unset 'COMPREPLY[i]'
|
|
Packit |
8462d6 |
continue
|
|
Packit |
8462d6 |
elif [[ -d ${COMPREPLY[i]} ]]; then
|
|
Packit |
8462d6 |
COMPREPLY[i]+=/
|
|
Packit |
8462d6 |
compopt -o nospace
|
|
Packit |
8462d6 |
fi
|
|
Packit |
8462d6 |
COMPREPLY[i]=${COMPREPLY[i]#/usr/share/zoneinfo/}
|
|
Packit |
8462d6 |
done
|
|
Packit |
8462d6 |
return 0
|
|
Packit |
8462d6 |
;;
|
|
Packit |
8462d6 |
esac
|
|
Packit |
8462d6 |
fi
|
|
Packit |
8462d6 |
return 1
|
|
Packit |
8462d6 |
}
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# Initialize completion and deal with various general things: do file
|
|
Packit |
8462d6 |
# and variable completion where appropriate, and adjust prev, words,
|
|
Packit |
8462d6 |
# and cword as if no redirections exist so that completions do not
|
|
Packit |
8462d6 |
# need to deal with them. Before calling this function, make sure
|
|
Packit |
8462d6 |
# cur, prev, words, and cword are local, ditto split if you use -s.
|
|
Packit |
8462d6 |
#
|
|
Packit |
8462d6 |
# Options:
|
|
Packit |
8462d6 |
# -n EXCLUDE Passed to _get_comp_words_by_ref -n with redirection chars
|
|
Packit |
8462d6 |
# -e XSPEC Passed to _filedir as first arg for stderr redirections
|
|
Packit |
8462d6 |
# -o XSPEC Passed to _filedir as first arg for other output redirections
|
|
Packit |
8462d6 |
# -i XSPEC Passed to _filedir as first arg for stdin redirections
|
|
Packit |
8462d6 |
# -s Split long options with _split_longopt, implies -n =
|
|
Packit |
8462d6 |
# @return True (0) if completion needs further processing,
|
|
Packit |
8462d6 |
# False (> 0) no further processing is necessary.
|
|
Packit |
8462d6 |
#
|
|
Packit |
8462d6 |
_init_completion()
|
|
Packit |
8462d6 |
{
|
|
Packit |
8462d6 |
local exclude= flag outx errx inx OPTIND=1
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
while getopts "n:e:o:i:s" flag "$@"; do
|
|
Packit |
8462d6 |
case $flag in
|
|
Packit |
8462d6 |
n) exclude+=$OPTARG ;;
|
|
Packit |
8462d6 |
e) errx=$OPTARG ;;
|
|
Packit |
8462d6 |
o) outx=$OPTARG ;;
|
|
Packit |
8462d6 |
i) inx=$OPTARG ;;
|
|
Packit |
8462d6 |
s) split=false ; exclude+== ;;
|
|
Packit |
8462d6 |
esac
|
|
Packit |
8462d6 |
done
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# For some reason completion functions are not invoked at all by
|
|
Packit |
8462d6 |
# bash (at least as of 4.1.7) after the command line contains an
|
|
Packit |
8462d6 |
# ampersand so we don't get a chance to deal with redirections
|
|
Packit |
8462d6 |
# containing them, but if we did, hopefully the below would also
|
|
Packit |
8462d6 |
# do the right thing with them...
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
COMPREPLY=()
|
|
Packit |
8462d6 |
local redir="@(?([0-9])<|?([0-9&])>?(>)|>&)"
|
|
Packit |
8462d6 |
_get_comp_words_by_ref -n "$exclude<>&" cur prev words cword
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# Complete variable names.
|
|
Packit |
8462d6 |
_variables && return 1
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# Complete on files if current is a redirect possibly followed by a
|
|
Packit |
8462d6 |
# filename, e.g. ">foo", or previous is a "bare" redirect, e.g. ">".
|
|
Packit |
8462d6 |
if [[ $cur == $redir* || $prev == $redir ]]; then
|
|
Packit |
8462d6 |
local xspec
|
|
Packit |
8462d6 |
case $cur in
|
|
Packit |
8462d6 |
2'>'*) xspec=$errx ;;
|
|
Packit |
8462d6 |
*'>'*) xspec=$outx ;;
|
|
Packit |
8462d6 |
*'<'*) xspec=$inx ;;
|
|
Packit |
8462d6 |
*)
|
|
Packit |
8462d6 |
case $prev in
|
|
Packit |
8462d6 |
2'>'*) xspec=$errx ;;
|
|
Packit |
8462d6 |
*'>'*) xspec=$outx ;;
|
|
Packit |
8462d6 |
*'<'*) xspec=$inx ;;
|
|
Packit |
8462d6 |
esac
|
|
Packit |
8462d6 |
;;
|
|
Packit |
8462d6 |
esac
|
|
Packit |
8462d6 |
cur="${cur##$redir}"
|
|
Packit |
8462d6 |
_filedir $xspec
|
|
Packit |
8462d6 |
return 1
|
|
Packit |
8462d6 |
fi
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# Remove all redirections so completions don't have to deal with them.
|
|
Packit |
8462d6 |
local i skip
|
|
Packit |
8462d6 |
for (( i=1; i < ${#words[@]}; )); do
|
|
Packit |
8462d6 |
if [[ ${words[i]} == $redir* ]]; then
|
|
Packit |
8462d6 |
# If "bare" redirect, remove also the next word (skip=2).
|
|
Packit |
8462d6 |
[[ ${words[i]} == $redir ]] && skip=2 || skip=1
|
|
Packit |
8462d6 |
words=( "${words[@]:0:i}" "${words[@]:i+skip}" )
|
|
Packit |
8462d6 |
[[ $i -le $cword ]] && cword=$(( cword - skip ))
|
|
Packit |
8462d6 |
else
|
|
Packit |
8462d6 |
i=$(( ++i ))
|
|
Packit |
8462d6 |
fi
|
|
Packit |
8462d6 |
done
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
[[ $cword -le 0 ]] && return 1
|
|
Packit |
8462d6 |
prev=${words[cword-1]}
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
[[ ${split-} ]] && _split_longopt && split=true
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
return 0
|
|
Packit |
8462d6 |
}
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# Helper function for _parse_help and _parse_usage.
|
|
Packit |
8462d6 |
__parse_options()
|
|
Packit |
8462d6 |
{
|
|
Packit |
8462d6 |
local option option2 i IFS=$' \t\n,/|'
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# Take first found long option, or first one (short) if not found.
|
|
Packit |
8462d6 |
option=
|
|
Packit |
8462d6 |
local -a array
|
|
Packit |
8462d6 |
read -a array <<<"$1"
|
|
Packit |
8462d6 |
for i in "${array[@]}"; do
|
|
Packit |
8462d6 |
case "$i" in
|
|
Packit |
8462d6 |
---*) break ;;
|
|
Packit |
8462d6 |
--?*) option=$i ; break ;;
|
|
Packit |
8462d6 |
-?*) [[ $option ]] || option=$i ;;
|
|
Packit |
8462d6 |
*) break ;;
|
|
Packit |
8462d6 |
esac
|
|
Packit |
8462d6 |
done
|
|
Packit |
8462d6 |
[[ $option ]] || return
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
IFS=$' \t\n' # affects parsing of the regexps below...
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# Expand --[no]foo to --foo and --nofoo etc
|
|
Packit |
8462d6 |
if [[ $option =~ (\[((no|dont)-?)\]). ]]; then
|
|
Packit |
8462d6 |
option2=${option/"${BASH_REMATCH[1]}"/}
|
|
Packit |
8462d6 |
option2=${option2%%[<{().[]*}
|
|
Packit |
8462d6 |
printf '%s\n' "${option2/=*/=}"
|
|
Packit |
8462d6 |
option=${option/"${BASH_REMATCH[1]}"/"${BASH_REMATCH[2]}"}
|
|
Packit |
8462d6 |
fi
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
option=${option%%[<{().[]*}
|
|
Packit |
8462d6 |
printf '%s\n' "${option/=*/=}"
|
|
Packit |
8462d6 |
}
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# Parse GNU style help output of the given command.
|
|
Packit |
8462d6 |
# @param $1 command; if "-", read from stdin and ignore rest of args
|
|
Packit |
8462d6 |
# @param $2 command options (default: --help)
|
|
Packit |
8462d6 |
#
|
|
Packit |
8462d6 |
_parse_help()
|
|
Packit |
8462d6 |
{
|
|
Packit |
8462d6 |
eval local cmd=$( quote "$1" )
|
|
Packit |
8462d6 |
local line
|
|
Packit |
8462d6 |
{ case $cmd in
|
|
Packit |
8462d6 |
-) cat ;;
|
|
Packit |
8462d6 |
*) LC_ALL=C "$( dequote "$cmd" )" ${2:---help} 2>&1 ;;
|
|
Packit |
8462d6 |
esac } \
|
|
Packit |
8462d6 |
| while read -r line; do
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
[[ $line == *([[:blank:]])-* ]] || continue
|
|
Packit |
8462d6 |
# transform "-f FOO, --foo=FOO" to "-f , --foo=FOO" etc
|
|
Packit |
8462d6 |
while [[ $line =~ \
|
|
Packit |
8462d6 |
((^|[^-])-[A-Za-z0-9?][[:space:]]+)\[?[A-Z0-9]+\]? ]]; do
|
|
Packit |
8462d6 |
line=${line/"${BASH_REMATCH[0]}"/"${BASH_REMATCH[1]}"}
|
|
Packit |
8462d6 |
done
|
|
Packit |
8462d6 |
__parse_options "${line// or /, }"
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
done
|
|
Packit |
8462d6 |
}
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# Parse BSD style usage output (options in brackets) of the given command.
|
|
Packit |
8462d6 |
# @param $1 command; if "-", read from stdin and ignore rest of args
|
|
Packit |
8462d6 |
# @param $2 command options (default: --usage)
|
|
Packit |
8462d6 |
#
|
|
Packit |
8462d6 |
_parse_usage()
|
|
Packit |
8462d6 |
{
|
|
Packit |
8462d6 |
eval local cmd=$( quote "$1" )
|
|
Packit |
8462d6 |
local line match option i char
|
|
Packit |
8462d6 |
{ case $cmd in
|
|
Packit |
8462d6 |
-) cat ;;
|
|
Packit |
8462d6 |
*) LC_ALL=C "$( dequote "$cmd" )" ${2:---usage} 2>&1 ;;
|
|
Packit |
8462d6 |
esac } \
|
|
Packit |
8462d6 |
| while read -r line; do
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
while [[ $line =~ \[[[:space:]]*(-[^]]+)[[:space:]]*\] ]]; do
|
|
Packit |
8462d6 |
match=${BASH_REMATCH[0]}
|
|
Packit |
8462d6 |
option=${BASH_REMATCH[1]}
|
|
Packit |
8462d6 |
case $option in
|
|
Packit |
8462d6 |
-?(\[)+([a-zA-Z0-9?]))
|
|
Packit |
8462d6 |
# Treat as bundled short options
|
|
Packit |
8462d6 |
for (( i=1; i < ${#option}; i++ )); do
|
|
Packit |
8462d6 |
char=${option:i:1}
|
|
Packit |
8462d6 |
[[ $char != '[' ]] && printf '%s\n' -$char
|
|
Packit |
8462d6 |
done
|
|
Packit |
8462d6 |
;;
|
|
Packit |
8462d6 |
*)
|
|
Packit |
8462d6 |
__parse_options "$option"
|
|
Packit |
8462d6 |
;;
|
|
Packit |
8462d6 |
esac
|
|
Packit |
8462d6 |
line=${line#*"$match"}
|
|
Packit |
8462d6 |
done
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
done
|
|
Packit |
8462d6 |
}
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# This function completes on signal names (minus the SIG prefix)
|
|
Packit |
8462d6 |
# @param $1 prefix
|
|
Packit |
8462d6 |
_signals()
|
|
Packit |
8462d6 |
{
|
|
Packit |
8462d6 |
local -a sigs=( $( compgen -P "$1" -A signal "SIG${cur#$1}" ) )
|
|
Packit |
8462d6 |
COMPREPLY+=( "${sigs[@]/#${1}SIG/${1}}" )
|
|
Packit |
8462d6 |
}
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# This function completes on known mac addresses
|
|
Packit |
8462d6 |
#
|
|
Packit |
8462d6 |
_mac_addresses()
|
|
Packit |
8462d6 |
{
|
|
Packit |
8462d6 |
local re='\([A-Fa-f0-9]\{2\}:\)\{5\}[A-Fa-f0-9]\{2\}'
|
|
Packit |
8462d6 |
local PATH="$PATH:/sbin:/usr/sbin"
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# Local interfaces
|
|
Packit |
8462d6 |
# - ifconfig on Linux: HWaddr or ether
|
|
Packit |
8462d6 |
# - ifconfig on FreeBSD: ether
|
|
Packit |
8462d6 |
# - ip link: link/ether
|
|
Packit |
8462d6 |
COMPREPLY+=( $( \
|
|
Packit |
8462d6 |
{ LC_ALL=C ifconfig -a || ip link show; } 2>/dev/null | command sed -ne \
|
|
Packit |
8462d6 |
"s/.*[[:space:]]HWaddr[[:space:]]\{1,\}\($re\)[[:space:]].*/\1/p" -ne \
|
|
Packit |
8462d6 |
"s/.*[[:space:]]HWaddr[[:space:]]\{1,\}\($re\)[[:space:]]*$/\1/p" -ne \
|
|
Packit |
8462d6 |
"s|.*[[:space:]]\(link/\)\{0,1\}ether[[:space:]]\{1,\}\($re\)[[:space:]].*|\2|p" -ne \
|
|
Packit |
8462d6 |
"s|.*[[:space:]]\(link/\)\{0,1\}ether[[:space:]]\{1,\}\($re\)[[:space:]]*$|\2|p"
|
|
Packit |
8462d6 |
) )
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# ARP cache
|
|
Packit |
8462d6 |
COMPREPLY+=( $( { arp -an || ip neigh show; } 2>/dev/null | command sed -ne \
|
|
Packit |
8462d6 |
"s/.*[[:space:]]\($re\)[[:space:]].*/\1/p" -ne \
|
|
Packit |
8462d6 |
"s/.*[[:space:]]\($re\)[[:space:]]*$/\1/p" ) )
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# /etc/ethers
|
|
Packit |
8462d6 |
COMPREPLY+=( $( command sed -ne \
|
|
Packit |
8462d6 |
"s/^[[:space:]]*\($re\)[[:space:]].*/\1/p" /etc/ethers 2>/dev/null ) )
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
COMPREPLY=( $( compgen -W '${COMPREPLY[@]}' -- "$cur" ) )
|
|
Packit |
8462d6 |
__ltrim_colon_completions "$cur"
|
|
Packit |
8462d6 |
}
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# This function completes on configured network interfaces
|
|
Packit |
8462d6 |
#
|
|
Packit |
8462d6 |
_configured_interfaces()
|
|
Packit |
8462d6 |
{
|
|
Packit |
8462d6 |
if [[ -f /etc/debian_version ]]; then
|
|
Packit |
8462d6 |
# Debian system
|
|
Packit |
8462d6 |
COMPREPLY=( $( compgen -W "$( command sed -ne 's|^iface \([^ ]\{1,\}\).*$|\1|p'\
|
|
Packit |
8462d6 |
/etc/network/interfaces /etc/network/interfaces.d/* 2>/dev/null )" \
|
|
Packit |
8462d6 |
-- "$cur" ) )
|
|
Packit |
8462d6 |
elif [[ -f /etc/SuSE-release ]]; then
|
|
Packit |
8462d6 |
# SuSE system
|
|
Packit |
8462d6 |
COMPREPLY=( $( compgen -W "$( printf '%s\n' \
|
|
Packit |
8462d6 |
/etc/sysconfig/network/ifcfg-* | \
|
|
Packit |
8462d6 |
command sed -ne 's|.*ifcfg-\([^*].*\)$|\1|p' )" -- "$cur" ) )
|
|
Packit |
8462d6 |
elif [[ -f /etc/pld-release ]]; then
|
|
Packit |
8462d6 |
# PLD Linux
|
|
Packit |
8462d6 |
COMPREPLY=( $( compgen -W "$( command ls -B \
|
|
Packit |
8462d6 |
/etc/sysconfig/interfaces | \
|
|
Packit |
8462d6 |
command sed -ne 's|.*ifcfg-\([^*].*\)$|\1|p' )" -- "$cur" ) )
|
|
Packit |
8462d6 |
else
|
|
Packit |
8462d6 |
# Assume Red Hat
|
|
Packit |
8462d6 |
COMPREPLY=( $( compgen -W "$( printf '%s\n' \
|
|
Packit |
8462d6 |
/etc/sysconfig/network-scripts/ifcfg-* | \
|
|
Packit |
8462d6 |
command sed -ne 's|.*ifcfg-\([^*].*\)$|\1|p' )" -- "$cur" ) )
|
|
Packit |
8462d6 |
fi
|
|
Packit |
8462d6 |
}
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# Local IP addresses.
|
|
Packit |
8462d6 |
#
|
|
Packit |
8462d6 |
_ip_addresses()
|
|
Packit |
8462d6 |
{
|
|
Packit |
8462d6 |
local PATH=$PATH:/sbin
|
|
Packit |
8462d6 |
COMPREPLY+=( $( compgen -W \
|
|
Packit |
8462d6 |
"$( { LC_ALL=C ifconfig -a || ip addr show; } 2>/dev/null | command sed -ne \
|
|
Packit |
8462d6 |
's/.*addr:\([^[:space:]]*\).*/\1/p' -ne \
|
|
Packit |
8462d6 |
's|.*inet[[:space:]]\{1,\}\([^[:space:]/]*\).*|\1|p' )" \
|
|
Packit |
8462d6 |
-- "$cur" ) )
|
|
Packit |
8462d6 |
}
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# This function completes on available kernels
|
|
Packit |
8462d6 |
#
|
|
Packit |
8462d6 |
_kernel_versions()
|
|
Packit |
8462d6 |
{
|
|
Packit |
8462d6 |
COMPREPLY=( $( compgen -W '$( command ls /lib/modules )' -- "$cur" ) )
|
|
Packit |
8462d6 |
}
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# This function completes on all available network interfaces
|
|
Packit |
8462d6 |
# -a: restrict to active interfaces only
|
|
Packit |
8462d6 |
# -w: restrict to wireless interfaces only
|
|
Packit |
8462d6 |
#
|
|
Packit |
8462d6 |
_available_interfaces()
|
|
Packit |
8462d6 |
{
|
|
Packit |
8462d6 |
local cmd PATH=$PATH:/sbin
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
if [[ ${1:-} == -w ]]; then
|
|
Packit |
8462d6 |
cmd="iwconfig"
|
|
Packit |
8462d6 |
elif [[ ${1:-} == -a ]]; then
|
|
Packit |
8462d6 |
cmd="{ ifconfig || ip link show up; }"
|
|
Packit |
8462d6 |
else
|
|
Packit |
8462d6 |
cmd="{ ifconfig -a || ip link show; }"
|
|
Packit |
8462d6 |
fi
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
COMPREPLY=( $( eval $cmd 2>/dev/null | awk \
|
|
Packit |
8462d6 |
'/^[^ \t]/ { if ($1 ~ /^[0-9]+:/) { print $2 } else { print $1 } }' ) )
|
|
Packit |
8462d6 |
COMPREPLY=( $( compgen -W '${COMPREPLY[@]/%[[:punct:]]/}' -- "$cur" ) )
|
|
Packit |
8462d6 |
}
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# Echo number of CPUs, falling back to 1 on failure.
|
|
Packit |
8462d6 |
_ncpus()
|
|
Packit |
8462d6 |
{
|
|
Packit |
8462d6 |
local var=NPROCESSORS_ONLN
|
|
Packit |
8462d6 |
[[ $OSTYPE == *linux* ]] && var=_$var
|
|
Packit |
8462d6 |
local n=$( getconf $var 2>/dev/null )
|
|
Packit |
8462d6 |
printf %s ${n:-1}
|
|
Packit |
8462d6 |
}
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# Perform tilde (~) completion
|
|
Packit |
8462d6 |
# @return True (0) if completion needs further processing,
|
|
Packit |
8462d6 |
# False (> 0) if tilde is followed by a valid username, completions
|
|
Packit |
8462d6 |
# are put in COMPREPLY and no further processing is necessary.
|
|
Packit |
8462d6 |
_tilde()
|
|
Packit |
8462d6 |
{
|
|
Packit |
8462d6 |
local result=0
|
|
Packit |
8462d6 |
if [[ $1 == \~* && $1 != */* ]]; then
|
|
Packit |
8462d6 |
# Try generate ~username completions
|
|
Packit |
8462d6 |
COMPREPLY=( $( compgen -P '~' -u -- "${1#\~}" ) )
|
|
Packit |
8462d6 |
result=${#COMPREPLY[@]}
|
|
Packit |
8462d6 |
# 2>/dev/null for direct invocation, e.g. in the _tilde unit test
|
|
Packit |
8462d6 |
[[ $result -gt 0 ]] && compopt -o filenames 2>/dev/null
|
|
Packit |
8462d6 |
fi
|
|
Packit |
8462d6 |
return $result
|
|
Packit |
8462d6 |
}
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# Expand variable starting with tilde (~)
|
|
Packit |
8462d6 |
# We want to expand ~foo/... to /home/foo/... to avoid problems when
|
|
Packit |
8462d6 |
# word-to-complete starting with a tilde is fed to commands and ending up
|
|
Packit |
8462d6 |
# quoted instead of expanded.
|
|
Packit |
8462d6 |
# Only the first portion of the variable from the tilde up to the first slash
|
|
Packit |
8462d6 |
# (~../) is expanded. The remainder of the variable, containing for example
|
|
Packit |
8462d6 |
# a dollar sign variable ($) or asterisk (*) is not expanded.
|
|
Packit |
8462d6 |
# Example usage:
|
|
Packit |
8462d6 |
#
|
|
Packit |
8462d6 |
# $ v="~"; __expand_tilde_by_ref v; echo "$v"
|
|
Packit |
8462d6 |
#
|
|
Packit |
8462d6 |
# Example output:
|
|
Packit |
8462d6 |
#
|
|
Packit |
8462d6 |
# v output
|
|
Packit |
8462d6 |
# -------- ----------------
|
|
Packit |
8462d6 |
# ~ /home/user
|
|
Packit |
8462d6 |
# ~foo/bar /home/foo/bar
|
|
Packit |
8462d6 |
# ~foo/$HOME /home/foo/$HOME
|
|
Packit |
8462d6 |
# ~foo/a b /home/foo/a b
|
|
Packit |
8462d6 |
# ~foo/* /home/foo/*
|
|
Packit |
8462d6 |
#
|
|
Packit |
8462d6 |
# @param $1 Name of variable (not the value of the variable) to expand
|
|
Packit |
8462d6 |
__expand_tilde_by_ref()
|
|
Packit |
8462d6 |
{
|
|
Packit |
8462d6 |
# Does $1 start with tilde (~)?
|
|
Packit |
8462d6 |
if [[ ${!1} == \~* ]]; then
|
|
Packit |
8462d6 |
# Does $1 contain slash (/)?
|
|
Packit |
8462d6 |
if [[ ${!1} == */* ]]; then
|
|
Packit |
8462d6 |
# Yes, $1 contains slash;
|
|
Packit |
8462d6 |
# 1: Remove * including and after first slash (/), i.e. "~a/b"
|
|
Packit |
8462d6 |
# becomes "~a". Double quotes allow eval.
|
|
Packit |
8462d6 |
# 2: Remove * before the first slash (/), i.e. "~a/b"
|
|
Packit |
8462d6 |
# becomes "b". Single quotes prevent eval.
|
|
Packit |
8462d6 |
# +-----1----+ +---2----+
|
|
Packit |
8462d6 |
eval $1="${!1/%\/*}"/'${!1#*/}'
|
|
Packit |
8462d6 |
else
|
|
Packit |
8462d6 |
# No, $1 doesn't contain slash
|
|
Packit |
8462d6 |
eval $1="${!1}"
|
|
Packit |
8462d6 |
fi
|
|
Packit |
8462d6 |
fi
|
|
Packit |
8462d6 |
} # __expand_tilde_by_ref()
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# This function expands tildes in pathnames
|
|
Packit |
8462d6 |
#
|
|
Packit |
8462d6 |
_expand()
|
|
Packit |
8462d6 |
{
|
|
Packit |
8462d6 |
# FIXME: Why was this here?
|
|
Packit |
8462d6 |
#[ "$cur" != "${cur%\\}" ] && cur+="\\"
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# Expand ~username type directory specifications. We want to expand
|
|
Packit |
8462d6 |
# ~foo/... to /home/foo/... to avoid problems when $cur starting with
|
|
Packit |
8462d6 |
# a tilde is fed to commands and ending up quoted instead of expanded.
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
if [[ "$cur" == \~*/* ]]; then
|
|
Packit |
8462d6 |
eval cur=$cur 2>/dev/null
|
|
Packit |
8462d6 |
elif [[ "$cur" == \~* ]]; then
|
|
Packit |
8462d6 |
cur=${cur#\~}
|
|
Packit |
8462d6 |
COMPREPLY=( $( compgen -P '~' -u -- "$cur" ) )
|
|
Packit |
8462d6 |
[[ ${#COMPREPLY[@]} -eq 1 ]] && eval COMPREPLY[0]=${COMPREPLY[0]}
|
|
Packit |
8462d6 |
return ${#COMPREPLY[@]}
|
|
Packit |
8462d6 |
fi
|
|
Packit |
8462d6 |
}
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# This function completes on process IDs.
|
|
Packit |
8462d6 |
# AIX and Solaris ps prefers X/Open syntax.
|
|
Packit |
8462d6 |
[[ $OSTYPE == *@(solaris|aix)* ]] &&
|
|
Packit |
8462d6 |
_pids()
|
|
Packit |
8462d6 |
{
|
|
Packit |
8462d6 |
COMPREPLY=( $( compgen -W '$( command ps -efo pid | command sed 1d )' -- "$cur" ))
|
|
Packit |
8462d6 |
} ||
|
|
Packit |
8462d6 |
_pids()
|
|
Packit |
8462d6 |
{
|
|
Packit |
8462d6 |
COMPREPLY=( $( compgen -W '$( command ps axo pid= )' -- "$cur" ) )
|
|
Packit |
8462d6 |
}
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# This function completes on process group IDs.
|
|
Packit |
8462d6 |
# AIX and SunOS prefer X/Open, all else should be BSD.
|
|
Packit |
8462d6 |
[[ $OSTYPE == *@(solaris|aix)* ]] &&
|
|
Packit |
8462d6 |
_pgids()
|
|
Packit |
8462d6 |
{
|
|
Packit |
8462d6 |
COMPREPLY=( $( compgen -W '$( command ps -efo pgid | command sed 1d )' -- "$cur" ))
|
|
Packit |
8462d6 |
} ||
|
|
Packit |
8462d6 |
_pgids()
|
|
Packit |
8462d6 |
{
|
|
Packit |
8462d6 |
COMPREPLY=( $( compgen -W '$( command ps axo pgid= )' -- "$cur" ))
|
|
Packit |
8462d6 |
}
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# This function completes on process names.
|
|
Packit |
8462d6 |
# AIX and SunOS prefer X/Open, all else should be BSD.
|
|
Packit |
8462d6 |
# @param $1 if -s, don't try to avoid truncated command names
|
|
Packit |
8462d6 |
[[ $OSTYPE == *@(solaris|aix)* ]] &&
|
|
Packit |
8462d6 |
_pnames()
|
|
Packit |
8462d6 |
{
|
|
Packit |
8462d6 |
COMPREPLY=( $( compgen -X '<defunct>' -W '$( command ps -efo comm | \
|
|
Packit |
8462d6 |
command sed -e 1d -e "s:.*/::" -e "s/^-//" | sort -u )' -- "$cur" ) )
|
|
Packit |
8462d6 |
} ||
|
|
Packit |
8462d6 |
_pnames()
|
|
Packit |
8462d6 |
{
|
|
Packit |
8462d6 |
if [[ "$1" == -s ]]; then
|
|
Packit |
8462d6 |
COMPREPLY=( $( compgen -X '<defunct>' \
|
|
Packit |
8462d6 |
-W '$( command ps axo comm | command sed -e 1d )' -- "$cur" ) )
|
|
Packit |
8462d6 |
else
|
|
Packit |
8462d6 |
# FIXME: completes "[kblockd/0]" to "0". Previously it was completed
|
|
Packit |
8462d6 |
# to "kblockd" which isn't correct either. "kblockd/0" would be
|
|
Packit |
8462d6 |
# arguably most correct, but killall from psmisc 22 treats arguments
|
|
Packit |
8462d6 |
# containing "/" specially unless -r is given so that wouldn't quite
|
|
Packit |
8462d6 |
# work either. Perhaps it'd be best to not complete these to anything
|
|
Packit |
8462d6 |
# for now.
|
|
Packit |
8462d6 |
COMPREPLY=( $( compgen -X '<defunct>' -W '$( command ps axo command= | command sed -e \
|
|
Packit |
8462d6 |
"s/ .*//" -e \
|
|
Packit |
8462d6 |
"s:.*/::" -e \
|
|
Packit |
8462d6 |
"s/:$//" -e \
|
|
Packit |
8462d6 |
"s/^[[(-]//" -e \
|
|
Packit |
8462d6 |
"s/[])]$//" | sort -u )' -- "$cur" ) )
|
|
Packit |
8462d6 |
fi
|
|
Packit |
8462d6 |
}
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# This function completes on user IDs
|
|
Packit |
8462d6 |
#
|
|
Packit |
8462d6 |
_uids()
|
|
Packit |
8462d6 |
{
|
|
Packit |
8462d6 |
if type getent &>/dev/null; then
|
|
Packit |
8462d6 |
COMPREPLY=( $( compgen -W '$( getent passwd | cut -d: -f3 )' -- "$cur" ) )
|
|
Packit |
8462d6 |
elif type perl &>/dev/null; then
|
|
Packit |
8462d6 |
COMPREPLY=( $( compgen -W '$( perl -e '"'"'while (($uid) = (getpwent)[2]) { print $uid . "\n" }'"'"' )' -- "$cur" ) )
|
|
Packit |
8462d6 |
else
|
|
Packit |
8462d6 |
# make do with /etc/passwd
|
|
Packit |
8462d6 |
COMPREPLY=( $( compgen -W '$( cut -d: -f3 /etc/passwd )' -- "$cur" ) )
|
|
Packit |
8462d6 |
fi
|
|
Packit |
8462d6 |
}
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# This function completes on group IDs
|
|
Packit |
8462d6 |
#
|
|
Packit |
8462d6 |
_gids()
|
|
Packit |
8462d6 |
{
|
|
Packit |
8462d6 |
if type getent &>/dev/null; then
|
|
Packit |
8462d6 |
COMPREPLY=( $( compgen -W '$( getent group | cut -d: -f3 )' \
|
|
Packit |
8462d6 |
-- "$cur" ) )
|
|
Packit |
8462d6 |
elif type perl &>/dev/null; then
|
|
Packit |
8462d6 |
COMPREPLY=( $( compgen -W '$( perl -e '"'"'while (($gid) = (getgrent)[2]) { print $gid . "\n" }'"'"' )' -- "$cur" ) )
|
|
Packit |
8462d6 |
else
|
|
Packit |
8462d6 |
# make do with /etc/group
|
|
Packit |
8462d6 |
COMPREPLY=( $( compgen -W '$( cut -d: -f3 /etc/group )' -- "$cur" ) )
|
|
Packit |
8462d6 |
fi
|
|
Packit |
8462d6 |
}
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# Glob for matching various backup files.
|
|
Packit |
8462d6 |
#
|
|
Packit |
8462d6 |
_backup_glob='@(#*#|*@(~|.@(bak|orig|rej|swp|dpkg*|rpm@(orig|new|save))))'
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# Complete on xinetd services
|
|
Packit |
8462d6 |
#
|
|
Packit |
8462d6 |
_xinetd_services()
|
|
Packit |
8462d6 |
{
|
|
Packit |
8462d6 |
local xinetddir=/etc/xinetd.d
|
|
Packit |
8462d6 |
if [[ -d $xinetddir ]]; then
|
|
Packit |
8462d6 |
local restore_nullglob=$(shopt -p nullglob); shopt -s nullglob
|
|
Packit |
8462d6 |
local -a svcs=( $( printf '%s\n' $xinetddir/!($_backup_glob) ) )
|
|
Packit |
8462d6 |
$restore_nullglob
|
|
Packit |
8462d6 |
COMPREPLY+=( $( compgen -W '${svcs[@]#$xinetddir/}' -- "$cur" ) )
|
|
Packit |
8462d6 |
fi
|
|
Packit |
8462d6 |
}
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# This function completes on services
|
|
Packit |
8462d6 |
#
|
|
Packit |
8462d6 |
_services()
|
|
Packit |
8462d6 |
{
|
|
Packit |
8462d6 |
local sysvdirs
|
|
Packit |
8462d6 |
_sysvdirs
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
local restore_nullglob=$(shopt -p nullglob); shopt -s nullglob
|
|
Packit |
8462d6 |
COMPREPLY=( \
|
|
Packit |
8462d6 |
$( printf '%s\n' ${sysvdirs[0]}/!($_backup_glob|functions|README) ) )
|
|
Packit |
8462d6 |
$restore_nullglob
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
COMPREPLY+=( $( systemctl list-units --full --all 2>/dev/null | \
|
|
Packit |
8462d6 |
awk '$1 ~ /\.service$/ { sub("\\.service$", "", $1); print $1 }' ) )
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
if [[ -x /sbin/upstart-udev-bridge ]]; then
|
|
Packit |
8462d6 |
COMPREPLY+=( $( initctl list 2>/dev/null | cut -d' ' -f1 ) )
|
|
Packit |
8462d6 |
fi
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
COMPREPLY=( $( compgen -W '${COMPREPLY[@]#${sysvdirs[0]}/}' -- "$cur" ) )
|
|
Packit |
8462d6 |
}
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# This completes on a list of all available service scripts for the
|
|
Packit |
8462d6 |
# 'service' command and/or the SysV init.d directory, followed by
|
|
Packit |
8462d6 |
# that script's available commands
|
|
Packit |
8462d6 |
#
|
|
Packit |
8462d6 |
_service()
|
|
Packit |
8462d6 |
{
|
|
Packit |
8462d6 |
local cur prev words cword
|
|
Packit |
8462d6 |
_init_completion || return
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# don't complete past 2nd token
|
|
Packit |
8462d6 |
[[ $cword -gt 2 ]] && return
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
if [[ $cword -eq 1 && $prev == ?(*/)service ]]; then
|
|
Packit |
8462d6 |
_services
|
|
Packit |
8462d6 |
[[ -e /etc/mandrake-release ]] && _xinetd_services
|
|
Packit |
8462d6 |
else
|
|
Packit |
8462d6 |
local sysvdirs
|
|
Packit |
8462d6 |
_sysvdirs
|
|
Packit |
8462d6 |
COMPREPLY=( $( compgen -W '`command sed -e "y/|/ /" \
|
|
Packit |
8462d6 |
-ne "s/^.*\(U\|msg_u\)sage.*{\(.*\)}.*$/\2/p" \
|
|
Packit |
8462d6 |
${sysvdirs[0]}/${prev##*/} 2>/dev/null` start stop' -- "$cur" ) )
|
|
Packit |
8462d6 |
fi
|
|
Packit |
8462d6 |
} &&
|
|
Packit |
8462d6 |
complete -F _service service
|
|
Packit |
8462d6 |
_sysvdirs
|
|
Packit |
8462d6 |
for svcdir in ${sysvdirs[@]}; do
|
|
Packit |
8462d6 |
for svc in $svcdir/!($_backup_glob); do
|
|
Packit |
8462d6 |
[[ -x $svc ]] && complete -F _service $svc
|
|
Packit |
8462d6 |
done
|
|
Packit |
8462d6 |
done
|
|
Packit |
8462d6 |
unset svc svcdir sysvdirs
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# This function completes on modules
|
|
Packit |
8462d6 |
#
|
|
Packit |
8462d6 |
_modules()
|
|
Packit |
8462d6 |
{
|
|
Packit |
8462d6 |
local modpath
|
|
Packit |
8462d6 |
modpath=/lib/modules/$1
|
|
Packit |
8462d6 |
COMPREPLY=( $( compgen -W "$( command ls -RL $modpath 2>/dev/null | \
|
|
Packit |
8462d6 |
command sed -ne 's/^\(.*\)\.k\{0,1\}o\(\.[gx]z\)\{0,1\}$/\1/p' )" -- "$cur" ) )
|
|
Packit |
8462d6 |
}
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# This function completes on installed modules
|
|
Packit |
8462d6 |
#
|
|
Packit |
8462d6 |
_installed_modules()
|
|
Packit |
8462d6 |
{
|
|
Packit |
8462d6 |
COMPREPLY=( $( compgen -W "$( PATH="$PATH:/sbin" lsmod | \
|
|
Packit |
8462d6 |
awk '{if (NR != 1) print $1}' )" -- "$1" ) )
|
|
Packit |
8462d6 |
}
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# This function completes on user or user:group format; as for chown and cpio.
|
|
Packit |
8462d6 |
#
|
|
Packit |
8462d6 |
# The : must be added manually; it will only complete usernames initially.
|
|
Packit |
8462d6 |
# The legacy user.group format is not supported.
|
|
Packit |
8462d6 |
#
|
|
Packit |
8462d6 |
# @param $1 If -u, only return users/groups the user has access to in
|
|
Packit |
8462d6 |
# context of current completion.
|
|
Packit |
8462d6 |
_usergroup()
|
|
Packit |
8462d6 |
{
|
|
Packit |
8462d6 |
if [[ $cur == *\\\\* || $cur == *:*:* ]]; then
|
|
Packit |
8462d6 |
# Give up early on if something seems horribly wrong.
|
|
Packit |
8462d6 |
return
|
|
Packit |
8462d6 |
elif [[ $cur == *\\:* ]]; then
|
|
Packit |
8462d6 |
# Completing group after 'user\:gr<TAB>'.
|
|
Packit |
8462d6 |
# Reply with a list of groups prefixed with 'user:', readline will
|
|
Packit |
8462d6 |
# escape to the colon.
|
|
Packit |
8462d6 |
local prefix
|
|
Packit |
8462d6 |
prefix=${cur%%*([^:])}
|
|
Packit |
8462d6 |
prefix=${prefix//\\}
|
|
Packit |
8462d6 |
local mycur="${cur#*[:]}"
|
|
Packit |
8462d6 |
if [[ $1 == -u ]]; then
|
|
Packit |
8462d6 |
_allowed_groups "$mycur"
|
|
Packit |
8462d6 |
else
|
|
Packit |
8462d6 |
local IFS=$'\n'
|
|
Packit |
8462d6 |
COMPREPLY=( $( compgen -g -- "$mycur" ) )
|
|
Packit |
8462d6 |
fi
|
|
Packit |
8462d6 |
COMPREPLY=( $( compgen -P "$prefix" -W "${COMPREPLY[@]}" ) )
|
|
Packit |
8462d6 |
elif [[ $cur == *:* ]]; then
|
|
Packit |
8462d6 |
# Completing group after 'user:gr<TAB>'.
|
|
Packit |
8462d6 |
# Reply with a list of unprefixed groups since readline with split on :
|
|
Packit |
8462d6 |
# and only replace the 'gr' part
|
|
Packit |
8462d6 |
local mycur="${cur#*:}"
|
|
Packit |
8462d6 |
if [[ $1 == -u ]]; then
|
|
Packit |
8462d6 |
_allowed_groups "$mycur"
|
|
Packit |
8462d6 |
else
|
|
Packit |
8462d6 |
local IFS=$'\n'
|
|
Packit |
8462d6 |
COMPREPLY=( $( compgen -g -- "$mycur" ) )
|
|
Packit |
8462d6 |
fi
|
|
Packit |
8462d6 |
else
|
|
Packit |
8462d6 |
# Completing a partial 'usernam<TAB>'.
|
|
Packit |
8462d6 |
#
|
|
Packit |
8462d6 |
# Don't suffix with a : because readline will escape it and add a
|
|
Packit |
8462d6 |
# slash. It's better to complete into 'chown username ' than 'chown
|
|
Packit |
8462d6 |
# username\:'.
|
|
Packit |
8462d6 |
if [[ $1 == -u ]]; then
|
|
Packit |
8462d6 |
_allowed_users "$cur"
|
|
Packit |
8462d6 |
else
|
|
Packit |
8462d6 |
local IFS=$'\n'
|
|
Packit |
8462d6 |
COMPREPLY=( $( compgen -u -- "$cur" ) )
|
|
Packit |
8462d6 |
fi
|
|
Packit |
8462d6 |
fi
|
|
Packit |
8462d6 |
}
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
_allowed_users()
|
|
Packit |
8462d6 |
{
|
|
Packit |
8462d6 |
if _complete_as_root; then
|
|
Packit |
8462d6 |
local IFS=$'\n'
|
|
Packit |
8462d6 |
COMPREPLY=( $( compgen -u -- "${1:-$cur}" ) )
|
|
Packit |
8462d6 |
else
|
|
Packit |
8462d6 |
local IFS=$'\n '
|
|
Packit |
8462d6 |
COMPREPLY=( $( compgen -W \
|
|
Packit |
8462d6 |
"$( id -un 2>/dev/null || whoami 2>/dev/null )" -- "${1:-$cur}" ) )
|
|
Packit |
8462d6 |
fi
|
|
Packit |
8462d6 |
}
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
_allowed_groups()
|
|
Packit |
8462d6 |
{
|
|
Packit |
8462d6 |
if _complete_as_root; then
|
|
Packit |
8462d6 |
local IFS=$'\n'
|
|
Packit |
8462d6 |
COMPREPLY=( $( compgen -g -- "$1" ) )
|
|
Packit |
8462d6 |
else
|
|
Packit |
8462d6 |
local IFS=$'\n '
|
|
Packit |
8462d6 |
COMPREPLY=( $( compgen -W \
|
|
Packit |
8462d6 |
"$( id -Gn 2>/dev/null || groups 2>/dev/null )" -- "$1" ) )
|
|
Packit |
8462d6 |
fi
|
|
Packit |
8462d6 |
}
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# This function completes on valid shells
|
|
Packit |
8462d6 |
#
|
|
Packit |
8462d6 |
_shells()
|
|
Packit |
8462d6 |
{
|
|
Packit |
8462d6 |
local shell rest
|
|
Packit |
8462d6 |
while read -r shell rest; do
|
|
Packit |
8462d6 |
[[ $shell == /* && $shell == "$cur"* ]] && COMPREPLY+=( $shell )
|
|
Packit |
8462d6 |
done 2>/dev/null < /etc/shells
|
|
Packit |
8462d6 |
}
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# This function completes on valid filesystem types
|
|
Packit |
8462d6 |
#
|
|
Packit |
8462d6 |
_fstypes()
|
|
Packit |
8462d6 |
{
|
|
Packit |
8462d6 |
local fss
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
if [[ -e /proc/filesystems ]]; then
|
|
Packit |
8462d6 |
# Linux
|
|
Packit |
8462d6 |
fss="$( cut -d$'\t' -f2 /proc/filesystems )
|
|
Packit |
8462d6 |
$( awk '! /\*/ { print $NF }' /etc/filesystems 2>/dev/null )"
|
|
Packit |
8462d6 |
else
|
|
Packit |
8462d6 |
# Generic
|
|
Packit |
8462d6 |
fss="$( awk '/^[ \t]*[^#]/ { print $3 }' /etc/fstab 2>/dev/null )
|
|
Packit |
8462d6 |
$( awk '/^[ \t]*[^#]/ { print $3 }' /etc/mnttab 2>/dev/null )
|
|
Packit |
8462d6 |
$( awk '/^[ \t]*[^#]/ { print $4 }' /etc/vfstab 2>/dev/null )
|
|
Packit |
8462d6 |
$( awk '{ print $1 }' /etc/dfs/fstypes 2>/dev/null )
|
|
Packit |
8462d6 |
$( [[ -d /etc/fs ]] && command ls /etc/fs )"
|
|
Packit |
8462d6 |
fi
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
[[ -n $fss ]] && COMPREPLY+=( $( compgen -W "$fss" -- "$cur" ) )
|
|
Packit |
8462d6 |
}
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# Get real command.
|
|
Packit |
8462d6 |
# - arg: $1 Command
|
|
Packit |
8462d6 |
# - stdout: Filename of command in PATH with possible symbolic links resolved.
|
|
Packit |
8462d6 |
# Empty string if command not found.
|
|
Packit |
8462d6 |
# - return: True (0) if command found, False (> 0) if not.
|
|
Packit |
8462d6 |
_realcommand()
|
|
Packit |
8462d6 |
{
|
|
Packit |
8462d6 |
type -P "$1" > /dev/null && {
|
|
Packit |
8462d6 |
if type -p realpath > /dev/null; then
|
|
Packit |
8462d6 |
realpath "$(type -P "$1")"
|
|
Packit |
8462d6 |
elif type -p greadlink > /dev/null; then
|
|
Packit |
8462d6 |
greadlink -f "$(type -P "$1")"
|
|
Packit |
8462d6 |
elif type -p readlink > /dev/null; then
|
|
Packit |
8462d6 |
readlink -f "$(type -P "$1")"
|
|
Packit |
8462d6 |
else
|
|
Packit |
8462d6 |
type -P "$1"
|
|
Packit |
8462d6 |
fi
|
|
Packit |
8462d6 |
}
|
|
Packit |
8462d6 |
}
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# This function returns the first argument, excluding options
|
|
Packit |
8462d6 |
# @param $1 chars Characters out of $COMP_WORDBREAKS which should
|
|
Packit |
8462d6 |
# NOT be considered word breaks. See __reassemble_comp_words_by_ref.
|
|
Packit |
8462d6 |
_get_first_arg()
|
|
Packit |
8462d6 |
{
|
|
Packit |
8462d6 |
local i
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
arg=
|
|
Packit |
8462d6 |
for (( i=1; i < COMP_CWORD; i++ )); do
|
|
Packit |
8462d6 |
if [[ "${COMP_WORDS[i]}" != -* ]]; then
|
|
Packit |
8462d6 |
arg=${COMP_WORDS[i]}
|
|
Packit |
8462d6 |
break
|
|
Packit |
8462d6 |
fi
|
|
Packit |
8462d6 |
done
|
|
Packit |
8462d6 |
}
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# This function counts the number of args, excluding options
|
|
Packit |
8462d6 |
# @param $1 chars Characters out of $COMP_WORDBREAKS which should
|
|
Packit |
8462d6 |
# NOT be considered word breaks. See __reassemble_comp_words_by_ref.
|
|
Packit |
8462d6 |
_count_args()
|
|
Packit |
8462d6 |
{
|
|
Packit |
8462d6 |
local i cword words
|
|
Packit |
8462d6 |
__reassemble_comp_words_by_ref "$1" words cword
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
args=1
|
|
Packit |
8462d6 |
for i in "${words[@]:1:cword-1}"; do
|
|
Packit |
8462d6 |
[[ "$i" != -* ]] && args=$(($args+1))
|
|
Packit |
8462d6 |
done
|
|
Packit |
8462d6 |
}
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# This function completes on PCI IDs
|
|
Packit |
8462d6 |
#
|
|
Packit |
8462d6 |
_pci_ids()
|
|
Packit |
8462d6 |
{
|
|
Packit |
8462d6 |
COMPREPLY+=( $( compgen -W \
|
|
Packit |
8462d6 |
"$( PATH="$PATH:/sbin" lspci -n | awk '{print $3}')" -- "$cur" ) )
|
|
Packit |
8462d6 |
}
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# This function completes on USB IDs
|
|
Packit |
8462d6 |
#
|
|
Packit |
8462d6 |
_usb_ids()
|
|
Packit |
8462d6 |
{
|
|
Packit |
8462d6 |
COMPREPLY+=( $( compgen -W \
|
|
Packit |
8462d6 |
"$( PATH="$PATH:/sbin" lsusb | awk '{print $6}' )" -- "$cur" ) )
|
|
Packit |
8462d6 |
}
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# CD device names
|
|
Packit |
8462d6 |
_cd_devices()
|
|
Packit |
8462d6 |
{
|
|
Packit |
8462d6 |
COMPREPLY+=( $( compgen -f -d -X "!*/?([amrs])cd*" -- "${cur:-/dev/}" ) )
|
|
Packit |
8462d6 |
}
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# DVD device names
|
|
Packit |
8462d6 |
_dvd_devices()
|
|
Packit |
8462d6 |
{
|
|
Packit |
8462d6 |
COMPREPLY+=( $( compgen -f -d -X "!*/?(r)dvd*" -- "${cur:-/dev/}" ) )
|
|
Packit |
8462d6 |
}
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# TERM environment variable values
|
|
Packit |
8462d6 |
_terms()
|
|
Packit |
8462d6 |
{
|
|
Packit |
8462d6 |
COMPREPLY+=( $( compgen -W \
|
|
Packit |
8462d6 |
"$( command sed -ne 's/^\([^[:space:]#|]\{2,\}\)|.*/\1/p' /etc/termcap \
|
|
Packit |
8462d6 |
2>/dev/null )" -- "$cur" ) )
|
|
Packit |
8462d6 |
COMPREPLY+=( $( compgen -W "$( { toe -a 2>/dev/null || toe 2>/dev/null; } \
|
|
Packit |
8462d6 |
| awk '{ print $1 }' | sort -u )" -- "$cur" ) )
|
|
Packit |
8462d6 |
}
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# a little help for FreeBSD ports users
|
|
Packit |
8462d6 |
[[ $OSTYPE == *freebsd* ]] && complete -W 'index search fetch fetch-list
|
|
Packit |
8462d6 |
extract patch configure build install reinstall deinstall clean
|
|
Packit |
8462d6 |
clean-depends kernel buildworld' make
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# This function provides simple user@host completion
|
|
Packit |
8462d6 |
#
|
|
Packit |
8462d6 |
_user_at_host()
|
|
Packit |
8462d6 |
{
|
|
Packit |
8462d6 |
local cur prev words cword
|
|
Packit |
8462d6 |
_init_completion -n : || return
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
if [[ $cur == *@* ]]; then
|
|
Packit |
8462d6 |
_known_hosts_real "$cur"
|
|
Packit |
8462d6 |
else
|
|
Packit |
8462d6 |
COMPREPLY=( $( compgen -u -S @ -- "$cur" ) )
|
|
Packit |
8462d6 |
compopt -o nospace
|
|
Packit |
8462d6 |
fi
|
|
Packit |
8462d6 |
}
|
|
Packit |
8462d6 |
shopt -u hostcomplete && complete -F _user_at_host talk ytalk finger
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# NOTE: Using this function as a helper function is deprecated. Use
|
|
Packit |
8462d6 |
# `_known_hosts_real' instead.
|
|
Packit |
8462d6 |
_known_hosts()
|
|
Packit |
8462d6 |
{
|
|
Packit |
8462d6 |
local cur prev words cword
|
|
Packit |
8462d6 |
_init_completion -n : || return
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# NOTE: Using `_known_hosts' as a helper function and passing options
|
|
Packit |
8462d6 |
# to `_known_hosts' is deprecated: Use `_known_hosts_real' instead.
|
|
Packit |
8462d6 |
local options
|
|
Packit |
8462d6 |
[[ "$1" == -a || "$2" == -a ]] && options=-a
|
|
Packit |
8462d6 |
[[ "$1" == -c || "$2" == -c ]] && options+=" -c"
|
|
Packit |
8462d6 |
_known_hosts_real $options -- "$cur"
|
|
Packit |
8462d6 |
} # _known_hosts()
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# Helper function to locate ssh included files in configs
|
|
Packit |
8462d6 |
# This function look for the "Include" keyword in ssh config files and include
|
|
Packit |
8462d6 |
# them recursively adding each result to the config variable
|
|
Packit |
8462d6 |
_included_ssh_config_files()
|
|
Packit |
8462d6 |
{
|
|
Packit |
8462d6 |
[[ $# -lt 1 ]] && echo "error: $FUNCNAME: missing mandatory argument CONFIG"
|
|
Packit |
8462d6 |
local configfile i f
|
|
Packit |
8462d6 |
configfile=$1
|
|
Packit |
8462d6 |
local included=$( command sed -ne 's/^[[:blank:]]*[Ii][Nn][Cc][Ll][Uu][Dd][Ee][[:blank:]]\{1,\}\([^#%]*\)\(#.*\)\{0,1\}$/\1/p' "${configfile}" )
|
|
Packit |
8462d6 |
for i in ${included[@]}; do
|
|
Packit |
8462d6 |
# Check the origin of $configfile to complete relative included paths on included
|
|
Packit |
8462d6 |
# files according to ssh_config(5):
|
|
Packit |
8462d6 |
# "[...] Files without absolute paths are assumed to be in ~/.ssh if included in a user
|
|
Packit |
8462d6 |
# configuration file or /etc/ssh if included from the system configuration file.[...]"
|
|
Packit |
8462d6 |
if ! [[ "$i" =~ ^\~.*|^\/.* ]]; then
|
|
Packit |
8462d6 |
if [[ "$configfile" =~ ^\/etc\/ssh.* ]]; then
|
|
Packit |
8462d6 |
i="/etc/ssh/$i"
|
|
Packit |
8462d6 |
else
|
|
Packit |
8462d6 |
i="$HOME/.ssh/$i"
|
|
Packit |
8462d6 |
fi
|
|
Packit |
8462d6 |
fi
|
|
Packit |
8462d6 |
__expand_tilde_by_ref i
|
|
Packit |
8462d6 |
# In case the expanded variable contains multiple paths
|
|
Packit |
8462d6 |
for f in ${i}; do
|
|
Packit |
8462d6 |
if [ -r $f ]; then
|
|
Packit |
8462d6 |
config+=( "$f" )
|
|
Packit |
8462d6 |
# The Included file is processed to look for Included files in itself
|
|
Packit |
8462d6 |
_included_ssh_config_files $f
|
|
Packit |
8462d6 |
fi
|
|
Packit |
8462d6 |
done
|
|
Packit |
8462d6 |
done
|
|
Packit |
8462d6 |
} # _included_ssh_config_files()
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# Helper function for completing _known_hosts.
|
|
Packit |
8462d6 |
# This function performs host completion based on ssh's config and known_hosts
|
|
Packit |
8462d6 |
# files, as well as hostnames reported by avahi-browse if
|
|
Packit |
8462d6 |
# COMP_KNOWN_HOSTS_WITH_AVAHI is set to a non-empty value. Also hosts from
|
|
Packit |
8462d6 |
# HOSTFILE (compgen -A hostname) are added, unless
|
|
Packit |
8462d6 |
# COMP_KNOWN_HOSTS_WITH_HOSTFILE is set to an empty value.
|
|
Packit |
8462d6 |
# Usage: _known_hosts_real [OPTIONS] CWORD
|
|
Packit |
8462d6 |
# Options: -a Use aliases
|
|
Packit |
8462d6 |
# -c Use `:' suffix
|
|
Packit |
8462d6 |
# -F configfile Use `configfile' for configuration settings
|
|
Packit |
8462d6 |
# -p PREFIX Use PREFIX
|
|
Packit |
8462d6 |
# Return: Completions, starting with CWORD, are added to COMPREPLY[]
|
|
Packit |
8462d6 |
_known_hosts_real()
|
|
Packit |
8462d6 |
{
|
|
Packit |
8462d6 |
local configfile flag prefix
|
|
Packit |
8462d6 |
local cur curd awkcur user suffix aliases i host
|
|
Packit |
8462d6 |
local -a kh khd config
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
local OPTIND=1
|
|
Packit |
8462d6 |
while getopts "acF:p:" flag "$@"; do
|
|
Packit |
8462d6 |
case $flag in
|
|
Packit |
8462d6 |
a) aliases='yes' ;;
|
|
Packit |
8462d6 |
c) suffix=':' ;;
|
|
Packit |
8462d6 |
F) configfile=$OPTARG ;;
|
|
Packit |
8462d6 |
p) prefix=$OPTARG ;;
|
|
Packit |
8462d6 |
esac
|
|
Packit |
8462d6 |
done
|
|
Packit |
8462d6 |
[[ $# -lt $OPTIND ]] && echo "error: $FUNCNAME: missing mandatory argument CWORD"
|
|
Packit |
8462d6 |
cur=${!OPTIND}; let "OPTIND += 1"
|
|
Packit |
8462d6 |
[[ $# -ge $OPTIND ]] && echo "error: $FUNCNAME("$@"): unprocessed arguments:"\
|
|
Packit |
8462d6 |
$(while [[ $# -ge $OPTIND ]]; do printf '%s\n' ${!OPTIND}; shift; done)
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
[[ $cur == *@* ]] && user=${cur%@*}@ && cur=${cur#*@}
|
|
Packit |
8462d6 |
kh=()
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# ssh config files
|
|
Packit |
8462d6 |
if [[ -n $configfile ]]; then
|
|
Packit |
8462d6 |
[[ -r $configfile ]] && config+=( "$configfile" )
|
|
Packit |
8462d6 |
else
|
|
Packit |
8462d6 |
for i in /etc/ssh/ssh_config ~/.ssh/config ~/.ssh2/config; do
|
|
Packit |
8462d6 |
[[ -r $i ]] && config+=( "$i" )
|
|
Packit |
8462d6 |
done
|
|
Packit |
8462d6 |
fi
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# "Include" keyword in ssh config files
|
|
Packit |
8462d6 |
for i in "${config[@]}"; do
|
|
Packit |
8462d6 |
_included_ssh_config_files "$i"
|
|
Packit |
8462d6 |
done
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# Known hosts files from configs
|
|
Packit |
8462d6 |
if [[ ${#config[@]} -gt 0 ]]; then
|
|
Packit |
8462d6 |
local OIFS=$IFS IFS=$'\n' j
|
|
Packit |
8462d6 |
local -a tmpkh
|
|
Packit |
8462d6 |
# expand paths (if present) to global and user known hosts files
|
|
Packit |
8462d6 |
# TODO(?): try to make known hosts files with more than one consecutive
|
|
Packit |
8462d6 |
# spaces in their name work (watch out for ~ expansion
|
|
Packit |
8462d6 |
# breakage! Alioth#311595)
|
|
Packit |
8462d6 |
tmpkh=( $( awk 'sub("^[ \t]*([Gg][Ll][Oo][Bb][Aa][Ll]|[Uu][Ss][Ee][Rr])[Kk][Nn][Oo][Ww][Nn][Hh][Oo][Ss][Tt][Ss][Ff][Ii][Ll][Ee][ \t]+", "") { print $0 }' "${config[@]}" | sort -u ) )
|
|
Packit |
8462d6 |
IFS=$OIFS
|
|
Packit |
8462d6 |
for i in "${tmpkh[@]}"; do
|
|
Packit |
8462d6 |
# First deal with quoted entries...
|
|
Packit |
8462d6 |
while [[ $i =~ ^([^\"]*)\"([^\"]*)\"(.*)$ ]]; do
|
|
Packit |
8462d6 |
i=${BASH_REMATCH[1]}${BASH_REMATCH[3]}
|
|
Packit |
8462d6 |
j=${BASH_REMATCH[2]}
|
|
Packit |
8462d6 |
__expand_tilde_by_ref j # Eval/expand possible `~' or `~user'
|
|
Packit |
8462d6 |
[[ -r $j ]] && kh+=( "$j" )
|
|
Packit |
8462d6 |
done
|
|
Packit |
8462d6 |
# ...and then the rest.
|
|
Packit |
8462d6 |
for j in $i; do
|
|
Packit |
8462d6 |
__expand_tilde_by_ref j # Eval/expand possible `~' or `~user'
|
|
Packit |
8462d6 |
[[ -r $j ]] && kh+=( "$j" )
|
|
Packit |
8462d6 |
done
|
|
Packit |
8462d6 |
done
|
|
Packit |
8462d6 |
fi
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
if [[ -z $configfile ]]; then
|
|
Packit |
8462d6 |
# Global and user known_hosts files
|
|
Packit |
8462d6 |
for i in /etc/ssh/ssh_known_hosts /etc/ssh/ssh_known_hosts2 \
|
|
Packit |
8462d6 |
/etc/known_hosts /etc/known_hosts2 ~/.ssh/known_hosts \
|
|
Packit |
8462d6 |
~/.ssh/known_hosts2; do
|
|
Packit |
8462d6 |
[[ -r $i ]] && kh+=( "$i" )
|
|
Packit |
8462d6 |
done
|
|
Packit |
8462d6 |
for i in /etc/ssh2/knownhosts ~/.ssh2/hostkeys; do
|
|
Packit |
8462d6 |
[[ -d $i ]] && khd+=( "$i"/*pub )
|
|
Packit |
8462d6 |
done
|
|
Packit |
8462d6 |
fi
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# If we have known_hosts files to use
|
|
Packit |
8462d6 |
if [[ ${#kh[@]} -gt 0 || ${#khd[@]} -gt 0 ]]; then
|
|
Packit |
8462d6 |
# Escape slashes and dots in paths for awk
|
|
Packit |
8462d6 |
awkcur=${cur//\//\\\/}
|
|
Packit |
8462d6 |
awkcur=${awkcur//\./\\\.}
|
|
Packit |
8462d6 |
curd=$awkcur
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
if [[ "$awkcur" == [0-9]*[.:]* ]]; then
|
|
Packit |
8462d6 |
# Digits followed by a dot or a colon - just search for that
|
|
Packit |
8462d6 |
awkcur="^$awkcur[.:]*"
|
|
Packit |
8462d6 |
elif [[ "$awkcur" == [0-9]* ]]; then
|
|
Packit |
8462d6 |
# Digits followed by no dot or colon - search for digits followed
|
|
Packit |
8462d6 |
# by a dot or a colon
|
|
Packit |
8462d6 |
awkcur="^$awkcur.*[.:]"
|
|
Packit |
8462d6 |
elif [[ -z $awkcur ]]; then
|
|
Packit |
8462d6 |
# A blank - search for a dot, a colon, or an alpha character
|
|
Packit |
8462d6 |
awkcur="[a-z.:]"
|
|
Packit |
8462d6 |
else
|
|
Packit |
8462d6 |
awkcur="^$awkcur"
|
|
Packit |
8462d6 |
fi
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
if [[ ${#kh[@]} -gt 0 ]]; then
|
|
Packit |
8462d6 |
# FS needs to look for a comma separated list
|
|
Packit |
8462d6 |
COMPREPLY+=( $( awk 'BEGIN {FS=","}
|
|
Packit |
8462d6 |
/^\s*[^|\#]/ {
|
|
Packit |
8462d6 |
sub("^@[^ ]+ +", ""); \
|
|
Packit |
8462d6 |
sub(" .*$", ""); \
|
|
Packit |
8462d6 |
for (i=1; i<=NF; ++i) { \
|
|
Packit |
8462d6 |
sub("^\\[", "", $i); sub("\\](:[0-9]+)?$", "", $i); \
|
|
Packit |
8462d6 |
if ($i !~ /[*?]/ && $i ~ /'"$awkcur"'/) {print $i} \
|
|
Packit |
8462d6 |
}}' "${kh[@]}" 2>/dev/null ) )
|
|
Packit |
8462d6 |
fi
|
|
Packit |
8462d6 |
if [[ ${#khd[@]} -gt 0 ]]; then
|
|
Packit |
8462d6 |
# Needs to look for files called
|
|
Packit |
8462d6 |
# .../.ssh2/key_22_<hostname>.pub
|
|
Packit |
8462d6 |
# dont fork any processes, because in a cluster environment,
|
|
Packit |
8462d6 |
# there can be hundreds of hostkeys
|
|
Packit |
8462d6 |
for i in "${khd[@]}" ; do
|
|
Packit |
8462d6 |
if [[ "$i" == *key_22_$curd*.pub && -r "$i" ]]; then
|
|
Packit |
8462d6 |
host=${i/#*key_22_/}
|
|
Packit |
8462d6 |
host=${host/%.pub/}
|
|
Packit |
8462d6 |
COMPREPLY+=( $host )
|
|
Packit |
8462d6 |
fi
|
|
Packit |
8462d6 |
done
|
|
Packit |
8462d6 |
fi
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# apply suffix and prefix
|
|
Packit |
8462d6 |
for (( i=0; i < ${#COMPREPLY[@]}; i++ )); do
|
|
Packit |
8462d6 |
COMPREPLY[i]=$prefix$user${COMPREPLY[i]}$suffix
|
|
Packit |
8462d6 |
done
|
|
Packit |
8462d6 |
fi
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# append any available aliases from config files
|
|
Packit |
8462d6 |
if [[ ${#config[@]} -gt 0 && -n "$aliases" ]]; then
|
|
Packit |
8462d6 |
local hosts=$( command sed -ne 's/^[[:blank:]]*[Hh][Oo][Ss][Tt][[:blank:]]\{1,\}\([^#*?%]*\)\(#.*\)\{0,1\}$/\1/p' "${config[@]}" )
|
|
Packit |
8462d6 |
COMPREPLY+=( $( compgen -P "$prefix$user" \
|
|
Packit |
8462d6 |
-S "$suffix" -W "$hosts" -- "$cur" ) )
|
|
Packit |
8462d6 |
fi
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# Add hosts reported by avahi-browse, if desired and it's available.
|
|
Packit |
8462d6 |
if [[ ${COMP_KNOWN_HOSTS_WITH_AVAHI:-} ]] && \
|
|
Packit |
8462d6 |
type avahi-browse &>/dev/null; then
|
|
Packit |
8462d6 |
# The original call to avahi-browse also had "-k", to avoid lookups
|
|
Packit |
8462d6 |
# into avahi's services DB. We don't need the name of the service, and
|
|
Packit |
8462d6 |
# if it contains ";", it may mistify the result. But on Gentoo (at
|
|
Packit |
8462d6 |
# least), -k wasn't available (even if mentioned in the manpage) some
|
|
Packit |
8462d6 |
# time ago, so...
|
|
Packit |
8462d6 |
COMPREPLY+=( $( compgen -P "$prefix$user" -S "$suffix" -W \
|
|
Packit |
8462d6 |
"$( avahi-browse -cpr _workstation._tcp 2>/dev/null | \
|
|
Packit |
8462d6 |
awk -F';' '/^=/ { print $7 }' | sort -u )" -- "$cur" ) )
|
|
Packit |
8462d6 |
fi
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# Add hosts reported by ruptime.
|
|
Packit |
8462d6 |
COMPREPLY+=( $( compgen -W \
|
|
Packit |
8462d6 |
"$( ruptime 2>/dev/null | awk '!/^ruptime:/ { print $1 }' )" \
|
|
Packit |
8462d6 |
-- "$cur" ) )
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# Add results of normal hostname completion, unless
|
|
Packit |
8462d6 |
# `COMP_KNOWN_HOSTS_WITH_HOSTFILE' is set to an empty value.
|
|
Packit |
8462d6 |
if [[ -n ${COMP_KNOWN_HOSTS_WITH_HOSTFILE-1} ]]; then
|
|
Packit |
8462d6 |
COMPREPLY+=(
|
|
Packit |
8462d6 |
$( compgen -A hostname -P "$prefix$user" -S "$suffix" -- "$cur" ) )
|
|
Packit |
8462d6 |
fi
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
__ltrim_colon_completions "$prefix$user$cur"
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
} # _known_hosts_real()
|
|
Packit |
8462d6 |
complete -F _known_hosts traceroute traceroute6 tracepath tracepath6 \
|
|
Packit |
8462d6 |
fping fping6 telnet rsh rlogin ftp dig mtr ssh-installkeys showmount
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# This meta-cd function observes the CDPATH variable, so that cd additionally
|
|
Packit |
8462d6 |
# completes on directories under those specified in CDPATH.
|
|
Packit |
8462d6 |
#
|
|
Packit |
8462d6 |
_cd()
|
|
Packit |
8462d6 |
{
|
|
Packit |
8462d6 |
local cur prev words cword
|
|
Packit |
8462d6 |
_init_completion || return
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
local IFS=$'\n' i j k
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
compopt -o filenames
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# Use standard dir completion if no CDPATH or parameter starts with /,
|
|
Packit |
8462d6 |
# ./ or ../
|
|
Packit |
8462d6 |
if [[ -z "${CDPATH:-}" || "$cur" == ?(.)?(.)/* ]]; then
|
|
Packit |
8462d6 |
_filedir -d
|
|
Packit |
8462d6 |
return
|
|
Packit |
8462d6 |
fi
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
local -r mark_dirs=$(_rl_enabled mark-directories && echo y)
|
|
Packit |
8462d6 |
local -r mark_symdirs=$(_rl_enabled mark-symlinked-directories && echo y)
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# we have a CDPATH, so loop on its contents
|
|
Packit |
8462d6 |
for i in ${CDPATH//:/$'\n'}; do
|
|
Packit |
8462d6 |
# create an array of matched subdirs
|
|
Packit |
8462d6 |
k="${#COMPREPLY[@]}"
|
|
Packit |
8462d6 |
for j in $( compgen -d -- $i/$cur ); do
|
|
Packit |
8462d6 |
if [[ ( $mark_symdirs && -h $j || $mark_dirs && ! -h $j ) && ! -d ${j#$i/} ]]; then
|
|
Packit |
8462d6 |
j+="/"
|
|
Packit |
8462d6 |
fi
|
|
Packit |
8462d6 |
COMPREPLY[k++]=${j#$i/}
|
|
Packit |
8462d6 |
done
|
|
Packit |
8462d6 |
done
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
_filedir -d
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
if [[ ${#COMPREPLY[@]} -eq 1 ]]; then
|
|
Packit |
8462d6 |
i=${COMPREPLY[0]}
|
|
Packit |
8462d6 |
if [[ "$i" == "$cur" && $i != "*/" ]]; then
|
|
Packit |
8462d6 |
COMPREPLY[0]="${i}/"
|
|
Packit |
8462d6 |
fi
|
|
Packit |
8462d6 |
fi
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
return
|
|
Packit |
8462d6 |
}
|
|
Packit |
8462d6 |
if shopt -q cdable_vars; then
|
|
Packit |
8462d6 |
complete -v -F _cd -o nospace cd pushd
|
|
Packit |
8462d6 |
else
|
|
Packit |
8462d6 |
complete -F _cd -o nospace cd pushd
|
|
Packit |
8462d6 |
fi
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# a wrapper method for the next one, when the offset is unknown
|
|
Packit |
8462d6 |
_command()
|
|
Packit |
8462d6 |
{
|
|
Packit |
8462d6 |
local offset i
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# find actual offset, as position of the first non-option
|
|
Packit |
8462d6 |
offset=1
|
|
Packit |
8462d6 |
for (( i=1; i <= COMP_CWORD; i++ )); do
|
|
Packit |
8462d6 |
if [[ "${COMP_WORDS[i]}" != -* ]]; then
|
|
Packit |
8462d6 |
offset=$i
|
|
Packit |
8462d6 |
break
|
|
Packit |
8462d6 |
fi
|
|
Packit |
8462d6 |
done
|
|
Packit |
8462d6 |
_command_offset $offset
|
|
Packit |
8462d6 |
}
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# A meta-command completion function for commands like sudo(8), which need to
|
|
Packit |
8462d6 |
# first complete on a command, then complete according to that command's own
|
|
Packit |
8462d6 |
# completion definition.
|
|
Packit |
8462d6 |
#
|
|
Packit |
8462d6 |
_command_offset()
|
|
Packit |
8462d6 |
{
|
|
Packit |
8462d6 |
# rewrite current completion context before invoking
|
|
Packit |
8462d6 |
# actual command completion
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# find new first word position, then
|
|
Packit |
8462d6 |
# rewrite COMP_LINE and adjust COMP_POINT
|
|
Packit |
8462d6 |
local word_offset=$1 i j
|
|
Packit |
8462d6 |
for (( i=0; i < $word_offset; i++ )); do
|
|
Packit |
8462d6 |
for (( j=0; j <= ${#COMP_LINE}; j++ )); do
|
|
Packit |
8462d6 |
[[ "$COMP_LINE" == "${COMP_WORDS[i]}"* ]] && break
|
|
Packit |
8462d6 |
COMP_LINE=${COMP_LINE:1}
|
|
Packit |
8462d6 |
((COMP_POINT--))
|
|
Packit |
8462d6 |
done
|
|
Packit |
8462d6 |
COMP_LINE=${COMP_LINE#"${COMP_WORDS[i]}"}
|
|
Packit |
8462d6 |
((COMP_POINT-=${#COMP_WORDS[i]}))
|
|
Packit |
8462d6 |
done
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# shift COMP_WORDS elements and adjust COMP_CWORD
|
|
Packit |
8462d6 |
for (( i=0; i <= COMP_CWORD - $word_offset; i++ )); do
|
|
Packit |
8462d6 |
COMP_WORDS[i]=${COMP_WORDS[i+$word_offset]}
|
|
Packit |
8462d6 |
done
|
|
Packit |
8462d6 |
for (( i; i <= COMP_CWORD; i++ )); do
|
|
Packit |
8462d6 |
unset 'COMP_WORDS[i]'
|
|
Packit |
8462d6 |
done
|
|
Packit |
8462d6 |
((COMP_CWORD -= $word_offset))
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
COMPREPLY=()
|
|
Packit |
8462d6 |
local cur
|
|
Packit |
8462d6 |
_get_comp_words_by_ref cur
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
if [[ $COMP_CWORD -eq 0 ]]; then
|
|
Packit |
8462d6 |
local IFS=$'\n'
|
|
Packit |
8462d6 |
compopt -o filenames
|
|
Packit |
8462d6 |
COMPREPLY=( $( compgen -d -c -- "$cur" ) )
|
|
Packit |
8462d6 |
else
|
|
Packit |
8462d6 |
local cmd=${COMP_WORDS[0]} compcmd=${COMP_WORDS[0]}
|
|
Packit |
8462d6 |
local cspec=$( complete -p $cmd 2>/dev/null )
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# If we have no completion for $cmd yet, see if we have for basename
|
|
Packit |
8462d6 |
if [[ ! $cspec && $cmd == */* ]]; then
|
|
Packit |
8462d6 |
cspec=$( complete -p ${cmd##*/} 2>/dev/null )
|
|
Packit |
8462d6 |
[[ $cspec ]] && compcmd=${cmd##*/}
|
|
Packit |
8462d6 |
fi
|
|
Packit |
8462d6 |
# If still nothing, just load it for the basename
|
|
Packit |
8462d6 |
if [[ ! $cspec ]]; then
|
|
Packit |
8462d6 |
compcmd=${cmd##*/}
|
|
Packit |
8462d6 |
_completion_loader $compcmd
|
|
Packit |
8462d6 |
cspec=$( complete -p $compcmd 2>/dev/null )
|
|
Packit |
8462d6 |
fi
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
if [[ -n $cspec ]]; then
|
|
Packit |
8462d6 |
if [[ ${cspec#* -F } != $cspec ]]; then
|
|
Packit |
8462d6 |
# complete -F <function>
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# get function name
|
|
Packit |
8462d6 |
local func=${cspec#*-F }
|
|
Packit |
8462d6 |
func=${func%% *}
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
if [[ ${#COMP_WORDS[@]} -ge 2 ]]; then
|
|
Packit |
8462d6 |
$func $cmd "${COMP_WORDS[${#COMP_WORDS[@]}-1]}" "${COMP_WORDS[${#COMP_WORDS[@]}-2]}"
|
|
Packit |
8462d6 |
else
|
|
Packit |
8462d6 |
$func $cmd "${COMP_WORDS[${#COMP_WORDS[@]}-1]}"
|
|
Packit |
8462d6 |
fi
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# restore initial compopts
|
|
Packit |
8462d6 |
local opt
|
|
Packit |
8462d6 |
while [[ $cspec == *" -o "* ]]; do
|
|
Packit |
8462d6 |
# FIXME: should we take "+o opt" into account?
|
|
Packit |
8462d6 |
cspec=${cspec#*-o }
|
|
Packit |
8462d6 |
opt=${cspec%% *}
|
|
Packit |
8462d6 |
compopt -o $opt
|
|
Packit |
8462d6 |
cspec=${cspec#$opt}
|
|
Packit |
8462d6 |
done
|
|
Packit |
8462d6 |
else
|
|
Packit |
8462d6 |
cspec=${cspec#complete}
|
|
Packit |
8462d6 |
cspec=${cspec%%$compcmd}
|
|
Packit |
8462d6 |
COMPREPLY=( $( eval compgen "$cspec" -- '$cur' ) )
|
|
Packit |
8462d6 |
fi
|
|
Packit |
8462d6 |
elif [[ ${#COMPREPLY[@]} -eq 0 ]]; then
|
|
Packit |
8462d6 |
# XXX will probably never happen as long as completion loader loads
|
|
Packit |
8462d6 |
# *something* for every command thrown at it ($cspec != empty)
|
|
Packit |
8462d6 |
_minimal
|
|
Packit |
8462d6 |
fi
|
|
Packit |
8462d6 |
fi
|
|
Packit |
8462d6 |
}
|
|
Packit |
8462d6 |
complete -F _command aoss command do else eval exec ltrace nice nohup padsp \
|
|
Packit |
8462d6 |
then time tsocks vsound xargs
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
_root_command()
|
|
Packit |
8462d6 |
{
|
|
Packit |
8462d6 |
local PATH=$PATH:/sbin:/usr/sbin:/usr/local/sbin
|
|
Packit |
8462d6 |
local root_command=$1
|
|
Packit |
8462d6 |
_command
|
|
Packit |
8462d6 |
}
|
|
Packit |
8462d6 |
complete -F _root_command fakeroot gksu gksudo kdesudo really
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# Return true if the completion should be treated as running as root
|
|
Packit |
8462d6 |
_complete_as_root()
|
|
Packit |
8462d6 |
{
|
|
Packit |
8462d6 |
[[ $EUID -eq 0 || ${root_command:-} ]]
|
|
Packit |
8462d6 |
}
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
_longopt()
|
|
Packit |
8462d6 |
{
|
|
Packit |
8462d6 |
local cur prev words cword split
|
|
Packit |
8462d6 |
_init_completion -s || return
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
case "${prev,,}" in
|
|
Packit |
8462d6 |
--help|--usage|--version)
|
|
Packit |
8462d6 |
return
|
|
Packit |
8462d6 |
;;
|
|
Packit |
8462d6 |
--*dir*)
|
|
Packit |
8462d6 |
_filedir -d
|
|
Packit |
8462d6 |
return
|
|
Packit |
8462d6 |
;;
|
|
Packit |
8462d6 |
--*file*|--*path*)
|
|
Packit |
8462d6 |
_filedir
|
|
Packit |
8462d6 |
return
|
|
Packit |
8462d6 |
;;
|
|
Packit |
8462d6 |
--+([-a-z0-9_]))
|
|
Packit |
8462d6 |
local argtype=$( LC_ALL=C $1 --help 2>&1 | command sed -ne \
|
|
Packit |
8462d6 |
"s|.*$prev\[\{0,1\}=[<[]\{0,1\}\([-A-Za-z0-9_]\{1,\}\).*|\1|p" )
|
|
Packit |
8462d6 |
case ${argtype,,} in
|
|
Packit |
8462d6 |
*dir*)
|
|
Packit |
8462d6 |
_filedir -d
|
|
Packit |
8462d6 |
return
|
|
Packit |
8462d6 |
;;
|
|
Packit |
8462d6 |
*file*|*path*)
|
|
Packit |
8462d6 |
_filedir
|
|
Packit |
8462d6 |
return
|
|
Packit |
8462d6 |
;;
|
|
Packit |
8462d6 |
esac
|
|
Packit |
8462d6 |
;;
|
|
Packit |
8462d6 |
esac
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
$split && return
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
if [[ "$cur" == -* ]]; then
|
|
Packit |
8462d6 |
COMPREPLY=( $( compgen -W "$( LC_ALL=C $1 --help 2>&1 | \
|
|
Packit |
8462d6 |
command sed -ne 's/.*\(--[-A-Za-z0-9]\{1,\}=\{0,1\}\).*/\1/p' | sort -u )" \
|
|
Packit |
8462d6 |
-- "$cur" ) )
|
|
Packit |
8462d6 |
[[ $COMPREPLY == *= ]] && compopt -o nospace
|
|
Packit |
8462d6 |
elif [[ "$1" == @(@(mk|rm)dir|chroot) ]]; then
|
|
Packit |
8462d6 |
_filedir -d
|
|
Packit |
8462d6 |
else
|
|
Packit |
8462d6 |
_filedir
|
|
Packit |
8462d6 |
fi
|
|
Packit |
8462d6 |
}
|
|
Packit |
8462d6 |
# makeinfo and texi2dvi are defined elsewhere.
|
|
Packit |
8462d6 |
complete -F _longopt a2ps awk base64 bash bc bison cat chroot colordiff cp \
|
|
Packit |
8462d6 |
csplit cut date df diff dir du enscript env expand fmt fold gperf \
|
|
Packit |
8462d6 |
grep grub head irb ld ldd less ln ls m4 md5sum mkdir mkfifo mknod \
|
|
Packit |
8462d6 |
mv netstat nl nm objcopy objdump od paste pr ptx readelf rm rmdir \
|
|
Packit |
8462d6 |
sed seq sha{,1,224,256,384,512}sum shar sort split strip sum tac tail tee \
|
|
Packit |
8462d6 |
texindex touch tr uname unexpand uniq units vdir wc who
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
declare -A _xspecs
|
|
Packit |
8462d6 |
_filedir_xspec()
|
|
Packit |
8462d6 |
{
|
|
Packit |
8462d6 |
local cur prev words cword
|
|
Packit |
8462d6 |
_init_completion || return
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
_tilde "$cur" || return
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
local IFS=$'\n' xspec=${_xspecs[${1##*/}]} tmp
|
|
Packit |
8462d6 |
local -a toks
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
toks=( $(
|
|
Packit |
8462d6 |
compgen -d -- "$(quote_readline "$cur")" | {
|
|
Packit |
8462d6 |
while read -r tmp; do
|
|
Packit |
8462d6 |
printf '%s\n' $tmp
|
|
Packit |
8462d6 |
done
|
|
Packit |
8462d6 |
}
|
|
Packit |
8462d6 |
))
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# Munge xspec to contain uppercase version too
|
|
Packit |
8462d6 |
# http://thread.gmane.org/gmane.comp.shells.bash.bugs/15294/focus=15306
|
|
Packit |
8462d6 |
eval xspec="${xspec}"
|
|
Packit |
8462d6 |
local matchop=!
|
|
Packit |
8462d6 |
if [[ $xspec == !* ]]; then
|
|
Packit |
8462d6 |
xspec=${xspec#!}
|
|
Packit |
8462d6 |
matchop=@
|
|
Packit |
8462d6 |
fi
|
|
Packit |
8462d6 |
xspec="$matchop($xspec|${xspec^^})"
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
toks+=( $(
|
|
Packit |
8462d6 |
eval compgen -f -X "'!$xspec'" -- "\$(quote_readline "\$cur")" | {
|
|
Packit |
8462d6 |
while read -r tmp; do
|
|
Packit |
8462d6 |
[[ -n $tmp ]] && printf '%s\n' $tmp
|
|
Packit |
8462d6 |
done
|
|
Packit |
8462d6 |
}
|
|
Packit |
8462d6 |
))
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
if [[ ${#toks[@]} -ne 0 ]]; then
|
|
Packit |
8462d6 |
compopt -o filenames
|
|
Packit |
8462d6 |
COMPREPLY=( "${toks[@]}" )
|
|
Packit |
8462d6 |
fi
|
|
Packit |
8462d6 |
}
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
_install_xspec()
|
|
Packit |
8462d6 |
{
|
|
Packit |
8462d6 |
local xspec=$1 cmd
|
|
Packit |
8462d6 |
shift
|
|
Packit |
8462d6 |
for cmd in $@; do
|
|
Packit |
8462d6 |
_xspecs[$cmd]=$xspec
|
|
Packit |
8462d6 |
done
|
|
Packit |
8462d6 |
complete -F _filedir_xspec $@
|
|
Packit |
8462d6 |
}
|
|
Packit |
8462d6 |
# bzcmp, bzdiff, bz*grep, bzless, bzmore intentionally not here, see Debian: #455510
|
|
Packit |
8462d6 |
_install_xspec '!*.?(t)bz?(2)' bunzip2 bzcat pbunzip2 pbzcat lbunzip2 lbzcat
|
|
Packit |
8462d6 |
_install_xspec '!*.@(zip|[ejsw]ar|exe|pk3|wsz|zargo|xpi|s[tx][cdiw]|sx[gm]|o[dt][tspgfc]|od[bm]|oxt|epub|apk|ipa|do[ct][xm]|p[op]t[mx]|xl[st][xm]|pyz)' unzip zipinfo
|
|
Packit |
8462d6 |
_install_xspec '*.Z' compress znew
|
|
Packit |
8462d6 |
# zcmp, zdiff, z*grep, zless, zmore intentionally not here, see Debian: #455510
|
|
Packit |
8462d6 |
_install_xspec '!*.@(Z|[gGd]z|t[ag]z)' gunzip zcat
|
|
Packit |
8462d6 |
_install_xspec '!*.@(Z|[gGdz]z|t[ag]z)' unpigz
|
|
Packit |
8462d6 |
_install_xspec '!*.Z' uncompress
|
|
Packit |
8462d6 |
# lzcmp, lzdiff intentionally not here, see Debian: #455510
|
|
Packit |
8462d6 |
_install_xspec '!*.@(tlz|lzma)' lzcat lzegrep lzfgrep lzgrep lzless lzmore unlzma
|
|
Packit |
8462d6 |
_install_xspec '!*.@(?(t)xz|tlz|lzma)' unxz xzcat
|
|
Packit |
8462d6 |
_install_xspec '!*.lrz' lrunzip
|
|
Packit |
8462d6 |
_install_xspec '!*.@(gif|jp?(e)g|miff|tif?(f)|pn[gm]|p[bgp]m|bmp|xpm|ico|xwd|tga|pcx)' ee
|
|
Packit |
8462d6 |
_install_xspec '!*.@(gif|jp?(e)g|tif?(f)|png|p[bgp]m|bmp|x[bp]m|rle|rgb|pcx|fits|pm|svg)' qiv
|
|
Packit |
8462d6 |
_install_xspec '!*.@(gif|jp?(e)g?(2)|j2[ck]|jp[2f]|tif?(f)|png|p[bgp]m|bmp|x[bp]m|rle|rgb|pcx|fits|pm|?(e)ps)' xv
|
|
Packit |
8462d6 |
_install_xspec '!*.@(@(?(e)ps|?(E)PS|pdf|PDF)?(.gz|.GZ|.bz2|.BZ2|.Z))' gv ggv kghostview
|
|
Packit |
8462d6 |
_install_xspec '!*.@(dvi|DVI)?(.@(gz|Z|bz2))' xdvi kdvi
|
|
Packit |
8462d6 |
_install_xspec '!*.dvi' dvips dviselect dvitype dvipdf advi dvipdfm dvipdfmx
|
|
Packit |
8462d6 |
_install_xspec '!*.[pf]df' acroread gpdf xpdf
|
|
Packit |
8462d6 |
_install_xspec '!*.@(?(e)ps|pdf)' kpdf
|
|
Packit |
8462d6 |
_install_xspec '!*.@(okular|@(?(e|x)ps|?(E|X)PS|[pf]df|[PF]DF|dvi|DVI|cb[rz]|CB[RZ]|djv?(u)|DJV?(U)|dvi|DVI|gif|jp?(e)g|miff|tif?(f)|pn[gm]|p[bgp]m|bmp|xpm|ico|xwd|tga|pcx|GIF|JP?(E)G|MIFF|TIF?(F)|PN[GM]|P[BGP]M|BMP|XPM|ICO|XWD|TGA|PCX|epub|EPUB|odt|ODT|fb?(2)|FB?(2)|mobi|MOBI|g3|G3|chm|CHM)?(.?(gz|GZ|bz2|BZ2)))' okular
|
|
Packit |
8462d6 |
_install_xspec '!*.pdf' epdfview pdfunite
|
|
Packit |
8462d6 |
_install_xspec '!*.@(cb[rz7t]|djv?(u)|?(e)ps|pdf)' zathura
|
|
Packit |
8462d6 |
_install_xspec '!*.@(?(e)ps|pdf)' ps2pdf ps2pdf12 ps2pdf13 ps2pdf14 ps2pdfwr
|
|
Packit |
8462d6 |
_install_xspec '!*.texi*' makeinfo texi2html
|
|
Packit |
8462d6 |
_install_xspec '!*.@(?(la)tex|texi|dtx|ins|ltx|dbj)' tex latex slitex jadetex pdfjadetex pdftex pdflatex texi2dvi xetex xelatex luatex lualatex
|
|
Packit |
8462d6 |
_install_xspec '!*.mp3' mpg123 mpg321 madplay
|
|
Packit |
8462d6 |
_install_xspec '!*@(.@(mp?(e)g|MP?(E)G|wm[av]|WM[AV]|avi|AVI|asf|vob|VOB|bin|dat|divx|DIVX|vcd|ps|pes|fli|flv|FLV|fxm|FXM|viv|rm|ram|yuv|mov|MOV|qt|QT|web[am]|WEB[AM]|mp[234]|MP[234]|m?(p)4[av]|M?(P)4[AV]|mkv|MKV|og[gmv]|OG[GMV]|t[ps]|T[PS]|m2t?(s)|M2T?(S)|mts|MTS|wav|WAV|flac|FLAC|asx|ASX|mng|MNG|srt|m[eo]d|M[EO]D|s[3t]m|S[3T]M|it|IT|xm|XM)|+([0-9]).@(vdr|VDR))?(.part)' xine aaxine fbxine
|
|
Packit |
8462d6 |
_install_xspec '!*@(.@(mp?(e)g|MP?(E)G|wm[av]|WM[AV]|avi|AVI|asf|vob|VOB|bin|dat|divx|DIVX|vcd|ps|pes|fli|flv|FLV|fxm|FXM|viv|rm|ram|yuv|mov|MOV|qt|QT|web[am]|WEB[AM]|mp[234]|MP[234]|m?(p)4[av]|M?(P)4[AV]|mkv|MKV|og[gmv]|OG[GMV]|t[ps]|T[PS]|m2t?(s)|M2T?(S)|mts|MTS|wav|WAV|flac|FLAC|asx|ASX|mng|MNG|srt|m[eo]d|M[EO]D|s[3t]m|S[3T]M|it|IT|xm|XM|iso|ISO)|+([0-9]).@(vdr|VDR))?(.part)' kaffeine dragon
|
|
Packit |
8462d6 |
_install_xspec '!*.@(avi|asf|wmv)' aviplay
|
|
Packit |
8462d6 |
_install_xspec '!*.@(rm?(j)|ra?(m)|smi?(l))' realplay
|
|
Packit |
8462d6 |
_install_xspec '!*.@(mpg|mpeg|avi|mov|qt)' xanim
|
|
Packit |
8462d6 |
_install_xspec '!*.@(ogg|m3u|flac|spx)' ogg123
|
|
Packit |
8462d6 |
_install_xspec '!*.@(mp3|ogg|pls|m3u)' gqmpeg freeamp
|
|
Packit |
8462d6 |
_install_xspec '!*.fig' xfig
|
|
Packit |
8462d6 |
_install_xspec '!*.@(mid?(i)|cmf)' playmidi
|
|
Packit |
8462d6 |
_install_xspec '!*.@(mid?(i)|rmi|rcp|[gr]36|g18|mod|xm|it|x3m|s[3t]m|kar)' timidity
|
|
Packit |
8462d6 |
_install_xspec '!*.@(669|abc|am[fs]|d[bs]m|dmf|far|it|mdl|m[eo]d|mid?(i)|mt[2m]|oct|okt?(a)|p[st]m|s[3t]m|ult|umx|wav|xm)' modplugplay modplug123
|
|
Packit |
8462d6 |
_install_xspec '*.@([ao]|so|so.!(conf|*/*)|[rs]pm|gif|jp?(e)g|mp3|mp?(e)g|avi|asf|ogg|class)' vi vim gvim rvim view rview rgvim rgview gview emacs xemacs sxemacs kate kwrite
|
|
Packit |
8462d6 |
_install_xspec '!*.@(zip|z|gz|tgz)' bzme
|
|
Packit |
8462d6 |
# konqueror not here on purpose, it's more than a web/html browser
|
|
Packit |
8462d6 |
_install_xspec '!*.@(?([xX]|[sS])[hH][tT][mM]?([lL]))' netscape mozilla lynx galeon dillo elinks amaya epiphany
|
|
Packit |
8462d6 |
_install_xspec '!*.@(?([xX]|[sS])[hH][tT][mM]?([lL])|[pP][dD][fF])' firefox mozilla-firefox iceweasel google-chrome chromium-browser
|
|
Packit |
8462d6 |
_install_xspec '!*.@(sxw|stw|sxg|sgl|doc?([mx])|dot?([mx])|rtf|txt|htm|html|?(f)odt|ott|odm|pdf)' oowriter
|
|
Packit |
8462d6 |
_install_xspec '!*.@(sxi|sti|pps?(x)|ppt?([mx])|pot?([mx])|?(f)odp|otp)' ooimpress
|
|
Packit |
8462d6 |
_install_xspec '!*.@(sxc|stc|xls?([bmx])|xlw|xlt?([mx])|[ct]sv|?(f)ods|ots)' oocalc
|
|
Packit |
8462d6 |
_install_xspec '!*.@(sxd|std|sda|sdd|?(f)odg|otg)' oodraw
|
|
Packit |
8462d6 |
_install_xspec '!*.@(sxm|smf|mml|odf)' oomath
|
|
Packit |
8462d6 |
_install_xspec '!*.odb' oobase
|
|
Packit |
8462d6 |
_install_xspec '!*.[rs]pm' rpm2cpio
|
|
Packit |
8462d6 |
_install_xspec '!*.aux' bibtex
|
|
Packit |
8462d6 |
_install_xspec '!*.po' poedit gtranslator kbabel lokalize
|
|
Packit |
8462d6 |
_install_xspec '!*.@([Pp][Rr][Gg]|[Cc][Ll][Pp])' harbour gharbour hbpp
|
|
Packit |
8462d6 |
_install_xspec '!*.[Hh][Rr][Bb]' hbrun
|
|
Packit |
8462d6 |
_install_xspec '!*.ly' lilypond ly2dvi
|
|
Packit |
8462d6 |
_install_xspec '!*.@(dif?(f)|?(d)patch)?(.@([gx]z|bz2|lzma))' cdiff
|
|
Packit |
8462d6 |
_install_xspec '!@(*.@(ks|jks|jceks|p12|pfx|bks|ubr|gkr|cer|crt|cert|p7b|pkipath|pem|p10|csr|crl)|cacerts)' portecle
|
|
Packit |
8462d6 |
_install_xspec '!*.@(mp[234c]|og[ag]|@(fl|a)ac|m4[abp]|spx|tta|w?(a)v|wma|aif?(f)|asf|ape)' kid3 kid3-qt
|
|
Packit |
8462d6 |
unset -f _install_xspec
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# Minimal completion to use as fallback in _completion_loader.
|
|
Packit |
8462d6 |
_minimal()
|
|
Packit |
8462d6 |
{
|
|
Packit |
8462d6 |
local cur prev words cword split
|
|
Packit |
8462d6 |
_init_completion -s || return
|
|
Packit |
8462d6 |
$split && return
|
|
Packit |
8462d6 |
_filedir
|
|
Packit |
8462d6 |
}
|
|
Packit |
8462d6 |
# Complete the empty string to allow completion of '>', '>>', and '<' on < 4.3
|
|
Packit |
8462d6 |
# http://lists.gnu.org/archive/html/bug-bash/2012-01/msg00045.html
|
|
Packit |
8462d6 |
complete -F _minimal ''
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
__load_completion()
|
|
Packit |
8462d6 |
{
|
|
Packit |
8462d6 |
local -a dirs=( ${BASH_COMPLETION_USER_DIR:-${XDG_DATA_HOME:-$HOME/.local/share}/bash-completion}/completions )
|
|
Packit |
8462d6 |
local OIFS=$IFS IFS=: dir cmd="$1" compfile
|
|
Packit |
8462d6 |
for dir in ${XDG_DATA_DIRS:-/usr/local/share:/usr/share}; do
|
|
Packit |
8462d6 |
dirs+=( $dir/bash-completion/completions )
|
|
Packit |
8462d6 |
done
|
|
Packit |
8462d6 |
IFS=$OIFS
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
if [[ $BASH_SOURCE == */* ]]; then
|
|
Packit |
8462d6 |
dirs+=( "${BASH_SOURCE%/*}/completions" )
|
|
Packit |
8462d6 |
else
|
|
Packit |
8462d6 |
dirs+=( ./completions )
|
|
Packit |
8462d6 |
fi
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
for dir in "${dirs[@]}"; do
|
|
Packit |
8462d6 |
for compfile in "${cmd##*/}" "${cmd##*/}".bash _"${cmd##*/}"; do
|
|
Packit |
8462d6 |
compfile="$dir/$compfile"
|
|
Packit |
8462d6 |
# Avoid trying to source dirs; https://bugzilla.redhat.com/903540
|
|
Packit |
8462d6 |
[[ -f "$compfile" ]] && . "$compfile" &>/dev/null && return 0
|
|
Packit |
8462d6 |
done
|
|
Packit |
8462d6 |
done
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
return 1
|
|
Packit |
8462d6 |
}
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# set up dynamic completion loading
|
|
Packit |
8462d6 |
_completion_loader()
|
|
Packit |
8462d6 |
{
|
|
Packit |
8462d6 |
# $1=_EmptycmD_ already for empty cmds in bash 4.3, set to it for earlier
|
|
Packit |
8462d6 |
local cmd="${1:-_EmptycmD_}"
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
__load_completion "$cmd" && return 124
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# Need to define *something*, otherwise there will be no completion at all.
|
|
Packit |
8462d6 |
complete -F _minimal -- "$cmd" && return 124
|
|
Packit |
8462d6 |
} &&
|
|
Packit |
8462d6 |
complete -D -F _completion_loader
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# Function for loading and calling functions from dynamically loaded
|
|
Packit |
8462d6 |
# completion files that may not have been sourced yet.
|
|
Packit |
8462d6 |
# @param $1 completion file to load function from in case it is missing
|
|
Packit |
8462d6 |
# @param $2... function and its arguments
|
|
Packit |
8462d6 |
_xfunc()
|
|
Packit |
8462d6 |
{
|
|
Packit |
8462d6 |
set -- "$@"
|
|
Packit |
8462d6 |
local srcfile=$1
|
|
Packit |
8462d6 |
shift
|
|
Packit |
8462d6 |
declare -F $1 &>/dev/null || {
|
|
Packit |
8462d6 |
__load_completion "$srcfile"
|
|
Packit |
8462d6 |
}
|
|
Packit |
8462d6 |
"$@"
|
|
Packit |
8462d6 |
}
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# source compat completion directory definitions
|
|
Packit |
8462d6 |
compat_dir=${BASH_COMPLETION_COMPAT_DIR:-/etc/bash_completion.d}
|
|
Packit |
8462d6 |
if [[ -d $compat_dir && -r $compat_dir && -x $compat_dir ]]; then
|
|
Packit |
8462d6 |
for i in "$compat_dir"/*; do
|
|
Packit |
8462d6 |
[[ ${i##*/} != @($_backup_glob|Makefile*|$_blacklist_glob) \
|
|
Packit |
8462d6 |
&& -f $i && -r $i ]] && . "$i"
|
|
Packit |
8462d6 |
done
|
|
Packit |
8462d6 |
fi
|
|
Packit |
8462d6 |
unset compat_dir i _blacklist_glob
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# source user completion file
|
|
Packit |
8462d6 |
user_completion=${BASH_COMPLETION_USER_FILE:-~/.bash_completion}
|
|
Packit |
8462d6 |
[[ ${BASH_SOURCE[0]} != $user_completion && -r $user_completion ]] \
|
|
Packit |
8462d6 |
&& . $user_completion
|
|
Packit |
8462d6 |
unset user_completion
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
unset -f have
|
|
Packit |
8462d6 |
unset have
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
set $BASH_COMPLETION_ORIGINAL_V_VALUE
|
|
Packit |
8462d6 |
unset BASH_COMPLETION_ORIGINAL_V_VALUE
|
|
Packit |
8462d6 |
|
|
Packit |
8462d6 |
# ex: filetype=sh
|