Merge pull request #10403 from Rylan12/zsh-completions
Generate zsh completions automatically
This commit is contained in:
commit
00fab0294b
@ -183,7 +183,9 @@ module Homebrew
|
||||
Homebrew::EnvConfig.try(:"#{env}?")
|
||||
end
|
||||
|
||||
def description(text)
|
||||
def description(text = nil)
|
||||
return @description if text.blank?
|
||||
|
||||
@description = text.chomp
|
||||
end
|
||||
|
||||
|
||||
@ -12,7 +12,7 @@ module Homebrew
|
||||
def __repository_args
|
||||
Homebrew::CLI::Parser.new do
|
||||
description <<~EOS
|
||||
Display where Homebrew's `.git` directory is located.
|
||||
Display where Homebrew's git repository is located.
|
||||
|
||||
If <user>`/`<repo> are provided, display where tap <user>`/`<repo>'s directory is located.
|
||||
EOS
|
||||
|
||||
@ -21,8 +21,8 @@ module Homebrew
|
||||
def uses_args
|
||||
Homebrew::CLI::Parser.new do
|
||||
description <<~EOS
|
||||
Show formulae and casks that specify <formula> as a dependency (i.e. show dependents
|
||||
of <formula>). When given multiple formula arguments, show the intersection
|
||||
Show formulae and casks that specify <formula> as a dependency; that is, show dependents
|
||||
of <formula>. When given multiple formula arguments, show the intersection
|
||||
of formulae that use <formula>. By default, `uses` shows all formulae and casks that
|
||||
specify <formula> as a required or recommended dependency for their stable builds.
|
||||
EOS
|
||||
|
||||
@ -201,8 +201,10 @@ module Commands
|
||||
cmd.start_with?("cask ") || Homebrew::Completions::COMPLETIONS_EXCLUSION_LIST.include?(cmd)
|
||||
end
|
||||
|
||||
file = HOMEBREW_CACHE/"all_commands_list.txt"
|
||||
file.atomic_write("#{cmds.sort.join("\n")}\n")
|
||||
all_commands_file = HOMEBREW_CACHE/"all_commands_list.txt"
|
||||
external_commands_file = HOMEBREW_CACHE/"external_commands_list.txt"
|
||||
all_commands_file.atomic_write("#{cmds.sort.join("\n")}\n")
|
||||
external_commands_file.atomic_write("#{external_commands.sort.join("\n")}\n")
|
||||
end
|
||||
|
||||
def command_options(command)
|
||||
@ -228,6 +230,30 @@ module Commands
|
||||
end
|
||||
end
|
||||
|
||||
def command_description(command, short: false)
|
||||
path = self.path(command)
|
||||
return if path.blank?
|
||||
|
||||
if cmd_parser = Homebrew::CLI::Parser.from_cmd_path(path)
|
||||
if short
|
||||
cmd_parser.description.split(".").first
|
||||
else
|
||||
cmd_parser.description
|
||||
end
|
||||
else
|
||||
comment_lines = path.read.lines.grep(/^#:/)
|
||||
|
||||
# skip the comment's initial usage summary lines
|
||||
comment_lines.slice(2..-1)&.each do |line|
|
||||
if /^#: (?<desc>\w.*+)$/ =~ line
|
||||
return desc.split(".").first if short
|
||||
|
||||
return desc
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def named_args_type(command)
|
||||
path = self.path(command)
|
||||
return if path.blank?
|
||||
|
||||
@ -38,6 +38,20 @@ module Homebrew
|
||||
file: "__brew_complete_files",
|
||||
}.freeze
|
||||
|
||||
ZSH_NAMED_ARGS_COMPLETION_FUNCTION_MAPPING = {
|
||||
formula: "__brew_formulae",
|
||||
installed_formula: "__brew_installed_formulae",
|
||||
outdated_formula: "__brew_outdated_formulae",
|
||||
cask: "__brew_casks",
|
||||
installed_cask: "__brew_installed_casks",
|
||||
outdated_cask: "__brew_outdated_casks",
|
||||
tap: "__brew_any_tap",
|
||||
installed_tap: "__brew_installed_taps",
|
||||
command: "__brew_commands",
|
||||
diagnostic_check: "__brew_diagnostic_checks",
|
||||
file: "__brew_formulae_or_ruby_files",
|
||||
}.freeze
|
||||
|
||||
sig { void }
|
||||
def link!
|
||||
Settings.write :linkcompletions, true
|
||||
@ -93,7 +107,10 @@ module Homebrew
|
||||
def update_shell_completions!
|
||||
commands = Commands.commands(external: false, aliases: true).sort
|
||||
|
||||
puts "Writing completions to #{COMPLETIONS_DIR}"
|
||||
|
||||
(COMPLETIONS_DIR/"bash/brew").atomic_write generate_bash_completion_file(commands)
|
||||
(COMPLETIONS_DIR/"zsh/_brew").atomic_write generate_zsh_completion_file(commands)
|
||||
end
|
||||
|
||||
sig { params(command: String).returns(T::Boolean) }
|
||||
@ -103,21 +120,27 @@ module Homebrew
|
||||
command_options(command).any?
|
||||
end
|
||||
|
||||
sig { params(command: String).returns(T::Array[String]) }
|
||||
sig { params(description: String).returns(String) }
|
||||
def format_description(description)
|
||||
description.gsub("'", "'\\\\''").gsub(/[<>]/, "").tr("\n", " ").chomp(".")
|
||||
end
|
||||
|
||||
sig { params(command: String).returns(T::Hash[String, String]) }
|
||||
def command_options(command)
|
||||
options = []
|
||||
options = {}
|
||||
Commands.command_options(command)&.each do |option|
|
||||
next if option.blank?
|
||||
|
||||
name = option.first
|
||||
desc = option.second
|
||||
if name.start_with? "--[no-]"
|
||||
options << name.remove("[no-]")
|
||||
options << name.sub("[no-]", "no-")
|
||||
options[name.remove("[no-]")] = desc
|
||||
options[name.sub("[no-]", "no-")] = desc
|
||||
else
|
||||
options << name
|
||||
options[name] = desc
|
||||
end
|
||||
end&.compact
|
||||
options.sort
|
||||
end
|
||||
options
|
||||
end
|
||||
|
||||
sig { params(command: String).returns(T.nilable(String)) }
|
||||
@ -143,7 +166,7 @@ module Homebrew
|
||||
case "$cur" in
|
||||
-*)
|
||||
__brewcomp "
|
||||
#{command_options(command).join("\n ")}
|
||||
#{command_options(command).keys.sort.join("\n ")}
|
||||
"
|
||||
return
|
||||
;;
|
||||
@ -152,7 +175,7 @@ module Homebrew
|
||||
COMPLETION
|
||||
end
|
||||
|
||||
sig { params(commands: T::Array[String]).returns(T.nilable(String)) }
|
||||
sig { params(commands: T::Array[String]).returns(String) }
|
||||
def generate_bash_completion_file(commands)
|
||||
variables = OpenStruct.new
|
||||
|
||||
@ -168,5 +191,62 @@ module Homebrew
|
||||
|
||||
ERB.new((TEMPLATE_DIR/"bash.erb").read, trim_mode: ">").result(variables.instance_eval { binding })
|
||||
end
|
||||
|
||||
sig { params(command: String).returns(T.nilable(String)) }
|
||||
def generate_zsh_subcommand_completion(command)
|
||||
return unless command_gets_completions? command
|
||||
|
||||
options = command_options(command).sort.map do |opt, desc|
|
||||
next opt if desc.blank?
|
||||
|
||||
"#{opt}[#{format_description desc}]"
|
||||
end
|
||||
if types = Commands.named_args_type(command)
|
||||
named_args_strings, named_args_types = types.partition { |type| type.is_a? String }
|
||||
|
||||
named_args_types.each do |type|
|
||||
next unless ZSH_NAMED_ARGS_COMPLETION_FUNCTION_MAPPING.key? type
|
||||
|
||||
options << "::#{type}:#{ZSH_NAMED_ARGS_COMPLETION_FUNCTION_MAPPING[type]}"
|
||||
end
|
||||
|
||||
options << "::subcommand:(#{named_args_strings.join(" ")})" if named_args_strings.any?
|
||||
end
|
||||
|
||||
<<~COMPLETION
|
||||
# brew #{command}
|
||||
_brew_#{Commands.method_name command}() {
|
||||
_arguments \\
|
||||
#{options.map! { |opt| "'#{opt}'" }.join(" \\\n ")}
|
||||
}
|
||||
COMPLETION
|
||||
end
|
||||
|
||||
sig { params(commands: T::Array[String]).returns(String) }
|
||||
def generate_zsh_completion_file(commands)
|
||||
variables = OpenStruct.new
|
||||
|
||||
variables[:aliases] = Commands::HOMEBREW_INTERNAL_COMMAND_ALIASES.map do |alias_command, command|
|
||||
alias_command = "'#{alias_command}'" if alias_command.start_with? "-"
|
||||
command = "'#{command}'" if command.start_with? "-"
|
||||
"#{alias_command} #{command}"
|
||||
end.compact
|
||||
|
||||
variables[:builtin_command_descriptions] = commands.map do |command|
|
||||
next if Commands::HOMEBREW_INTERNAL_COMMAND_ALIASES.key? command
|
||||
|
||||
description = Commands.command_description(command, short: true)
|
||||
next if description.blank?
|
||||
|
||||
description = format_description description
|
||||
"'#{command}:#{description}'"
|
||||
end.compact
|
||||
|
||||
variables[:completion_functions] = commands.map do |command|
|
||||
generate_zsh_subcommand_completion command
|
||||
end.compact
|
||||
|
||||
ERB.new((TEMPLATE_DIR/"zsh.erb").read, trim_mode: ">").result(variables.instance_eval { binding })
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
193
Library/Homebrew/completions/zsh.erb
Normal file
193
Library/Homebrew/completions/zsh.erb
Normal file
@ -0,0 +1,193 @@
|
||||
<%
|
||||
# To make changes to the completions:
|
||||
#
|
||||
# - For changes to a command under `COMMANDS` or `DEVELOPER COMMANDS` sections):
|
||||
# - Find the source file in `Library/Homebrew/[dev-]cmd/<command>.{rb,sh}`.
|
||||
# - For `.rb` files, edit the `<command>_args` method.
|
||||
# - For `.sh` files, edit the top comment, being sure to use the line prefix
|
||||
# `#:` for the comments to be recognized as documentation. If in doubt,
|
||||
# compare with already documented commands.
|
||||
# - For other changes: Edit this file.
|
||||
#
|
||||
# When done, regenerate the completions by running `brew man`.
|
||||
%>
|
||||
#compdef brew
|
||||
#autoload
|
||||
|
||||
# Brew ZSH completion function
|
||||
|
||||
# functions starting with __brew are helper functions that complete or list
|
||||
# various types of items.
|
||||
# functions starting with _brew_ are completions for brew commands
|
||||
# this mechanism can be extended by external commands by defining a function
|
||||
# named _brew_<external-name>. See _brew_cask for an example of this.
|
||||
|
||||
# a list of aliased internal commands
|
||||
__brew_list_aliases() {
|
||||
local -a aliases
|
||||
aliases=(
|
||||
<%= aliases.join("\n ") + "\n" %>
|
||||
)
|
||||
echo "${aliases}"
|
||||
}
|
||||
|
||||
__brew_formulae_or_ruby_files() {
|
||||
_alternative 'files:files:{_files -g "*.rb"}'
|
||||
}
|
||||
|
||||
# completions remain in cache until any tap has new commits
|
||||
__brew_completion_caching_policy() {
|
||||
local -a tmp
|
||||
|
||||
# invalidate if cache file is missing or >=2 weeks old
|
||||
tmp=( $1(mw-2N) )
|
||||
(( $#tmp )) || return 0
|
||||
|
||||
# otherwise, invalidate if latest tap index file is missing or newer than cache file
|
||||
tmp=( ${HOMEBREW_REPOSITORY:-/usr/local/Homebrew}/Library/Taps/*/*/.git/index(om[1]N) )
|
||||
[[ -z $tmp || $tmp -nt $1 ]]
|
||||
}
|
||||
|
||||
__brew_formulae() {
|
||||
local -a list
|
||||
local comp_cachename=brew_formulae
|
||||
if ! _retrieve_cache $comp_cachename; then
|
||||
list=( $(brew formulae) )
|
||||
_store_cache $comp_cachename list
|
||||
fi
|
||||
_describe -t formulae 'all formulae' list
|
||||
}
|
||||
|
||||
__brew_installed_formulae() {
|
||||
local -a formulae
|
||||
formulae=($(brew list --formula))
|
||||
_describe -t formulae 'installed formulae' formulae
|
||||
}
|
||||
|
||||
__brew_outdated_formulae() {
|
||||
local -a formulae
|
||||
formulae=($(brew outdated --formula))
|
||||
_describe -t formulae 'outdated formulae' formulae
|
||||
}
|
||||
|
||||
__brew_casks() {
|
||||
local -a list
|
||||
local expl
|
||||
local comp_cachename=brew_casks
|
||||
|
||||
if ! _retrieve_cache $comp_cachename; then
|
||||
list=( $(brew search --cask) )
|
||||
_store_cache $comp_cachename list
|
||||
fi
|
||||
|
||||
_wanted list expl 'all casks' compadd -a list
|
||||
}
|
||||
|
||||
__brew_installed_casks() {
|
||||
local -a list
|
||||
local expl
|
||||
list=( $(brew list --cask) )
|
||||
_wanted list expl 'installed casks' compadd -a list
|
||||
}
|
||||
|
||||
__brew_outdated_casks() {
|
||||
local -a casks
|
||||
casks=($(brew outdated --cask))
|
||||
_describe -t casks 'outdated casks' casks
|
||||
}
|
||||
|
||||
__brew_installed_taps() {
|
||||
local -a taps
|
||||
taps=($(brew tap))
|
||||
_describe -t installed-taps 'installed taps' taps
|
||||
}
|
||||
|
||||
__brew_any_tap() {
|
||||
_alternative \
|
||||
'installed-taps:installed taps:__brew_installed_taps'
|
||||
}
|
||||
|
||||
__brew_internal_commands() {
|
||||
local -a commands
|
||||
commands=(
|
||||
<%= builtin_command_descriptions.join("\n ") + "\n" %>
|
||||
)
|
||||
_describe -t internal-commands 'internal commands' commands
|
||||
}
|
||||
|
||||
__brew_external_commands() {
|
||||
local -a list
|
||||
local comp_cachename=brew_all_commands
|
||||
if ! _retrieve_cache $comp_cachename; then
|
||||
local cache_dir=$(brew --cache)
|
||||
[[ -f $cache_dir/external_commands_list.txt ]] &&
|
||||
list=( $(<$cache_dir/external_commands_list.txt) )
|
||||
_store_cache $comp_cachename list
|
||||
fi
|
||||
_describe -t all-commands 'all commands' list
|
||||
}
|
||||
|
||||
__brew_commands() {
|
||||
_alternative \
|
||||
'internal-commands:command:__brew_internal_commands' \
|
||||
'external-commands:command:__brew_external_commands'
|
||||
}
|
||||
|
||||
__brew_diagnostic_checks() {
|
||||
local -a diagnostic_checks
|
||||
diagnostic_checks=($(brew doctor --list-checks))
|
||||
_describe -t diagnostic-checks 'diagnostic checks' diagnostic_checks
|
||||
}
|
||||
|
||||
<%= completion_functions.join("\n") %>
|
||||
|
||||
# The main completion function
|
||||
_brew() {
|
||||
local curcontext="$curcontext" state state_descr line expl
|
||||
local tmp ret=1
|
||||
|
||||
_arguments -C : \
|
||||
'(-v)-v[verbose]' \
|
||||
'1:command:->command' \
|
||||
'*::options:->options' && return 0
|
||||
|
||||
case "$state" in
|
||||
command)
|
||||
# set default cache policy
|
||||
zstyle -s ":completion:${curcontext%:*}:*" cache-policy tmp ||
|
||||
zstyle ":completion:${curcontext%:*}:*" cache-policy __brew_completion_caching_policy
|
||||
zstyle -s ":completion:${curcontext%:*}:*" use-cache tmp ||
|
||||
zstyle ":completion:${curcontext%:*}:*" use-cache true
|
||||
|
||||
__brew_commands && return 0
|
||||
;;
|
||||
options)
|
||||
local command_or_alias command
|
||||
local -A aliases
|
||||
|
||||
# expand alias e.g. ls -> list
|
||||
command_or_alias="${line[1]}"
|
||||
aliases=($(__brew_list_aliases))
|
||||
command="${aliases[$command_or_alias]:-$command_or_alias}"
|
||||
|
||||
# change context to e.g. brew-list
|
||||
curcontext="${curcontext%:*}-${command}:${curcontext##*:}"
|
||||
|
||||
# set default cache policy (we repeat this dance because the context
|
||||
# service differs from above)
|
||||
zstyle -s ":completion:${curcontext%:*}:*" cache-policy tmp ||
|
||||
zstyle ":completion:${curcontext%:*}:*" cache-policy __brew_completion_caching_policy
|
||||
zstyle -s ":completion:${curcontext%:*}:*" use-cache tmp ||
|
||||
zstyle ":completion:${curcontext%:*}:*" use-cache true
|
||||
|
||||
# call completion for named command e.g. _brew_list
|
||||
local completion_func="_brew_${command//-/_}"
|
||||
_call_function ret "${completion_func}" && return ret
|
||||
|
||||
_message "a completion function is not defined for command or alias: ${command_or_alias}"
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
_brew "$@"
|
||||
@ -86,7 +86,8 @@ module Homebrew
|
||||
usage_banner "`extract` [<--version>`=`] [<--force>] <formula> <tap>"
|
||||
description <<~EOS
|
||||
Look through repository history to find the most recent version of <formula> and
|
||||
create a copy in <tap>`/Formula/`<formula>`@`<version>`.rb`. If the tap is not
|
||||
create a copy in <tap>. Specifically, the command will create the new
|
||||
formula file at <tap>`/Formula/`<formula>`@`<version>`.rb`. If the tap is not
|
||||
installed yet, attempt to install/clone the tap before continuing. To extract
|
||||
a formula from a tap that is not `homebrew/core` use its fully-qualified form of
|
||||
<user>`/`<repo>`/`<formula>.
|
||||
|
||||
@ -12,7 +12,7 @@ module Homebrew
|
||||
def prof_args
|
||||
Homebrew::CLI::Parser.new do
|
||||
description <<~EOS
|
||||
Run Homebrew with a Ruby profiler, e.g. `brew prof readall`.
|
||||
Run Homebrew with a Ruby profiler. For example, `brew prof readall`.
|
||||
EOS
|
||||
switch "--stackprof",
|
||||
description: "Use `stackprof` instead of `ruby-prof` (the default)."
|
||||
|
||||
@ -13,7 +13,7 @@ module Homebrew
|
||||
Homebrew::CLI::Parser.new do
|
||||
usage_banner "`ruby` [<options>] (`-e` <text>|<file>)"
|
||||
description <<~EOS
|
||||
Run a Ruby instance with Homebrew's libraries loaded, e.g.
|
||||
Run a Ruby instance with Homebrew's libraries loaded. For example,
|
||||
`brew ruby -e "puts :gcc.f.deps"` or `brew ruby script.rb`.
|
||||
EOS
|
||||
flag "-r=",
|
||||
|
||||
@ -14,7 +14,7 @@ module Homebrew
|
||||
def sh_args
|
||||
Homebrew::CLI::Parser.new do
|
||||
description <<~EOS
|
||||
Homebrew build environment that uses years-battle-hardened
|
||||
Enter an interactive shell for Homebrew's build environment. Use years-battle-hardened
|
||||
build logic to help your `./configure && make && make install`
|
||||
and even your `gem install` succeed. Especially handy if you run Homebrew
|
||||
in an Xcode-only configuration since it adds tools like `make` to your `PATH`
|
||||
|
||||
@ -153,37 +153,67 @@ describe Homebrew::Completions do
|
||||
end
|
||||
end
|
||||
|
||||
describe ".format_description" do
|
||||
it "escapes single quotes" do
|
||||
expect(described_class.format_description("Homebrew's")).to eq "Homebrew'\\''s"
|
||||
end
|
||||
|
||||
it "removes angle brackets" do
|
||||
expect(described_class.format_description("<formula>")).to eq "formula"
|
||||
end
|
||||
|
||||
it "replaces newlines with spaces" do
|
||||
expect(described_class.format_description("Homebrew\ncommand")).to eq "Homebrew command"
|
||||
end
|
||||
|
||||
it "removes trailing period" do
|
||||
expect(described_class.format_description("Homebrew.")).to eq "Homebrew"
|
||||
end
|
||||
end
|
||||
|
||||
describe ".command_options" do
|
||||
it "returns an array of options for a ruby command" do
|
||||
expected_options = %w[--debug --help --hide --quiet --verbose]
|
||||
expected_options = {
|
||||
"--debug" => "Display any debugging information.",
|
||||
"--help" => "Show this message.",
|
||||
"--hide" => "Act as if none of the specified <hidden> are installed. <hidden> should be " \
|
||||
"a comma-separated list of formulae.",
|
||||
"--quiet" => "Make some output more quiet.",
|
||||
"--verbose" => "Make some output more verbose.",
|
||||
}
|
||||
expect(described_class.command_options("missing")).to eq expected_options
|
||||
end
|
||||
|
||||
it "returns an array of options for a shell command" do
|
||||
expected_options = %w[--debug --force --help --merge --preinstall --verbose]
|
||||
expected_options = {
|
||||
"--debug" => "Display a trace of all shell commands as they are executed.",
|
||||
"--force" => "Always do a slower, full update check (even if unnecessary).",
|
||||
"--help" => "Show this message.",
|
||||
"--merge" => "Use `git merge` to apply updates (rather than `git rebase`).",
|
||||
"--preinstall" => "Run on auto-updates (e.g. before `brew install`). Skips some slower steps.",
|
||||
"--verbose" => "Print the directories checked and `git` operations performed.",
|
||||
}
|
||||
expect(described_class.command_options("update")).to eq expected_options
|
||||
end
|
||||
|
||||
it "handles --[no]- options correctly" do
|
||||
options = described_class.command_options("audit")
|
||||
expect(options.include?("--appcast")).to eq true
|
||||
expect(options.include?("--no-appcast")).to eq true
|
||||
expect(options.key?("--appcast")).to eq true
|
||||
expect(options.key?("--no-appcast")).to eq true
|
||||
expect(options["--appcast"] == options["--no-appcast"]).to eq true
|
||||
end
|
||||
|
||||
it "return an empty array if command is not found" do
|
||||
expect(described_class.command_options("foobar")).to eq []
|
||||
expect(described_class.command_options("foobar")).to eq({})
|
||||
end
|
||||
|
||||
it "return an empty array for a command with no options" do
|
||||
expect(described_class.command_options("help")).to eq []
|
||||
expect(described_class.command_options("help")).to eq({})
|
||||
end
|
||||
|
||||
it "will list global options only once if overriden" do
|
||||
count = 0
|
||||
described_class.command_options("upgrade").each do |opt|
|
||||
count += 1 if opt == "--verbose"
|
||||
end
|
||||
expect(count).to eq 1
|
||||
it "will override global options with local descriptions" do
|
||||
options = described_class.command_options("upgrade")
|
||||
expect(options["--verbose"]).to eq "Print the verification and postinstall steps."
|
||||
end
|
||||
end
|
||||
|
||||
@ -208,16 +238,46 @@ describe Homebrew::Completions do
|
||||
|
||||
it "returns appropriate completion for a ruby command" do
|
||||
completion = described_class.generate_bash_subcommand_completion("missing")
|
||||
expect(completion).to match(/^_brew_missing\(\) {/)
|
||||
expect(completion).to match(/__brewcomp "\n +--debug\n +--help\n +--hide\n +--quiet\n +--verbose/s)
|
||||
expect(completion).to match(/__brew_complete_formulae\n}$/)
|
||||
expect(completion).to eq <<~COMPLETION
|
||||
_brew_missing() {
|
||||
local cur="${COMP_WORDS[COMP_CWORD]}"
|
||||
case "$cur" in
|
||||
-*)
|
||||
__brewcomp "
|
||||
--debug
|
||||
--help
|
||||
--hide
|
||||
--quiet
|
||||
--verbose
|
||||
"
|
||||
return
|
||||
;;
|
||||
esac
|
||||
__brew_complete_formulae
|
||||
}
|
||||
COMPLETION
|
||||
end
|
||||
|
||||
it "returns appropriate completion for a shell command" do
|
||||
completion = described_class.generate_bash_subcommand_completion("update")
|
||||
options_regex = /__brewcomp "\n +--debug\n +--force\n +--help\n +--merge\n +--preinstall\n +--verbose/
|
||||
expect(completion).to match(/^_brew_update\(\) {/)
|
||||
expect(completion).to match(options_regex)
|
||||
expect(completion).to eq <<~COMPLETION
|
||||
_brew_update() {
|
||||
local cur="${COMP_WORDS[COMP_CWORD]}"
|
||||
case "$cur" in
|
||||
-*)
|
||||
__brewcomp "
|
||||
--debug
|
||||
--force
|
||||
--help
|
||||
--merge
|
||||
--preinstall
|
||||
--verbose
|
||||
"
|
||||
return
|
||||
;;
|
||||
esac
|
||||
}
|
||||
COMPLETION
|
||||
end
|
||||
|
||||
it "returns appropriate completion for a command with multiple named arg types" do
|
||||
@ -240,5 +300,66 @@ describe Homebrew::Completions do
|
||||
expect(file).to match(/^complete -o bashdefault -o default -F _brew brew$/)
|
||||
end
|
||||
end
|
||||
|
||||
describe ".generate_zsh_subcommand_completion" do
|
||||
it "returns nil if completions aren't needed" do
|
||||
expect(described_class.generate_zsh_subcommand_completion("help")).to be_nil
|
||||
end
|
||||
|
||||
it "returns appropriate completion for a ruby command" do
|
||||
completion = described_class.generate_zsh_subcommand_completion("missing")
|
||||
expect(completion).to eq <<~COMPLETION
|
||||
# brew missing
|
||||
_brew_missing() {
|
||||
_arguments \\
|
||||
'--debug[Display any debugging information]' \\
|
||||
'--help[Show this message]' \\
|
||||
'--hide[Act as if none of the specified hidden are installed. hidden should be a comma-separated list of formulae]' \\
|
||||
'--quiet[Make some output more quiet]' \\
|
||||
'--verbose[Make some output more verbose]' \\
|
||||
'::formula:__brew_formulae'
|
||||
}
|
||||
COMPLETION
|
||||
end
|
||||
|
||||
it "returns appropriate completion for a shell command" do
|
||||
completion = described_class.generate_zsh_subcommand_completion("update")
|
||||
expect(completion).to eq <<~COMPLETION
|
||||
# brew update
|
||||
_brew_update() {
|
||||
_arguments \\
|
||||
'--debug[Display a trace of all shell commands as they are executed]' \\
|
||||
'--force[Always do a slower, full update check (even if unnecessary)]' \\
|
||||
'--help[Show this message]' \\
|
||||
'--merge[Use `git merge` to apply updates (rather than `git rebase`)]' \\
|
||||
'--preinstall[Run on auto-updates (e.g. before `brew install`). Skips some slower steps]' \\
|
||||
'--verbose[Print the directories checked and `git` operations performed]'
|
||||
}
|
||||
COMPLETION
|
||||
end
|
||||
|
||||
it "returns appropriate completion for a command with multiple named arg types" do
|
||||
completion = described_class.generate_zsh_subcommand_completion("upgrade")
|
||||
expect(completion).to match(
|
||||
/'::outdated_formula:__brew_outdated_formulae' \\\n '::outdated_cask:__brew_outdated_casks'\n}$/,
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
describe ".generate_zsh_completion_file" do
|
||||
it "returns the correct completion file" do
|
||||
file = described_class.generate_zsh_completion_file(%w[install missing update])
|
||||
expect(file).to match(/^__brew_list_aliases\(\) {$/)
|
||||
expect(file).to match(/^ up update$/)
|
||||
expect(file).to match(/^__brew_internal_commands\(\) {$/)
|
||||
expect(file).to match(/^ 'install:Install a formula or cask'$/)
|
||||
expect(file).to match(/^ 'missing:Check the given formula kegs for missing dependencies'$/)
|
||||
expect(file).to match(/^ 'update:Fetch the newest version of Homebrew and all formulae from GitHub .*'$/)
|
||||
expect(file).to match(/^_brew_install\(\) {$/)
|
||||
expect(file).to match(/^_brew_missing\(\) {$/)
|
||||
expect(file).to match(/^_brew_update\(\) {$/)
|
||||
expect(file).to match(/^_brew "\$@"$/)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,203 +0,0 @@
|
||||
#compdef brew-cask
|
||||
#autoload
|
||||
|
||||
# Zsh Autocompletion script for Homebrew Cask
|
||||
# https://github.com/homebrew/brew
|
||||
|
||||
# Authors:
|
||||
# Patrick Stadler (https://github.com/pstadler)
|
||||
# Josh McKinney (https://github.com/joshka)
|
||||
|
||||
# only display the main commands (but enable completing aliases like 'ls')
|
||||
zstyle -T ':completion:*:*:*:brew-cask:*' tag-order && \
|
||||
zstyle ':completion:*:*:*:brew-cask:*' tag-order 'commands'
|
||||
|
||||
__brew_all_casks() {
|
||||
local -a list
|
||||
local expl
|
||||
local comp_cachename=brew_casks
|
||||
|
||||
if ! _retrieve_cache $comp_cachename; then
|
||||
list=( $(brew casks) )
|
||||
_store_cache $comp_cachename list
|
||||
fi
|
||||
|
||||
_wanted list expl 'all casks' compadd -a list
|
||||
}
|
||||
|
||||
__brew_installed_casks() {
|
||||
local -a list
|
||||
local expl
|
||||
list=( $(brew list --cask) )
|
||||
_wanted list expl 'installed casks' compadd -a list
|
||||
}
|
||||
|
||||
__brew_cask_commands() {
|
||||
local -a commands
|
||||
commands=(
|
||||
'audit:verifies installability of Casks'
|
||||
'cat:dump raw source of the given Cask to the standard output'
|
||||
'create:creates the given Cask and opens it in an editor'
|
||||
'doctor:checks for configuration issues'
|
||||
'edit:edits the given Cask'
|
||||
'fetch:downloads remote application files to local cache'
|
||||
'home:opens the homepage of the given Cask'
|
||||
'info:displays information about the given Cask'
|
||||
'install:installs the given Cask'
|
||||
'list:with no args, lists installed Casks; given installed Casks, lists staged files'
|
||||
'outdated:list the outdated installed Casks'
|
||||
'reinstall:reinstalls the given Cask'
|
||||
'style:checks Cask style using RuboCop'
|
||||
'uninstall:uninstalls the given Cask'
|
||||
'upgrade:upgrade installed Casks with newer versions'
|
||||
'zap:zaps all files associated with the given Cask'
|
||||
)
|
||||
_describe -t commands "brew cask command" commands
|
||||
}
|
||||
|
||||
__brew_cask_aliases() {
|
||||
local -a aliases
|
||||
aliases=(
|
||||
'dr'
|
||||
'homepage'
|
||||
'abv'
|
||||
'ls'
|
||||
'-S'
|
||||
'rm'
|
||||
'remove'
|
||||
)
|
||||
_describe -t commands "brew cask command aliases" aliases
|
||||
}
|
||||
|
||||
__brew_cask_command() {
|
||||
local command="$1"
|
||||
local completion_func="_brew_cask_${command//-/_}"
|
||||
declare -f "$completion_func" >/dev/null && "$completion_func" && return
|
||||
}
|
||||
|
||||
_brew_cask_abv() {
|
||||
_brew_cask_info
|
||||
}
|
||||
|
||||
_brew_cask_audit() {
|
||||
__brew_all_casks
|
||||
}
|
||||
|
||||
_brew_cask_cat() {
|
||||
__brew_all_casks
|
||||
}
|
||||
|
||||
_brew_cask_create() {
|
||||
_arguments '*::token:'
|
||||
}
|
||||
|
||||
_brew_cask_edit() {
|
||||
__brew_all_casks
|
||||
}
|
||||
|
||||
_brew_cask_fetch() {
|
||||
_arguments : \
|
||||
'--force:force re-download even if the files are already cached' \
|
||||
'*::token:__brew_all_casks'
|
||||
}
|
||||
|
||||
_brew_cask_home() {
|
||||
__brew_all_casks
|
||||
}
|
||||
|
||||
_brew_cask_homepage() {
|
||||
__brew_cask_home
|
||||
}
|
||||
|
||||
_brew_cask_info() {
|
||||
__brew_all_casks
|
||||
}
|
||||
|
||||
_brew_cask_install() {
|
||||
_arguments : \
|
||||
'--force:re-install even if the Cask appears to be already present' \
|
||||
'--skip-cask-deps:skip any Cask dependencies' \
|
||||
'--require-sha:abort installation if the Cask does not have a checksum defined' \
|
||||
'*::token:__brew_all_casks'
|
||||
}
|
||||
|
||||
_brew_cask_list() {
|
||||
_arguments : \
|
||||
'-1[format output in a single column]' \
|
||||
'-l[format as detailed list]' \
|
||||
'*::token:__brew_installed_casks'
|
||||
}
|
||||
|
||||
_brew_cask_outdated() {
|
||||
_arguments : \
|
||||
'--greedy:also list Casks with auto_updates or version \:latest' \
|
||||
'*::token:__brew_installed_casks'
|
||||
}
|
||||
|
||||
_brew_cask_remove() {
|
||||
_brew_cask_uninstall
|
||||
}
|
||||
|
||||
_brew_cask_rm() {
|
||||
_brew_cask_uninstall
|
||||
}
|
||||
|
||||
_brew_cask_style() {
|
||||
_arguments : \
|
||||
'--fix:auto-correct any style errors if possible' \
|
||||
'*::token:__brew_all_casks'
|
||||
}
|
||||
|
||||
_brew_cask_uninstall() {
|
||||
_arguments : \
|
||||
'--force:uninstall even if the Cask does not appear to be present' \
|
||||
'*::token:__brew_installed_casks'
|
||||
}
|
||||
|
||||
_brew_cask_upgrade() {
|
||||
_arguments : \
|
||||
'--force:upgrade even if Cask is not present, and --force the install' \
|
||||
'--greedy:also upgrade Casks with auto_updates or version \:latest' \
|
||||
'*::token:__brew_installed_casks'
|
||||
}
|
||||
|
||||
_brew_cask_zap() {
|
||||
__brew_all_casks
|
||||
}
|
||||
|
||||
_brew_cask()
|
||||
{
|
||||
local curcontext="$curcontext" state state_descr line
|
||||
typeset -A opt_args
|
||||
|
||||
_arguments -C : \
|
||||
'--verbose:Give additional feedback during installation.' \
|
||||
'--appdir=-:Target location for Applications. The default value is /Applications:' \
|
||||
'--colorpickerdir=-:Target location for Color Pickers. The default value is ~/Library/ColorPickers.' \
|
||||
'--prefpanedir=-:Target location for Preference Panes. The default value is ~/Library/PreferencePanes.' \
|
||||
'--qlplugindir=-:Target location for QuickLook Plugins. The default value is ~/Library/QuickLook.' \
|
||||
'--dictionarydir=-:Target location for Dictionaries. The default value is ~/Library/Dictionaries.' \
|
||||
'--fontdir=-:Target location for Fonts. The default value is ~/Library/Fonts.' \
|
||||
'--servicedir=-:Target location for Services. The default value is ~/Library/Services.' \
|
||||
'--input-methoddir=-:Target location for Input Methods. The default value is ~/Library/Input Methods.' \
|
||||
'--internet-plugindir=-:Target location for Internet Plugins. The default value is ~/Library/Internet Plug-Ins.' \
|
||||
'--audio-unit-plugindir=-:Target location for Audio Unit Plugins. The default value is ~/Library/Audio/Plug-Ins/Components.' \
|
||||
'--vst-plugindir=-:Target location for VST Plugins. The default value is ~/Library/Audio/Plug-Ins/VST.' \
|
||||
'--vst3-plugindir=-:Target location for VST3 Plugins. The default value is ~/Library/Audio/Plug-Ins/VST3.' \
|
||||
'--screen-saverdir=-:Target location for Screen Savers. The default value is ~/Library/Screen Savers.' \
|
||||
'--no-binaries:Do not link "helper" executables to /usr/local/bin.' \
|
||||
'--debug:Output debugging information of use to Cask authors and developers.' \
|
||||
':command:->command' \
|
||||
'*::options:->options'
|
||||
|
||||
case "$state" in
|
||||
(command)
|
||||
_alternative -C 'brew-cask' \
|
||||
'aliases:alias:__brew_cask_aliases' \
|
||||
'commands:command:__brew_cask_commands' ;;
|
||||
(options)
|
||||
__brew_cask_command "$line[1]" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
_brew_cask "$@"
|
||||
@ -659,8 +659,8 @@ upgraded formulae or, every 30 days, for all formulae.
|
||||
|
||||
### `uses` [*`options`*] *`formula`* [...]
|
||||
|
||||
Show formulae and casks that specify *`formula`* as a dependency (i.e. show dependents
|
||||
of *`formula`*). When given multiple formula arguments, show the intersection
|
||||
Show formulae and casks that specify *`formula`* as a dependency; that is, show dependents
|
||||
of *`formula`*. When given multiple formula arguments, show the intersection
|
||||
of formulae that use *`formula`*. By default, `uses` shows all formulae and casks that
|
||||
specify *`formula`* as a required or recommended dependency for their stable builds.
|
||||
|
||||
@ -739,7 +739,7 @@ is or would be installed.
|
||||
|
||||
### `--repository`, `--repo` [*`tap`* ...]
|
||||
|
||||
Display where Homebrew's `.git` directory is located.
|
||||
Display where Homebrew's git repository is located.
|
||||
|
||||
If *`user`*`/`*`repo`* are provided, display where tap *`user`*`/`*`repo`*'s directory is located.
|
||||
|
||||
@ -1022,7 +1022,8 @@ or open the Homebrew repository for editing if no formula is provided.
|
||||
### `extract` [*`--version`*`=`] [*`--force`*] *`formula`* *`tap`*
|
||||
|
||||
Look through repository history to find the most recent version of *`formula`* and
|
||||
create a copy in *`tap`*`/Formula/`*`formula`*`@`*`version`*`.rb`. If the tap is not
|
||||
create a copy in *`tap`*. Specifically, the command will create the new
|
||||
formula file at *`tap`*`/Formula/`*`formula`*`@`*`version`*`.rb`. If the tap is not
|
||||
installed yet, attempt to install/clone the tap before continuing. To extract
|
||||
a formula from a tap that is not `homebrew/core` use its fully-qualified form of
|
||||
*`user`*`/`*`repo`*`/`*`formula`*.
|
||||
@ -1203,7 +1204,7 @@ Apply the bottle commit and publish bottles to Bintray or GitHub Releases.
|
||||
|
||||
### `prof` [*`--stackprof`*] [*`command`* ...]
|
||||
|
||||
Run Homebrew with a Ruby profiler, e.g. `brew prof readall`.
|
||||
Run Homebrew with a Ruby profiler. For example, `brew prof readall`.
|
||||
|
||||
* `--stackprof`:
|
||||
Use `stackprof` instead of `ruby-prof` (the default).
|
||||
@ -1243,7 +1244,7 @@ Installs, configures and runs Homebrew's `rubocop`.
|
||||
|
||||
### `ruby` [*`options`*] (`-e` *`text`*|*`file`*)
|
||||
|
||||
Run a Ruby instance with Homebrew's libraries loaded, e.g.
|
||||
Run a Ruby instance with Homebrew's libraries loaded. For example,
|
||||
`brew ruby -e "puts :gcc.f.deps"` or `brew ruby script.rb`.
|
||||
|
||||
* `-r`:
|
||||
@ -1253,7 +1254,7 @@ Run a Ruby instance with Homebrew's libraries loaded, e.g.
|
||||
|
||||
### `sh` [*`--env`*`=`] [*`--cmd`*`=`] [*`file`*]
|
||||
|
||||
Homebrew build environment that uses years-battle-hardened
|
||||
Enter an interactive shell for Homebrew's build environment. Use years-battle-hardened
|
||||
build logic to help your `./configure && make && make install`
|
||||
and even your `gem install` succeed. Especially handy if you run Homebrew
|
||||
in an Xcode-only configuration since it adds tools like `make` to your `PATH`
|
||||
|
||||
@ -896,7 +896,7 @@ Skip installing cask dependencies\.
|
||||
Also include casks with \fBauto_updates true\fR or \fBversion :latest\fR\.
|
||||
.
|
||||
.SS "\fBuses\fR [\fIoptions\fR] \fIformula\fR [\.\.\.]"
|
||||
Show formulae and casks that specify \fIformula\fR as a dependency (i\.e\. show dependents of \fIformula\fR)\. When given multiple formula arguments, show the intersection of formulae that use \fIformula\fR\. By default, \fBuses\fR shows all formulae and casks that specify \fIformula\fR as a required or recommended dependency for their stable builds\.
|
||||
Show formulae and casks that specify \fIformula\fR as a dependency; that is, show dependents of \fIformula\fR\. When given multiple formula arguments, show the intersection of formulae that use \fIformula\fR\. By default, \fBuses\fR shows all formulae and casks that specify \fIformula\fR as a required or recommended dependency for their stable builds\.
|
||||
.
|
||||
.TP
|
||||
\fB\-\-recursive\fR
|
||||
@ -1000,7 +1000,7 @@ If \fIformula\fR is provided, display the location in the Cellar where \fIformul
|
||||
List files in Homebrew\'s prefix not installed by Homebrew\.
|
||||
.
|
||||
.SS "\fB\-\-repository\fR, \fB\-\-repo\fR [\fItap\fR \.\.\.]"
|
||||
Display where Homebrew\'s \fB\.git\fR directory is located\.
|
||||
Display where Homebrew\'s git repository is located\.
|
||||
.
|
||||
.P
|
||||
If \fIuser\fR\fB/\fR\fIrepo\fR are provided, display where tap \fIuser\fR\fB/\fR\fIrepo\fR\'s directory is located\.
|
||||
@ -1418,7 +1418,7 @@ Treat all named arguments as formulae\.
|
||||
Treat all named arguments as casks\.
|
||||
.
|
||||
.SS "\fBextract\fR [\fI\-\-version\fR\fB=\fR] [\fI\-\-force\fR] \fIformula\fR \fItap\fR"
|
||||
Look through repository history to find the most recent version of \fIformula\fR and create a copy in \fItap\fR\fB/Formula/\fR\fIformula\fR\fB@\fR\fIversion\fR\fB\.rb\fR\. If the tap is not installed yet, attempt to install/clone the tap before continuing\. To extract a formula from a tap that is not \fBhomebrew/core\fR use its fully\-qualified form of \fIuser\fR\fB/\fR\fIrepo\fR\fB/\fR\fIformula\fR\.
|
||||
Look through repository history to find the most recent version of \fIformula\fR and create a copy in \fItap\fR\. Specifically, the command will create the new formula file at \fItap\fR\fB/Formula/\fR\fIformula\fR\fB@\fR\fIversion\fR\fB\.rb\fR\. If the tap is not installed yet, attempt to install/clone the tap before continuing\. To extract a formula from a tap that is not \fBhomebrew/core\fR use its fully\-qualified form of \fIuser\fR\fB/\fR\fIrepo\fR\fB/\fR\fIformula\fR\.
|
||||
.
|
||||
.TP
|
||||
\fB\-\-version\fR
|
||||
@ -1680,7 +1680,7 @@ Upload to the specified Bintray organisation (default: \fBhomebrew\fR)\.
|
||||
Use the specified \fIURL\fR as the root of the bottle\'s URL instead of Homebrew\'s default\.
|
||||
.
|
||||
.SS "\fBprof\fR [\fI\-\-stackprof\fR] [\fIcommand\fR \.\.\.]"
|
||||
Run Homebrew with a Ruby profiler, e\.g\. \fBbrew prof readall\fR\.
|
||||
Run Homebrew with a Ruby profiler\. For example, \fBbrew prof readall\fR\.
|
||||
.
|
||||
.TP
|
||||
\fB\-\-stackprof\fR
|
||||
@ -1717,7 +1717,7 @@ Print as a Markdown list\.
|
||||
Installs, configures and runs Homebrew\'s \fBrubocop\fR\.
|
||||
.
|
||||
.SS "\fBruby\fR [\fIoptions\fR] (\fB\-e\fR \fItext\fR|\fIfile\fR)"
|
||||
Run a Ruby instance with Homebrew\'s libraries loaded, e\.g\. \fBbrew ruby \-e "puts :gcc\.f\.deps"\fR or \fBbrew ruby script\.rb\fR\.
|
||||
Run a Ruby instance with Homebrew\'s libraries loaded\. For example, \fBbrew ruby \-e "puts :gcc\.f\.deps"\fR or \fBbrew ruby script\.rb\fR\.
|
||||
.
|
||||
.TP
|
||||
\fB\-r\fR
|
||||
@ -1728,7 +1728,7 @@ Load a library using \fBrequire\fR\.
|
||||
Execute the given text string as a script\.
|
||||
.
|
||||
.SS "\fBsh\fR [\fI\-\-env\fR\fB=\fR] [\fI\-\-cmd\fR\fB=\fR] [\fIfile\fR]"
|
||||
Homebrew build environment that uses years\-battle\-hardened build logic to help your \fB\./configure && make && make install\fR and even your \fBgem install\fR succeed\. Especially handy if you run Homebrew in an Xcode\-only configuration since it adds tools like \fBmake\fR to your \fBPATH\fR which build systems would not find otherwise\.
|
||||
Enter an interactive shell for Homebrew\'s build environment\. Use years\-battle\-hardened build logic to help your \fB\./configure && make && make install\fR and even your \fBgem install\fR succeed\. Especially handy if you run Homebrew in an Xcode\-only configuration since it adds tools like \fBmake\fR to your \fBPATH\fR which build systems would not find otherwise\.
|
||||
.
|
||||
.TP
|
||||
\fB\-\-env\fR
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user