Refactor handling of formula options in CLI::Parser.

This commit is contained in:
Markus Reiter 2020-07-31 17:37:36 +02:00
parent 05aada4333
commit be2d19fe07
6 changed files with 54 additions and 58 deletions

View File

@ -41,6 +41,7 @@ begin
empty_argv = ARGV.empty? empty_argv = ARGV.empty?
help_flag_list = %w[-h --help --usage -?] help_flag_list = %w[-h --help --usage -?]
help_flag = !ENV["HOMEBREW_HELP"].nil? help_flag = !ENV["HOMEBREW_HELP"].nil?
help_cmd_index = nil
cmd = nil cmd = nil
ARGV.each_with_index do |arg, i| ARGV.each_with_index do |arg, i|
@ -49,13 +50,16 @@ begin
if arg == "help" && !cmd if arg == "help" && !cmd
# Command-style help: `help <cmd>` is fine, but `<cmd> help` is not. # Command-style help: `help <cmd>` is fine, but `<cmd> help` is not.
help_flag = true help_flag = true
help_cmd_index = i
elsif !cmd && !help_flag_list.include?(arg) elsif !cmd && !help_flag_list.include?(arg)
cmd = ARGV.delete_at(i) cmd = ARGV.delete_at(i)
cmd = Commands::HOMEBREW_INTERNAL_COMMAND_ALIASES.fetch(cmd, cmd) cmd = Commands::HOMEBREW_INTERNAL_COMMAND_ALIASES.fetch(cmd, cmd)
end end
end end
Homebrew.args = Homebrew::CLI::Parser.new.parse(ignore_invalid_options: true) ARGV.delete_at(help_cmd_index) if help_cmd_index
Homebrew.args = Homebrew::CLI::Parser.new.parse(ARGV.dup.freeze, ignore_invalid_options: true)
path = PATH.new(ENV["PATH"]) path = PATH.new(ENV["PATH"])
homebrew_path = PATH.new(ENV["HOMEBREW_PATH"]) homebrew_path = PATH.new(ENV["HOMEBREW_PATH"])

View File

@ -10,32 +10,21 @@ module Homebrew
# undefine tap to allow --tap argument # undefine tap to allow --tap argument
undef tap undef tap
def initialize(argv = ARGV.dup.freeze, set_default_args: false) def initialize
super() super()
@processed_options = [] @processed_options = []
@options_only = args_options_only(argv) @options_only = []
@flags_only = args_flags_only(argv) @flags_only = []
# Can set these because they will be overwritten by freeze_named_args! # Can set these because they will be overwritten by freeze_named_args!
# (whereas other values below will only be overwritten if passed). # (whereas other values below will only be overwritten if passed).
self[:named_args] = argv.reject { |arg| arg.start_with?("-") } self[:named_args] = []
self[:remaining] = [] self[:remaining] = []
# Set values needed before Parser#parse has been run.
return unless set_default_args
self[:build_from_source?] = argv.include?("--build-from-source") || argv.include?("-s")
self[:build_bottle?] = argv.include?("--build-bottle")
self[:force_bottle?] = argv.include?("--force-bottle")
self[:HEAD?] = argv.include?("--HEAD")
self[:devel?] = argv.include?("--devel")
self[:universal?] = argv.include?("--universal")
end end
def freeze_remaining_args!(remaining_args) def freeze_remaining_args!(remaining_args)
self[:remaining] = remaining_args self[:remaining] = remaining_args.freeze
self[:remaining].freeze
end end
def freeze_named_args!(named_args) def freeze_named_args!(named_args)
@ -49,8 +38,7 @@ module Homebrew
@kegs = nil @kegs = nil
@kegs_casks = nil @kegs_casks = nil
self[:named_args] = named_args self[:named_args] = named_args.freeze
self[:named_args].freeze
end end
def freeze_processed_options!(processed_options) def freeze_processed_options!(processed_options)
@ -60,8 +48,8 @@ module Homebrew
@processed_options += processed_options @processed_options += processed_options
@processed_options.freeze @processed_options.freeze
@options_only = args_options_only(cli_args) @options_only = cli_args.select { |a| a.start_with?("-") }.freeze
@flags_only = args_flags_only(cli_args) @flags_only = cli_args.select { |a| a.start_with?("--") }.freeze
end end
def named def named
@ -221,16 +209,6 @@ module Homebrew
@cli_args.freeze @cli_args.freeze
end end
def args_options_only(args)
args.select { |arg| arg.start_with?("-") }
.freeze
end
def args_flags_only(args)
args.select { |arg| arg.start_with?("--") }
.freeze
end
def downcased_unique_named def downcased_unique_named
# Only lowercase names, not paths, bottle filenames or URLs # Only lowercase names, not paths, bottle filenames or URLs
named.map do |arg| named.map do |arg|

View File

@ -33,11 +33,10 @@ module Homebrew
] ]
end end
def initialize(argv = ARGV.dup.freeze, &block) def initialize(&block)
@parser = OptionParser.new @parser = OptionParser.new
@argv = argv @args = Homebrew::CLI::Args.new
@args = Homebrew::CLI::Args.new(@argv)
@constraints = [] @constraints = []
@conflicts = [] @conflicts = []
@ -47,6 +46,7 @@ module Homebrew
@min_named_args = nil @min_named_args = nil
@min_named_type = nil @min_named_type = nil
@hide_from_man_page = false @hide_from_man_page = false
@formula_options = false
self.class.global_options.each do |short, long, desc| self.class.global_options.each do |short, long, desc|
switch short, long, description: desc switch short, long, description: desc
@ -63,7 +63,7 @@ module Homebrew
# Disable default handling of `--help` switch. # Disable default handling of `--help` switch.
@parser.on_tail("-h", "--help", "Show this message.") do @parser.on_tail("-h", "--help", "Show this message.") do
raise OptionParser::InvalidOption # Handled in `brew.rb`.
end end
end end
@ -190,9 +190,31 @@ module Homebrew
[remaining, non_options] [remaining, non_options]
end end
def parse(argv = @argv, ignore_invalid_options: false) def parse(argv = ARGV.freeze, ignore_invalid_options: false)
raise "Arguments were already parsed!" if @args_parsed raise "Arguments were already parsed!" if @args_parsed
# If we accept formula options, parse once allowing invalid options
# so we can get the remaining list containing formula names.
if @formula_options
remaining, non_options = parse_remaining(argv, ignore_invalid_options: true)
argv = [*remaining, "--", *non_options]
formulae(argv).each do |f|
next if f.options.empty?
f.options.each do |o|
name = o.flag
description = "`#{f.name}`: #{o.description}"
if name.end_with? "="
flag name, description: description
else
switch name, description: description
end
end
end
end
remaining, non_options = parse_remaining(argv, ignore_invalid_options: ignore_invalid_options) remaining, non_options = parse_remaining(argv, ignore_invalid_options: ignore_invalid_options)
named_args = if ignore_invalid_options named_args = if ignore_invalid_options
@ -201,8 +223,8 @@ module Homebrew
remaining + non_options remaining + non_options
end end
check_constraint_violations check_constraint_violations unless ignore_invalid_options
check_named_args(named_args) check_named_args(named_args) unless ignore_invalid_options
@args.freeze_named_args!(named_args) @args.freeze_named_args!(named_args)
@args.freeze_remaining_args!(non_options.empty? ? remaining : [*remaining, "--", non_options]) @args.freeze_remaining_args!(non_options.empty? ? remaining : [*remaining, "--", non_options])
@args.freeze_processed_options!(@processed_options) @args.freeze_processed_options!(@processed_options)
@ -221,21 +243,7 @@ module Homebrew
end end
def formula_options def formula_options
formulae(@argv).each do |f| @formula_options = true
next if f.options.empty?
f.options.each do |o|
name = o.flag
description = "`#{f.name}`: #{o.description}"
if name.end_with? "="
flag name, description: description
else
switch name, description: description
end
end
end
rescue FormulaUnavailableError
[]
end end
def max_named(count) def max_named(count)
@ -385,9 +393,9 @@ module Homebrew
end end
def formulae(argv) def formulae(argv)
argv, named_argv = split_double_dash(argv) argv, non_options = split_double_dash(argv)
named_args = argv.reject { |arg| arg.start_with?("-") } + named_argv named_args = argv.reject { |arg| arg.start_with?("-") } + non_options
spec = if argv.include?("--HEAD") spec = if argv.include?("--HEAD")
:head :head
elsif argv.include?("--devel") elsif argv.include?("--devel")
@ -400,7 +408,11 @@ module Homebrew
named_args.map do |arg| named_args.map do |arg|
next if arg.match?(HOMEBREW_CASK_TAP_CASK_REGEX) next if arg.match?(HOMEBREW_CASK_TAP_CASK_REGEX)
Formulary.factory(arg, spec, flags: @args.flags_only) begin
Formulary.factory(arg, spec, flags: argv.select { |a| a.start_with?("--") })
rescue FormulaUnavailableError
nil
end
end.compact.uniq(&:name) end.compact.uniq(&:name)
end end
end end

View File

@ -34,7 +34,7 @@ module Homebrew
end end
def irb def irb
args = irb_args.parse args = irb_args.parse(ARGV.dup.freeze)
if args.examples? if args.examples?
puts "'v8'.f # => instance of the v8 formula" puts "'v8'.f # => instance of the v8 formula"

View File

@ -82,7 +82,7 @@ module Homebrew
end end
def args def args
@args ||= CLI::Args.new(set_default_args: true) @args ||= CLI::Args.new
end end
def messages def messages

View File

@ -95,6 +95,8 @@ module Homebrew
cmd_parser = CLI::Parser.from_cmd_path(path) cmd_parser = CLI::Parser.from_cmd_path(path)
return unless cmd_parser return unless cmd_parser
# Try parsing arguments here in order to show formula options in help output.
cmd_parser.parse(Homebrew.args.remaining, ignore_invalid_options: true)
cmd_parser.generate_help_text cmd_parser.generate_help_text
end end