开发者

Bash completion with none space delimited words

I am working on completion for a command that takes argument like "one:two:three".

In the simplest terms, I want ':' to be ha开发者_运维百科ndled just like a space character is by default. Is there a simple way to do this that I am missing?

I've found the ':' is in COMP_WORDBREAKS, but that the character in COMP_WORDBREAKS are also treated as words as well.

So if the commandline is:

cmd one:tw[TAB]

COMP_CWORD will be 3 and COMP_WORDS[COMP_CWORD-1] will be ':'

For comparison, if the commandline is:

cmd one tw[TAB]

COMP_CWORD will be 2 and COMP_WORDS[COMP_CWORD-1] will be 'one'

Even worse is that if you hit the [TAB] right after the ':' delimiter it acts mostly like a space:

cmd one:[TAB]

Now COMP_CWORD will be 2 and COMP_WORDS[COMP_CWORD-1] will be 'one'.

I can parse the commandline myself from COMP_LINE easily enough, but nicer to find a way to just make ':' act like ' ' in my custom completion. Possible?


Unfortunately, not really. This is actually a 'feature' of bash.

While you could modify COMP_WORDBREAKS, modifying COMP_WORDBREAKS could cause other issues as it is a global variable and will affect the behavior of other completion scripts.

If you take a look at the source for bash-completion, two helper methods exist that can help with this:

  • _get_comp_words_by_ref with the -n option gets the word-to-complete without considering the characters in EXCLUDE as word breaks
# Available VARNAMES:
#     cur         Return cur via $cur
#     prev        Return prev via $prev
#     words       Return words via $words
#     cword       Return cword via $cword
#
# Available OPTIONS:
#     -n EXCLUDE  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, so we
#                 would pass the colon (:) as -n option in this case.
#     -c VARNAME  Return cur via $VARNAME
#     -p VARNAME  Return prev via $VARNAME
#     -w VARNAME  Return words via $VARNAME
#     -i VARNAME  Return cword via $VARNAME
#
  • __ltrim_colon_completions removes colon containing prefix from COMPREPLY items
# word-to-complete.
# With a colon in COMP_WORDBREAKS, words containing
# colons are always completed as entire words if the word to complete contains
# a colon.  This function fixes this, by removing the colon-containing-prefix
# from COMPREPLY items.
# The preferred solution is to remove the colon (:) from COMP_WORDBREAKS in
# your .bashrc:
#
#    # Remove colon (:) from list of word completion separators
#    COMP_WORDBREAKS=${COMP_WORDBREAKS//:}
#
# See also: Bash FAQ - E13) Why does filename completion misbehave if a colon
# appears in the filename? - http://tiswww.case.edu/php/chet/bash/FAQ
# @param $1 current word to complete (cur)
# @modifies global array $COMPREPLY

For example:

{
    local cur
    _get_comp_words_by_ref -n : cur
    __ltrim_colon_completions "$cur"
}
complete -F _thing thing


First take on a custom parsed solution. Love to know if there is a better way:

parms=$(echo "$COMP_LINE" | cut -d ' ' -f 2)
vals="${parms}XYZZY"
IFS=$":"
words=( $vals )
unset IFS
count=${#words[@]}
cur="${words[$count-1]%%XYZZY}"
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜