如何打破完整的三部曲模式

Ale*_*der 13 bash bash-completion

我有一个命令行工具,它以三部分形式接受参数:

$ t first_second_third
Run Code Online (Sandbox Code Playgroud)

我有一组有效值first,一组有效值second,以及一组有效值third.我想使用Bash完整功能来完成选项值的每个部分,如下例所示:

$ t [tab][tab]           # shows options for first part
walk run skip bike
$ t w[tab]               # completes first part and appends delimiter
$ t walk_[tab][tab]      # shows options for second part
home work park
$ t walk_h[tab]          # completes second part and appends delimiter
$ t walk_home_[tab][tab] # shows options for second part
morning afternoon evening
$ t walk_home_a[tab]     # completes second part and appends space
$ t walk_home_afternoon
Run Code Online (Sandbox Code Playgroud)

我有这个代码:

_tool () {
  local cur="${COMP_WORDS[COMP_CWORD]}"

  local first="walk run skip bike"
  local second="home work park"
  local third="morning afternoon evening"

  case "${cur}" in
    *_*_*)
      COMPREPLY=( $(compgen -W "${third}" -- "") ); return 0;;
    *_*)
      COMPREPLY=( $(compgen -W "${second}" -S "_" -- ${cur}) ); compopt -o nospace; return 0;;
    *)
      COMPREPLY=( $(compgen -W "${first}" -S "_" -- ${cur}) ); compopt -o nospace; return 0;;
  esac
}

complete -F _tool t
Run Code Online (Sandbox Code Playgroud)

第一个条款很有效; 没什么特别的.但第二个条款没有给我任何选择或完成.

$ t [tab][tab]
bike_  run_   skip_  walk_
$ t b[tab]
$ t bike_[tab][tab] # nothing but bells
Run Code Online (Sandbox Code Playgroud)

我用以下代码替换了第二个子句(即我${cur}COMPREPLY调用中用空字符串替换):

COMPREPLY=( $(compgen -W "${second}" -S "_" -- "") ); compopt -o nospace; return 0;;
Run Code Online (Sandbox Code Playgroud)

我在命令行上获得了所有选项的列表,但没有完成.

$ t bike_[tab][tab]
home_  park_  work_
$ t bike_h[tab][tab]
home_  park_  work_
$ t bike_ho[tab][tab]
home_  park_  work_
Run Code Online (Sandbox Code Playgroud)

我想可能有一些不良的相互作用${cur}COMPREPLY单词列表,所以我又换了第二条,加上其当前单词的第一部分相匹配的前缀:

local prefix=( $(expr "${cur}" : '\(.*_\)') )
COMPREPLY=( $(compgen -W "${second}" -P "${prefix}" -S "_" -- "") ); compopt -o nospace; return 0;;
Run Code Online (Sandbox Code Playgroud)

这没什么用.随着${cur}在静止COMPREPLY的命令,我没有选择或完成一次.换了一个空字符串,我得到了完整的选项(不仅仅是当前的部分).但是,按Tab键会删除键入的内容.

$ t bike_[tab][tab]
bike_home_  bike_park_  bike_work_
$ t bike_ho[tab]
$ t bike_ # "ho" was erased
Run Code Online (Sandbox Code Playgroud)

当然,我对第三部分也有同样的问题.

  1. 我怎样才能让Bash逐个完成当前的单词?
  2. 在选择某个选项之前,如何让Bash不附加分隔符?

这类似于另一个Bash完整问题,但我不想列出值的每个可能的排列,并且它们没有被格式化为文件名(不确定文件名模式是否有所不同).

谢谢您的帮助!
留学美国相关考试

msb*_*msb 5

我能够创造你想要的。请参阅下面的代码:

_tool () {
  local cur="${COMP_WORDS[COMP_CWORD]}"

  local first="walk run skip bike"

  case "${cur}" in
    *_*_*)
      local firstsecond=`echo ${cur} | awk -F '_' '{print $1"_"$2}'`
      local third="${firstsecond}_morning ${firstsecond}_afternoon ${firstsecond}_evening"
      COMPREPLY=( $(compgen -W "${third}" -- ${cur}) ); return 0;;
    *_*)
      local firstcomp=`echo ${cur} | awk -F '_' '{print $1}'`
      local second="${firstcomp}_home ${firstcomp}_work ${firstcomp}_park"
      COMPREPLY=( $(compgen -W "${second}" -S "_" -- ${cur}) ); compopt -o nospace; return 0;;
    *)
      COMPREPLY=( $(compgen -W "${first}" -S "_" -- ${cur}) ); compopt -o nospace; return 0;;
  esac
}

complete -F _tool t
Run Code Online (Sandbox Code Playgroud)

我对自动完成不太熟悉,这是我第一次使用compgencomplete,所以我不确定我能回答你关于事物理论的问题。我可以告诉你我做了什么,以防它帮助你理解这个记录错误的函数是如何工作的。首先,我试图了解你所拥有的。我成功地重现了您的问题。然后我有了这样的想法,即使你不想在代码中自己列出每个排列,我也可以使用局部变量来模拟,好像它有一样。我做的第一件事是在我们有了第一个下划线后获取“第一个”元素,然后向其中添加第二个元素,并将其提供给 compgen。令我惊讶的是,它运行良好。然后我尝试对第三级做同样的事情......然后问题开始了。我发现第二部分并没有我想象的那么好。完成第一个词后,我会得到第二个词的建议;

$ t [tab][tab]           # shows options for first part
bike_ run_ skip_ walk_
$ t w[tab]               # completes first part and appends delimiter
$ t walk_[tab][tab]      # shows options for second part
walk_home_ walk_park_ walk_work_
$ t walk_h[tab]          # completes second part and appends delimiter
$ t walk_home_[tab][tab] # screws up with it
$ t walkhome_            
Run Code Online (Sandbox Code Playgroud)

我尝试将下划线移动到 awk 中,但没有成功:

      local first=`echo ${cur} | awk -F '_' '{print $1"_"}'`
      local second="${first}home ${first}work ${first}park"
Run Code Online (Sandbox Code Playgroud)

出于某种原因,我不得不将变量名更改为与“first”不同的名称,然后它就开始工作了。然后,在第三个元素上,我遇到了您最后描述的相同问题,我在第三个元素中输入的任何内容都会消失,但是 [tab][tab] 会给我以下选项:

$ t walk_home_[tab][tab] # shows options for second part
morning afternoon evening
$ t walk_home_aft[tab]     # erases what I typed
$ t walk_home_
Run Code Online (Sandbox Code Playgroud)

${cur}在第三个单词中添加到 compgen 并且它起作用了。这只是我所做工作的总结......但我得到了一个工作版本,所以我很高兴。:-)