首页 > 解决方案 > 启用 bash-completion 会禁用自动完成文件名的默认行为

问题描述

make在 macOS High Sierra 版本 10.13.6 上的版本如下所示:

$ 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:

案例一:没有bash-completion

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

make a<TAB>

它会自动完成:

make a.txt

案例2:有bash-completion

当我确实有bash-completion(例如 with brew install bash-completion)时,我不能再使用这种行为。

如果我输入:

make a<TAB>

它根本不会自动完成。make he<TAB>它现在会自动完成其他目标,例如make FO<TAB>之前不可能的,但我失去了自动完成任何任意文件名的功能。

问题

标签: bashmakefilebash-completion

解决方案


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

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

可以在这里找到一些关于 Bash Tab Completion 的有用文档。

看起来 Mac OS X 上使用的 Bash Completion 的源代码在这里。您关心的是这一行:

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 ..

你可以破解它以按照你想要的方式工作。首先,将特定于 make 的自动完成文件复制到您的用户 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以便它认为工作目录中的文件也可能是选项卡完成。

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


推荐阅读