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:
|