为自定义脚本添加自动完成功能

Luk*_*ich 6 bash autocomplete

我目前正在开发一个我调用makeyourself.sh(链接到/usr/bin/mys)的 shell 脚本,它会自动从源代码(通过apt-get source -b $1)安装一个 debian 包。

所以我决定为作为第一个参数给出的包名称添加一个自动完成功能:sudo mys panth<tab><tab>然后应该列出每个以panth-开头的包,我的尝试如下:

complete -C "apt-cache --no-generate pkgnames" mys
Run Code Online (Sandbox Code Playgroud)

但它似乎不起作用:当我按上面提到的 tab 键时, at 将参数更改为mys,这将返回 me sudo mys mys

我究竟做错了什么?我是否必须在命令中指定complete必须插入应完成的字符串的位置,例如{}$1

我使用 ElementaryOS,一个基于 Ubuntu 的 Linux 发行版。该脚本是一个标准的 *.sh shell 脚本,它使用标准#!/bin/bash

Gil*_*il' 2

正如您所怀疑的,该命令会收到一些有关要完成的操作的信息。这在手册中有记录,但在内置文档complete中没有记录,您需要阅读有关可编程完成的介绍部分

\n\n
\n

调用使用-F和选项指定的任何 shell 函数或命令。-C当调用命令或函数时,COMP_LINECOMP_POINTCOMP_KEYCOMP_TYPE变量将按上述方式分配值(请参阅Bash 变量)。如果正在调用 shell 函数,则还会设置COMP_WORDS和变量。COMP_CWORD当调用函数或命令时,第一个参数是正在完成其参数的命令的名称,第二个参数是正在完成的单词,第三个参数是当前命令行上正在完成的单词之前的单词。不会根据正在完成的单词对生成的完成进行过滤;函数或命令在生成匹配时具有完全的自由。

\n
\n\n

因此,使用三个参数调用该命令:

\n\n
    \n
  • 命令名称为 \xe2\x80\x94,以便您可以在一个脚本中合并类似命令的完成。
  • \n
  • 要完成的单词 \xe2\x80\x94\xc2\xa0,因此您可以将输出限制为无论如何都会被过滤的前缀。
  • \n
  • 前面的单词 \xe2\x80\x94\xc2\xa0 有用,例如用于完成选项。
  • \n
\n\n

相同的参数被传递给完成函数 ( complete -F somefunction)。请注意,无论您使用函数还是命令,过滤所需的匹配项都是您的工作。

\n\n

根据您的尝试,最终执行的命令是apt-cache --no-generate pkgnames mys \'\' mysmys这将打印以(apt-cache pkgnames仅查看第一个操作数)开头的包名称列表。最长的公共前缀是mys,因此 bash 开始完成mys并期望您选择下一个字母。

\n\n

鉴于参数被附加到命令(不作为位置参数 \xe2\x80\x94 传递,参数被-C解析为 shell 命令),没有简单的方法来解析它们。最简单的解决方案是使用包装函数。

\n\n
_mys () {\n  COMPREPLY=$(apt-cache --no-generate pkgnames "$2")\n}\ncomplete -F _mys mys\n
Run Code Online (Sandbox Code Playgroud)\n