Merge pull request #11510 from Rylan12/add-hidden-option-to-parser

cli/parser: allow options to be hidden
This commit is contained in:
Mike McQuaid 2021-06-09 09:36:32 +01:00 committed by GitHub
commit ed0ed9f0bf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 49 additions and 25 deletions

View File

@ -10,6 +10,7 @@ require "utils/tty"
COMMAND_DESC_WIDTH = 80 COMMAND_DESC_WIDTH = 80
OPTION_DESC_WIDTH = 43 OPTION_DESC_WIDTH = 43
HIDDEN_DESC_PLACEHOLDER = "@@HIDDEN@@"
module Homebrew module Homebrew
module CLI module CLI
@ -148,13 +149,13 @@ module Homebrew
end end
def switch(*names, description: nil, replacement: nil, env: nil, required_for: nil, depends_on: nil, def switch(*names, description: nil, replacement: nil, env: nil, required_for: nil, depends_on: nil,
method: :on) method: :on, hidden: false)
global_switch = names.first.is_a?(Symbol) global_switch = names.first.is_a?(Symbol)
return if global_switch return if global_switch
description = option_to_description(*names) if description.nil? description = option_description(description, *names, hidden: hidden)
if replacement.nil? if replacement.nil?
process_option(*names, description, type: :switch) process_option(*names, description, type: :switch, hidden: hidden)
else else
description += " (disabled#{"; replaced by #{replacement}" if replacement.present?})" description += " (disabled#{"; replaced by #{replacement}" if replacement.present?})"
end end
@ -198,10 +199,10 @@ module Homebrew
@parser.banner @parser.banner
end end
def comma_array(name, description: nil) def comma_array(name, description: nil, hidden: false)
name = name.chomp "=" name = name.chomp "="
description = option_to_description(name) if description.nil? description = option_description(description, name, hidden: hidden)
process_option(name, description, type: :comma_array) process_option(name, description, type: :comma_array, hidden: hidden)
@parser.on(name, OptionParser::REQUIRED_ARGUMENT, Array, *wrap_option_desc(description)) do |list| @parser.on(name, OptionParser::REQUIRED_ARGUMENT, Array, *wrap_option_desc(description)) do |list|
@args[option_to_name(name)] = list @args[option_to_name(name)] = list
end end
@ -215,7 +216,7 @@ module Homebrew
[OptionParser::OPTIONAL_ARGUMENT, :optional_flag] [OptionParser::OPTIONAL_ARGUMENT, :optional_flag]
end end
names.map! { |name| name.chomp "=" } names.map! { |name| name.chomp "=" }
description = option_to_description(*names) if description.nil? description = option_description(description, *names, hidden: hidden)
if replacement.nil? if replacement.nil?
process_option(*names, description, type: flag_type, hidden: hidden) process_option(*names, description, type: flag_type, hidden: hidden)
else else
@ -255,6 +256,13 @@ module Homebrew
names.map { |name| name.to_s.sub(/\A--?/, "").tr("-", " ") }.max names.map { |name| name.to_s.sub(/\A--?/, "").tr("-", " ") }.max
end end
def option_description(description, *names, hidden: false)
return HIDDEN_DESC_PLACEHOLDER if hidden
return description if description.present?
option_to_description(*names)
end
def parse_remaining(argv, ignore_invalid_options: false) def parse_remaining(argv, ignore_invalid_options: false)
i = 0 i = 0
remaining = [] remaining = []
@ -347,6 +355,7 @@ module Homebrew
def generate_help_text def generate_help_text
Formatter.wrap(@parser.to_s, COMMAND_DESC_WIDTH) Formatter.wrap(@parser.to_s, COMMAND_DESC_WIDTH)
.gsub(/\n.*?@@HIDDEN@@.*?(?=\n)/, "")
.sub(/^/, "#{Tty.bold}Usage: brew#{Tty.reset} ") .sub(/^/, "#{Tty.bold}Usage: brew#{Tty.reset} ")
.gsub(/`(.*?)`/m, "#{Tty.bold}\\1#{Tty.reset}") .gsub(/`(.*?)`/m, "#{Tty.bold}\\1#{Tty.reset}")
.gsub(%r{<([^\s]+?://[^\s]+?)>}) { |url| Formatter.url(url) } .gsub(%r{<([^\s]+?://[^\s]+?)>}) { |url| Formatter.url(url) }
@ -597,7 +606,7 @@ module Homebrew
def process_option(*args, type:, hidden: false) def process_option(*args, type:, hidden: false)
option, = @parser.make_switch(args) option, = @parser.make_switch(args)
@processed_options.reject! { |existing| existing.second == option.long.first } if option.long.first.present? @processed_options.reject! { |existing| existing.second == option.long.first } if option.long.first.present?
@processed_options << [option.short.first, option.long.first, option.arg, option.desc.first] @processed_options << [option.short.first, option.long.first, option.arg, option.desc.first, hidden]
if type == :switch if type == :switch
disable_switch(*args) disable_switch(*args)
@ -607,6 +616,7 @@ module Homebrew
end end
end end
return if hidden
return if self.class.global_options.include? [option.short.first, option.long.first, option.desc.first] return if self.class.global_options.include? [option.short.first, option.long.first, option.desc.first]
@non_global_processed_options << [option.long.first || option.short.first, type] @non_global_processed_options << [option.long.first || option.short.first, type]

View File

@ -52,7 +52,8 @@ module Homebrew
"JSON output: <https://docs.brew.sh/Querying-Brew>" "JSON output: <https://docs.brew.sh/Querying-Brew>"
switch "--bottle", switch "--bottle",
depends_on: "--json", depends_on: "--json",
description: "Output information about the bottles for <formula> and its dependencies." description: "Output information about the bottles for <formula> and its dependencies.",
hidden: true
switch "--installed", switch "--installed",
depends_on: "--json", depends_on: "--json",
description: "Print JSON of formulae that are currently installed." description: "Print JSON of formulae that are currently installed."

View File

@ -176,9 +176,11 @@ module Commands
return if path.blank? return if path.blank?
if (cmd_parser = Homebrew::CLI::Parser.from_cmd_path(path)) if (cmd_parser = Homebrew::CLI::Parser.from_cmd_path(path))
cmd_parser.processed_options.map do |short, long, _, desc| cmd_parser.processed_options.map do |short, long, _, desc, hidden|
next if hidden
[long || short, desc] [long || short, desc]
end end.compact
else else
options = [] options = []
comment_lines = path.read.lines.grep(/^#:/) comment_lines = path.read.lines.grep(/^#:/)

View File

@ -172,7 +172,9 @@ module Homebrew
def cmd_parser_manpage_lines(cmd_parser) def cmd_parser_manpage_lines(cmd_parser)
lines = [format_usage_banner(cmd_parser.usage_banner_text)] lines = [format_usage_banner(cmd_parser.usage_banner_text)]
lines += cmd_parser.processed_options.map do |short, long, _, desc| lines += cmd_parser.processed_options.map do |short, long, _, desc, hidden|
next if hidden
if long.present? if long.present?
next if Homebrew::CLI::Parser.global_options.include?([short, long, desc]) next if Homebrew::CLI::Parser.global_options.include?([short, long, desc])
next if Homebrew::CLI::Parser.global_cask_options.any? do |_, option, description:, **| next if Homebrew::CLI::Parser.global_cask_options.any? do |_, option, description:, **|
@ -181,7 +183,7 @@ module Homebrew
end end
generate_option_doc(short, long, desc) generate_option_doc(short, long, desc)
end.reject(&:blank?) end.compact
lines lines
end end

View File

@ -9,6 +9,7 @@ describe Homebrew::CLI::Parser do
described_class.new do described_class.new do
switch "--more-verbose", description: "Flag for higher verbosity" switch "--more-verbose", description: "Flag for higher verbosity"
switch "--pry", env: :pry switch "--pry", env: :pry
switch "--hidden", hidden: true
end end
} }
@ -98,6 +99,11 @@ describe Homebrew::CLI::Parser do
expect(args.more_verbose?).to be false expect(args.more_verbose?).to be false
end end
it "sets the correct value for a hidden switch" do
args = parser.parse([])
expect(args.hidden?).to be false
end
it "raises an exception and outputs help text when an invalid option is passed" do it "raises an exception and outputs help text when an invalid option is passed" do
expect { parser.parse(["--random"]) }.to raise_error(OptionParser::InvalidOption, /--random/) expect { parser.parse(["--random"]) }.to raise_error(OptionParser::InvalidOption, /--random/)
.and output(/Usage: brew/).to_stderr .and output(/Usage: brew/).to_stderr
@ -114,6 +120,8 @@ describe Homebrew::CLI::Parser do
described_class.new do described_class.new do
flag "--filename=", description: "Name of the file" flag "--filename=", description: "Name of the file"
comma_array "--files", description: "Comma separated filenames" comma_array "--files", description: "Comma separated filenames"
flag "--hidden=", hidden: true
comma_array "--hidden-array", hidden: true
end end
} }
@ -130,6 +138,12 @@ describe Homebrew::CLI::Parser do
args = parser.parse(["--files=random1.txt,random2.txt"]) args = parser.parse(["--files=random1.txt,random2.txt"])
expect(args.files).to eq %w[random1.txt random2.txt] expect(args.files).to eq %w[random1.txt random2.txt]
end end
it "sets the correct value for hidden flags" do
args = parser.parse(["--hidden=foo", "--hidden-array=bar,baz"])
expect(args.hidden).to eq "foo"
expect(args.hidden_array).to eq %w[bar baz]
end
end end
describe "test short flag options" do describe "test short flag options" do
@ -361,6 +375,13 @@ describe Homebrew::CLI::Parser do
expect(parser.generate_help_text).to match(/\[--foo=\]/) expect(parser.generate_help_text).to match(/\[--foo=\]/)
end end
it "does not include hidden options" do
parser = described_class.new do
switch "--foo", hidden: true
end
expect(parser.generate_help_text).not_to match(/\[--foo\]/)
end
it "doesn't include `[options]` if non non-global options are available" do it "doesn't include `[options]` if non non-global options are available" do
parser = described_class.new parser = described_class.new
expect(parser.generate_help_text).not_to match(/\[options\]/) expect(parser.generate_help_text).not_to match(/\[options\]/)

View File

@ -298,7 +298,6 @@ _brew_abv() {
__brewcomp " __brewcomp "
--all --all
--analytics --analytics
--bottle
--cask --cask
--category --category
--days --days
@ -996,7 +995,6 @@ _brew_info() {
__brewcomp " __brewcomp "
--all --all
--analytics --analytics
--bottle
--cask --cask
--category --category
--days --days

View File

@ -293,7 +293,6 @@ __fish_brew_complete_arg '-S' -l verbose -d 'Make some output more verbose'
__fish_brew_complete_cmd 'abv' 'Display brief statistics for your Homebrew installation' __fish_brew_complete_cmd 'abv' 'Display brief statistics for your Homebrew installation'
__fish_brew_complete_arg 'abv' -l all -d 'Print JSON of all available formulae' __fish_brew_complete_arg 'abv' -l all -d 'Print JSON of all available formulae'
__fish_brew_complete_arg 'abv' -l analytics -d 'List global Homebrew analytics data or, if specified, installation and build error data for formula (provided neither `HOMEBREW_NO_ANALYTICS` nor `HOMEBREW_NO_GITHUB_API` are set)' __fish_brew_complete_arg 'abv' -l analytics -d 'List global Homebrew analytics data or, if specified, installation and build error data for formula (provided neither `HOMEBREW_NO_ANALYTICS` nor `HOMEBREW_NO_GITHUB_API` are set)'
__fish_brew_complete_arg 'abv' -l bottle -d 'Output information about the bottles for formula and its dependencies'
__fish_brew_complete_arg 'abv' -l cask -d 'Treat all named arguments as casks' __fish_brew_complete_arg 'abv' -l cask -d 'Treat all named arguments as casks'
__fish_brew_complete_arg 'abv' -l category -d 'Which type of analytics data to retrieve. The value for category must be `install`, `install-on-request` or `build-error`; `cask-install` or `os-version` may be specified if formula is not. The default is `install`' __fish_brew_complete_arg 'abv' -l category -d 'Which type of analytics data to retrieve. The value for category must be `install`, `install-on-request` or `build-error`; `cask-install` or `os-version` may be specified if formula is not. The default is `install`'
__fish_brew_complete_arg 'abv' -l days -d 'How many days of analytics data to retrieve. The value for days must be `30`, `90` or `365`. The default is `30`' __fish_brew_complete_arg 'abv' -l days -d 'How many days of analytics data to retrieve. The value for days must be `30`, `90` or `365`. The default is `30`'
@ -716,7 +715,6 @@ __fish_brew_complete_arg 'homepage; and not __fish_seen_argument -l formula -l f
__fish_brew_complete_cmd 'info' 'Display brief statistics for your Homebrew installation' __fish_brew_complete_cmd 'info' 'Display brief statistics for your Homebrew installation'
__fish_brew_complete_arg 'info' -l all -d 'Print JSON of all available formulae' __fish_brew_complete_arg 'info' -l all -d 'Print JSON of all available formulae'
__fish_brew_complete_arg 'info' -l analytics -d 'List global Homebrew analytics data or, if specified, installation and build error data for formula (provided neither `HOMEBREW_NO_ANALYTICS` nor `HOMEBREW_NO_GITHUB_API` are set)' __fish_brew_complete_arg 'info' -l analytics -d 'List global Homebrew analytics data or, if specified, installation and build error data for formula (provided neither `HOMEBREW_NO_ANALYTICS` nor `HOMEBREW_NO_GITHUB_API` are set)'
__fish_brew_complete_arg 'info' -l bottle -d 'Output information about the bottles for formula and its dependencies'
__fish_brew_complete_arg 'info' -l cask -d 'Treat all named arguments as casks' __fish_brew_complete_arg 'info' -l cask -d 'Treat all named arguments as casks'
__fish_brew_complete_arg 'info' -l category -d 'Which type of analytics data to retrieve. The value for category must be `install`, `install-on-request` or `build-error`; `cask-install` or `os-version` may be specified if formula is not. The default is `install`' __fish_brew_complete_arg 'info' -l category -d 'Which type of analytics data to retrieve. The value for category must be `install`, `install-on-request` or `build-error`; `cask-install` or `os-version` may be specified if formula is not. The default is `install`'
__fish_brew_complete_arg 'info' -l days -d 'How many days of analytics data to retrieve. The value for days must be `30`, `90` or `365`. The default is `30`' __fish_brew_complete_arg 'info' -l days -d 'How many days of analytics data to retrieve. The value for days must be `30`, `90` or `365`. The default is `30`'

View File

@ -372,7 +372,6 @@ _brew_abv() {
_arguments \ _arguments \
'(--installed)--all[Print JSON of all available formulae]' \ '(--installed)--all[Print JSON of all available formulae]' \
'(--bottle)--analytics[List global Homebrew analytics data or, if specified, installation and build error data for formula (provided neither `HOMEBREW_NO_ANALYTICS` nor `HOMEBREW_NO_GITHUB_API` are set)]' \ '(--bottle)--analytics[List global Homebrew analytics data or, if specified, installation and build error data for formula (provided neither `HOMEBREW_NO_ANALYTICS` nor `HOMEBREW_NO_GITHUB_API` are set)]' \
'(--cask --analytics --github)--bottle[Output information about the bottles for formula and its dependencies]' \
'--category[Which type of analytics data to retrieve. The value for category must be `install`, `install-on-request` or `build-error`; `cask-install` or `os-version` may be specified if formula is not. The default is `install`]' \ '--category[Which type of analytics data to retrieve. The value for category must be `install`, `install-on-request` or `build-error`; `cask-install` or `os-version` may be specified if formula is not. The default is `install`]' \
'--days[How many days of analytics data to retrieve. The value for days must be `30`, `90` or `365`. The default is `30`]' \ '--days[How many days of analytics data to retrieve. The value for days must be `30`, `90` or `365`. The default is `30`]' \
'--debug[Display any debugging information]' \ '--debug[Display any debugging information]' \
@ -892,7 +891,6 @@ _brew_info() {
_arguments \ _arguments \
'(--installed)--all[Print JSON of all available formulae]' \ '(--installed)--all[Print JSON of all available formulae]' \
'(--bottle)--analytics[List global Homebrew analytics data or, if specified, installation and build error data for formula (provided neither `HOMEBREW_NO_ANALYTICS` nor `HOMEBREW_NO_GITHUB_API` are set)]' \ '(--bottle)--analytics[List global Homebrew analytics data or, if specified, installation and build error data for formula (provided neither `HOMEBREW_NO_ANALYTICS` nor `HOMEBREW_NO_GITHUB_API` are set)]' \
'(--cask --analytics --github)--bottle[Output information about the bottles for formula and its dependencies]' \
'--category[Which type of analytics data to retrieve. The value for category must be `install`, `install-on-request` or `build-error`; `cask-install` or `os-version` may be specified if formula is not. The default is `install`]' \ '--category[Which type of analytics data to retrieve. The value for category must be `install`, `install-on-request` or `build-error`; `cask-install` or `os-version` may be specified if formula is not. The default is `install`]' \
'--days[How many days of analytics data to retrieve. The value for days must be `30`, `90` or `365`. The default is `30`]' \ '--days[How many days of analytics data to retrieve. The value for days must be `30`, `90` or `365`. The default is `30`]' \
'--debug[Display any debugging information]' \ '--debug[Display any debugging information]' \

View File

@ -267,8 +267,6 @@ If a *`formula`* or *`cask`* is provided, show summary of information about it.
Open the GitHub source page for *`formula`* in a browser. To view formula history locally: `brew log -p` *`formula`* Open the GitHub source page for *`formula`* in a browser. To view formula history locally: `brew log -p` *`formula`*
* `--json`: * `--json`:
Print a JSON representation. Currently the default value for *`version`* is `v1` for *`formula`*. For *`formula`* and *`cask`* use `v2`. See the docs for examples of using the JSON output: <https://docs.brew.sh/Querying-Brew> Print a JSON representation. Currently the default value for *`version`* is `v1` for *`formula`*. For *`formula`* and *`cask`* use `v2`. See the docs for examples of using the JSON output: <https://docs.brew.sh/Querying-Brew>
* `--bottle`:
Output information about the bottles for *`formula`* and its dependencies.
* `--installed`: * `--installed`:
Print JSON of formulae that are currently installed. Print JSON of formulae that are currently installed.
* `--all`: * `--all`:

View File

@ -343,10 +343,6 @@ Open the GitHub source page for \fIformula\fR in a browser\. To view formula his
Print a JSON representation\. Currently the default value for \fIversion\fR is \fBv1\fR for \fIformula\fR\. For \fIformula\fR and \fIcask\fR use \fBv2\fR\. See the docs for examples of using the JSON output: \fIhttps://docs\.brew\.sh/Querying\-Brew\fR Print a JSON representation\. Currently the default value for \fIversion\fR is \fBv1\fR for \fIformula\fR\. For \fIformula\fR and \fIcask\fR use \fBv2\fR\. See the docs for examples of using the JSON output: \fIhttps://docs\.brew\.sh/Querying\-Brew\fR
. .
.TP .TP
\fB\-\-bottle\fR
Output information about the bottles for \fIformula\fR and its dependencies\.
.
.TP
\fB\-\-installed\fR \fB\-\-installed\fR
Print JSON of formulae that are currently installed\. Print JSON of formulae that are currently installed\.
. .