lib/everyday-cli-utils/option.rb in everyday-cli-utils-1.4.0 vs lib/everyday-cli-utils/option.rb in everyday-cli-utils-1.5.0
- old
+ new
@@ -20,96 +20,276 @@
yield if block_given?
}
end
end
- module OptionUtil
- attr_reader :options, :opts
+ class OptionType
+ def initialize(default_value_block, value_determine_block, name_mod_block = nil, value_transform_block = nil)
+ @default_value_block = default_value_block
+ @value_determine_block = value_determine_block
+ @name_mod_block = name_mod_block
+ @value_transform_block = value_transform_block
+ end
- def option(opt_name, names, settings = {})
- @opts ||= OptionParser.new
- @options ||= {}
- @default_settings ||= {}
- settings[:toggle] = @default_settings[:toggle] unless settings.has_key?(:toggle) || !@default_settings.has_key?(:toggle)
- names << settings[:desc] if settings.has_key?(:desc)
- @options[opt_name] = false
- @opts.on(*names) {
- @options[opt_name] = !settings[:toggle] || !@options[opt_name]
- yield if block_given?
- }
+ def default_value(settings = {})
+ @default_value_block.call(settings)
end
- def option_with_param(opt_name, names, settings = {})
- @opts ||= OptionParser.new
- @options ||= {}
- @default_settings ||= {}
- settings[:append] = @default_settings[:append] unless settings.has_key?(:append) || !@default_settings.has_key?(:append)
- settings[:type] = @default_settings[:type] unless settings.has_key?(:type) || !@default_settings.has_key?(:type)
- names[0] << ' PARAM' unless names.any? { |v| v.include?(' ') }
- names << settings[:desc] if settings.has_key?(:desc)
- @options[opt_name] = settings[:append] ? [] : nil
- @opts.on(*names, settings[:type] || String) { |param|
- settings[:append] ? @options[opt_name] << param : @options[opt_name] = param
- yield if block_given?
+ def updated_value(current_value, new_value, settings = {})
+ new_value = @value_transform_block.call(new_value, settings) unless @value_transform_block.nil?
+ @value_determine_block.call(current_value, new_value, settings)
+ end
+
+ def mod_names(names, settings = {})
+ @name_mod_block.call(names, settings)
+ end
+ end
+
+ class OptionTypes
+ def self.def_type(type, default_value_block, value_determine_block, name_mod_block = nil, value_transform_block = nil)
+ @types ||= {}
+ @types[type] = OptionType.new(default_value_block, value_determine_block, name_mod_block, value_transform_block)
+ end
+
+ def self.default_value(type, settings = {})
+ @types ||= {}
+ @types.has_key?(type) ? @types[type].default_value(settings) : nil
+ end
+
+ def self.updated_value(type, current_value, new_value, settings = {})
+ @types ||= {}
+ @types.has_key?(type) ? @types[type].updated_value(current_value, new_value, settings) : current_value
+ end
+
+ def self.mod_names(type, names, settings = {})
+ @types ||= {}
+ @types.has_key?(type) ? @types[type].mod_names(names, settings) : names
+ end
+
+ def_type(:option,
+ ->(_) {
+ false
+ },
+ ->(current_value, new_value, settings) {
+ new_value ? (!settings[:toggle] || !current_value) : current_value
+ },
+ ->(names, settings) {
+ settings.has_key?(:desc) ? (names + [settings[:desc]]) : names
+ },
+ ->(new_value, _) {
+ !(!new_value)
+ })
+ def_type(:option_with_param,
+ ->(settings) {
+ settings[:append] ? [] : nil
+ },
+ ->(current_value, new_value, settings) {
+ settings[:append] ? (current_value + new_value) : new_value
+ },
+ ->(names, settings) {
+ names[0] << ' PARAM' unless names.any? { |v| v.include?(' ') }
+ names = settings.has_key?(:desc) ? (names + [settings[:desc]]) : names
+ settings.has_key?(:type) ? (names + [settings[:type]]) : names
+ },
+ ->(new_value, settings) {
+ new_value.is_a?(Array) ? (settings[:append] ? new_value : new_value[0]) : (settings[:append] ? [new_value] : new_value)
+ })
+ end
+
+ class OptionDef
+ attr_reader :value
+
+ def initialize(type, settings = {}, &block)
+ @type = type
+ @settings = settings
+ @block = block
+ @value = OptionTypes.default_value(type, settings)
+ @values = {}
+ end
+
+ def set(value)
+ @value = value
+ @values = {}
+ end
+
+ def update(value, layer)
+ @values[layer] = OptionTypes.default_value(@type, @settings) unless @values.has_key?(layer)
+ @values[layer] = OptionTypes.updated_value(@type, @values[layer], value, @settings)
+ end
+
+ def run
+ @block.call unless @block.nil? || !@block
+ end
+
+ def composite(*layers)
+ value = @value
+ layers.each { |layer| value = OptionTypes.updated_value(@type, value, @values[layer], @settings) if @values.has_key?(layer) }
+ value
+ end
+
+ def self.register(opts, options, type, opt_name, names, settings = {}, default_settings = {}, &block)
+ settings = settings.clone
+ default_settings.each { |v| settings[v[0]] = v[1] unless settings.has_key?(v[0]) }
+ opt = OptionDef.new(type, settings, &block)
+ options[opt_name] = opt
+ names = OptionTypes.mod_names(type, names, settings)
+ opts.on(*names) { |*args|
+ opt.update(args, :arg)
+ opt.run
}
end
+ end
+ class OptionList
+ attr_reader :opts
+ attr_accessor :default_settings, :help_str
+
+ def initialize
+ @options = {}
+ @default_settings = {}
+ @opts = OptionParser.new
+ @help_str = nil
+ end
+
+ def []=(opt_name, opt)
+ @options[opt_name] = opt
+ end
+
+ def set(opt_name, value)
+ @options[opt_name].set(value) if @options.has_key?(opt_name)
+ end
+
+ def update(opt_name, value, layer)
+ @options[opt_name].update(value, layer) if @options.has_key?(opt_name)
+ end
+
+ def register(type, opt_name, names, settings = {}, &block)
+ OptionDef.register(@opts, @options, type, opt_name, names, settings, @default_settings, &block)
+ end
+
+ def composite(*layers)
+ hash = {}
+ @options.each { |v| hash[v[0]] = v[1].composite(*layers) }
+ hash
+ end
+
+ def help
+ @help_str.nil? ? @opts.help : @help_str
+ end
+
+ def to_s
+ @help_str.nil? ? @opts.to_s : @help_str
+ end
+
+ def banner=(banner)
+ @opts.banner = banner
+ end
+
+ def parse!(argv = ARGV)
+ @opts.parse!(argv)
+ end
+ end
+
+ module OptionUtil
+ def option(opt_name, names, settings = {}, &block)
+ @options ||= OptionList.new
+ @options.register(:option, opt_name, names, settings, &block)
+ end
+
+ def option_with_param(opt_name, names, settings = {}, &block)
+ @options ||= OptionList.new
+ @options.register(:option_with_param, opt_name, names, settings, &block)
+ end
+
def defaults_option(file_path, names, settings = {})
- @opts ||= OptionParser.new
+ @options ||= OptionList.new
@set_defaults = false
@defaults_file = File.expand_path(file_path)
@exit_on_save = !settings.has_key?(:exit_on_save) || settings[:exit_on_save]
names << settings[:desc] if settings.has_key?(:desc)
- @opts.on(*names) { @set_defaults = true }
+ @options.opts.on(*names) { @set_defaults = true }
end
+ def global_defaults_option(file_path, names, settings = {})
+ @options ||= OptionList.new
+ @set_global_defaults = false
+ @global_defaults_file = File.expand_path(file_path)
+ @exit_on_global_save = !settings.has_key?(:exit_on_save) || settings[:exit_on_save]
+ names << settings[:desc] if settings.has_key?(:desc)
+ @options.opts.on(*names) { @set_global_defaults = true }
+ end
+
def help_option(names, settings = {})
- @opts ||= OptionParser.new
+ @options ||= OptionList.new
@display_help = false
@exit_on_print = !settings.has_key?(:exit_on_print) || settings[:exit_on_print]
names << settings[:desc] if settings.has_key?(:desc)
- @opts.on(*names) { @display_help = true }
+ @options.opts.on(*names) { @display_help = true }
end
def default_settings(settings = {})
- @default_settings = settings
+ @options ||= OptionList.new
+ @options.default_settings = settings
end
def default_options(opts = {})
- opts.each { |opt| @options[opt[0]] = opt[1] }
+ @options ||= OptionList.new
+ opts.each { |opt| @options.set(opt[0], opt[1]) }
end
+ def apply_options(layer, opts = {})
+ @options ||= OptionList.new
+ opts.each { |opt| @options.update(opt[0], opt[1], layer) }
+ end
+
def banner(banner)
- @opts ||= OptionParser.new
- @opts.banner = banner
+ @options ||= OptionList.new
+ @options.banner = banner
end
+ def opts
+ @options.opts
+ end
+
+ def options
+ @options.composite(:global, :local, :arg)
+ end
+
+ def option_list
+ @options
+ end
+
def help
- @opts ||= OptionParser.new
- @help_str ||= nil
- @help_str.nil? ? @opts.help : @help_str
+ @options ||= OptionList.new
+ @options.help
end
def to_s
- @opts ||= OptionParser.new
- @help_str ||= nil
- @help_str.nil? ? @opts.to_s : @help_str
+ @options ||= OptionList.new
+ @options.to_s
end
def help_str=(str)
- @help_str = str
+ @options.help_str = str
end
def parse!(argv = ARGV)
- @opts ||= OptionParser.new
- default_options YAML::load_file(@defaults_file) unless @defaults_file.nil? || !File.exist?(@defaults_file)
- @opts.parse!(argv)
+ @options ||= OptionList.new
+ apply_options :global, YAML::load_file(@global_defaults_file) unless @global_defaults_file.nil? || !File.exist?(@global_defaults_file)
+ apply_options :local, YAML::load_file(@defaults_file) unless @defaults_file.nil? || !File.exist?(@defaults_file)
+ @options.parse!(argv)
if @display_help
puts help
exit 0 if @exit_on_print
end
- if @set_defaults
- IO.write(@defaults_file, @options.to_yaml)
+ if @set_global_defaults
+ IO.write(@global_defaults_file, @options.composite(:global, :arg).to_yaml)
+ if @exit_on_global_save
+ puts 'Global defaults set'
+ exit 0
+ end
+ elsif @set_defaults
+ IO.write(@defaults_file, @options.composite(:local, :arg).to_yaml)
if @exit_on_save
puts 'Defaults set'
exit 0
end
end
\ No newline at end of file