From e7b369273a9b23f0674491fe33a8d3aaf197c292 Mon Sep 17 00:00:00 2001 From: Rylan Polster Date: Mon, 11 Jan 2021 12:24:48 -0500 Subject: [PATCH] completions: link official taps automatically --- Library/Homebrew/cmd/update-report.rb | 13 +--- Library/Homebrew/completions.rb | 64 +++++++++++++------ Library/Homebrew/tap.rb | 9 ++- Library/Homebrew/test/cmd/completions_spec.rb | 6 -- Library/Homebrew/test/tap_spec.rb | 30 +++++++-- Library/Homebrew/utils/link.rb | 7 -- docs/Shell-Completion.md | 4 +- 7 files changed, 82 insertions(+), 51 deletions(-) diff --git a/Library/Homebrew/cmd/update-report.rb b/Library/Homebrew/cmd/update-report.rb index 4d7af92b36..f38b341394 100644 --- a/Library/Homebrew/cmd/update-report.rb +++ b/Library/Homebrew/cmd/update-report.rb @@ -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 diff --git a/Library/Homebrew/completions.rb b/Library/Homebrew/completions.rb index d266d95fa9..9bde547f40 100644 --- a/Library/Homebrew/completions.rb +++ b/Library/Homebrew/completions.rb @@ -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 diff --git a/Library/Homebrew/tap.rb b/Library/Homebrew/tap.rb index da99c5ff0a..b8daea201a 100644 --- a/Library/Homebrew/tap.rb +++ b/Library/Homebrew/tap.rb @@ -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}. diff --git a/Library/Homebrew/test/cmd/completions_spec.rb b/Library/Homebrew/test/cmd/completions_spec.rb index 23f0365402..0c093bec6f 100644 --- a/Library/Homebrew/test/cmd/completions_spec.rb +++ b/Library/Homebrew/test/cmd/completions_spec.rb @@ -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 diff --git a/Library/Homebrew/test/tap_spec.rb b/Library/Homebrew/test/tap_spec.rb index 0236f6a6f5..eb4a64e121 100644 --- a/Library/Homebrew/test/tap_spec.rb +++ b/Library/Homebrew/test/tap_spec.rb @@ -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 diff --git a/Library/Homebrew/utils/link.rb b/Library/Homebrew/utils/link.rb index 8ca992a802..8078390f60 100644 --- a/Library/Homebrew/utils/link.rb +++ b/Library/Homebrew/utils/link.rb @@ -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) diff --git a/docs/Shell-Completion.md b/docs/Shell-Completion.md index 6dd1785bca..b68d23744b 100644 --- a/docs/Shell-Completion.md +++ b/docs/Shell-Completion.md @@ -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`):