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