首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >防止bash补全打印两次回复

防止bash补全打印两次回复
EN

Stack Overflow用户
提问于 2018-07-13 20:21:00
回答 1查看 300关注 0票数 4

我很难让我的bash完成脚本像预期的那样运行。

下面是我正在尝试做的事情的最简化版本,以及问题的截屏视频。

除了一个例外,一切都运行得很好:

当补全中只有一个匹配项时,当我按Tab键两次时,它会打印相同的命令两次,这不是预期的效果。

在我的完成案例中,我只对完成第一个参数(即“子命令”)感兴趣。我认为下面的if [ "$#" -gt "2" ]行应该可以防止这种情况,但它没有-因为在第一个选项卡之后COMP_LINE仍然没有更新。

代码语言:javascript
运行
复制
#!/usr/bin/env bash

send_completions() {
  if [[ -z "$COMP_LINE" ]]; then
    return
  fi

  set $COMP_LINE

  if [ "$#" -gt "2" ]; then
    return
  fi

  compgen -W "one two test" "$2"
}

send_completions

通过运行以下命令启用完成:

代码语言:javascript
运行
复制
$ complete -C './complete.sh' asd

然后键入asd o<tab><tab>查看问题。

任何帮助都是非常感谢的。

EN

回答 1

Stack Overflow用户

发布于 2018-07-13 21:40:43

此时检查COMP_LINE的值:

代码语言:javascript
运行
复制
$ asd one <TAB>

您会注意到,该值为:

代码语言:javascript
运行
复制
declare -x COMP_LINE="asd one "

这将在您发出set之后产生两个位置参数,并且您的条件不会被触发。尝试输入一个额外的字符:$ asd one o<TAB>,您将看到您的条件将被正确触发,并且不会完成任何操作。

我所见过的大多数完成都是使用函数完成的。事实上,现在检查我系统上定义的所有补全(大多数是默认的),其中没有一个是使用脚本完成的。

使用函数有一些好处,例如,支持引号的COMP_WORDS数组。您的脚本可以大致重写如下:

代码语言:javascript
运行
复制
_asd_comp() {
    (( COMP_CWORD > 1 )) && return
    local cur=${COMP_WORDS[COMP_CWORD]} IFS=$' \t\n'
    COMPREPLY=( $(compgen -W "one two three" -- "$cur") )    
}

complete -o bashdefault -o default -F _asd_comp asd

我添加了-o选项,以便在第一个参数之后执行默认完成。你可以在manual上阅读更多关于这方面的内容。

关于如何更改您的脚本,我想您唯一想到的就是添加相当不干净的条件,例如:

代码语言:javascript
运行
复制
(( $# > 1 )) && [[ ${COMP_LINE: -1} = " " ]] && return
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51324984

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档