bash 完成 makefile 目标

发布于 2024-10-02 18:34:00 字数 326 浏览 5 评论 0原文

假设我有一个简单的 makefile,例如:

hello:
   echo "hello world"

bye:
   echo "bye bye"

然后在 bash 中我想要类似的东西:

使 h <标签>

所以它可以完成

打个招呼

我找到了一种简单的方法,例如创建空文件 hellobye,但我正在寻找更复杂的方法。

Suppose I have a simple makefile like:

hello:
   echo "hello world"

bye:
   echo "bye bye"

Then in bash I want something like:

make h < tab >

so it can complete to

make hello

I found a simple way like creating empty files hello and bye but I'm looking for something more sophisticated.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

も星光 2024-10-09 18:34:00

将其添加到您的 ~/.bash_profile 文件或 ~/.bashrc 文件中

complete -W "\`grep -oE '^[a-zA-Z0-9_.-]+:([^=]|$)' ?akefile | sed 's/[^a-zA-Z0-9_.-]*$//'\`" make

这将在您的 Makefile 中搜索标题为“Makefile”或“makefile”的目标(注意大写 < code>? 通配符 (?akefile) 使用 grep,并将其通过管道传输到 bash 中的 complete 命令,该命令用于指定如何自动完成参数。 -W 标志表示 complete 命令的输入将是一个单词列表,这是通过将 grep 的结果传递给 sed 来完成的,sed 会排列将其转换为所需的单词列表格式。

注意事项和陷阱:

  1. 您的 make 文件名为“GNUMakefile”或“Makefile”或“makefile”以外的任何其他名称。如果您经常遇到此类标题,请考虑相应地更改正则表达式 ?akefile

  2. 进行更改后忘记获取 ~/.bash_profile 或 ~/.bashrc 文件。我添加这个看似微不足道的细节,因为对于外行来说它是陌生的。
    要使 bash 文件的任何更改生效,请使用以下命令获取它们

    源 ~/.bashrc
    

    源 ~/.bash_profile
    

PSsource 它们。现在,您还可以通过按两次 [Tab] 来显示可能的 make 目标,就像在 bash 补全中一样。只需确保在键入 [Tab] 两次之前在命令 make 之后添加一个空格即可。

Add this in your ~/.bash_profile file or ~/.bashrc file

complete -W "\`grep -oE '^[a-zA-Z0-9_.-]+:([^=]|$)' ?akefile | sed 's/[^a-zA-Z0-9_.-]*$//'\`" make

This searches for a target in your Makefile titled 'Makefile' or 'makefile' (note the capital ? wildcard in ?akefile) using grep, and pipes it over to the complete command in bash which is used to specify how arguments are autocompleted. The -W flag denotes that the input to the complete command will be a wordlist which is accomplished by passing the results of grep through sed which arranges it into the desirable wordlist format.

Caveats and gotchas:

  1. Your make file is named 'GNUMakefile' or anything else other than 'Makefile' or 'makefile'. If you frequently encounter such titles consider changing the regular expression ?akefile accordingly.

  2. Forgetting to source your ~/.bash_profile or ~/.bashrc file after making the changes. I add this seemingly trivial detail since, to the uninitiated it is unfamiliar.
    For any change to your bash files to take effect, source them using the command

    source ~/.bashrc
    

    or

    source ~/.bash_profile
    

PS. You also now have the added ability to display the possible make targets by pressing [Tab] twice just like in bash completion. Just make sure you add a space after the command make before typing [Tab] twice.

过气美图社 2024-10-09 18:34:00

有一个名为 bash-completion 的有用软件包适用于大多数操作系统。它包括 Makefile 完成。

(如果您使用的是 macOS 和 Homebrew,您可以通过 brew install bash-completion 获取此信息.)

There's a useful package called bash-completion available for most every OS. It includes Makefile completion.

(If you're using macOS and Homebrew, you can get this via brew install bash-completion.)

守望孤独 2024-10-09 18:34:00

这个 2010 年的答案已经过时了 - 这里提到的项目似乎已经停止了。

这可能是您正在寻找的东西吗?

http://freshmeat.net/projects/bashcompletion/

make [Tab] 将完成所有
Makefile 中的目标。这个项目是
旨在生产可编程
大多数人的完成例程
常见的Linux/UNIX命令,减少
系统管理员的打字量和
程序员每天需要做的事
基础。

This answer from 2010 is outdated - the project mentioned here seems to have been discontinued.

Could this be what you're looking for?

http://freshmeat.net/projects/bashcompletion/

make [Tab] would complete on all
targets in Makefile. This project was
conceived to produce programmable
completion routines for the most
common Linux/UNIX commands, reducing
the amount of typing sysadmins and
programmers need to do on a daily
basis.

撕心裂肺的伤痛 2024-10-09 18:34:00

这似乎是至少在 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

This seems to be default in at least 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 header of this file states:

#   The latest version of this software can be obtained here:
#
#   http://bash-completion.alioth.debian.org/
#
#   RELEASE: 20080617.5
晌融 2024-10-09 18:34:00

这是一个查看 .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

Here is a completion script that looks at the .PHONY: declaration.

_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
谁的新欢旧爱 2024-10-09 18:34:00

类固醇完成 Makefile!

我在正常完成时遇到了 2 个问题

问题 #1

有时你有想要调用的目标,例如 makegreet:himakegreet:hola 有点像命名空间 Makefile 目标名称。因此,您的 Makefile 最终看起来像:

greet\:hola:
   echo "hola world"

# OR a .PHONY target
.PHONY: greet\:hi
greet\:hi:
   echo "hi world"

在这种情况下,: 之后的自动完成不会显示,因为它在Makefile如上所示。

问题 #2

没有办法使用箭头键(或 CTRL-p / CTRL-)浏览与我的输入匹配的所有 Makefile 目标的列表。 n) 在我的 bash shell 中。

基本上,我想在目标上使用类似模糊搜索的方法(即fzf)。
FZF Repo: https://github.com/junegunn/fzf

解决方案

安装 FZF 依赖项

使用 Homebrew

您可以使用 Homebrew(在 macOS 或 Linux 上)
安装fzf。

brew install fzf
$(brew --prefix)/opt/fzf/install
使用 Linux 软件包管理器
软件包管理器Linux 分发命令
APKAlpine Linuxsudo apk add fzf
APTDebian 9+/Ubuntu 19.10+sudo apt-get install fzf
Condaconda install -c conda-forge fzf
DNFFedorasudo dnf install fzf
NixNixOS 等nix-env -iA nixpkgs.fzf
PacmanArch Linuxsudo pacman -S fzf
pkgFreeBSDpkg install fzf
pkginNetBSDpkgin install fzf
pkg_addOpenBSDpkg_add fzf
XBPSVoid Linuxsudo xbps-install -S fzf
ZypperopenSUSEsudo zypper install fzf

FZF 和 : 兼容的自动完成命令

将其放入您的 .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 然后按一下键就可以了!

演示:在行动!

然后你可以使用如下:

make using fzf

Makefile completion on steroids!

I had 2 problems with the normal completions:

Problem #1

Sometimes you have targets you want to call like make greet:hi and make greet:hola sort of like namespacing Makefile target names. So your Makefile ends up looking like:

greet\:hola:
   echo "hola world"

# OR a .PHONY target
.PHONY: greet\:hi
greet\:hi:
   echo "hi world"

In this case the auto-completions after : don't show up as it uses \: in the Makefile as shown above.

Problem #2

There wasn't a way to navigate through the list of all Makefile targets that match my input using arrow keys (or CTRL-p / CTRL-n) in my bash shell.

Basically, I wanted to use fuzzy search like approach on the targets (i.e. fzf).
FZF Repo: https://github.com/junegunn/fzf

Solution

Install FZF Dependency

Using Homebrew

You can use Homebrew (on macOS or Linux)
to install fzf.

brew install fzf
$(brew --prefix)/opt/fzf/install
Using Linux package managers
Package ManagerLinux DistributionCommand
APKAlpine Linuxsudo apk add fzf
APTDebian 9+/Ubuntu 19.10+sudo apt-get install fzf
Condaconda install -c conda-forge fzf
DNFFedorasudo dnf install fzf
NixNixOS, etc.nix-env -iA nixpkgs.fzf
PacmanArch Linuxsudo pacman -S fzf
pkgFreeBSDpkg install fzf
pkginNetBSDpkgin install fzf
pkg_addOpenBSDpkg_add fzf
XBPSVoid Linuxsudo xbps-install -S fzf
ZypperopenSUSEsudo zypper install fzf

FZF and : compatible auto-complete command

Put this in your .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

Now just typing make and then hitting the key will work!

DEMO: in action!

Then you can use as following:

make using fzf

秋意浓 2024-10-09 18:34:00

我添加了所以我遵循 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

I added so I follow "include" directives in Makefile. So my .bashrc looks like this:

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
情感失落者 2024-10-09 18:34:00

在 Ubuntu 10.04 中,获取以下文件:

. /etc/bash_completion

或取消注释

/etc/bash.bashrc

In Ubuntu 10.04, source the following file:

. /etc/bash_completion

or uncomment it in

/etc/bash.bashrc
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文