假设我有一个简单的 makefile,例如:
hello:
echo "hello world"
bye:
echo "bye bye"
然后在 bash 中我想要这样的东西:
做h< tab >
所以它可以完成
打个招呼
我找到了一个简单的方法,比如创建空文件
hello
和 bye
但我正在寻找更复杂的东西 sophisticated.
将此添加到您的 ~/.bash_profile 文件或 ~/.bashrc 文件
complete -W "\`grep -oE '^[a-zA-Z0-9_.-]+:([^=]|$)' ?akefile | sed 's/[^a-zA-Z0-9_.-]*$//'\`" make
这会使用 grep 在名为“Makefile”或“makefile”的 Makefile 中搜索目标(注意
?
中的大写 ?akefile
通配符),并将其通过管道传递给 bash 中的 complete
命令,该命令用于指定如何自动完成参数。 -W
标志表示 complete
命令的输入将是一个单词列表,它是通过将 grep 的结果传递给 sed
来完成的,它将其排列成所需的 wordlist 格式。
注意事项和陷阱:
您的 make 文件名为“GNUMakefile”或除“Makefile”或“makefile”以外的任何其他名称。如果您经常遇到此类标题,请考虑相应地更改正则表达式
?akefile
。在进行更改后忘记获取 ~/.bash_profile 或 ~/.bashrc 文件。我添加这个看似微不足道的细节,因为对于外行来说,它是陌生的。 要使 bash 文件的任何更改生效,请使用以下命令source它们
source ~/.bashrc
或
source ~/.bash_profile
附言。您现在还可以通过按 [Tab] 两次来显示 possible make 目标,就像在 bash 完成中一样。在键入 [Tab] 两次之前,请确保在命令 make 之后添加一个空格。
这个 2010 年的答案已经过时了——这里提到的项目似乎已经停止了。
这会是您要找的吗?
http://freshmeat.net/projects/bashcompletion/
make [Tab] 将完成所有 Makefile 中的目标。这个项目是 设想生产可编程 大多数完成例程 常用的 Linux/UNIX 命令,减少 键入系统管理员的数量和 程序员需要每天做 基础。
有一个名为 bash-completion 的有用包,适用于大多数操作系统。它包括 Makefile 补全。
(如果您使用的是 macOS 和 Homebrew,您可以通过
brew install bash-completion
获取。)
这似乎至少在 Debian Lenny 中是默认的:
$ grep Makefile /etc/bash_completion
# make reads `GNUmakefile', then `makefile', then `Makefile'
elif [ -f ${makef_dir}/Makefile ]; then
makef=${makef_dir}/Makefile
# before we scan for targets, see if a Makefile name was
# deal with included Makefiles
此文件的标题说明:
# The latest version of this software can be obtained here:
#
# http://bash-completion.alioth.debian.org/
#
# RELEASE: 20080617.5
这是一个查看 .PHONY: 声明的完成脚本。
_make_phony_words() {
local opt_revert
if [ -n "${BASH_VERSION:-}" ]; then
shopt -q nullglob || {
opt_revert=1 ; shopt -s nullglob ;
}
elif [ -n "${ZSH_VERSION:-}" ]; then
[[ -o nullglob ]] || {
opt_revert=1 ; setopt nullglob
}
fi
for f in ./?akefile ./*.make ; do
sed -nEe '/^.PHONY/ { s/^.PHONY:[ ]?// ; p ; } ' "$f" | tr ' ' $'\n' | sort -u
done
if [ -n "$opt_revert" ]; then
[ -n "${ZSH_VERSION:-}" ] && unsetopt nullglob
[ -n "${BASH_VERSION:-}" ] && shopt -u nullglob
fi
unset opt_revert
}
_make_phony_complete() {
local cur="${COMP_WORDS[COMP_CWORD]}"
COMPREPLY+=( $(compgen -W "$( _make_phony_words )" -- ${cur}) )
}
complete -F _make_phony_complete make
正常完成时我有2个问题:
有时你有你想要调用的目标,比如
make greet:hi
和 make greet:hola
有点像命名空间 Makefile
目标名称。所以你的Makefile
最终看起来像:
greet\:hola:
echo "hola world"
# OR a .PHONY target
.PHONY: greet\:hi
greet\:hi:
echo "hi world"
在这种情况下,
:
之后的自动完成不会显示,因为它在 Makefile 中使用了 \:
,如上所示。
没有办法在我的
Makefile
shell 中使用箭头键(或 CTRL-p
/ CTRL-n
)浏览与我的输入匹配的所有 bash
目标列表。
基本上,我想在目标上使用类似模糊搜索的方法(即
fzf
)。
FZF 回购:https://github.com/junegunn/fzf
您可以使用 Homebrew(在 macOS 或 Linux 上) 安装 fzf.
brew install fzf
$(brew --prefix)/opt/fzf/install
包管理器 | Linux 发行版 | 命令 |
---|---|---|
APK | 高山Linux |
|
公寓 | Debian 9+/Ubuntu 19.10+ |
|
康达 |
|
|
地下城与勇士 | 软呢帽 |
|
尼克斯 | NixOS等 |
|
吃豆子 | Arch Linux |
|
包装 | FreeBSD |
|
打包 | NetBSD |
|
pkg_add | OpenBSD |
|
XBPS | 虚空 Linux |
|
Zypper | openSUSE |
|
:
兼容的自动完成命令把这个放在你的
.bashrc
complete -W "\`grep -oE '^[a-zA-Z0-9_.-]+[\\:]*[a-zA-Z0-9_.-]+:([^=]|$)' ?akefile | sort | uniq | sed 's/[^a-zA-Z0-9_.-]*$//' | sed 's/[\]//g' | fzf\`" make
现在只要输入
make
然后敲击键就可以了!
然后你可以使用如下:
我添加了所以我遵循 Makefile 中的“include”指令。所以我的 .bashrc 看起来像这样:
function followMakefile() {
grep -oE '^[a-zA-Z0-9_.-]+:([^=]|$)' ?akefile | sed 's/[^a-zA-Z0-9_.-]*$//'
for x in `grep -E '^include' ?akefile | sed 's/include //'`
do
grep -oE '^[a-zA-Z0-9_.-]+:([^=]|$)' $x | sed 's/[^a-zA-Z0-9_.-]*$//'
done
}
complete -W "\`followMakefile\`" make
在 Ubuntu 10.04 中,获取以下文件:
. /etc/bash_completion
或在
中取消注释/etc/bash.bashrc