在带有冒号的 OS X 上完成 Bash 完成



我是面向开发人员的基于 PHP 的命令行应用程序的创建和维护者。 我的命令的语法遵循其他 PHP 命令行应用程序的规范,如下所示

pestle.phar some:command:name ...arguments and options here...
pestle.phar some:command      ...arguments and options here...    

也就是说 -- 冒号用于命令名称。当我尝试使用 bash 的股票自动完成功能时,这带来了问题。

多亏了其他一些答案,我能够确定这是bash将:视为单词分隔符,并且bash完成项目(brew install bash-completion)可以提供帮助。 我已经能够将脚本组合在一起,但是我被困在一些事情上,并且对系统的理解不够好,无法自行诊断。 另外,我的 bash 脚本技能很生疏。

这是某种工作示例。

#File: /usr/local/etc/bash_completion.d/pestle-autocomplete.sh
#!/bin/bash
_commandList ()
{
echo "codecept:convert-selenium-id-for-codecept"
echo "magento2:check-templates"
echo "magento2:generate:acl"
#.. other comand names..
return 0;
}
_pestleAutocomplete ()
{
local cur
local all
_get_comp_words_by_ref -n : cur
all=$(_commandList)
COMPREPLY=( $(compgen -W "$all" $cur) )
__ltrim_colon_completions "$cur"
return 0
}
complete -F _pestleAutocomplete -o filenames pestle.phar

如果我输入$ pestle.phar mag然后点击选项卡,则以下内容将输出在我的 shell 中

$ pestle.phar magento2:    

也就是说,magento2:自动完成,但:用斜杠转义。 如果我完成一个命令名称,这"有效",但看起来有点好笑。 所以问题1 - 我如何摆脱斜杠,它来自哪里。

其次,我不明白__ltrim_colon_completions命令的作用。 在我看到的例子中,它通常使用类似的东西

_mytool()
{
local cur
_get_comp_words_by_ref -n : cur
# my implementation here
__ltrim_colon_completions "$cur"
}
complete -F _mytool mytool

然而,在我天真的眼中 - 这似乎无济于事。 它是脚本末尾使用局部变量的无关调用。 我假设它改变了 bash 完成系统中的某些状态,但同样,我在那里的知识是不完整的。 我不确定这是否与我的逃跑问题有关。

如果这里有人有一个具体的答案,或者能让我指出正确的方向,我将不胜感激。OS X 10.11,El Cap,股票狂欢 - 如果它很重要的话。

可以调整COMP_WORDBREAKS变量,使冒号的行为与其正常的完成行为不同:

COMP_WORDBREAKS=${COMP_WORDBREAKS//:}

从该值中删除:足以使冒号在完成时不是特别的(这可能是您想要的,也可能不是您想要的)。我怀疑它前面:反斜杠是因为您用_get_comp_words_by_ref -n : cur排除它的方式.您也可以用反斜杠引用冒号,以暂时获得相同的结果。

文件名完成(以及一般的单词完成)可能显示为 如果要完成的单词中有冒号,则行为不当。

冒号对于readline的单词完成代码是特殊的:它是以下之一 为完成者破坏单词的字符。 阅读线使用 这些字符与 Bash 使用$IFS:的方式相同,因为它们 断开或分隔完成代码交给 特定于应用程序的或默认的单词完成函数。 这 最初的目的是使编辑冒号分隔的列表变得容易 (例如 bash 中的$PATH)在各种应用程序中使用 readline for 输入。

由于某些版本的流行 "bash-complete"可编程完成包存在问题 存在冒号时的默认完成行为。

当前完成分词符集在 bash 作为COMP_WORDBREAKS变量的值。 从中删除":" 该值足以使冒号不特别完成。

__ltrim_colon_completions

这个函数基本上只是修剪补全,以便返回的单词只是前缀(或右侧最后一个冒号左侧剩余的任何内容)。一个例子是命令,例如hello:world我开始输入he并按下TAB,hello:部分是将返回的内容。功能正是这样的:

# Define preload__ltrim_colon_completions="false", if the function
# __perf__ltrim_colon_completions() is required instead.
preload__ltrim_colon_completions="true"
if [ $preload__ltrim_colon_completions = "true" ]; then
type __ltrim_colon_completions &>/dev/null ||
preload__ltrim_colon_completions="false"
fi
[ $preload__ltrim_colon_completions = "true" ] ||
__perf___ltrim_colon_completions()
{
if [[ "$1" == *:* && "$COMP_WORDBREAKS" == *:* ]]; then
# Remove colon-word prefix from COMPREPLY items
local colon_word=${1%"${1##*:}"}
local i=${#COMPREPLY[*]}
while [[ $((--i)) -ge 0 ]]; do
COMPREPLY[$i]=${COMPREPLY[$i]#"$colon_word"}
echo $COMPREPLY[$i]
done
echo $colon_word
fi
}

完成代码中的其他一些变量可以设置为根据应用程序以不同的方式处理单词;也许尝试最顶部的方法,如果这不是您要查找的,那么可以浏览负责控制它的代码。

最新更新