command_builder 0.0.2 → 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/lib/command_builder/code_generator/code_generator.rb +88 -0
 - data/lib/command_builder/code_generator/command.rb +52 -0
 - data/lib/command_builder/code_generator/command_argument.rb +32 -0
 - data/lib/command_builder/code_generator/command_code_names.rb +80 -0
 - data/lib/command_builder/code_generator/command_definition.rb +26 -0
 - data/lib/command_builder/code_generator/fragment.rb +37 -0
 - data/lib/command_builder/code_generator/node.rb +67 -0
 - data/lib/command_builder/code_generator/node_code_generator.rb +101 -0
 - data/lib/command_builder/code_generator/node_code_names.rb +33 -0
 - data/lib/command_builder/code_generator/ruby_code_writer.rb +62 -0
 - data/lib/command_builder/code_generator/string_extensions.rb +34 -0
 - data/lib/command_builder/code_generator/version.rb +47 -0
 - data/lib/command_builder/code_generator.rb +1 -0
 - metadata +15 -2
 
| 
         @@ -0,0 +1,88 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'erb'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require_relative 'command_definition'
         
     | 
| 
      
 3 
     | 
    
         
            +
            require_relative 'command_code_names'
         
     | 
| 
      
 4 
     | 
    
         
            +
            require_relative 'ruby_code_writer'
         
     | 
| 
      
 5 
     | 
    
         
            +
            require_relative 'node_code_generator'
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
            module CommandBuilder
         
     | 
| 
      
 8 
     | 
    
         
            +
              module CodeGenerator
         
     | 
| 
      
 9 
     | 
    
         
            +
                class Generator
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                  def initialize(options={})
         
     | 
| 
      
 12 
     | 
    
         
            +
                    @definitions_dir = 'command_definitions'
         
     | 
| 
      
 13 
     | 
    
         
            +
                    @command_builders_dir = options[:command_builders_dir] || 'lib/command_builder'
         
     | 
| 
      
 14 
     | 
    
         
            +
                  end
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                  def execute
         
     | 
| 
      
 17 
     | 
    
         
            +
                    pattern = File.join @definitions_dir, '*.txt'
         
     | 
| 
      
 18 
     | 
    
         
            +
                    Dir[pattern].each { |f| process_definition f }
         
     | 
| 
      
 19 
     | 
    
         
            +
                  end
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
                  private
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                  def process_definition(definition_file)
         
     | 
| 
      
 24 
     | 
    
         
            +
                    puts "Processing: #{File.basename definition_file}"
         
     | 
| 
      
 25 
     | 
    
         
            +
                    d = CommandDefinition.new File.new(definition_file)
         
     | 
| 
      
 26 
     | 
    
         
            +
                    d.versions.each { |v| process_version d.command, v }
         
     | 
| 
      
 27 
     | 
    
         
            +
                  end
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
                  def process_version(command, version)
         
     | 
| 
      
 30 
     | 
    
         
            +
                    generate_command_module command, version
         
     | 
| 
      
 31 
     | 
    
         
            +
                    generate_version_module command, version
         
     | 
| 
      
 32 
     | 
    
         
            +
                  end
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                  def generate_command_module(command, version)
         
     | 
| 
      
 35 
     | 
    
         
            +
                    code_names = CommandCodeNames.new command, version
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
                    model = {
         
     | 
| 
      
 38 
     | 
    
         
            +
                        module_name: code_names.command_module_name,
         
     | 
| 
      
 39 
     | 
    
         
            +
                        factory_method_name: code_names.command_factory_method_name,
         
     | 
| 
      
 40 
     | 
    
         
            +
                        command_name: command.command_name
         
     | 
| 
      
 41 
     | 
    
         
            +
                    }
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
                    template_file = File.expand_path(File.dirname(__FILE__) + '/templates/command_module.erb')
         
     | 
| 
      
 44 
     | 
    
         
            +
                    result_file = File.join @command_builders_dir, "#{code_names.command_factory_method_name}.rb"
         
     | 
| 
      
 45 
     | 
    
         
            +
                    sub_template model, template_file, result_file
         
     | 
| 
      
 46 
     | 
    
         
            +
                  end
         
     | 
| 
      
 47 
     | 
    
         
            +
             
     | 
| 
      
 48 
     | 
    
         
            +
                  def generate_version_module(command, version)
         
     | 
| 
      
 49 
     | 
    
         
            +
                    code_names = CommandCodeNames.new command, version
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
                    model = {
         
     | 
| 
      
 52 
     | 
    
         
            +
                        command_factory_method_signature: code_names.command_factory_method_signature,
         
     | 
| 
      
 53 
     | 
    
         
            +
                        version_factory_method_signature: code_names.version_factory_method_signature,
         
     | 
| 
      
 54 
     | 
    
         
            +
                        create_method_signature: code_names.create_method_signature,
         
     | 
| 
      
 55 
     | 
    
         
            +
                        create_method_call: code_names.create_method_call,
         
     | 
| 
      
 56 
     | 
    
         
            +
                        command_initializer_call: code_names.command_initializer_call,
         
     | 
| 
      
 57 
     | 
    
         
            +
                        command_module_name: code_names.command_module_name,
         
     | 
| 
      
 58 
     | 
    
         
            +
                        version_module_name: code_names.version_module_name,
         
     | 
| 
      
 59 
     | 
    
         
            +
                        version: version,
         
     | 
| 
      
 60 
     | 
    
         
            +
                        command_class: generate_command_class(command),
         
     | 
| 
      
 61 
     | 
    
         
            +
                        factory_method_name: code_names.command_factory_method_name,
         
     | 
| 
      
 62 
     | 
    
         
            +
                        command_factory_method_call: code_names.command_factory_method_call,
         
     | 
| 
      
 63 
     | 
    
         
            +
                        command_name: command.command_name
         
     | 
| 
      
 64 
     | 
    
         
            +
                    }
         
     | 
| 
      
 65 
     | 
    
         
            +
             
     | 
| 
      
 66 
     | 
    
         
            +
                    template_file = File.expand_path(File.dirname(__FILE__) + '/templates/version_module.erb')
         
     | 
| 
      
 67 
     | 
    
         
            +
                    result_file = File.join @command_builders_dir, "#{code_names.version_factory_method_name}.rb"
         
     | 
| 
      
 68 
     | 
    
         
            +
                    sub_template model, template_file, result_file
         
     | 
| 
      
 69 
     | 
    
         
            +
                  end
         
     | 
| 
      
 70 
     | 
    
         
            +
             
     | 
| 
      
 71 
     | 
    
         
            +
                  def sub_template(model, template_file, result_file)
         
     | 
| 
      
 72 
     | 
    
         
            +
                    template = ERB.new File.read(template_file)
         
     | 
| 
      
 73 
     | 
    
         
            +
                    result = template.result(binding)
         
     | 
| 
      
 74 
     | 
    
         
            +
                    File.open(result_file, 'w') { |f| f.write result }
         
     | 
| 
      
 75 
     | 
    
         
            +
                  end
         
     | 
| 
      
 76 
     | 
    
         
            +
             
     | 
| 
      
 77 
     | 
    
         
            +
                  def generate_command_class(command)
         
     | 
| 
      
 78 
     | 
    
         
            +
                    stream = StringIO.new
         
     | 
| 
      
 79 
     | 
    
         
            +
                    writer = RubyCodeWriter.new stream
         
     | 
| 
      
 80 
     | 
    
         
            +
                    writer.indent = 3
         
     | 
| 
      
 81 
     | 
    
         
            +
                    node_code_generator = NodeCodeGenerator.new command, command, writer
         
     | 
| 
      
 82 
     | 
    
         
            +
                    node_code_generator.render
         
     | 
| 
      
 83 
     | 
    
         
            +
                    stream.string
         
     | 
| 
      
 84 
     | 
    
         
            +
                  end
         
     | 
| 
      
 85 
     | 
    
         
            +
             
     | 
| 
      
 86 
     | 
    
         
            +
                end
         
     | 
| 
      
 87 
     | 
    
         
            +
              end
         
     | 
| 
      
 88 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,52 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'yaml'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require_relative 'string_extensions'
         
     | 
| 
      
 3 
     | 
    
         
            +
            require_relative 'node'
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            module CommandBuilder
         
     | 
| 
      
 6 
     | 
    
         
            +
              module CodeGenerator
         
     | 
| 
      
 7 
     | 
    
         
            +
                class Command < Node
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                  attr_reader :command_name
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                  def initialize(command_def)
         
     | 
| 
      
 12 
     | 
    
         
            +
                    hash = Command.command_hash command_def
         
     | 
| 
      
 13 
     | 
    
         
            +
                    command_text = hash.keys[0]
         
     | 
| 
      
 14 
     | 
    
         
            +
                    command_name = Command.command_name command_text
         
     | 
| 
      
 15 
     | 
    
         
            +
                    node_def = command_text[command_name.length, command_text.length]
         
     | 
| 
      
 16 
     | 
    
         
            +
                    super node_def
         
     | 
| 
      
 17 
     | 
    
         
            +
                    Command.process_array hash.values[0], self
         
     | 
| 
      
 18 
     | 
    
         
            +
                    @command_name = command_name
         
     | 
| 
      
 19 
     | 
    
         
            +
                  end
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
                  def node_name
         
     | 
| 
      
 22 
     | 
    
         
            +
                    @node_name ||= node_alias || @command_name
         
     | 
| 
      
 23 
     | 
    
         
            +
                  end
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                  private
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                  def Command.command_name(command_text)
         
     | 
| 
      
 28 
     | 
    
         
            +
                    command_text[/^([-\.\w]+)/, 1]
         
     | 
| 
      
 29 
     | 
    
         
            +
                  end
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
                  def Command.command_hash(command_text)
         
     | 
| 
      
 32 
     | 
    
         
            +
                    yaml = command_text.split(String::NEW_LINE).map { |l| l.gsub(/^( *)(\S.+)$/, '\1- "\2":') }.join String::NEW_LINE
         
     | 
| 
      
 33 
     | 
    
         
            +
                    array = YAML.load yaml
         
     | 
| 
      
 34 
     | 
    
         
            +
                    array[0]
         
     | 
| 
      
 35 
     | 
    
         
            +
                  end
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
                  def Command.process_array(array, parent_node=nil)
         
     | 
| 
      
 38 
     | 
    
         
            +
                    array ||= []
         
     | 
| 
      
 39 
     | 
    
         
            +
                    array.each { |hash| Command.process_hash hash, parent_node }
         
     | 
| 
      
 40 
     | 
    
         
            +
                  end
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
                  def Command.process_hash(hash, parent_node)
         
     | 
| 
      
 43 
     | 
    
         
            +
                    hash.each_pair do |node_text, child_nodes|
         
     | 
| 
      
 44 
     | 
    
         
            +
                      node = Node.new " #{node_text}"
         
     | 
| 
      
 45 
     | 
    
         
            +
                      parent_node.child_nodes << node
         
     | 
| 
      
 46 
     | 
    
         
            +
                      process_array child_nodes, node
         
     | 
| 
      
 47 
     | 
    
         
            +
                    end
         
     | 
| 
      
 48 
     | 
    
         
            +
                  end
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
                end
         
     | 
| 
      
 51 
     | 
    
         
            +
              end
         
     | 
| 
      
 52 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,32 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module CommandBuilder
         
     | 
| 
      
 2 
     | 
    
         
            +
              module CodeGenerator
         
     | 
| 
      
 3 
     | 
    
         
            +
                class CommandArgument
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
                  def initialize(arg_text, required=true)
         
     | 
| 
      
 6 
     | 
    
         
            +
                    @arg_text = arg_text
         
     | 
| 
      
 7 
     | 
    
         
            +
                    @required = required
         
     | 
| 
      
 8 
     | 
    
         
            +
                  end
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                  def arg_name
         
     | 
| 
      
 11 
     | 
    
         
            +
                    @arg_name ||= @arg_text[/<(\w+)/, 1]
         
     | 
| 
      
 12 
     | 
    
         
            +
                  end
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                  def key_value_separator
         
     | 
| 
      
 15 
     | 
    
         
            +
                    @key_value_separator ||= @arg_text[/(\W)\W>/, 1]
         
     | 
| 
      
 16 
     | 
    
         
            +
                  end
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                  def delimiter
         
     | 
| 
      
 19 
     | 
    
         
            +
                    @delimiter ||= @arg_text[/(\W)>/, 1]
         
     | 
| 
      
 20 
     | 
    
         
            +
                  end
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                  def required?
         
     | 
| 
      
 23 
     | 
    
         
            +
                    @required
         
     | 
| 
      
 24 
     | 
    
         
            +
                  end
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
                  def optional?
         
     | 
| 
      
 27 
     | 
    
         
            +
                    !required?
         
     | 
| 
      
 28 
     | 
    
         
            +
                  end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
                end
         
     | 
| 
      
 31 
     | 
    
         
            +
              end
         
     | 
| 
      
 32 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,80 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require_relative 'string_extensions'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module CommandBuilder
         
     | 
| 
      
 4 
     | 
    
         
            +
              module CodeGenerator
         
     | 
| 
      
 5 
     | 
    
         
            +
                class CommandCodeNames
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
                  def initialize(command, version=nil)
         
     | 
| 
      
 8 
     | 
    
         
            +
                    @command = command
         
     | 
| 
      
 9 
     | 
    
         
            +
                    @compact_version = version.to_s.gsub('.', '')
         
     | 
| 
      
 10 
     | 
    
         
            +
                  end
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                  def command_module_name
         
     | 
| 
      
 13 
     | 
    
         
            +
                    @command.node_name.camelcase
         
     | 
| 
      
 14 
     | 
    
         
            +
                  end
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                  def version_module_name
         
     | 
| 
      
 17 
     | 
    
         
            +
                    result = @compact_version =~ /^\d/ ? "V#{@compact_version}" : @compact_version
         
     | 
| 
      
 18 
     | 
    
         
            +
                    result.camelcase
         
     | 
| 
      
 19 
     | 
    
         
            +
                  end
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
                  def command_factory_method_name
         
     | 
| 
      
 22 
     | 
    
         
            +
                    @command.node_name.downcase.snakecase
         
     | 
| 
      
 23 
     | 
    
         
            +
                  end
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                  def command_factory_method_signature
         
     | 
| 
      
 26 
     | 
    
         
            +
                    format_method command_factory_method_name, factory_method_args
         
     | 
| 
      
 27 
     | 
    
         
            +
                  end
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
                  def version_factory_method_name
         
     | 
| 
      
 30 
     | 
    
         
            +
                    "#{command_factory_method_name}_#{@compact_version.downcase.snakecase}"
         
     | 
| 
      
 31 
     | 
    
         
            +
                  end
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
                  def version_factory_method_signature
         
     | 
| 
      
 34 
     | 
    
         
            +
                    format_method version_factory_method_name, factory_method_args
         
     | 
| 
      
 35 
     | 
    
         
            +
                  end
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
                  def create_method_signature
         
     | 
| 
      
 38 
     | 
    
         
            +
                    format_method 'self.create', factory_method_args
         
     | 
| 
      
 39 
     | 
    
         
            +
                  end
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
                  def create_method_call
         
     | 
| 
      
 42 
     | 
    
         
            +
                    format_method "FluentCommandBuilder::#{command_module_name}::#{version_module_name}.create", initializer_values
         
     | 
| 
      
 43 
     | 
    
         
            +
                  end
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
                  def command_factory_method_call
         
     | 
| 
      
 46 
     | 
    
         
            +
                    format_method command_factory_method_name, initializer_values
         
     | 
| 
      
 47 
     | 
    
         
            +
                  end
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
                  def command_initializer_call
         
     | 
| 
      
 50 
     | 
    
         
            +
                    format_method "#{class_name}.new", %w(b) + initializer_values
         
     | 
| 
      
 51 
     | 
    
         
            +
                  end
         
     | 
| 
      
 52 
     | 
    
         
            +
             
     | 
| 
      
 53 
     | 
    
         
            +
                  private
         
     | 
| 
      
 54 
     | 
    
         
            +
             
     | 
| 
      
 55 
     | 
    
         
            +
                  def format_method(method_name, method_args)
         
     | 
| 
      
 56 
     | 
    
         
            +
                    method_args = method_args.join ', '
         
     | 
| 
      
 57 
     | 
    
         
            +
                    result = method_name
         
     | 
| 
      
 58 
     | 
    
         
            +
                    result << "(#{method_args})" unless method_args.empty?
         
     | 
| 
      
 59 
     | 
    
         
            +
                    result
         
     | 
| 
      
 60 
     | 
    
         
            +
                  end
         
     | 
| 
      
 61 
     | 
    
         
            +
             
     | 
| 
      
 62 
     | 
    
         
            +
                  def factory_method_args
         
     | 
| 
      
 63 
     | 
    
         
            +
                    @command.args.map do |arg|
         
     | 
| 
      
 64 
     | 
    
         
            +
                      arg_name = arg.arg_name.snakecase
         
     | 
| 
      
 65 
     | 
    
         
            +
                      arg_name << '=nil' if arg.optional?
         
     | 
| 
      
 66 
     | 
    
         
            +
                      arg_name
         
     | 
| 
      
 67 
     | 
    
         
            +
                    end
         
     | 
| 
      
 68 
     | 
    
         
            +
                  end
         
     | 
| 
      
 69 
     | 
    
         
            +
             
     | 
| 
      
 70 
     | 
    
         
            +
                  def initializer_values
         
     | 
| 
      
 71 
     | 
    
         
            +
                    @command.args.map { |arg| arg.arg_name.snakecase }
         
     | 
| 
      
 72 
     | 
    
         
            +
                  end
         
     | 
| 
      
 73 
     | 
    
         
            +
             
     | 
| 
      
 74 
     | 
    
         
            +
                  def class_name
         
     | 
| 
      
 75 
     | 
    
         
            +
                    @command.node_name.camelcase
         
     | 
| 
      
 76 
     | 
    
         
            +
                  end
         
     | 
| 
      
 77 
     | 
    
         
            +
             
     | 
| 
      
 78 
     | 
    
         
            +
                end
         
     | 
| 
      
 79 
     | 
    
         
            +
              end
         
     | 
| 
      
 80 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,26 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require_relative 'command'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require_relative 'version'
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            module CommandBuilder
         
     | 
| 
      
 5 
     | 
    
         
            +
              module CodeGenerator
         
     | 
| 
      
 6 
     | 
    
         
            +
                class CommandDefinition
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
                  attr_reader :versions, :command
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                  def initialize(stream)
         
     | 
| 
      
 11 
     | 
    
         
            +
                    s = stream.read
         
     | 
| 
      
 12 
     | 
    
         
            +
                    @versions = parse_versions s.first_line
         
     | 
| 
      
 13 
     | 
    
         
            +
                    @command = Command.new s.strip_first_line
         
     | 
| 
      
 14 
     | 
    
         
            +
                  end
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                  private
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                  def parse_versions(line)
         
     | 
| 
      
 19 
     | 
    
         
            +
                    versions = line.split_and_strip ','
         
     | 
| 
      
 20 
     | 
    
         
            +
                    versions.each { |v| Version.new v }
         
     | 
| 
      
 21 
     | 
    
         
            +
                    versions
         
     | 
| 
      
 22 
     | 
    
         
            +
                  end
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                end
         
     | 
| 
      
 25 
     | 
    
         
            +
              end
         
     | 
| 
      
 26 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,37 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require_relative 'command_argument'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module CommandBuilder
         
     | 
| 
      
 4 
     | 
    
         
            +
              module CodeGenerator
         
     | 
| 
      
 5 
     | 
    
         
            +
                class Fragment
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
                  def initialize(fragment_def)
         
     | 
| 
      
 8 
     | 
    
         
            +
                    @fragment_def = fragment_def
         
     | 
| 
      
 9 
     | 
    
         
            +
                  end
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                  def fragment_text
         
     | 
| 
      
 12 
     | 
    
         
            +
                    @fragment_text ||= optional? ? @fragment_def[1, @fragment_def.length - 2] : @fragment_def
         
     | 
| 
      
 13 
     | 
    
         
            +
                  end
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                  def required?
         
     | 
| 
      
 16 
     | 
    
         
            +
                    !optional?
         
     | 
| 
      
 17 
     | 
    
         
            +
                  end
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                  def optional?
         
     | 
| 
      
 20 
     | 
    
         
            +
                    @optional ||= @fragment_def.start_with?('[') && @fragment_def.end_with?(']')
         
     | 
| 
      
 21 
     | 
    
         
            +
                  end
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                  def args
         
     | 
| 
      
 24 
     | 
    
         
            +
                    @args ||= fragment_text.scan(/<.+?>/).flatten.map { |m| CommandArgument.new m, required? }
         
     | 
| 
      
 25 
     | 
    
         
            +
                  end
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                  def arg_names
         
     | 
| 
      
 28 
     | 
    
         
            +
                    @arg_names ||= args.map { |a| a.arg_name }
         
     | 
| 
      
 29 
     | 
    
         
            +
                  end
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
                  def has_args?
         
     | 
| 
      
 32 
     | 
    
         
            +
                    @has_args ||= !args.empty?
         
     | 
| 
      
 33 
     | 
    
         
            +
                  end
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
                end
         
     | 
| 
      
 36 
     | 
    
         
            +
              end
         
     | 
| 
      
 37 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,67 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require_relative 'fragment'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module CommandBuilder
         
     | 
| 
      
 4 
     | 
    
         
            +
              module CodeGenerator
         
     | 
| 
      
 5 
     | 
    
         
            +
                class Node
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
                  def initialize(node_def)
         
     | 
| 
      
 8 
     | 
    
         
            +
                    @node_def = node_def
         
     | 
| 
      
 9 
     | 
    
         
            +
                  end
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                  def child_nodes
         
     | 
| 
      
 12 
     | 
    
         
            +
                    @child_nodes ||= []
         
     | 
| 
      
 13 
     | 
    
         
            +
                  end
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                  def branch?
         
     | 
| 
      
 16 
     | 
    
         
            +
                    !child_nodes.empty?
         
     | 
| 
      
 17 
     | 
    
         
            +
                  end
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                  def leaf?
         
     | 
| 
      
 20 
     | 
    
         
            +
                    child_nodes.empty?
         
     | 
| 
      
 21 
     | 
    
         
            +
                  end
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                  def node_name
         
     | 
| 
      
 24 
     | 
    
         
            +
                    @node_name ||= node_alias || (starts_with_arg? ? first_arg_name : words_preceding_args)
         
     | 
| 
      
 25 
     | 
    
         
            +
                  end
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                  def fragments
         
     | 
| 
      
 28 
     | 
    
         
            +
                    @fragments ||= @node_def.gsub(/ \(.+?\)/, '').gsub(']', ']|').gsub('[', '|[').split('|').compact.map { |f| Fragment.new f }
         
     | 
| 
      
 29 
     | 
    
         
            +
                  end
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
                  def args
         
     | 
| 
      
 32 
     | 
    
         
            +
                    required_args + optional_args
         
     | 
| 
      
 33 
     | 
    
         
            +
                  end
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
                  protected
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
                  def required_args
         
     | 
| 
      
 38 
     | 
    
         
            +
                    select_args { |a| a.required? }
         
     | 
| 
      
 39 
     | 
    
         
            +
                  end
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
                  def optional_args
         
     | 
| 
      
 42 
     | 
    
         
            +
                    select_args { |a| a.optional? }
         
     | 
| 
      
 43 
     | 
    
         
            +
                  end
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
                  def starts_with_arg?
         
     | 
| 
      
 46 
     | 
    
         
            +
                    words_preceding_args.empty?
         
     | 
| 
      
 47 
     | 
    
         
            +
                  end
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
                  def first_arg_name
         
     | 
| 
      
 50 
     | 
    
         
            +
                    @node_def[/<(.+?)>/, 1]
         
     | 
| 
      
 51 
     | 
    
         
            +
                  end
         
     | 
| 
      
 52 
     | 
    
         
            +
             
     | 
| 
      
 53 
     | 
    
         
            +
                  def words_preceding_args
         
     | 
| 
      
 54 
     | 
    
         
            +
                    @node_def.gsub(/<.*/, '').gsub(/\W/, ' ').strip
         
     | 
| 
      
 55 
     | 
    
         
            +
                  end
         
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
      
 57 
     | 
    
         
            +
                  def node_alias
         
     | 
| 
      
 58 
     | 
    
         
            +
                    @node_def[/\((.+?)\)/, 1]
         
     | 
| 
      
 59 
     | 
    
         
            +
                  end
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
      
 61 
     | 
    
         
            +
                  def select_args
         
     | 
| 
      
 62 
     | 
    
         
            +
                    fragments.map { |f| f.args.map { |a| a if yield a } }.flatten.compact
         
     | 
| 
      
 63 
     | 
    
         
            +
                  end
         
     | 
| 
      
 64 
     | 
    
         
            +
             
     | 
| 
      
 65 
     | 
    
         
            +
                end
         
     | 
| 
      
 66 
     | 
    
         
            +
              end
         
     | 
| 
      
 67 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,101 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require_relative 'string_extensions'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require_relative 'node'
         
     | 
| 
      
 3 
     | 
    
         
            +
            require_relative 'node_code_names'
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            module CommandBuilder
         
     | 
| 
      
 6 
     | 
    
         
            +
              module CodeGenerator
         
     | 
| 
      
 7 
     | 
    
         
            +
                class NodeCodeGenerator
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                  def initialize(node, command, writer)
         
     | 
| 
      
 10 
     | 
    
         
            +
                    @node = node
         
     | 
| 
      
 11 
     | 
    
         
            +
                    @command = command
         
     | 
| 
      
 12 
     | 
    
         
            +
                    @writer = writer
         
     | 
| 
      
 13 
     | 
    
         
            +
                  end
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                  def render
         
     | 
| 
      
 16 
     | 
    
         
            +
                    render_branch_node if @node.branch?
         
     | 
| 
      
 17 
     | 
    
         
            +
                    render_leaf_node if @node.leaf?
         
     | 
| 
      
 18 
     | 
    
         
            +
                  end
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                  def render_method
         
     | 
| 
      
 21 
     | 
    
         
            +
                    @writer.write_method node_code_names.method_name, node_code_names.method_args do
         
     | 
| 
      
 22 
     | 
    
         
            +
                      if @node.branch?
         
     | 
| 
      
 23 
     | 
    
         
            +
                        render_branch_node_method_body
         
     | 
| 
      
 24 
     | 
    
         
            +
                      else
         
     | 
| 
      
 25 
     | 
    
         
            +
                        render_leaf_node_method_body
         
     | 
| 
      
 26 
     | 
    
         
            +
                        @writer.write_line 'yield @b if block_given?'
         
     | 
| 
      
 27 
     | 
    
         
            +
                        @writer.write_line 'self'
         
     | 
| 
      
 28 
     | 
    
         
            +
                      end
         
     | 
| 
      
 29 
     | 
    
         
            +
                    end
         
     | 
| 
      
 30 
     | 
    
         
            +
                  end
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
                  private
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                  def render_branch_node
         
     | 
| 
      
 35 
     | 
    
         
            +
                    @writer.write_class node_code_names.class_name, 'CommandBase' do
         
     | 
| 
      
 36 
     | 
    
         
            +
                      render_constructor
         
     | 
| 
      
 37 
     | 
    
         
            +
                      @node.child_nodes.each do |n|
         
     | 
| 
      
 38 
     | 
    
         
            +
                        generator = NodeCodeGenerator.new n, @command, @writer
         
     | 
| 
      
 39 
     | 
    
         
            +
                        generator.render_method
         
     | 
| 
      
 40 
     | 
    
         
            +
                      end
         
     | 
| 
      
 41 
     | 
    
         
            +
                    end
         
     | 
| 
      
 42 
     | 
    
         
            +
                    render_child_nodes
         
     | 
| 
      
 43 
     | 
    
         
            +
                  end
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
                  def render_leaf_node
         
     | 
| 
      
 46 
     | 
    
         
            +
                    render_child_nodes
         
     | 
| 
      
 47 
     | 
    
         
            +
                  end
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
                  def render_child_nodes
         
     | 
| 
      
 50 
     | 
    
         
            +
                    @node.child_nodes.each do |n|
         
     | 
| 
      
 51 
     | 
    
         
            +
                      generator = NodeCodeGenerator.new n, @command, @writer
         
     | 
| 
      
 52 
     | 
    
         
            +
                      generator.render
         
     | 
| 
      
 53 
     | 
    
         
            +
                    end
         
     | 
| 
      
 54 
     | 
    
         
            +
                  end
         
     | 
| 
      
 55 
     | 
    
         
            +
             
     | 
| 
      
 56 
     | 
    
         
            +
                  def render_constructor
         
     | 
| 
      
 57 
     | 
    
         
            +
                    @writer.write_method 'initialize', 'underlying_builder', node_code_names.method_args do
         
     | 
| 
      
 58 
     | 
    
         
            +
                      @writer.write_line 'super underlying_builder'
         
     | 
| 
      
 59 
     | 
    
         
            +
                      render_leaf_node_method_body
         
     | 
| 
      
 60 
     | 
    
         
            +
                    end
         
     | 
| 
      
 61 
     | 
    
         
            +
                  end
         
     | 
| 
      
 62 
     | 
    
         
            +
             
     | 
| 
      
 63 
     | 
    
         
            +
                  def render_branch_node_method_body
         
     | 
| 
      
 64 
     | 
    
         
            +
                    args = node_code_names.initializer_values
         
     | 
| 
      
 65 
     | 
    
         
            +
                    @writer.write_line "#{node_code_names.class_name}.new #{args.join ', '}"
         
     | 
| 
      
 66 
     | 
    
         
            +
                  end
         
     | 
| 
      
 67 
     | 
    
         
            +
             
     | 
| 
      
 68 
     | 
    
         
            +
                  def render_leaf_node_method_body
         
     | 
| 
      
 69 
     | 
    
         
            +
                    @node.fragments.each { |f| write_append_statement f }
         
     | 
| 
      
 70 
     | 
    
         
            +
                  end
         
     | 
| 
      
 71 
     | 
    
         
            +
             
     | 
| 
      
 72 
     | 
    
         
            +
                  def write_append_statement(fragment)
         
     | 
| 
      
 73 
     | 
    
         
            +
                    return if fragment.fragment_text.empty?
         
     | 
| 
      
 74 
     | 
    
         
            +
                    unless_condition = fragment.arg_names.map { |a| "#{a.snakecase}.nil?" }.join ' or '
         
     | 
| 
      
 75 
     | 
    
         
            +
                    statement = "@b.append #{append_arg fragment}"
         
     | 
| 
      
 76 
     | 
    
         
            +
                    statement << " unless #{unless_condition}" if fragment.optional? and fragment.has_args?
         
     | 
| 
      
 77 
     | 
    
         
            +
                    @writer.write_line statement
         
     | 
| 
      
 78 
     | 
    
         
            +
                  end
         
     | 
| 
      
 79 
     | 
    
         
            +
             
     | 
| 
      
 80 
     | 
    
         
            +
                  def append_arg(fragment)
         
     | 
| 
      
 81 
     | 
    
         
            +
                    value = fragment.fragment_text.gsub(/<.+?>/) do |m|
         
     | 
| 
      
 82 
     | 
    
         
            +
                      arg = CommandArgument.new m
         
     | 
| 
      
 83 
     | 
    
         
            +
                      is_password = arg.arg_name.downcase.include? 'password'
         
     | 
| 
      
 84 
     | 
    
         
            +
             
     | 
| 
      
 85 
     | 
    
         
            +
                      if is_password
         
     | 
| 
      
 86 
     | 
    
         
            +
                        "\#{@b.format_password #{arg.arg_name.snakecase}}"
         
     | 
| 
      
 87 
     | 
    
         
            +
                      else
         
     | 
| 
      
 88 
     | 
    
         
            +
                        format_args = [arg.arg_name.snakecase, [arg.delimiter, arg.key_value_separator].compact.map { |v| "'#{v}'" }].flatten
         
     | 
| 
      
 89 
     | 
    
         
            +
                        "\#{@b.format #{format_args.join ', '}}"
         
     | 
| 
      
 90 
     | 
    
         
            +
                      end
         
     | 
| 
      
 91 
     | 
    
         
            +
                    end
         
     | 
| 
      
 92 
     | 
    
         
            +
                    value.include?('#{') ? %Q["#{value}"] : "'#{value}'"
         
     | 
| 
      
 93 
     | 
    
         
            +
                  end
         
     | 
| 
      
 94 
     | 
    
         
            +
             
     | 
| 
      
 95 
     | 
    
         
            +
                  def node_code_names
         
     | 
| 
      
 96 
     | 
    
         
            +
                    @node_code_names ||= NodeCodeNames.new @node
         
     | 
| 
      
 97 
     | 
    
         
            +
                  end
         
     | 
| 
      
 98 
     | 
    
         
            +
             
     | 
| 
      
 99 
     | 
    
         
            +
                end
         
     | 
| 
      
 100 
     | 
    
         
            +
              end
         
     | 
| 
      
 101 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,33 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require_relative 'string_extensions'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module CommandBuilder
         
     | 
| 
      
 4 
     | 
    
         
            +
              module CodeGenerator
         
     | 
| 
      
 5 
     | 
    
         
            +
                class NodeCodeNames
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
                  def initialize(node)
         
     | 
| 
      
 8 
     | 
    
         
            +
                    @node = node
         
     | 
| 
      
 9 
     | 
    
         
            +
                  end
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                  def class_name
         
     | 
| 
      
 12 
     | 
    
         
            +
                    @node.node_name.camelcase
         
     | 
| 
      
 13 
     | 
    
         
            +
                  end
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                  def method_name
         
     | 
| 
      
 16 
     | 
    
         
            +
                    @node.node_name.snakecase
         
     | 
| 
      
 17 
     | 
    
         
            +
                  end
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                  def method_args
         
     | 
| 
      
 20 
     | 
    
         
            +
                    @node.args.map do |arg|
         
     | 
| 
      
 21 
     | 
    
         
            +
                      arg_name = arg.arg_name.snakecase
         
     | 
| 
      
 22 
     | 
    
         
            +
                      arg_name << '=nil' if arg.optional?
         
     | 
| 
      
 23 
     | 
    
         
            +
                      arg_name
         
     | 
| 
      
 24 
     | 
    
         
            +
                    end
         
     | 
| 
      
 25 
     | 
    
         
            +
                  end
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                  def initializer_values
         
     | 
| 
      
 28 
     | 
    
         
            +
                    %w(@b) + @node.args.map { |arg| arg.arg_name.snakecase }
         
     | 
| 
      
 29 
     | 
    
         
            +
                  end
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
                end
         
     | 
| 
      
 32 
     | 
    
         
            +
              end
         
     | 
| 
      
 33 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,62 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module CommandBuilder
         
     | 
| 
      
 2 
     | 
    
         
            +
              module CodeGenerator
         
     | 
| 
      
 3 
     | 
    
         
            +
                class RubyCodeWriter
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
                  INDENT_SPACES = 2
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
                  attr_accessor :indent
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                  def initialize(stream)
         
     | 
| 
      
 10 
     | 
    
         
            +
                    @stream = stream
         
     | 
| 
      
 11 
     | 
    
         
            +
                    @indent = 0
         
     | 
| 
      
 12 
     | 
    
         
            +
                  end
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                  def indent
         
     | 
| 
      
 15 
     | 
    
         
            +
                    @indent += 1
         
     | 
| 
      
 16 
     | 
    
         
            +
                    if block_given?
         
     | 
| 
      
 17 
     | 
    
         
            +
                      yield
         
     | 
| 
      
 18 
     | 
    
         
            +
                      dedent
         
     | 
| 
      
 19 
     | 
    
         
            +
                    end
         
     | 
| 
      
 20 
     | 
    
         
            +
                  end
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                  def dedent
         
     | 
| 
      
 23 
     | 
    
         
            +
                    @indent -= 1
         
     | 
| 
      
 24 
     | 
    
         
            +
                  end
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
                  def write(code)
         
     | 
| 
      
 27 
     | 
    
         
            +
                    @stream.print code
         
     | 
| 
      
 28 
     | 
    
         
            +
                  end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
                  def write_line(line='')
         
     | 
| 
      
 31 
     | 
    
         
            +
                    @stream.puts line.rjust(line.length + @indent * INDENT_SPACES, ' ')
         
     | 
| 
      
 32 
     | 
    
         
            +
                  end
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                  def write_block(line)
         
     | 
| 
      
 35 
     | 
    
         
            +
                    write_line line
         
     | 
| 
      
 36 
     | 
    
         
            +
                    indent
         
     | 
| 
      
 37 
     | 
    
         
            +
                    yield
         
     | 
| 
      
 38 
     | 
    
         
            +
                    dedent
         
     | 
| 
      
 39 
     | 
    
         
            +
                    write_line 'end'
         
     | 
| 
      
 40 
     | 
    
         
            +
                    line
         
     | 
| 
      
 41 
     | 
    
         
            +
                  end
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
                  def write_module(module_name)
         
     | 
| 
      
 44 
     | 
    
         
            +
                    write_block("module #{module_name}") { yield }
         
     | 
| 
      
 45 
     | 
    
         
            +
                  end
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
                  def write_class(class_name, base_class_name=nil)
         
     | 
| 
      
 48 
     | 
    
         
            +
                    line = "class #{class_name}"
         
     | 
| 
      
 49 
     | 
    
         
            +
                    line << " < #{base_class_name}" if base_class_name
         
     | 
| 
      
 50 
     | 
    
         
            +
                    write_block(line) { yield }
         
     | 
| 
      
 51 
     | 
    
         
            +
                  end
         
     | 
| 
      
 52 
     | 
    
         
            +
             
     | 
| 
      
 53 
     | 
    
         
            +
                  def write_method(method_name, *args)
         
     | 
| 
      
 54 
     | 
    
         
            +
                    args = [args].flatten
         
     | 
| 
      
 55 
     | 
    
         
            +
                    line = "def #{method_name}"
         
     | 
| 
      
 56 
     | 
    
         
            +
                    line << "(#{args.join ', '})" unless args.empty?
         
     | 
| 
      
 57 
     | 
    
         
            +
                    write_block(line) { yield }
         
     | 
| 
      
 58 
     | 
    
         
            +
                  end
         
     | 
| 
      
 59 
     | 
    
         
            +
             
     | 
| 
      
 60 
     | 
    
         
            +
                end
         
     | 
| 
      
 61 
     | 
    
         
            +
              end
         
     | 
| 
      
 62 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,34 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            class String
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
              NEW_LINE = "\n"
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
              def camelcase
         
     | 
| 
      
 6 
     | 
    
         
            +
                words.join
         
     | 
| 
      
 7 
     | 
    
         
            +
              end
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
              def snakecase
         
     | 
| 
      
 10 
     | 
    
         
            +
                words.join('_').downcase
         
     | 
| 
      
 11 
     | 
    
         
            +
              end
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
              def first_line
         
     | 
| 
      
 14 
     | 
    
         
            +
                match(/^.*$/)[0]
         
     | 
| 
      
 15 
     | 
    
         
            +
              end
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
              def strip_first_line
         
     | 
| 
      
 18 
     | 
    
         
            +
                first_line_index = self.index NEW_LINE
         
     | 
| 
      
 19 
     | 
    
         
            +
                return '' unless first_line_index
         
     | 
| 
      
 20 
     | 
    
         
            +
                self[first_line_index+1..self.length-1]
         
     | 
| 
      
 21 
     | 
    
         
            +
              end
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
              def split_and_strip(pattern)
         
     | 
| 
      
 24 
     | 
    
         
            +
                split(pattern).map { |s| s.strip }
         
     | 
| 
      
 25 
     | 
    
         
            +
              end
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
              private
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
              def words
         
     | 
| 
      
 30 
     | 
    
         
            +
                result = self =~ /^[A-Z]+$/ ? downcase : self
         
     | 
| 
      
 31 
     | 
    
         
            +
                result.gsub(/[\W_]/, ' ').gsub(/[A-Z*]/, ' \0').split(' ').map { |s| s.capitalize }
         
     | 
| 
      
 32 
     | 
    
         
            +
              end
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,47 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module CommandBuilder
         
     | 
| 
      
 2 
     | 
    
         
            +
              module CodeGenerator
         
     | 
| 
      
 3 
     | 
    
         
            +
                class Version
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
                  VERSION_REGEX = '(?:\d+\.)+(?:\d+)'
         
     | 
| 
      
 6 
     | 
    
         
            +
                  DELIMITER = '.'
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
                  attr_accessor :version
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                  def initialize(version)
         
     | 
| 
      
 11 
     | 
    
         
            +
                    raise "#{version} is not a valid version." unless Version.is_valid? version
         
     | 
| 
      
 12 
     | 
    
         
            +
                    @version = version
         
     | 
| 
      
 13 
     | 
    
         
            +
                  end
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                  def compact
         
     | 
| 
      
 16 
     | 
    
         
            +
                    first 2, ''
         
     | 
| 
      
 17 
     | 
    
         
            +
                  end
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                  def first(count, delimiter=DELIMITER)
         
     | 
| 
      
 20 
     | 
    
         
            +
                    to_a.first(count).join(delimiter)
         
     | 
| 
      
 21 
     | 
    
         
            +
                  end
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                  def to_s
         
     | 
| 
      
 24 
     | 
    
         
            +
                    @version
         
     | 
| 
      
 25 
     | 
    
         
            +
                  end
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                  def to_a
         
     | 
| 
      
 28 
     | 
    
         
            +
                    @version.split DELIMITER
         
     | 
| 
      
 29 
     | 
    
         
            +
                  end
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
                  def self.match(value)
         
     | 
| 
      
 32 
     | 
    
         
            +
                    exp = Regexp.new VERSION_REGEX
         
     | 
| 
      
 33 
     | 
    
         
            +
                    version = value.scan(exp)[0]
         
     | 
| 
      
 34 
     | 
    
         
            +
                    return unless version
         
     | 
| 
      
 35 
     | 
    
         
            +
                    Version.new(version)
         
     | 
| 
      
 36 
     | 
    
         
            +
                  end
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
                  private
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
                  def self.is_valid?(version)
         
     | 
| 
      
 41 
     | 
    
         
            +
                    exp = Regexp.new "^#{VERSION_REGEX}$"
         
     | 
| 
      
 42 
     | 
    
         
            +
                    version.scan(exp)[0] != nil
         
     | 
| 
      
 43 
     | 
    
         
            +
                  end
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
                end
         
     | 
| 
      
 46 
     | 
    
         
            +
              end
         
     | 
| 
      
 47 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require_relative 'code_generator/code_generator'
         
     | 
    
        metadata
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            --- !ruby/object:Gem::Specification
         
     | 
| 
       2 
2 
     | 
    
         
             
            name: command_builder
         
     | 
| 
       3 
3 
     | 
    
         
             
            version: !ruby/object:Gem::Version
         
     | 
| 
       4 
     | 
    
         
            -
              version: 0.0. 
     | 
| 
      
 4 
     | 
    
         
            +
              version: 0.0.3
         
     | 
| 
       5 
5 
     | 
    
         
             
              prerelease: 
         
     | 
| 
       6 
6 
     | 
    
         
             
            platform: ruby
         
     | 
| 
       7 
7 
     | 
    
         
             
            authors:
         
     | 
| 
         @@ -16,7 +16,20 @@ email: matthew@matthewriley.name 
     | 
|
| 
       16 
16 
     | 
    
         
             
            executables: []
         
     | 
| 
       17 
17 
     | 
    
         
             
            extensions: []
         
     | 
| 
       18 
18 
     | 
    
         
             
            extra_rdoc_files: []
         
     | 
| 
       19 
     | 
    
         
            -
            files: 
     | 
| 
      
 19 
     | 
    
         
            +
            files:
         
     | 
| 
      
 20 
     | 
    
         
            +
            - lib/command_builder/code_generator/code_generator.rb
         
     | 
| 
      
 21 
     | 
    
         
            +
            - lib/command_builder/code_generator/command.rb
         
     | 
| 
      
 22 
     | 
    
         
            +
            - lib/command_builder/code_generator/command_argument.rb
         
     | 
| 
      
 23 
     | 
    
         
            +
            - lib/command_builder/code_generator/command_code_names.rb
         
     | 
| 
      
 24 
     | 
    
         
            +
            - lib/command_builder/code_generator/command_definition.rb
         
     | 
| 
      
 25 
     | 
    
         
            +
            - lib/command_builder/code_generator/fragment.rb
         
     | 
| 
      
 26 
     | 
    
         
            +
            - lib/command_builder/code_generator/node.rb
         
     | 
| 
      
 27 
     | 
    
         
            +
            - lib/command_builder/code_generator/node_code_generator.rb
         
     | 
| 
      
 28 
     | 
    
         
            +
            - lib/command_builder/code_generator/node_code_names.rb
         
     | 
| 
      
 29 
     | 
    
         
            +
            - lib/command_builder/code_generator/ruby_code_writer.rb
         
     | 
| 
      
 30 
     | 
    
         
            +
            - lib/command_builder/code_generator/string_extensions.rb
         
     | 
| 
      
 31 
     | 
    
         
            +
            - lib/command_builder/code_generator/version.rb
         
     | 
| 
      
 32 
     | 
    
         
            +
            - lib/command_builder/code_generator.rb
         
     | 
| 
       20 
33 
     | 
    
         
             
            homepage: 
         
     | 
| 
       21 
34 
     | 
    
         
             
            licenses: []
         
     | 
| 
       22 
35 
     | 
    
         
             
            post_install_message: 
         
     |