command_builder_generator 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/command_builder_generator.rb +1 -0
- data/lib/command_builder_generator/code_generator.rb +82 -0
- data/lib/command_builder_generator/command.rb +50 -0
- data/lib/command_builder_generator/command_argument.rb +30 -0
- data/lib/command_builder_generator/command_code_names.rb +77 -0
- data/lib/command_builder_generator/command_definition.rb +25 -0
- data/lib/command_builder_generator/fragment.rb +35 -0
- data/lib/command_builder_generator/lib/argument_formatter.rb +22 -0
- data/lib/command_builder_generator/lib/argument_formatters/array_argument_formatter.rb +22 -0
- data/lib/command_builder_generator/lib/argument_formatters/hash_argument_formatter.rb +27 -0
- data/lib/command_builder_generator/lib/argument_formatters/string_argument_formatter.rb +17 -0
- data/lib/command_builder_generator/lib/command_base.rb +20 -0
- data/lib/command_builder_generator/node.rb +65 -0
- data/lib/command_builder_generator/node_code_generator.rb +99 -0
- data/lib/command_builder_generator/node_code_names.rb +31 -0
- data/lib/command_builder_generator/ruby_code_writer.rb +61 -0
- data/lib/command_builder_generator/string_extensions.rb +35 -0
- data/lib/command_builder_generator/version.rb +45 -0
- metadata +95 -0
@@ -0,0 +1 @@
|
|
1
|
+
require_relative 'command_builder_generator/code_generator'
|
@@ -0,0 +1,82 @@
|
|
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
|
+
require 'fileutils'
|
7
|
+
|
8
|
+
module CommandBuilderGenerator
|
9
|
+
class CodeGenerator
|
10
|
+
|
11
|
+
def initialize(definition_file)
|
12
|
+
@definition_file = definition_file
|
13
|
+
end
|
14
|
+
|
15
|
+
def execute
|
16
|
+
puts "Processing: #{File.basename @definition_file}"
|
17
|
+
d = CommandDefinition.new File.new(@definition_file)
|
18
|
+
d.versions.each { |v| process_version d.command, v }
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def process_version(command, version)
|
24
|
+
generate_command_module command, version
|
25
|
+
generate_version_module command, version
|
26
|
+
FileUtils.cp_r File.expand_path(File.dirname(__FILE__) + '/lib'), Dir.getwd
|
27
|
+
end
|
28
|
+
|
29
|
+
def generate_command_module(command, version)
|
30
|
+
code_names = CommandCodeNames.new command, version
|
31
|
+
|
32
|
+
model = {
|
33
|
+
module_name: code_names.command_module_name,
|
34
|
+
factory_method_name: code_names.command_factory_method_name,
|
35
|
+
command_name: command.command_name
|
36
|
+
}
|
37
|
+
|
38
|
+
template_file = File.expand_path(File.dirname(__FILE__) + '/templates/command_module.erb')
|
39
|
+
result_file = "#{code_names.command_factory_method_name}.rb"
|
40
|
+
sub_template model, template_file, result_file
|
41
|
+
end
|
42
|
+
|
43
|
+
def generate_version_module(command, version)
|
44
|
+
code_names = CommandCodeNames.new command, version
|
45
|
+
|
46
|
+
model = {
|
47
|
+
command_factory_method_signature: code_names.command_factory_method_signature,
|
48
|
+
version_factory_method_signature: code_names.version_factory_method_signature,
|
49
|
+
create_method_signature: code_names.create_method_signature,
|
50
|
+
create_method_call: code_names.create_method_call,
|
51
|
+
command_initializer_call: code_names.command_initializer_call,
|
52
|
+
command_module_name: code_names.command_module_name,
|
53
|
+
version_module_name: code_names.version_module_name,
|
54
|
+
version: version,
|
55
|
+
command_class: generate_command_class(command),
|
56
|
+
factory_method_name: code_names.command_factory_method_name,
|
57
|
+
command_factory_method_call: code_names.command_factory_method_call,
|
58
|
+
command_name: command.command_name
|
59
|
+
}
|
60
|
+
|
61
|
+
template_file = File.expand_path(File.dirname(__FILE__) + '/templates/version_module.erb')
|
62
|
+
result_file = File.join "#{code_names.version_factory_method_name}.rb"
|
63
|
+
sub_template model, template_file, result_file
|
64
|
+
end
|
65
|
+
|
66
|
+
def sub_template(model, template_file, result_file)
|
67
|
+
template = ERB.new File.read(template_file)
|
68
|
+
result = template.result(binding)
|
69
|
+
File.open(result_file, 'w') { |f| f.write result }
|
70
|
+
end
|
71
|
+
|
72
|
+
def generate_command_class(command)
|
73
|
+
stream = StringIO.new
|
74
|
+
writer = RubyCodeWriter.new stream
|
75
|
+
writer.indent = 3
|
76
|
+
node_code_generator = NodeCodeGenerator.new command, command, writer
|
77
|
+
node_code_generator.render
|
78
|
+
stream.string
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
require_relative 'string_extensions'
|
3
|
+
require_relative 'node'
|
4
|
+
|
5
|
+
module CommandBuilderGenerator
|
6
|
+
class Command < Node
|
7
|
+
|
8
|
+
attr_reader :command_name
|
9
|
+
|
10
|
+
def initialize(command_def)
|
11
|
+
hash = Command.command_hash command_def
|
12
|
+
command_text = hash.keys[0]
|
13
|
+
command_name = Command.command_name command_text
|
14
|
+
node_def = command_text[command_name.length, command_text.length]
|
15
|
+
super node_def
|
16
|
+
Command.process_array hash.values[0], self
|
17
|
+
@command_name = command_name
|
18
|
+
end
|
19
|
+
|
20
|
+
def node_name
|
21
|
+
@node_name ||= node_alias || @command_name
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def Command.command_name(command_text)
|
27
|
+
command_text[/^([-\.\w]+)/, 1]
|
28
|
+
end
|
29
|
+
|
30
|
+
def Command.command_hash(command_text)
|
31
|
+
yaml = command_text.split(String::NEW_LINE).map { |l| l.gsub(/^( *)(\S.+)$/, '\1- "\2":') }.join String::NEW_LINE
|
32
|
+
array = YAML.load yaml
|
33
|
+
array[0]
|
34
|
+
end
|
35
|
+
|
36
|
+
def Command.process_array(array, parent_node=nil)
|
37
|
+
array ||= []
|
38
|
+
array.each { |hash| Command.process_hash hash, parent_node }
|
39
|
+
end
|
40
|
+
|
41
|
+
def Command.process_hash(hash, parent_node)
|
42
|
+
hash.each_pair do |node_text, child_nodes|
|
43
|
+
node = Node.new " #{node_text}"
|
44
|
+
parent_node.child_nodes << node
|
45
|
+
process_array child_nodes, node
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module CommandBuilderGenerator
|
2
|
+
class CommandArgument
|
3
|
+
|
4
|
+
def initialize(arg_text, required=true)
|
5
|
+
@arg_text = arg_text
|
6
|
+
@required = required
|
7
|
+
end
|
8
|
+
|
9
|
+
def arg_name
|
10
|
+
@arg_name ||= @arg_text[/<(\w+)/, 1]
|
11
|
+
end
|
12
|
+
|
13
|
+
def key_value_separator
|
14
|
+
@key_value_separator ||= @arg_text[/(\W)\W>/, 1]
|
15
|
+
end
|
16
|
+
|
17
|
+
def delimiter
|
18
|
+
@delimiter ||= @arg_text[/(\W)>/, 1]
|
19
|
+
end
|
20
|
+
|
21
|
+
def required?
|
22
|
+
@required
|
23
|
+
end
|
24
|
+
|
25
|
+
def optional?
|
26
|
+
!required?
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
require_relative 'string_extensions'
|
2
|
+
|
3
|
+
module CommandBuilderGenerator
|
4
|
+
class CommandCodeNames
|
5
|
+
|
6
|
+
def initialize(command, version=nil)
|
7
|
+
@command = command
|
8
|
+
@compact_version = version.to_s.gsub('.', '_')
|
9
|
+
end
|
10
|
+
|
11
|
+
def command_module_name
|
12
|
+
@command.node_name.camelcase
|
13
|
+
end
|
14
|
+
|
15
|
+
def version_module_name
|
16
|
+
"V#{@compact_version}"
|
17
|
+
end
|
18
|
+
|
19
|
+
def command_factory_method_name
|
20
|
+
@command.node_name.downcase.snakecase
|
21
|
+
end
|
22
|
+
|
23
|
+
def command_factory_method_signature
|
24
|
+
format_method command_factory_method_name, factory_method_args
|
25
|
+
end
|
26
|
+
|
27
|
+
def version_factory_method_name
|
28
|
+
"#{command_factory_method_name}_#{@compact_version.downcase.snakecase}"
|
29
|
+
end
|
30
|
+
|
31
|
+
def version_factory_method_signature
|
32
|
+
format_method version_factory_method_name, factory_method_args
|
33
|
+
end
|
34
|
+
|
35
|
+
def create_method_signature
|
36
|
+
format_method 'self.create', factory_method_args
|
37
|
+
end
|
38
|
+
|
39
|
+
def create_method_call
|
40
|
+
format_method "CommandBuilder::#{command_module_name}::#{version_module_name}.create", initializer_values
|
41
|
+
end
|
42
|
+
|
43
|
+
def command_factory_method_call
|
44
|
+
format_method command_factory_method_name, initializer_values
|
45
|
+
end
|
46
|
+
|
47
|
+
def command_initializer_call
|
48
|
+
format_method "#{class_name}.new", initializer_values
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
def format_method(method_name, method_args)
|
54
|
+
method_args = method_args.join ', '
|
55
|
+
result = method_name
|
56
|
+
result << "(#{method_args})" unless method_args.empty?
|
57
|
+
result
|
58
|
+
end
|
59
|
+
|
60
|
+
def factory_method_args
|
61
|
+
@command.args.map do |arg|
|
62
|
+
arg_name = arg.arg_name.snakecase
|
63
|
+
arg_name << '=nil' if arg.optional?
|
64
|
+
arg_name
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def initializer_values
|
69
|
+
@command.args.map { |arg| arg.arg_name.snakecase }
|
70
|
+
end
|
71
|
+
|
72
|
+
def class_name
|
73
|
+
@command.node_name.camelcase
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require_relative 'command'
|
2
|
+
require_relative 'version'
|
3
|
+
require_relative 'string_extensions'
|
4
|
+
|
5
|
+
module CommandBuilderGenerator
|
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
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require_relative 'command_argument'
|
2
|
+
|
3
|
+
module CommandBuilderGenerator
|
4
|
+
class Fragment
|
5
|
+
|
6
|
+
def initialize(fragment_def)
|
7
|
+
@fragment_def = fragment_def
|
8
|
+
end
|
9
|
+
|
10
|
+
def fragment_text
|
11
|
+
@fragment_text ||= optional? ? @fragment_def[1, @fragment_def.length - 2] : @fragment_def
|
12
|
+
end
|
13
|
+
|
14
|
+
def required?
|
15
|
+
!optional?
|
16
|
+
end
|
17
|
+
|
18
|
+
def optional?
|
19
|
+
@optional ||= @fragment_def.start_with?('[') && @fragment_def.end_with?(']')
|
20
|
+
end
|
21
|
+
|
22
|
+
def args
|
23
|
+
@args ||= fragment_text.scan(/<.+?>/).flatten.map { |m| CommandArgument.new m, required? }
|
24
|
+
end
|
25
|
+
|
26
|
+
def arg_names
|
27
|
+
@arg_names ||= args.map { |a| a.arg_name }
|
28
|
+
end
|
29
|
+
|
30
|
+
def has_args?
|
31
|
+
@has_args ||= !args.empty?
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require_relative 'argument_formatters/array_argument_formatter'
|
2
|
+
require_relative 'argument_formatters/hash_argument_formatter'
|
3
|
+
require_relative 'argument_formatters/string_argument_formatter'
|
4
|
+
|
5
|
+
module CommandBuilder
|
6
|
+
class ArgumentFormatter
|
7
|
+
|
8
|
+
def format(argument, options={})
|
9
|
+
|
10
|
+
formatter = case
|
11
|
+
when argument.kind_of?(Array)
|
12
|
+
ArrayArgumentFormatter.new options[:delimiter]
|
13
|
+
when argument.kind_of?(Hash)
|
14
|
+
HashArgumentFormatter.new options[:delimiter], options[:key_value_separator]
|
15
|
+
else
|
16
|
+
StringArgumentFormatter.new
|
17
|
+
end
|
18
|
+
formatter.format argument
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require_relative 'string_argument_formatter'
|
2
|
+
|
3
|
+
module CommandBuilder
|
4
|
+
class ArrayArgumentFormatter
|
5
|
+
|
6
|
+
def initialize(delimiter)
|
7
|
+
@delimiter = delimiter
|
8
|
+
@string_argument_formatter = StringArgumentFormatter.new
|
9
|
+
end
|
10
|
+
|
11
|
+
def format(argument)
|
12
|
+
argument.map { |v| format_string_argument v }.join @delimiter
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def format_string_argument(s)
|
18
|
+
@string_argument_formatter.format s
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require_relative 'string_argument_formatter'
|
2
|
+
|
3
|
+
module CommandBuilder
|
4
|
+
class HashArgumentFormatter
|
5
|
+
|
6
|
+
def initialize(delimiter, key_value_separator)
|
7
|
+
@delimiter = delimiter
|
8
|
+
@key_value_separator = key_value_separator
|
9
|
+
@string_argument_formatter = StringArgumentFormatter.new
|
10
|
+
end
|
11
|
+
|
12
|
+
def format(argument)
|
13
|
+
argument.map { |k, v| format_pair k, v }.join @delimiter
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def format_pair(k, v)
|
19
|
+
format_string_argument(k) + @key_value_separator + format_string_argument(v)
|
20
|
+
end
|
21
|
+
|
22
|
+
def format_string_argument(s)
|
23
|
+
@string_argument_formatter.format s
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require_relative 'argument_formatter'
|
2
|
+
|
3
|
+
module CommandBuilder
|
4
|
+
class CommandBase
|
5
|
+
|
6
|
+
attr_reader :passwords
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
puts 'aaaa'
|
10
|
+
@s = StringIO.new
|
11
|
+
@f = ArgumentFormatter.new
|
12
|
+
@passwords = []
|
13
|
+
end
|
14
|
+
|
15
|
+
def to_s
|
16
|
+
@s.string
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
require_relative 'fragment'
|
2
|
+
|
3
|
+
module CommandBuilderGenerator
|
4
|
+
class Node
|
5
|
+
|
6
|
+
def initialize(node_def)
|
7
|
+
@node_def = node_def
|
8
|
+
end
|
9
|
+
|
10
|
+
def child_nodes
|
11
|
+
@child_nodes ||= []
|
12
|
+
end
|
13
|
+
|
14
|
+
def branch?
|
15
|
+
!child_nodes.empty?
|
16
|
+
end
|
17
|
+
|
18
|
+
def leaf?
|
19
|
+
child_nodes.empty?
|
20
|
+
end
|
21
|
+
|
22
|
+
def node_name
|
23
|
+
@node_name ||= node_alias || (starts_with_arg? ? first_arg_name : words_preceding_args)
|
24
|
+
end
|
25
|
+
|
26
|
+
def fragments
|
27
|
+
@fragments ||= @node_def.gsub(/ \(.+?\)/, '').gsub(']', ']|').gsub('[', '|[').split('|').compact.map { |f| Fragment.new f }
|
28
|
+
end
|
29
|
+
|
30
|
+
def args
|
31
|
+
required_args + optional_args
|
32
|
+
end
|
33
|
+
|
34
|
+
protected
|
35
|
+
|
36
|
+
def required_args
|
37
|
+
select_args { |a| a.required? }
|
38
|
+
end
|
39
|
+
|
40
|
+
def optional_args
|
41
|
+
select_args { |a| a.optional? }
|
42
|
+
end
|
43
|
+
|
44
|
+
def starts_with_arg?
|
45
|
+
words_preceding_args.empty?
|
46
|
+
end
|
47
|
+
|
48
|
+
def first_arg_name
|
49
|
+
@node_def[/<(.+?)>/, 1]
|
50
|
+
end
|
51
|
+
|
52
|
+
def words_preceding_args
|
53
|
+
@node_def.gsub(/<.*/, '').gsub(/\W/, ' ').strip
|
54
|
+
end
|
55
|
+
|
56
|
+
def node_alias
|
57
|
+
@node_def[/\((.+?)\)/, 1]
|
58
|
+
end
|
59
|
+
|
60
|
+
def select_args
|
61
|
+
fragments.map { |f| f.args.map { |a| a if yield a } }.flatten.compact
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
require_relative 'string_extensions'
|
2
|
+
require_relative 'node'
|
3
|
+
require_relative 'node_code_names'
|
4
|
+
|
5
|
+
module CommandBuilderGenerator
|
6
|
+
class NodeCodeGenerator
|
7
|
+
|
8
|
+
def initialize(node, command, writer)
|
9
|
+
@node = node
|
10
|
+
@command = command
|
11
|
+
@writer = writer
|
12
|
+
end
|
13
|
+
|
14
|
+
def render
|
15
|
+
render_branch_node if @node.branch?
|
16
|
+
render_leaf_node if @node.leaf?
|
17
|
+
end
|
18
|
+
|
19
|
+
def render_method
|
20
|
+
@writer.write_method node_code_names.method_name, node_code_names.method_args do
|
21
|
+
if @node.branch?
|
22
|
+
render_branch_node_method_body
|
23
|
+
else
|
24
|
+
render_leaf_node_method_body
|
25
|
+
@writer.write_line '@s << yield if block_given?'
|
26
|
+
@writer.write_line 'self'
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def render_branch_node
|
34
|
+
@writer.write_class node_code_names.class_name, 'CommandBase' do
|
35
|
+
render_constructor
|
36
|
+
@node.child_nodes.each do |n|
|
37
|
+
generator = NodeCodeGenerator.new n, @command, @writer
|
38
|
+
generator.render_method
|
39
|
+
end
|
40
|
+
end
|
41
|
+
render_child_nodes
|
42
|
+
end
|
43
|
+
|
44
|
+
def render_leaf_node
|
45
|
+
render_child_nodes
|
46
|
+
end
|
47
|
+
|
48
|
+
def render_child_nodes
|
49
|
+
@node.child_nodes.each do |n|
|
50
|
+
generator = NodeCodeGenerator.new n, @command, @writer
|
51
|
+
generator.render
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def render_constructor
|
56
|
+
@writer.write_method 'initialize', node_code_names.method_args do
|
57
|
+
@writer.write_line 'super()'
|
58
|
+
render_leaf_node_method_body
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def render_branch_node_method_body
|
63
|
+
args = node_code_names.initializer_values
|
64
|
+
@writer.write_line "#{node_code_names.class_name}.new #{args.join ', '}"
|
65
|
+
end
|
66
|
+
|
67
|
+
def render_leaf_node_method_body
|
68
|
+
@node.fragments.each { |f| write_append_statement f }
|
69
|
+
end
|
70
|
+
|
71
|
+
def write_append_statement(fragment)
|
72
|
+
return if fragment.fragment_text.empty?
|
73
|
+
unless_condition = fragment.arg_names.map { |a| "#{a.snakecase}.nil?" }.join ' or '
|
74
|
+
statement = "@s << #{append_arg fragment}"
|
75
|
+
statement << " unless #{unless_condition}" if fragment.optional? and fragment.has_args?
|
76
|
+
@writer.write_line statement
|
77
|
+
end
|
78
|
+
|
79
|
+
def append_arg(fragment)
|
80
|
+
value = fragment.fragment_text.gsub(/<.+?>/) do |m|
|
81
|
+
arg = CommandArgument.new m
|
82
|
+
is_password = arg.arg_name.downcase.include? 'password'
|
83
|
+
|
84
|
+
if is_password
|
85
|
+
"\#{format_password #{arg.arg_name.snakecase}}"
|
86
|
+
else
|
87
|
+
format_args = [arg.arg_name.snakecase, [arg.delimiter, arg.key_value_separator].compact.map { |v| "'#{v}'" }].flatten
|
88
|
+
"\#{@f.format #{format_args.join ', '}}"
|
89
|
+
end
|
90
|
+
end
|
91
|
+
value.include?('#{') ? %Q["#{value}"] : "'#{value}'"
|
92
|
+
end
|
93
|
+
|
94
|
+
def node_code_names
|
95
|
+
@node_code_names ||= NodeCodeNames.new @node
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
99
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require_relative 'string_extensions'
|
2
|
+
|
3
|
+
module CommandBuilderGenerator
|
4
|
+
class NodeCodeNames
|
5
|
+
|
6
|
+
def initialize(node)
|
7
|
+
@node = node
|
8
|
+
end
|
9
|
+
|
10
|
+
def class_name
|
11
|
+
@node.node_name.camelcase
|
12
|
+
end
|
13
|
+
|
14
|
+
def method_name
|
15
|
+
@node.node_name.snakecase
|
16
|
+
end
|
17
|
+
|
18
|
+
def method_args
|
19
|
+
@node.args.map do |arg|
|
20
|
+
arg_name = arg.arg_name.snakecase
|
21
|
+
arg_name << '=nil' if arg.optional?
|
22
|
+
arg_name
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def initializer_values
|
27
|
+
@node.args.map { |arg| arg.arg_name.snakecase }
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
module CommandBuilderGenerator
|
2
|
+
class RubyCodeWriter
|
3
|
+
|
4
|
+
INDENT_SPACES = 2
|
5
|
+
|
6
|
+
attr_accessor :indent
|
7
|
+
|
8
|
+
def initialize(stream)
|
9
|
+
@stream = stream
|
10
|
+
@indent = 0
|
11
|
+
end
|
12
|
+
|
13
|
+
def indent
|
14
|
+
@indent += 1
|
15
|
+
if block_given?
|
16
|
+
yield
|
17
|
+
dedent
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def dedent
|
22
|
+
@indent -= 1
|
23
|
+
end
|
24
|
+
|
25
|
+
def write(code)
|
26
|
+
@stream.print code
|
27
|
+
end
|
28
|
+
|
29
|
+
def write_line(line='')
|
30
|
+
@stream.puts line.rjust(line.length + @indent * INDENT_SPACES, ' ')
|
31
|
+
end
|
32
|
+
|
33
|
+
def write_block(line)
|
34
|
+
write_line line
|
35
|
+
indent
|
36
|
+
yield
|
37
|
+
dedent
|
38
|
+
write_line 'end'
|
39
|
+
line
|
40
|
+
end
|
41
|
+
|
42
|
+
def write_module(module_name)
|
43
|
+
write_block("module #{module_name}") { yield }
|
44
|
+
end
|
45
|
+
|
46
|
+
def write_class(class_name, base_class_name=nil)
|
47
|
+
line = "class #{class_name}"
|
48
|
+
line << " < #{base_class_name}" if base_class_name
|
49
|
+
write_block(line) { yield }
|
50
|
+
end
|
51
|
+
|
52
|
+
def write_method(method_name, *args)
|
53
|
+
args = [args].flatten
|
54
|
+
line = "def #{method_name}"
|
55
|
+
line << "(#{args.join ', '})" unless args.empty?
|
56
|
+
write_block(line) { yield }
|
57
|
+
@stream.puts
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
|
2
|
+
class String
|
3
|
+
|
4
|
+
NEW_LINE = "\n"
|
5
|
+
|
6
|
+
def camelcase
|
7
|
+
words.join
|
8
|
+
end
|
9
|
+
|
10
|
+
def snakecase
|
11
|
+
words.join('_').downcase
|
12
|
+
end
|
13
|
+
|
14
|
+
def first_line
|
15
|
+
match(/^.*$/)[0]
|
16
|
+
end
|
17
|
+
|
18
|
+
def strip_first_line
|
19
|
+
first_line_index = self.index NEW_LINE
|
20
|
+
return '' unless first_line_index
|
21
|
+
self[first_line_index+1..self.length-1]
|
22
|
+
end
|
23
|
+
|
24
|
+
def split_and_strip(pattern)
|
25
|
+
split(pattern).map { |s| s.strip }
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def words
|
31
|
+
result = self =~ /^[A-Z]+$/ ? downcase : self
|
32
|
+
result.gsub(/[\W_]/, ' ').gsub(/[A-Z*]/, ' \0').split(' ').map { |s| s.capitalize }
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module CommandBuilderGenerator
|
2
|
+
class Version
|
3
|
+
|
4
|
+
VERSION_REGEX = '(?:\d+\.)+(?:\d+)'
|
5
|
+
DELIMITER = '.'
|
6
|
+
|
7
|
+
attr_accessor :version
|
8
|
+
|
9
|
+
def initialize(version)
|
10
|
+
raise "#{version} is not a valid version." unless Version.is_valid? version
|
11
|
+
@version = version
|
12
|
+
end
|
13
|
+
|
14
|
+
def compact
|
15
|
+
first 2, '_'
|
16
|
+
end
|
17
|
+
|
18
|
+
def first(count, delimiter=DELIMITER)
|
19
|
+
to_a.first(count).join(delimiter)
|
20
|
+
end
|
21
|
+
|
22
|
+
def to_s
|
23
|
+
@version
|
24
|
+
end
|
25
|
+
|
26
|
+
def to_a
|
27
|
+
@version.split DELIMITER
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.match(value)
|
31
|
+
exp = Regexp.new VERSION_REGEX
|
32
|
+
version = value.scan(exp)[0]
|
33
|
+
return unless version
|
34
|
+
Version.new(version)
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def self.is_valid?(version)
|
40
|
+
exp = Regexp.new "^#{VERSION_REGEX}$"
|
41
|
+
version.scan(exp)[0] != nil
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
end
|
metadata
ADDED
@@ -0,0 +1,95 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: command_builder_generator
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Matthew Riley
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-10-12 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: mocha
|
16
|
+
requirement: &70225892059240 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0.14'
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *70225892059240
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: rake
|
27
|
+
requirement: &70225892058760 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ~>
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '10.1'
|
33
|
+
type: :development
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *70225892058760
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: test-unit
|
38
|
+
requirement: &70225892058300 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ~>
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '2.5'
|
44
|
+
type: :development
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *70225892058300
|
47
|
+
description: Description
|
48
|
+
email: matthew@matthewriley.name
|
49
|
+
executables: []
|
50
|
+
extensions: []
|
51
|
+
extra_rdoc_files: []
|
52
|
+
files:
|
53
|
+
- lib/command_builder_generator/code_generator.rb
|
54
|
+
- lib/command_builder_generator/command.rb
|
55
|
+
- lib/command_builder_generator/command_argument.rb
|
56
|
+
- lib/command_builder_generator/command_code_names.rb
|
57
|
+
- lib/command_builder_generator/command_definition.rb
|
58
|
+
- lib/command_builder_generator/fragment.rb
|
59
|
+
- lib/command_builder_generator/lib/argument_formatter.rb
|
60
|
+
- lib/command_builder_generator/lib/argument_formatters/array_argument_formatter.rb
|
61
|
+
- lib/command_builder_generator/lib/argument_formatters/hash_argument_formatter.rb
|
62
|
+
- lib/command_builder_generator/lib/argument_formatters/string_argument_formatter.rb
|
63
|
+
- lib/command_builder_generator/lib/command_base.rb
|
64
|
+
- lib/command_builder_generator/node.rb
|
65
|
+
- lib/command_builder_generator/node_code_generator.rb
|
66
|
+
- lib/command_builder_generator/node_code_names.rb
|
67
|
+
- lib/command_builder_generator/ruby_code_writer.rb
|
68
|
+
- lib/command_builder_generator/string_extensions.rb
|
69
|
+
- lib/command_builder_generator/version.rb
|
70
|
+
- lib/command_builder_generator.rb
|
71
|
+
homepage:
|
72
|
+
licenses: []
|
73
|
+
post_install_message:
|
74
|
+
rdoc_options: []
|
75
|
+
require_paths:
|
76
|
+
- lib
|
77
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
78
|
+
none: false
|
79
|
+
requirements:
|
80
|
+
- - ! '>='
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
84
|
+
none: false
|
85
|
+
requirements:
|
86
|
+
- - ! '>='
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: '0'
|
89
|
+
requirements: []
|
90
|
+
rubyforge_project:
|
91
|
+
rubygems_version: 1.8.15
|
92
|
+
signing_key:
|
93
|
+
specification_version: 3
|
94
|
+
summary: Summary
|
95
|
+
test_files: []
|