启用bash-completion会禁用自动完成文件名的默认行为

时间:2019-02-06 02:16:15

标签: bash makefile bash-completion

我在macOS High Sierra版本10.13.6上的make版本看起来像这样:

$ make --version
GNU Make 3.81
Copyright (C) 2006  Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.

This program built for i386-apple-darwin11.3.0

我的Bash版本如下:

$ bash --version
GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin17)
Copyright (C) 2007 Free Software Foundation, Inc.

我当前的目录如下:

$ ls -1
Makefile
a.txt
b.txt
c.txt

我的Makefile如下:

hello:
        echo hello

%.txt: FORCE
        cat "$@"

FORCE:

情况1:没有bash-completion

当我没有安装bash-completion时,可以方便地自动完成当前目录中的文件名作为make的目标参数。我的意思是,如果我输入:

make a<TAB>

它将自动完成:

make a.txt

情况2:使用bash-completion

当我确实有bash-completion(例如使用brew install bash-completion)时,我将无法再使用此行为。

如果我输入:

make a<TAB>

它根本不会自动完成。它确实可以自动完成其他目标,例如make he<TAB>make FO<TAB>,这在以前是不可能的,但是我会丢失自动完成的所有任意文件名。

问题

  • 为什么安装bash-completion会禁用自动完成当前文件名的默认行为?我认为这是非常方便的行为。
  • 如何在不删除bash-completion的情况下恢复该行为。如果我能做到这一点,那么我可以两全其美。使用bash-completion提供的自动完成功能以及当前目录中的自动完成文件名。

1 个答案:

答案 0 :(得分:0)

要回答您问题的第一部分,我认为大多数人不希望Bash在工作目录中提供文件作为make的建议目标。

但是您可以自定义行为,而不会带来太多麻烦。

可以在here上找到有关Bash Tab完成的一些有用文档。

看起来在Mac OS X上使用的Bash完成的源代码是here。您关心的这一行是

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

您可以看到,内置的compgen根据make -qp Makefile .的输出生成了可能的补全列表。

您可以修改此代码,使其按照您希望的方式工作。首先,将特定品牌的自动完成文件复制到您的用户bash完成文件中:

cp /usr/local/Cellar/bash-completion/1.3_3/etc/bash_completion.d/make ~/.bash_completion

然后编辑该文件以指定稍有不同的行为。在这里,我将展示差异:

--- /usr/local/Cellar/bash-completion/1.3_3/etc/bash_completion.d/make  2019-02-06 18:35:00.000000000 +1100
+++ /Users/alexharvey/.bash_completion  2019-02-06 18:34:36.000000000 +1100
@@ -62,7 +62,7 @@

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

     fi

请注意,我所做的只是将ls *的输出添加到返回到compgen的响应中,以便它认为工作目录中的文件也可能是制表符补全。

就是这样。启动一个新的外壳程序。