[Bash-completion-commits] [SCM] bash-completion branch, master, updated. 884c3f5af68e11825c7044092f7fe62975d03459
Freddy Vulto
fvulto at gmail.com
Sat Oct 31 08:58:45 UTC 2009
The following commit has been merged in the master branch:
commit 545750eb2c9b21013ef0dce777e790ee3cb27d32
Author: Freddy Vulto <fvulto at gmail.com>
Date: Sat Oct 31 09:24:20 2009 +0100
Added _get_pword() helper function.
Thanks to Sung Pae (Alioth #312030):
"This patch extends both __get_cword3() and __get_cword4() to accept an
additional integer argument that specifies how many places previous to
the current word the desired word resides, respecting any user
exceptions to COMP_WORDBREAKS."
diff --git a/CHANGES b/CHANGES
index d01f378..d9e3ae9 100644
--- a/CHANGES
+++ b/CHANGES
@@ -28,6 +28,9 @@ bash-completion (2.x)
* Drop support for bash < 3.
* Fix sed error in qdbus completions containing slashes (Debian: 552631).
+ [ Freddy Vulto ]
+ * Added _get_pword() helper function, thanks to Sung Pae (Alioth: #312030)
+
-- David Paleino <d.paleino at gmail.com> Sun, 11 Oct 2009 11:11:57 +0200
bash-completion (1.1)
diff --git a/bash_completion b/bash_completion
index 99ce63a..f648113 100644
--- a/bash_completion
+++ b/bash_completion
@@ -243,10 +243,17 @@ _get_cword()
if [ ${BASH_VERSINFO[0]} -ge 4 ] ; then
__get_cword4 "$@"
else
- __get_cword3
+ __get_cword3 "$2"
fi
} # _get_cword()
+# Get word previous to the current word;
+# Accepts the same arguments as _get_cword()
+#
+# This is a good alternative to `prev=${COMP_WORDS[COMP_CWORD-1]}' because bash4
+# will properly return the previous word with respect to any given exclusions to
+# COMP_WORDBREAKS.
+_get_pword() { _get_cword "${@:-}" 1; }
# Get the word to complete on bash-3, where words are not broken by
# COMP_WORDBREAKS characters and the COMP_CWORD variables look like this, for
@@ -265,7 +272,10 @@ _get_cword()
[ ${BASH_VERSINFO[0]} -lt 4 ] &&
__get_cword3()
{
- if [[ "${#COMP_WORDS[COMP_CWORD]}" -eq 0 ]] || [[ "$COMP_POINT" == "${#COMP_LINE}" ]]; then
+ # return previous word offset by $1
+ if [[ ${1//[^0-9]/} ]]; then
+ printf "%s" "${COMP_WORDS[COMP_CWORD-$1]}"
+ elif [[ "${#COMP_WORDS[COMP_CWORD]}" -eq 0 ]] || [[ "$COMP_POINT" == "${#COMP_LINE}" ]]; then
printf "%s" "${COMP_WORDS[COMP_CWORD]}"
else
local i
@@ -317,10 +327,14 @@ __get_cword3()
# 2: :
# 3: c
#
-# @oaram $1 string
+# @param $1 string
# $1 string (optional) Characters out of $COMP_WORDBREAKS which should
# NOT be considered word breaks. This is useful for things like scp where
# we want to return host:path and not only path.
+# @param $2 integer
+# $2 integer (optional) Return word according to $COMP_WORDBREAKS, negatively
+# offset by the value. For example, `__get_cword4 "=:" -1' returns the word
+# left of the current word, respecting the exclusions given at $1
# See also:
# _get_cword, main routine
# __get_cword3, bash-3 variant
@@ -328,9 +342,10 @@ __get_cword3()
[ ${BASH_VERSINFO[0]} -ge 4 ] &&
__get_cword4()
{
+ local exclude="$1" n_idx="${2:-0}"
local i
local LC_CTYPE=C
- local WORDBREAKS=$COMP_WORDBREAKS
+ local WORDBREAKS="$COMP_WORDBREAKS"
# Strip single quote (') and double quote (") from WORDBREAKS to
# workaround a bug in bash-4.0, where quoted words are split
# unintended, see:
@@ -338,32 +353,50 @@ __get_cword4()
# This fixes simple quoting (e.g. $ a "b<TAB> returns "b instead of b)
# but still fails quoted spaces (e.g. $ a "b c<TAB> returns c instead
# of "b c).
- WORDBREAKS=${WORDBREAKS//\"/}
- WORDBREAKS=${WORDBREAKS//\'/}
- if [ -n "$1" ]; then
- for (( i=0; i<${#1}; ++i )); do
- local char=${1:$i:1}
- WORDBREAKS=${WORDBREAKS//$char/}
+ WORDBREAKS="${WORDBREAKS//[\"\']/}"
+ if [[ $exclude ]]; then
+ for (( i=0; i<${#exclude}; ++i )); do
+ local char="${exclude:$i:1}"
+ WORDBREAKS="${WORDBREAKS//$char/}"
done
fi
- local cur=${COMP_LINE:0:$COMP_POINT}
- local tmp=$cur
- local word_start=`expr "$tmp" : '.*['"$WORDBREAKS"']'`
- while [ "$word_start" -ge 2 ]; do
- # Get character before $word_start
- local char=${cur:$(( $word_start - 2 )):1}
- # If the WORDBREAK character isn't escaped, exit loop
- if [ "$char" != "\\" ]; then
- break
+ local cur="${COMP_LINE:0:$COMP_POINT}"
+ local tmp="$cur"
+
+ local break_index word_start
+ # return index of first occuring break character in $1; return 0 if none
+ break_index() {
+ if [[ $1 == *[$WORDBREAKS]* ]]; then
+ local w="${1%[$WORDBREAKS]*}"
+ echo $((${#w}+1))
+ else
+ echo 0
fi
- # The WORDBREAK character is escaped;
- # Recalculate $word_start
- tmp=${COMP_LINE:0:$(( $word_start - 2 ))}
- word_start=`expr "$tmp" : '.*['"$WORDBREAKS"']'`
- done
+ }
+ # return the index of the start of the last word in $@
+ word_start() {
+ local buf="$@"
+ local start="$(break_index "$buf")"
+ while [[ $start -ge 2 ]]; do
+ # Get character before $start
+ local char="${cur:$(( start - 2 )):1}"
+ # If the WORDBREAK character isn't escaped, exit loop
+ [[ $char != \\ ]] && break
+ # The WORDBREAK character is escaped; recalculate $start
+ buf="${COMP_LINE:0:$(( start - 2 ))}"
+ start=$(break_index "$buf")
+ done
+ echo $start
+ }
- cur=${cur:$word_start}
- printf "%s" "$cur"
+ # calculate current word, negatively offset by n_idx
+ cur="${tmp:$(word_start "$tmp")}"
+ while [[ $n_idx -gt 0 ]]; do
+ local tmp="${tmp%[$WORDBREAKS]$cur}" # truncate passed string
+ local cur="${tmp:$(word_start "$tmp")}" # then recalculate
+ ((--n_idx))
+ done
+ echo -n "$cur"
} # __get_cword4()
--
bash-completion
More information about the Bash-completion-commits
mailing list