completions: link official taps automatically
This commit is contained in:
		
							parent
							
								
									bed16128cc
								
							
						
					
					
						commit
						e7b369273a
					
				@ -8,7 +8,6 @@ require "descriptions"
 | 
			
		||||
require "cleanup"
 | 
			
		||||
require "description_cache_store"
 | 
			
		||||
require "cli/parser"
 | 
			
		||||
require "completions"
 | 
			
		||||
 | 
			
		||||
module Homebrew
 | 
			
		||||
  extend T::Sig
 | 
			
		||||
@ -151,15 +150,6 @@ module Homebrew
 | 
			
		||||
      puts "Already up-to-date." unless args.quiet?
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    if Completions.read_completions_option.empty?
 | 
			
		||||
      ohai "Homebrew completions are unlinked by default!"
 | 
			
		||||
      puts <<~EOS
 | 
			
		||||
        To opt-in to automatically linking Homebrew shell competion files, run:
 | 
			
		||||
          brew completions link
 | 
			
		||||
        Then, follow the directions at #{Formatter.url("https://docs.brew.sh/Shell-Completion")}
 | 
			
		||||
      EOS
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    Commands.rebuild_commands_completion_list
 | 
			
		||||
    link_completions_manpages_and_docs
 | 
			
		||||
    Tap.each(&:link_completions_and_manpages)
 | 
			
		||||
@ -198,8 +188,7 @@ module Homebrew
 | 
			
		||||
 | 
			
		||||
  def link_completions_manpages_and_docs(repository = HOMEBREW_REPOSITORY)
 | 
			
		||||
    command = "brew update"
 | 
			
		||||
 | 
			
		||||
    Completions.link_if_allowed! command: command
 | 
			
		||||
    Utils::Link.link_completions(repository, command)
 | 
			
		||||
    Utils::Link.link_manpages(repository, command)
 | 
			
		||||
    Utils::Link.link_docs(repository, command)
 | 
			
		||||
  rescue => e
 | 
			
		||||
 | 
			
		||||
@ -11,25 +11,22 @@ module Completions
 | 
			
		||||
 | 
			
		||||
  module_function
 | 
			
		||||
 | 
			
		||||
  sig { params(command: String).void }
 | 
			
		||||
  def link_if_allowed!(command: "brew completions link")
 | 
			
		||||
    if link_completions?
 | 
			
		||||
      link! command: command
 | 
			
		||||
    else
 | 
			
		||||
      unlink!
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  sig { params(command: String).void }
 | 
			
		||||
  def link!(command: "brew completions link")
 | 
			
		||||
  sig { void }
 | 
			
		||||
  def link!
 | 
			
		||||
    write_completions_option "yes"
 | 
			
		||||
    Utils::Link.link_completions HOMEBREW_REPOSITORY, command
 | 
			
		||||
    Tap.each do |tap|
 | 
			
		||||
      Utils::Link.link_completions tap.path, "brew completions link"
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  sig { void }
 | 
			
		||||
  def unlink!
 | 
			
		||||
    write_completions_option "no"
 | 
			
		||||
    Utils::Link.unlink_completions HOMEBREW_REPOSITORY
 | 
			
		||||
    Tap.each do |tap|
 | 
			
		||||
      next if tap.official?
 | 
			
		||||
 | 
			
		||||
      Utils::Link.unlink_completions tap.path
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  sig { returns(T::Boolean) }
 | 
			
		||||
@ -37,17 +34,46 @@ module Completions
 | 
			
		||||
    read_completions_option == "yes"
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  sig { returns(String) }
 | 
			
		||||
  def read_completions_option
 | 
			
		||||
  sig { returns(T::Boolean) }
 | 
			
		||||
  def completions_to_link?
 | 
			
		||||
    shells = %w[bash fish zsh]
 | 
			
		||||
    Tap.each do |tap|
 | 
			
		||||
      next if tap.official?
 | 
			
		||||
 | 
			
		||||
      shells.each do |shell|
 | 
			
		||||
        return true if (tap.path/"completions/#{shell}").exist?
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    false
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  sig { params(option: String).returns(String) }
 | 
			
		||||
  def read_completions_option(option: "linkcompletions")
 | 
			
		||||
    HOMEBREW_REPOSITORY.cd do
 | 
			
		||||
      Utils.popen_read("git", "config", "--get", "homebrew.linkcompletions").chomp
 | 
			
		||||
      Utils.popen_read("git", "config", "--get", "homebrew.#{option}").chomp
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  sig { params(state: String).void }
 | 
			
		||||
  def write_completions_option(state)
 | 
			
		||||
  sig { params(state: String, option: String).void }
 | 
			
		||||
  def write_completions_option(state, option: "linkcompletions")
 | 
			
		||||
    HOMEBREW_REPOSITORY.cd do
 | 
			
		||||
      T.unsafe(self).safe_system "git", "config", "--replace-all", "homebrew.linkcompletions", state.to_s
 | 
			
		||||
      T.unsafe(self).safe_system "git", "config", "--replace-all", "homebrew.#{option}", state.to_s
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  sig { void }
 | 
			
		||||
  def show_completions_message_if_needed
 | 
			
		||||
    return if read_completions_option(option: "completionsmessageshown") == "yes"
 | 
			
		||||
    return unless completions_to_link?
 | 
			
		||||
 | 
			
		||||
    T.unsafe(self).ohai "Homebrew completions for external commands are unlinked by default!"
 | 
			
		||||
    T.unsafe(self).puts <<~EOS
 | 
			
		||||
      To opt-in to automatically linking Homebrew shell competion files, run:
 | 
			
		||||
        brew completions link
 | 
			
		||||
      Then, follow the directions at #{Formatter.url("https://docs.brew.sh/Shell-Completion")}
 | 
			
		||||
    EOS
 | 
			
		||||
 | 
			
		||||
    write_completions_option("yes", option: "completionsmessageshown")
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
@ -2,6 +2,7 @@
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
require "commands"
 | 
			
		||||
require "completions"
 | 
			
		||||
require "extend/cachable"
 | 
			
		||||
require "description_cache_store"
 | 
			
		||||
 | 
			
		||||
@ -340,7 +341,13 @@ class Tap
 | 
			
		||||
  def link_completions_and_manpages
 | 
			
		||||
    command = "brew tap --repair"
 | 
			
		||||
    Utils::Link.link_manpages(path, command)
 | 
			
		||||
    Utils::Link.link_completions(path, command)
 | 
			
		||||
 | 
			
		||||
    Completions.show_completions_message_if_needed
 | 
			
		||||
    if official? || Completions.link_completions?
 | 
			
		||||
      Utils::Link.link_completions(path, command)
 | 
			
		||||
    else
 | 
			
		||||
      Utils::Link.unlink_completions(path)
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  # Uninstall this {Tap}.
 | 
			
		||||
 | 
			
		||||
@ -18,11 +18,5 @@ describe "brew completions", :integration_test do
 | 
			
		||||
      .to output(/Completions are linked/).to_stdout
 | 
			
		||||
      .and not_to_output.to_stderr
 | 
			
		||||
      .and be_a_success
 | 
			
		||||
 | 
			
		||||
    brew "completions", "unlink"
 | 
			
		||||
    expect { brew "completions" }
 | 
			
		||||
    .to output(/Completions are not linked/).to_stdout
 | 
			
		||||
    .and not_to_output.to_stderr
 | 
			
		||||
    .and be_a_success
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
@ -88,6 +88,7 @@ describe Tap do
 | 
			
		||||
    HOMEBREW_REPOSITORY.cd do
 | 
			
		||||
      system "git", "init"
 | 
			
		||||
      system "git", "config", "--replace-all", "homebrew.linkcompletions", link
 | 
			
		||||
      system "git", "config", "--replace-all", "homebrew.completionsmessageshown", "yes"
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
@ -316,11 +317,11 @@ describe Tap do
 | 
			
		||||
    (HOMEBREW_PREFIX/"share").rmtree if (HOMEBREW_PREFIX/"share").exist?
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  specify "#link_completions_and_manpages when completions are enabled" do
 | 
			
		||||
  specify "#link_completions_and_manpages when completions are enabled for non-official tap" do
 | 
			
		||||
    setup_tap_files
 | 
			
		||||
    setup_git_repo
 | 
			
		||||
    setup_completion link: "yes"
 | 
			
		||||
    tap = described_class.new("Homebrew", "baz")
 | 
			
		||||
    tap = described_class.new("NotHomebrew", "baz")
 | 
			
		||||
    tap.install clone_target: subject.path/".git"
 | 
			
		||||
    (HOMEBREW_PREFIX/"share/man/man1/brew-tap-cmd.1").delete
 | 
			
		||||
    (HOMEBREW_PREFIX/"etc/bash_completion.d/brew-tap-cmd").delete
 | 
			
		||||
@ -337,11 +338,11 @@ describe Tap do
 | 
			
		||||
    (HOMEBREW_PREFIX/"share").rmtree if (HOMEBREW_PREFIX/"share").exist?
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  specify "#link_completions_and_manpages when completions are disabled" do
 | 
			
		||||
  specify "#link_completions_and_manpages when completions are disabled for non-official tap" do
 | 
			
		||||
    setup_tap_files
 | 
			
		||||
    setup_git_repo
 | 
			
		||||
    setup_completion link: "no"
 | 
			
		||||
    tap = described_class.new("Homebrew", "baz")
 | 
			
		||||
    tap = described_class.new("NotHomebrew", "baz")
 | 
			
		||||
    tap.install clone_target: subject.path/".git"
 | 
			
		||||
    (HOMEBREW_PREFIX/"share/man/man1/brew-tap-cmd.1").delete
 | 
			
		||||
    tap.link_completions_and_manpages
 | 
			
		||||
@ -355,6 +356,27 @@ describe Tap do
 | 
			
		||||
    (HOMEBREW_PREFIX/"share").rmtree if (HOMEBREW_PREFIX/"share").exist?
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  specify "#link_completions_and_manpages when completions are enabled for official tap" do
 | 
			
		||||
    setup_tap_files
 | 
			
		||||
    setup_git_repo
 | 
			
		||||
    setup_completion link: "no"
 | 
			
		||||
    tap = described_class.new("Homebrew", "baz")
 | 
			
		||||
    tap.install clone_target: subject.path/".git"
 | 
			
		||||
    (HOMEBREW_PREFIX/"share/man/man1/brew-tap-cmd.1").delete
 | 
			
		||||
    (HOMEBREW_PREFIX/"etc/bash_completion.d/brew-tap-cmd").delete
 | 
			
		||||
    (HOMEBREW_PREFIX/"share/zsh/site-functions/_brew-tap-cmd").delete
 | 
			
		||||
    (HOMEBREW_PREFIX/"share/fish/vendor_completions.d/brew-tap-cmd.fish").delete
 | 
			
		||||
    tap.link_completions_and_manpages
 | 
			
		||||
    expect(HOMEBREW_PREFIX/"share/man/man1/brew-tap-cmd.1").to be_a_file
 | 
			
		||||
    expect(HOMEBREW_PREFIX/"etc/bash_completion.d/brew-tap-cmd").to be_a_file
 | 
			
		||||
    expect(HOMEBREW_PREFIX/"share/zsh/site-functions/_brew-tap-cmd").to be_a_file
 | 
			
		||||
    expect(HOMEBREW_PREFIX/"share/fish/vendor_completions.d/brew-tap-cmd.fish").to be_a_file
 | 
			
		||||
    tap.uninstall
 | 
			
		||||
  ensure
 | 
			
		||||
    (HOMEBREW_PREFIX/"etc").rmtree if (HOMEBREW_PREFIX/"etc").exist?
 | 
			
		||||
    (HOMEBREW_PREFIX/"share").rmtree if (HOMEBREW_PREFIX/"share").exist?
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  specify "#config" do
 | 
			
		||||
    setup_git_repo
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,8 +1,6 @@
 | 
			
		||||
# typed: true
 | 
			
		||||
# frozen_string_literal: true
 | 
			
		||||
 | 
			
		||||
require "completions"
 | 
			
		||||
 | 
			
		||||
module Utils
 | 
			
		||||
  # Helper functions for creating symlinks.
 | 
			
		||||
  #
 | 
			
		||||
@ -66,11 +64,6 @@ module Utils
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def link_completions(path, command)
 | 
			
		||||
      unless Completions.link_completions?
 | 
			
		||||
        unlink_completions path
 | 
			
		||||
        return
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      link_src_dst_dirs(path/"completions/bash", HOMEBREW_PREFIX/"etc/bash_completion.d", command)
 | 
			
		||||
      link_src_dst_dirs(path/"completions/zsh", HOMEBREW_PREFIX/"share/zsh/site-functions", command)
 | 
			
		||||
      link_src_dst_dirs(path/"completions/fish", HOMEBREW_PREFIX/"share/fish/vendor_completions.d", command)
 | 
			
		||||
 | 
			
		||||
@ -4,10 +4,10 @@ Homebrew comes with completion definitions for the `brew` command. Some packages
 | 
			
		||||
 | 
			
		||||
`zsh`, `bash` and `fish` are currently supported.
 | 
			
		||||
 | 
			
		||||
Shell completions for built-in Homebrew commands are not automatically installed. To opt-in to using our completions, they need to be linked to `HOMEBREW_PREFIX` by running `brew completions link`.
 | 
			
		||||
 | 
			
		||||
You must then configure your shell to enable its completion support. This is because the Homebrew-managed completions are stored under `HOMEBREW_PREFIX` which your system shell may not be aware of, and since it is difficult to automatically configure `bash` and `zsh` completions in a robust manner, the Homebrew installer does not do it for you.
 | 
			
		||||
 | 
			
		||||
Shell completions for external Homebrew commands are not automatically installed. To opt-in to using completions for external commands (if provided), they need to be linked to `HOMEBREW_PREFIX` by running `brew completions link`.
 | 
			
		||||
 | 
			
		||||
## Configuring Completions in `bash`
 | 
			
		||||
 | 
			
		||||
To make Homebrew's completions available in `bash`, you must source the definitions as part of your shell's startup. Add the following to your `~/.bash_profile` (or, if it doesn't exist, `~/.profile`):
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user