bash: simple reimplementation of _get_comp_words_by_ref
Add a minimal implementation of _get_comp_words_by_ref so $ git show head:g <tab><tab> on bash 4 can complete paths within the head commit without requiring the bash_completion functions to be loaded. This is a follow-up to the previous patch (bash: get --pretty=m<tab> completion to work with bash v4). Based on bash-completion 2.x (commit bf763033, 2010-10-26) but tweaked for simplicity and to allow zsh to parse the code. Signed-off-by: Jonathan Nieder <jrnieder@gmail.com> Improved-by: SZEDER Gábor <szeder@ira.uka.de>
Jonathan Nieder committed
Dec 14, 2010 at 22:57 UTC
dbda3b10902e13826862505900eb7a537505a492
1 file changed
+110
-8
contrib/completion/git-completion.bash
+110
-8
@@ -321,26 +321,128 @@ __gitcomp_1 ()
321
done
322
}
323
324
+# The following function is based on code from:
325
+#
326
+# bash_completion - programmable completion functions for bash 3.2+
327
+#
328
+# Copyright © 2006-2008, Ian Macdonald <ian@caliban.org>
329
+# © 2009-2010, Bash Completion Maintainers
330
+# <bash-completion-devel@lists.alioth.debian.org>
331
+#
332
+# This program is free software; you can redistribute it and/or modify
333
+# it under the terms of the GNU General Public License as published by
334
+# the Free Software Foundation; either version 2, or (at your option)
335
+# any later version.
336
+#
337
+# This program is distributed in the hope that it will be useful,
338
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
339
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
340
+# GNU General Public License for more details.
341
+#
342
+# You should have received a copy of the GNU General Public License
343
+# along with this program; if not, write to the Free Software Foundation,
344
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
345
+#
346
+# The latest version of this software can be obtained here:
347
+#
348
+# http://bash-completion.alioth.debian.org/
349
+#
350
+# RELEASE: 2.x
351
+
352
+# This function can be used to access a tokenized list of words
353
+# on the command line:
354
+#
355
+# __git_reassemble_comp_words_by_ref '=:'
356
+# if test "${words_[cword_-1]}" = -w
357
+# then
358
+# ...
359
+# fi
360
+#
361
+# The argument should be a collection of characters from the list of
362
+# word completion separators (COMP_WORDBREAKS) to treat as ordinary
363
+# characters.
364
+#
365
+# This is roughly equivalent to going back in time and setting
366
+# COMP_WORDBREAKS to exclude those characters. The intent is to
367
+# make option types like --date=<type> and <rev>:<path> easy to
368
+# recognize by treating each shell word as a single token.
369
+#
370
+# It is best not to set COMP_WORDBREAKS directly because the value is
371
+# shared with other completion scripts. By the time the completion
372
+# function gets called, COMP_WORDS has already been populated so local
373
+# changes to COMP_WORDBREAKS have no effect.
374
+#
375
+# Output: words_, cword_, cur_.
376
+
377
+__git_reassemble_comp_words_by_ref()
378
+{
379
+ local exclude i j first
380
+ # Which word separators to exclude?
381
+ exclude="${1//[^$COMP_WORDBREAKS]}"
382
+ cword_=$COMP_CWORD
383
+ if [ -z "$exclude" ]; then
384
+ words_=("${COMP_WORDS[@]}")
385
+ return
386
+ fi
387
+ # List of word completion separators has shrunk;
388
+ # re-assemble words to complete.
389
+ for ((i=0, j=0; i < ${#COMP_WORDS[@]}; i++, j++)); do
390
+ # Append each nonempty word consisting of just
391
+ # word separator characters to the current word.
392
+ first=t
393
+ while
394
+ [ $i -gt 0 ] &&
395
+ [ -n "${COMP_WORDS[$i]}" ] &&
396
+ # word consists of excluded word separators
397
+ [ "${COMP_WORDS[$i]//[^$exclude]}" = "${COMP_WORDS[$i]}" ]
398
+ do
399
+ # Attach to the previous token,
400
+ # unless the previous token is the command name.
401
+ if [ $j -ge 2 ] && [ -n "$first" ]; then
402
+ ((j--))
403
+ fi
404
+ first=
405
+ words_[$j]=${words_[j]}${COMP_WORDS[i]}
406
+ if [ $i = $COMP_CWORD ]; then
407
+ cword_=$j
408
+ fi
409
+ if (($i < ${#COMP_WORDS[@]} - 1)); then
410
+ ((i++))
411
+ else
412
+ # Done.
413
+ return
414
+ fi
415
+ done
416
+ words_[$j]=${words_[j]}${COMP_WORDS[i]}
417
+ if [ $i = $COMP_CWORD ]; then
418
+ cword_=$j
419
+ fi
420
+ done
421
+}
422
+
423
if ! type _get_comp_words_by_ref >/dev/null 2>&1; then
424
_get_comp_words_by_ref ()
425
{
426
+ local exclude cur_ words_ cword_
427
+ if [ "$1" = "-n" ]; then
428
+ exclude=$2
429
+ shift 2
430
+ fi
431
+ __git_reassemble_comp_words_by_ref "$exclude"
432
+ cur_=${words_[cword_]}
433
while [ $# -gt 0 ]; do
434
case "$1" in
435
cur)
330
- cur=${COMP_WORDS[COMP_CWORD]}
436
+ cur=$cur_
437
;;
438
prev)
333
- prev=${COMP_WORDS[COMP_CWORD-1]}
439
+ prev=${words_[$cword_-1]}
440
;;
441
words)
336
- words=("${COMP_WORDS[@]}")
442
+ words=("${words_[@]}")
443
;;
444
cword)
339
- cword=$COMP_CWORD
340
- ;;
341
- -n)
342
- # assume COMP_WORDBREAKS is already set sanely
343
- shift
445
+ cword=$cword_
446
;;
447
esac
448
shift