如何使bash自动完成工作在行中间?

时间:2016-11-30 14:37:29

标签: bash compgen

如何在bash中编写自动完成,这样如果我有:

mycommand first_argument|garbage

其中|表示光标,它应该将"first_argument"而不是"first_argumentgarbage"传递给compgen?

在示例中,我的行为方式错误

COMPREPLY=( $(compgen -W "add remove list use current" -- "$cur") ) # buggy

1 个答案:

答案 0 :(得分:1)

Bash完成使用lot of different variables。其中一些用于处理输入并确定要完成的参数。

对于以下说明,我将使用此测试输入(以|作为光标):

./test.sh ad re|garbage
  • ${COMP_WORDS}:以数组的形式包含输入的所有单词。在这种情况下,它包含:${COMP_WORDS[@]} == {"./test.sh", "ad", "regarbage"}
    • 单词分隔符可在$COMP_WORDBREAKS变量
    • 中找到
  • $COMP_CWORD:包含光标正在选择的单词的位置。在这种情况下,它包含:$COMP_CWORD == 2
  • $COMP_LINE:包含字符串形式的整个输入。在这种情况下,它包含:$COMP_LINE == "./test.sh ad regarbage"
  • $COMP_POINT:包含光标在整行中的位置。在这种情况下,它包含:$COMP_POINT == 15

仍然使用相同的数据,执行cur=${COMP_WORDS[COMP_CWORD]}将返回${COMP_WORD}数组中索引2处的元素,即regarbage

要规避此行为,您还必须使用$COMP_LINE$COMP_POINT变量。以下是我提出的建议:

# we truncate our line up to the position of our cursor
# we transform the result into an array
cur=(${COMP_LINE:0:$COMP_POINT})

# we use ${cur} the same way we would use ${COMP_WORDS}
COMPREPLY=( $( compgen -W "add remove list use current" -- "${cur[$COMP_CWORD]}" ) )

输出:

> ./test2.sh ad re|garbage
# press TAB
> ./test2.sh ad remove|garbage

请注意,默认情况下,removegarbage之间不会有空格。如果这是你想要的行为,你将不得不玩完成机制。