command_builder 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- 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:
|