Merge pull request #10403 from Rylan12/zsh-completions

Generate zsh completions automatically
This commit is contained in:
Mike McQuaid 2021-01-26 10:19:59 +00:00 committed by GitHub
commit 00fab0294b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 1935 additions and 792 deletions

View File

@ -183,7 +183,9 @@ module Homebrew
Homebrew::EnvConfig.try(:"#{env}?") Homebrew::EnvConfig.try(:"#{env}?")
end end
def description(text) def description(text = nil)
return @description if text.blank?
@description = text.chomp @description = text.chomp
end end

View File

@ -12,7 +12,7 @@ module Homebrew
def __repository_args def __repository_args
Homebrew::CLI::Parser.new do Homebrew::CLI::Parser.new do
description <<~EOS 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. If <user>`/`<repo> are provided, display where tap <user>`/`<repo>'s directory is located.
EOS EOS

View File

@ -21,8 +21,8 @@ module Homebrew
def uses_args def uses_args
Homebrew::CLI::Parser.new do Homebrew::CLI::Parser.new do
description <<~EOS description <<~EOS
Show formulae and casks that specify <formula> as a dependency (i.e. show dependents 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 <formula>. When given multiple formula arguments, show the intersection
of formulae that use <formula>. By default, `uses` shows all formulae and casks that 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. specify <formula> as a required or recommended dependency for their stable builds.
EOS EOS

View File

@ -201,8 +201,10 @@ module Commands
cmd.start_with?("cask ") || Homebrew::Completions::COMPLETIONS_EXCLUSION_LIST.include?(cmd) cmd.start_with?("cask ") || Homebrew::Completions::COMPLETIONS_EXCLUSION_LIST.include?(cmd)
end end
file = HOMEBREW_CACHE/"all_commands_list.txt" all_commands_file = HOMEBREW_CACHE/"all_commands_list.txt"
file.atomic_write("#{cmds.sort.join("\n")}\n") 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 end
def command_options(command) def command_options(command)
@ -228,6 +230,30 @@ module Commands
end end
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) def named_args_type(command)
path = self.path(command) path = self.path(command)
return if path.blank? return if path.blank?

View File

@ -38,6 +38,20 @@ module Homebrew
file: "__brew_complete_files", file: "__brew_complete_files",
}.freeze }.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 } sig { void }
def link! def link!
Settings.write :linkcompletions, true Settings.write :linkcompletions, true
@ -93,7 +107,10 @@ module Homebrew
def update_shell_completions! def update_shell_completions!
commands = Commands.commands(external: false, aliases: true).sort 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/"bash/brew").atomic_write generate_bash_completion_file(commands)
(COMPLETIONS_DIR/"zsh/_brew").atomic_write generate_zsh_completion_file(commands)
end end
sig { params(command: String).returns(T::Boolean) } sig { params(command: String).returns(T::Boolean) }
@ -103,21 +120,27 @@ module Homebrew
command_options(command).any? command_options(command).any?
end 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) def command_options(command)
options = [] options = {}
Commands.command_options(command)&.each do |option| Commands.command_options(command)&.each do |option|
next if option.blank? next if option.blank?
name = option.first name = option.first
desc = option.second
if name.start_with? "--[no-]" if name.start_with? "--[no-]"
options << name.remove("[no-]") options[name.remove("[no-]")] = desc
options << name.sub("[no-]", "no-") options[name.sub("[no-]", "no-")] = desc
else else
options << name options[name] = desc
end end
end&.compact end
options.sort options
end end
sig { params(command: String).returns(T.nilable(String)) } sig { params(command: String).returns(T.nilable(String)) }
@ -143,7 +166,7 @@ module Homebrew
case "$cur" in case "$cur" in
-*) -*)
__brewcomp " __brewcomp "
#{command_options(command).join("\n ")} #{command_options(command).keys.sort.join("\n ")}
" "
return return
;; ;;
@ -152,7 +175,7 @@ module Homebrew
COMPLETION COMPLETION
end 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) def generate_bash_completion_file(commands)
variables = OpenStruct.new variables = OpenStruct.new
@ -168,5 +191,62 @@ module Homebrew
ERB.new((TEMPLATE_DIR/"bash.erb").read, trim_mode: ">").result(variables.instance_eval { binding }) ERB.new((TEMPLATE_DIR/"bash.erb").read, trim_mode: ">").result(variables.instance_eval { binding })
end 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
end end

View 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 "$@"

View File

@ -86,7 +86,8 @@ module Homebrew
usage_banner "`extract` [<--version>`=`] [<--force>] <formula> <tap>" usage_banner "`extract` [<--version>`=`] [<--force>] <formula> <tap>"
description <<~EOS description <<~EOS
Look through repository history to find the most recent version of <formula> and 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 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 a formula from a tap that is not `homebrew/core` use its fully-qualified form of
<user>`/`<repo>`/`<formula>. <user>`/`<repo>`/`<formula>.

View File

@ -12,7 +12,7 @@ module Homebrew
def prof_args def prof_args
Homebrew::CLI::Parser.new do Homebrew::CLI::Parser.new do
description <<~EOS 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 EOS
switch "--stackprof", switch "--stackprof",
description: "Use `stackprof` instead of `ruby-prof` (the default)." description: "Use `stackprof` instead of `ruby-prof` (the default)."

View File

@ -13,7 +13,7 @@ module Homebrew
Homebrew::CLI::Parser.new do Homebrew::CLI::Parser.new do
usage_banner "`ruby` [<options>] (`-e` <text>|<file>)" usage_banner "`ruby` [<options>] (`-e` <text>|<file>)"
description <<~EOS 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`. `brew ruby -e "puts :gcc.f.deps"` or `brew ruby script.rb`.
EOS EOS
flag "-r=", flag "-r=",

View File

@ -14,7 +14,7 @@ module Homebrew
def sh_args def sh_args
Homebrew::CLI::Parser.new do Homebrew::CLI::Parser.new do
description <<~EOS 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` build logic to help your `./configure && make && make install`
and even your `gem install` succeed. Especially handy if you run Homebrew 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` in an Xcode-only configuration since it adds tools like `make` to your `PATH`

View File

@ -153,37 +153,67 @@ describe Homebrew::Completions do
end end
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 describe ".command_options" do
it "returns an array of options for a ruby command" 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 expect(described_class.command_options("missing")).to eq expected_options
end end
it "returns an array of options for a shell command" do 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 expect(described_class.command_options("update")).to eq expected_options
end end
it "handles --[no]- options correctly" do it "handles --[no]- options correctly" do
options = described_class.command_options("audit") options = described_class.command_options("audit")
expect(options.include?("--appcast")).to eq true expect(options.key?("--appcast")).to eq true
expect(options.include?("--no-appcast")).to eq true expect(options.key?("--no-appcast")).to eq true
expect(options["--appcast"] == options["--no-appcast"]).to eq true
end end
it "return an empty array if command is not found" do 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 end
it "return an empty array for a command with no options" do 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 end
it "will list global options only once if overriden" do it "will override global options with local descriptions" do
count = 0 options = described_class.command_options("upgrade")
described_class.command_options("upgrade").each do |opt| expect(options["--verbose"]).to eq "Print the verification and postinstall steps."
count += 1 if opt == "--verbose"
end
expect(count).to eq 1
end end
end end
@ -208,16 +238,46 @@ describe Homebrew::Completions do
it "returns appropriate completion for a ruby command" do it "returns appropriate completion for a ruby command" do
completion = described_class.generate_bash_subcommand_completion("missing") completion = described_class.generate_bash_subcommand_completion("missing")
expect(completion).to match(/^_brew_missing\(\) {/) expect(completion).to eq <<~COMPLETION
expect(completion).to match(/__brewcomp "\n +--debug\n +--help\n +--hide\n +--quiet\n +--verbose/s) _brew_missing() {
expect(completion).to match(/__brew_complete_formulae\n}$/) local cur="${COMP_WORDS[COMP_CWORD]}"
case "$cur" in
-*)
__brewcomp "
--debug
--help
--hide
--quiet
--verbose
"
return
;;
esac
__brew_complete_formulae
}
COMPLETION
end end
it "returns appropriate completion for a shell command" do it "returns appropriate completion for a shell command" do
completion = described_class.generate_bash_subcommand_completion("update") 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 eq <<~COMPLETION
expect(completion).to match(/^_brew_update\(\) {/) _brew_update() {
expect(completion).to match(options_regex) local cur="${COMP_WORDS[COMP_CWORD]}"
case "$cur" in
-*)
__brewcomp "
--debug
--force
--help
--merge
--preinstall
--verbose
"
return
;;
esac
}
COMPLETION
end end
it "returns appropriate completion for a command with multiple named arg types" do 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$/) expect(file).to match(/^complete -o bashdefault -o default -F _brew brew$/)
end end
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
end end

File diff suppressed because it is too large Load Diff

View File

@ -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 "$@"

View File

@ -659,8 +659,8 @@ upgraded formulae or, every 30 days, for all formulae.
### `uses` [*`options`*] *`formula`* [...] ### `uses` [*`options`*] *`formula`* [...]
Show formulae and casks that specify *`formula`* as a dependency (i.e. show dependents 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 *`formula`*. When given multiple formula arguments, show the intersection
of formulae that use *`formula`*. By default, `uses` shows all formulae and casks that 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. specify *`formula`* as a required or recommended dependency for their stable builds.
@ -739,7 +739,7 @@ is or would be installed.
### `--repository`, `--repo` [*`tap`* ...] ### `--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. 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`* ### `extract` [*`--version`*`=`] [*`--force`*] *`formula`* *`tap`*
Look through repository history to find the most recent version of *`formula`* and 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 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 a formula from a tap that is not `homebrew/core` use its fully-qualified form of
*`user`*`/`*`repo`*`/`*`formula`*. *`user`*`/`*`repo`*`/`*`formula`*.
@ -1203,7 +1204,7 @@ Apply the bottle commit and publish bottles to Bintray or GitHub Releases.
### `prof` [*`--stackprof`*] [*`command`* ...] ### `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`: * `--stackprof`:
Use `stackprof` instead of `ruby-prof` (the default). Use `stackprof` instead of `ruby-prof` (the default).
@ -1243,7 +1244,7 @@ Installs, configures and runs Homebrew's `rubocop`.
### `ruby` [*`options`*] (`-e` *`text`*|*`file`*) ### `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`. `brew ruby -e "puts :gcc.f.deps"` or `brew ruby script.rb`.
* `-r`: * `-r`:
@ -1253,7 +1254,7 @@ Run a Ruby instance with Homebrew's libraries loaded, e.g.
### `sh` [*`--env`*`=`] [*`--cmd`*`=`] [*`file`*] ### `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` build logic to help your `./configure && make && make install`
and even your `gem install` succeed. Especially handy if you run Homebrew 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` in an Xcode-only configuration since it adds tools like `make` to your `PATH`

View File

@ -896,7 +896,7 @@ Skip installing cask dependencies\.
Also include casks with \fBauto_updates true\fR or \fBversion :latest\fR\. Also include casks with \fBauto_updates true\fR or \fBversion :latest\fR\.
. .
.SS "\fBuses\fR [\fIoptions\fR] \fIformula\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 .TP
\fB\-\-recursive\fR \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\. List files in Homebrew\'s prefix not installed by Homebrew\.
. .
.SS "\fB\-\-repository\fR, \fB\-\-repo\fR [\fItap\fR \.\.\.]" .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 .P
If \fIuser\fR\fB/\fR\fIrepo\fR are provided, display where tap \fIuser\fR\fB/\fR\fIrepo\fR\'s directory is located\. 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\. Treat all named arguments as casks\.
. .
.SS "\fBextract\fR [\fI\-\-version\fR\fB=\fR] [\fI\-\-force\fR] \fIformula\fR \fItap\fR" .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 .TP
\fB\-\-version\fR \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\. 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 \.\.\.]" .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 .TP
\fB\-\-stackprof\fR \fB\-\-stackprof\fR
@ -1717,7 +1717,7 @@ Print as a Markdown list\.
Installs, configures and runs Homebrew\'s \fBrubocop\fR\. Installs, configures and runs Homebrew\'s \fBrubocop\fR\.
. .
.SS "\fBruby\fR [\fIoptions\fR] (\fB\-e\fR \fItext\fR|\fIfile\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 .TP
\fB\-r\fR \fB\-r\fR
@ -1728,7 +1728,7 @@ Load a library using \fBrequire\fR\.
Execute the given text string as a script\. Execute the given text string as a script\.
. .
.SS "\fBsh\fR [\fI\-\-env\fR\fB=\fR] [\fI\-\-cmd\fR\fB=\fR] [\fIfile\fR]" .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 .TP
\fB\-\-env\fR \fB\-\-env\fR