completions: link official taps automatically

This commit is contained in:
Rylan Polster 2021-01-11 12:24:48 -05:00
parent bed16128cc
commit e7b369273a
7 changed files with 82 additions and 51 deletions

View File

@ -8,7 +8,6 @@ require "descriptions"
require "cleanup" require "cleanup"
require "description_cache_store" require "description_cache_store"
require "cli/parser" require "cli/parser"
require "completions"
module Homebrew module Homebrew
extend T::Sig extend T::Sig
@ -151,15 +150,6 @@ module Homebrew
puts "Already up-to-date." unless args.quiet? puts "Already up-to-date." unless args.quiet?
end 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 Commands.rebuild_commands_completion_list
link_completions_manpages_and_docs link_completions_manpages_and_docs
Tap.each(&:link_completions_and_manpages) Tap.each(&:link_completions_and_manpages)
@ -198,8 +188,7 @@ module Homebrew
def link_completions_manpages_and_docs(repository = HOMEBREW_REPOSITORY) def link_completions_manpages_and_docs(repository = HOMEBREW_REPOSITORY)
command = "brew update" command = "brew update"
Utils::Link.link_completions(repository, command)
Completions.link_if_allowed! command: command
Utils::Link.link_manpages(repository, command) Utils::Link.link_manpages(repository, command)
Utils::Link.link_docs(repository, command) Utils::Link.link_docs(repository, command)
rescue => e rescue => e

View File

@ -11,25 +11,22 @@ module Completions
module_function module_function
sig { params(command: String).void } sig { void }
def link_if_allowed!(command: "brew completions link") def link!
if link_completions?
link! command: command
else
unlink!
end
end
sig { params(command: String).void }
def link!(command: "brew completions link")
write_completions_option "yes" 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 end
sig { void } sig { void }
def unlink! def unlink!
write_completions_option "no" 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 end
sig { returns(T::Boolean) } sig { returns(T::Boolean) }
@ -37,17 +34,46 @@ module Completions
read_completions_option == "yes" read_completions_option == "yes"
end end
sig { returns(String) } sig { returns(T::Boolean) }
def read_completions_option 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 HOMEBREW_REPOSITORY.cd do
Utils.popen_read("git", "config", "--get", "homebrew.linkcompletions").chomp Utils.popen_read("git", "config", "--get", "homebrew.#{option}").chomp
end end
end end
sig { params(state: String).void } sig { params(state: String, option: String).void }
def write_completions_option(state) def write_completions_option(state, option: "linkcompletions")
HOMEBREW_REPOSITORY.cd do 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
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 end

View File

@ -2,6 +2,7 @@
# frozen_string_literal: true # frozen_string_literal: true
require "commands" require "commands"
require "completions"
require "extend/cachable" require "extend/cachable"
require "description_cache_store" require "description_cache_store"
@ -340,7 +341,13 @@ class Tap
def link_completions_and_manpages def link_completions_and_manpages
command = "brew tap --repair" command = "brew tap --repair"
Utils::Link.link_manpages(path, command) 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 end
# Uninstall this {Tap}. # Uninstall this {Tap}.

View File

@ -18,11 +18,5 @@ describe "brew completions", :integration_test do
.to output(/Completions are linked/).to_stdout .to output(/Completions are linked/).to_stdout
.and not_to_output.to_stderr .and not_to_output.to_stderr
.and be_a_success .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
end end

View File

@ -88,6 +88,7 @@ describe Tap do
HOMEBREW_REPOSITORY.cd do HOMEBREW_REPOSITORY.cd do
system "git", "init" system "git", "init"
system "git", "config", "--replace-all", "homebrew.linkcompletions", link system "git", "config", "--replace-all", "homebrew.linkcompletions", link
system "git", "config", "--replace-all", "homebrew.completionsmessageshown", "yes"
end end
end end
@ -316,11 +317,11 @@ describe Tap do
(HOMEBREW_PREFIX/"share").rmtree if (HOMEBREW_PREFIX/"share").exist? (HOMEBREW_PREFIX/"share").rmtree if (HOMEBREW_PREFIX/"share").exist?
end 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_tap_files
setup_git_repo setup_git_repo
setup_completion link: "yes" setup_completion link: "yes"
tap = described_class.new("Homebrew", "baz") tap = described_class.new("NotHomebrew", "baz")
tap.install clone_target: subject.path/".git" tap.install clone_target: subject.path/".git"
(HOMEBREW_PREFIX/"share/man/man1/brew-tap-cmd.1").delete (HOMEBREW_PREFIX/"share/man/man1/brew-tap-cmd.1").delete
(HOMEBREW_PREFIX/"etc/bash_completion.d/brew-tap-cmd").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? (HOMEBREW_PREFIX/"share").rmtree if (HOMEBREW_PREFIX/"share").exist?
end 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_tap_files
setup_git_repo setup_git_repo
setup_completion link: "no" setup_completion link: "no"
tap = described_class.new("Homebrew", "baz") tap = described_class.new("NotHomebrew", "baz")
tap.install clone_target: subject.path/".git" tap.install clone_target: subject.path/".git"
(HOMEBREW_PREFIX/"share/man/man1/brew-tap-cmd.1").delete (HOMEBREW_PREFIX/"share/man/man1/brew-tap-cmd.1").delete
tap.link_completions_and_manpages tap.link_completions_and_manpages
@ -355,6 +356,27 @@ describe Tap do
(HOMEBREW_PREFIX/"share").rmtree if (HOMEBREW_PREFIX/"share").exist? (HOMEBREW_PREFIX/"share").rmtree if (HOMEBREW_PREFIX/"share").exist?
end 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 specify "#config" do
setup_git_repo setup_git_repo

View File

@ -1,8 +1,6 @@
# typed: true # typed: true
# frozen_string_literal: true # frozen_string_literal: true
require "completions"
module Utils module Utils
# Helper functions for creating symlinks. # Helper functions for creating symlinks.
# #
@ -66,11 +64,6 @@ module Utils
end end
def link_completions(path, command) 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/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/zsh", HOMEBREW_PREFIX/"share/zsh/site-functions", command)
link_src_dst_dirs(path/"completions/fish", HOMEBREW_PREFIX/"share/fish/vendor_completions.d", command) link_src_dst_dirs(path/"completions/fish", HOMEBREW_PREFIX/"share/fish/vendor_completions.d", command)

View File

@ -4,10 +4,10 @@ Homebrew comes with completion definitions for the `brew` command. Some packages
`zsh`, `bash` and `fish` are currently supported. `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. 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` ## 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`): 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`):