当用户在 bash 中自动完成时隐藏 shell 中的 make 目标

当用户在 bash 中自动完成时隐藏 shell 中的 make 目标

有没有办法在 a 中标记某些目标,以便当用户键入然后按 时Makefile它们根本不会出现在 shell 中?我有太多的食谱,当用户按下寻找目标时,我不希望它们全部出现在 shell 自动完成中。makeTabMakefileTab

答案1

在研究了这个问题并提出了我在第一个答案中写的解决方案之后,我意识到还有另一个很简单方式。

只需以您不想显示的目标名称开头

例子:

.PHONY: foo .hiddentarget
foo: foo.x .hiddentarget
foo.x: foo.c
        touch foo.x
.hiddentarget: foo.x
        echo foo.x ok, I believe

这就是您所需要的!

在尝试找出如何阻止名为的目标后,我想到了这个想法.隐藏的目标被错误调用并运行所有隐藏目标。 :)

警告虽然我没有看到任何,但我不确定使用这样的目标名称是否有任何副作用“.目标名称“(以点开头)。

答案2

要隐藏某些目标,您需要破解 shell 的自动完成功能。bash用途/etc/bash_completion/etc/bash_completion.d/*用途。

不记得 tcsh 是如何做到的。

答案3

我发现这也可以通过以下划线开始目标来实现

_hiddentarget:
    @echo "Running hidden target" 

答案4

编辑最好阅读其他答案(目标名称以点开头)。但我会在这里回答这个问题,因为编程部分可能会帮助其他类似的问题。

好吧,我花了一些时间才想出解决方案。这是一份(很好的)草案,希望它能顺利完成工作。

您必须编辑该文件 /usr/share/bash-completion/completions/make (对于 Debian Wheezy 或某些与您的系统类似的系统)

在我当前的版本中,第 70 到 73 行的代码为:

70         COMPREPLY=( $( compgen -W "$( make -qp $makef $makef_dir 2>/dev/null | \
71             awk -F':' '/^[a-zA-Z0-9][^$#\/\t=]*:([^=]|$)/ \
72             {split($1,A,/ /);for(i in A)print A[i]}' )" \
73             -- "$cur" ) )

然后替换为以下代码:

 70         HIDDENGOALS="$(make -qp | grep '^\.HIDDENGOALS:' | cut -d' ' -f2- | sed 's/ /\\|/g')"
 71         if [[ "$HIDDENGOALS" == "" || "$HIDDENGOALS" == ".HIDDENGOALS:" ]]; then
 72             COMPREPLY=( $( compgen -W "$( make -qp $makef $makef_dir 2>/dev/null | \
 73                 awk -F':' '/^[a-zA-Z0-9][^$#\/\t=]*:([^=]|$)/ \
 74                 {split($1,A,/ /);for(i in A)print A[i]}' )" \
 75                 -- "$cur" ) )
 76         else
 77             COMPREPLY=( $( compgen -W "$( make -qp $makef $makef_dir 2>/dev/null | \
 78                 awk -F':' '/^[a-zA-Z0-9][^$#\/\t=]*:([^=]|$)/ \
 79                 {split($1,A,/ /);for(i in A)print A[i]}' \
 80                 | grep -ve "$HIDDENGOALS" )" \
 81                 -- "$cur" ) )

现在makefile你可以使用以下内容特殊目标隐藏 bash 自动完成的目标:

 .HIDDENGOALS: somegoal anothergoal goalstohide

很像一个.PHONY特殊的目标(有一些区别)。

小心:

(我)由于此解决方案通过 a 工作grep -ev,因此特殊目标并不完全如此。它将使用行中的任何内容来匹配正则表达式的方式。

所以,如果你有一个目标,比如说,,copy2还有另一个copy,写

 .HIDDENGOALS: copy

将隐藏两个目标!

我将这种行为的解决方案作为练习提供给读者! ;)

(二)另一件需要注意的事情是,:被硬编码为位于 旁边.HIDDENGOALS:,这意味着尽管目标允许空间就像.PHONY :,这个特殊的黑客没有。

(三)我认为编辑本地文件而不是更好/usr/share/bash-completion/completions/make,避免升级时丢失信息。但我没有测试任何选项。如果你知道,请评论,我会更新这个答案。

(四)有一个微小的机会好奇的运行目标.隐藏的目标make .HIDDENGOALS.这将实现所有隐藏的目标。并且自动完成名称是不可能的,这使我得到了另一个非常简单的答案!

相关内容