How to use bash_completion in a custom formula?

I have a formula that goes like this:

class CLI < Formula
  @@version = '4.2.1'
  @@hash = '123'

  @@ruby_version = "2.5.8"

  desc "CLI"
  homepage "abc"
  url "abc"
  sha256 @@hash
  version @@version

  def install
    ...

    libexec.install Dir["*"]
    (libexec/"vendor").mkpath
    ENV['GEM_HOME'] = "#{libexec}/vendor"
    ENV['GEM_PATH'] = "#{libexec}/vendor"
    system "#{libexec/'ruby'}/#{@@ruby_version}/bin/gem", "source", "-a", "abc"
    system "#{libexec/'ruby'}/#{@@ruby_version}/bin/gem", "install", "xyz", "--no-document"

    (bin/"cli").write(exec_script)

    bash_completion.install "cli-completion.bash"
    zsh_completion.install "cli-completion.zsh"
  end
end

As you can see from above, I have my own bash and zsh autocompletion scripts. I read here (https://www.rubydoc.info/github/Homebrew/brew/Formula:bash_completion) that Brew can link these scripts to my formula on installation.

On installing cli through the above formula I get the following error clearly because of my incorrect usage of bash_completion and zsh_completion:

Error: An exception occurred within a child process:
  Errno::ENOENT: No such file or directory - cli-completion.bash

I’m not sure how to make use of these and would be grateful if someone could point me the right way. Thanks.

That suggests that cli-completion.bash is not in the current directory at the point where bash_completion.install went looking for it.

@gromgit unfortunately that doesn’t seem to be the case. The code for the formula above is in a file cli.rb which is in a directory also containing cli-completion.bash and cli-completion.zsh.

I also tried putting the absolute paths to cli-completion.bash and cli-completion.zsh but I get the same error. I have a feeling it’s due to my incorrect usage of bash_completion and zsh_completion functions. It would be really helpful if you could provide a sample usage of these functions. Thank you so much for looking into this.

The location of the file doesn’t matter, the location within the url that it’s downloading matters.

There’s nothing wrong with your bash_completion syntax, but you seem to be lost in filespace.

Think of it this way: When your formula does this:

    libexec.install Dir["*"]

it copied everything from your current working directory into the destination libexec directory. You know what was copied over, so you know where you are in the “CLI” source directory. Where is cli-completion.bash relative to that directory? I’m guessing it’s in a subdirectory, perhaps called completions, in which case:

    bash_completion.install "completions/cli-completion.bash"

@gromgit Good to know nothing wrong with the bash_completion syntax (Phew!)

I have a directory Formula within which I have cli.rb and cli-completion.bash and cli-completion.zsh. I noticed when I do a brew install cli.rb it actually deletes both cli-completion.bash and cli-completion.zsh and then gives the No such file or directory - cli-completion.bash error.

On following your suggestion, I put both cli-completion.bash and cli-completion.zsh into a completions folder in Formula and cli.rb as you suggested:

bash_completion.install "completions/cli-completion.bash"
zsh_completion.install "completions/cli-completion.zsh"

This time it doesn’t delete these files from the folder but still gives the same error.

@SMillerDev I’m not sure I understand that. Can you please elaborate specific to the current case? Thank you so much.

Sorry, something else completely slipped my mind.

If I remember correctly, that moves everything to libexec, so there’s nothing left in your source directory. That’s probably why your subsequent completion installs fail.

You simply need to move your completion installs before libexec.install.

1 Like

That’s almost entirely irrelevant. Assuming you did:

brew install /path/to/Formula/cli.rb

the only file that Homebrew reads from that directory is cli.rb. Literally everything else is expected to be in, and is taken from, the resource pointed to by url.