【问题标题】:How to extend bash completion in other directory?如何在其他目录中扩展 bash 完成?
【发布时间】:2016-07-09 20:02:03
【问题描述】:

我正在学习 bash 补全。我只能列出当前目录的内容。这是我的代码:

   _foo()
   {
       local cur prev opts
       COMPREPLY=()
       cur="${COMP_WORDS[COMP_CWORD]}"
       prev="${COMP_WORDS[COMP_CWORD-1]}"

       opts="push pull"
       OUTPUT=" $(ls) "

      case "${prev}" in
          push)
              COMPREPLY=( $(compgen -W "--in --out" -- ${cur}) )
              return 0
              ;;
          --in)
              COMPREPLY=( $(compgen -W "$OUTPUT" -- ${cur}) )
              return 0
              ;;
      esac

        COMPREPLY=($(compgen -W "${opts}" -- ${cur}))
        return 0
  }
  complete -F _foo foo

它的输出是:

$ foo push --in[TAB]
file1.txt file2.txt foo  ;; content of pwd

但是当我这样做时:

$ foo push --in ~[TAB]

它不工作。 所以我想知道如何在不同的目录中完成 bash(不仅在 pwd 中)?谢谢。

【问题讨论】:

  • 哦,它们实际上不在脚本中。这些只是因为 Vim 编辑器。我从那里复制了这个脚本,所以也复制了行号。

标签: bash autocomplete bash-completion


【解决方案1】:

您可以使用-f 来匹配文件名:

#!/bin/bash
_foo()    {
       local cur prev opts
       COMPREPLY=()
       cur="${COMP_WORDS[COMP_CWORD]}"
       prev="${COMP_WORDS[COMP_CWORD-1]}"
       opts="push pull"

       case "${prev}" in
          push)
              COMPREPLY=( $(compgen -W "--in --out" -- ${cur}) )
              return 0
              ;;
          --in)
              COMPREPLY=( $(compgen -f ${cur}) )
              return 0
              ;;
      esac

      COMPREPLY=($(compgen -W "${opts}" -- ${cur}))
      return 0   
}

complete -F _foo foo

但它似乎不适用于 ~ 单独但 $ foo push --in ~/[TAB] 和所有其他目录都有效 此解决方案不包括在目录中查找文件的斜线:$ foo push --in /etc[TAB] 将给出foo push --in /etc 而不是foo push --in /etc/

以下帖子使用默认模式解决了该问题:
Getting compgen to include slashes on directories when looking for files

默认

如果 compspec 未生成匹配项,则使用 Readline 的默认文件名完成。

所以你可以使用:

#!/bin/bash
_foo()
   {
       local cur prev opts
       COMPREPLY=()
       cur="${COMP_WORDS[COMP_CWORD]}"
       prev="${COMP_WORDS[COMP_CWORD-1]}"

       opts="push pull"
       OUTPUT=" $(ls) "

      case "${prev}" in
          push)
              COMPREPLY=( $(compgen -W "--in --out" -- ${cur}) )
              return 0
              ;;
          --in)
              COMPREPLY=()
              return 0
              ;;
          --port)
              COMPREPLY=("")
              return 0
              ;;
      esac

        COMPREPLY=($(compgen -W "${opts}" -- ${cur}))
        return 0
  }
  complete -o default -F _foo foo

或者当你需要喜欢这篇文章时设置为默认模式:https://unix.stackexchange.com/a/149398/146783

【讨论】:

  • 这很好。但是,如果我不想在特定情况下做任何事情怎么办。假设有参数--port,我想从键盘上获取它。应该是这样的$ foo push --port[TAB];;自动完成应该停止,没有结果。它指示用户从键盘传递 --port 值。但是根据您的回答,它将是$ foo push --port[TAB] ;; pwd 的内容那么有什么办法可以指定,在这些情况下我们不默认结果?
  • 但这不起作用。 $ foo push --in[TAB] bash: compopt: command not found这是我收到的错误消息。
  • 您是否在 bash_completion.d 中获取文件?尝试在顶部添加 #!/bin/bash 以确保它使用正确的 bash。如果您的 bash 不在 /bin/bash 中,请替换为正确的 bash 位置 (which bash)
  • 如果你这样做,这不会包括斜线来查找子目录
猜你喜欢
  • 2014-12-20
  • 2019-04-14
  • 1970-01-01
  • 1970-01-01
  • 2019-10-19
  • 1970-01-01
  • 2020-06-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多