redbreast 0.1.0 → 1.0.2
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.
- checksums.yaml +5 -5
- data/.DS_Store +0 -0
- data/.rubocop.yml +5 -0
- data/README.md +102 -4
- data/Rakefile +3 -3
- data/bin/console +3 -3
- data/exe/redbreast +17 -5
- data/lib/.DS_Store +0 -0
- data/lib/redbreast.rb +25 -17
- data/lib/redbreast/.DS_Store +0 -0
- data/lib/redbreast/commands/color_generator.rb +54 -0
- data/lib/redbreast/commands/color_test_generator.rb +57 -0
- data/lib/redbreast/commands/configuration_installer.rb +37 -0
- data/lib/redbreast/commands/image_generator.rb +49 -47
- data/lib/redbreast/commands/image_test_generator.rb +57 -0
- data/lib/redbreast/commands/setup.rb +139 -91
- data/lib/redbreast/crawlers/color_crawler.rb +38 -0
- data/lib/redbreast/crawlers/image_crawler.rb +30 -10
- data/lib/redbreast/error_handler.rb +7 -6
- data/lib/redbreast/helpers/general.rb +73 -63
- data/lib/redbreast/helpers/hash.rb +8 -8
- data/lib/redbreast/helpers/terminal.rb +2 -3
- data/lib/redbreast/io/config.rb +14 -15
- data/lib/redbreast/serializers/objc_serializer.rb +66 -19
- data/lib/redbreast/serializers/serializer.rb +17 -16
- data/lib/redbreast/serializers/swift_serializer.rb +90 -2
- data/lib/redbreast/template_generators/.DS_Store +0 -0
- data/lib/redbreast/template_generators/colors/objc_colors_template_generator.rb +35 -0
- data/lib/redbreast/template_generators/colors/swift_colors_template_generator.rb +22 -0
- data/lib/redbreast/template_generators/images/objc_images_template_generator.rb +27 -41
- data/lib/redbreast/template_generators/images/swift_images_template_generator.rb +16 -21
- data/lib/redbreast/template_generators/objc_template_generator.rb +19 -19
- data/lib/redbreast/template_generators/swift_template_generator.rb +9 -10
- data/lib/redbreast/template_generators/tests/colors/objc_colors_tests_template_generator.rb +35 -0
- data/lib/redbreast/template_generators/tests/colors/swift_colors_tests_template_generator.rb +27 -0
- data/lib/redbreast/template_generators/tests/images/objc_images_tests_template_generator.rb +36 -0
- data/lib/redbreast/template_generators/tests/images/swift_images_tests_template_generator.rb +27 -0
- data/lib/redbreast/version.rb +1 -1
- data/redbreast.gemspec +22 -22
- metadata +54 -15
- data/lib/redbreast/commands/test_generator.rb +0 -56
- data/lib/redbreast/template_generators/tests/objc_tests_template_generator.rb +0 -39
- data/lib/redbreast/template_generators/tests/swift_tests_template_generator.rb +0 -31
@@ -0,0 +1,57 @@
|
|
1
|
+
module Redbreast
|
2
|
+
module Command
|
3
|
+
# Class for generating image tests
|
4
|
+
class ImageTestGenerator
|
5
|
+
include Helper::Terminal
|
6
|
+
include Helper::General
|
7
|
+
|
8
|
+
def self.init
|
9
|
+
new.call
|
10
|
+
end
|
11
|
+
|
12
|
+
def call
|
13
|
+
filtered_bundles = bundles.select { |bundle| bundle[:outputTestPathImages] }
|
14
|
+
return if filtered_bundles.empty?
|
15
|
+
|
16
|
+
prompt.say('Generating images test resources...')
|
17
|
+
generate_test_sources(bundles, programming_language, app_name)
|
18
|
+
success('Images test resources generated!')
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def generate_test_sources(bundles, programming_language, app_name)
|
24
|
+
bundles.each do |bundle|
|
25
|
+
image_names = pull_asset_names(bundle[:assetsSearchPath])
|
26
|
+
write_tests(image_names, bundle, programming_language, app_name)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# Serializing data
|
31
|
+
|
32
|
+
def write_tests(image_names, bundle, programming_language, app_name)
|
33
|
+
output_path = bundle[:outputTestPathImages]
|
34
|
+
|
35
|
+
return if output_path.to_s.empty?
|
36
|
+
|
37
|
+
case programming_language.downcase
|
38
|
+
when 'objc'
|
39
|
+
serializer = Redbreast::Serializer::ObjC
|
40
|
+
template_generator = Redbreast::TemplateGenerator::ImageTest::ObjC
|
41
|
+
when 'swift'
|
42
|
+
serializer = Redbreast::Serializer::Swift
|
43
|
+
template_generator = Redbreast::TemplateGenerator::ImageTest::Swift
|
44
|
+
end
|
45
|
+
serializer.new(image_names, bundle, app_name).save(output_source_path: output_path, template_generator: template_generator.new, generate_colors: false)
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
# Pulling data
|
50
|
+
|
51
|
+
def pull_asset_names(assetsSearchPath)
|
52
|
+
Redbreast::Crawler::Image
|
53
|
+
.image_names_uniq(assetsSearchPath)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -2,115 +2,163 @@ require 'commander/blank'
|
|
2
2
|
require 'commander/command'
|
3
3
|
|
4
4
|
module Redbreast
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
5
|
+
module Command
|
6
|
+
# Class for setting up the program
|
7
|
+
class Setup
|
8
|
+
include Helper::Terminal
|
9
|
+
include Helper::General
|
10
|
+
include Helper::HashHelper
|
11
|
+
|
12
|
+
def self.init(options = Commander::Command::Options.new)
|
13
|
+
new(options).call
|
14
|
+
end
|
15
|
+
|
16
|
+
def initialize(options = Commander::Command::Options.new)
|
17
|
+
@options = options
|
18
|
+
end
|
19
|
+
|
20
|
+
def call
|
21
|
+
language = language_prompt
|
22
|
+
app_name = app_name_prompt
|
23
|
+
bundle_names = bundle_names_prompt(language).split(' ')
|
24
|
+
assets_types = assets_types_prompt
|
25
|
+
bundles = bundle_names.map do |bundle|
|
26
|
+
reference = bundle_reference(bundle, language)
|
27
|
+
assets_search_path = assets_search_path_prompt(bundle)
|
28
|
+
output_source_path_images = assets_types == 1 ? nil : images_sources_path_prompt(bundle, language)
|
29
|
+
output_source_path_colors = assets_types.zero? ? nil : colors_sources_path_prompt(bundle, language)
|
30
|
+
include_tests = create_tests_path_prompt?(bundle)
|
31
|
+
output_test_path_images = assets_types != 1 && include_tests ? images_tests_path_prompt(bundle, language) : nil
|
32
|
+
output_test_path_colors = assets_types != 0 && include_tests ? colors_tests_path_prompt(bundle, language) : nil
|
33
|
+
fields = {
|
34
|
+
name: bundle,
|
35
|
+
reference: reference,
|
36
|
+
assetsSearchPath: assets_search_path,
|
37
|
+
outputSourcePathImages: output_source_path_images,
|
38
|
+
outputSourcePathColors: output_source_path_colors,
|
39
|
+
outputTestPathImages: output_test_path_images,
|
40
|
+
outputTestPathColors: output_test_path_colors,
|
41
|
+
testableImport: include_tests ? testable_import_prompt(bundle, app_name, language) : nil
|
39
42
|
}
|
40
|
-
|
41
|
-
success
|
42
|
-
end
|
43
|
-
|
44
|
-
private
|
45
|
-
|
46
|
-
# Language
|
47
|
-
|
48
|
-
def language_prompt
|
49
|
-
languages = {'Swift' => 'swift', 'Objective-C' => 'objc'}
|
50
|
-
prompt.select('Choose a language: ', languages)
|
43
|
+
compact fields
|
51
44
|
end
|
52
|
-
|
53
|
-
|
45
|
+
config = {
|
46
|
+
language: language,
|
47
|
+
bundles: bundles,
|
48
|
+
app_name: app_name
|
49
|
+
}
|
50
|
+
Redbreast::IO::Config.write(config)
|
51
|
+
success
|
52
|
+
end
|
53
|
+
|
54
|
+
private
|
55
|
+
|
56
|
+
# Language
|
57
|
+
|
58
|
+
def language_prompt
|
59
|
+
languages = { 'Swift' => 'swift', 'Objective-C' => 'objc' }
|
60
|
+
prompt.select('Choose a language: ', languages)
|
61
|
+
end
|
62
|
+
|
63
|
+
# Assets source path
|
64
|
+
|
65
|
+
def assets_search_path_prompt(bundle)
|
66
|
+
prompt_text = "Please enter assets folder search paths for bundle #{bundle}?"
|
67
|
+
prompt.ask(prompt_text, default: '**/*.xcassets')
|
68
|
+
end
|
54
69
|
|
55
|
-
|
56
|
-
|
70
|
+
# Bundle names promt
|
71
|
+
|
72
|
+
def bundle_names_prompt(language)
|
73
|
+
prompt_text = 'Please enter bundle names that you use separated by spaces'
|
74
|
+
case language
|
75
|
+
when 'objc'
|
76
|
+
prompt.ask(prompt_text, default: 'mainBundle')
|
77
|
+
when 'swift'
|
78
|
+
prompt.ask(prompt_text, default: 'main')
|
57
79
|
end
|
80
|
+
end
|
58
81
|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
when "swift"
|
66
|
-
prompt.ask('Please enter bundle names that you use separated by spaces', default: 'main')
|
67
|
-
end
|
82
|
+
def bundle_reference(bundle_name, language)
|
83
|
+
case language
|
84
|
+
when 'objc'
|
85
|
+
"[NSBundle #{bundle_name}]"
|
86
|
+
when 'swift'
|
87
|
+
".#{bundle_name}"
|
68
88
|
end
|
89
|
+
end
|
90
|
+
|
91
|
+
# Images source path
|
69
92
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
93
|
+
def images_sources_path_prompt(bundle, language)
|
94
|
+
prompt_text = "Where would you like to store images resources files for bundle #{bundle}?"
|
95
|
+
case language
|
96
|
+
when 'objc'
|
97
|
+
prompt.ask(prompt_text, default: './Common/Categories/Images')
|
98
|
+
when 'swift'
|
99
|
+
prompt.ask(prompt_text, default: './Common/Extensions/UIImageExtension.swift')
|
77
100
|
end
|
101
|
+
end
|
78
102
|
|
79
|
-
|
103
|
+
# Colors source path
|
80
104
|
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
105
|
+
def colors_sources_path_prompt(bundle, language)
|
106
|
+
prompt_text = "Where would you like to store colors resources files for bundle #{bundle}?"
|
107
|
+
case language
|
108
|
+
when 'objc'
|
109
|
+
prompt.ask(prompt_text, default: './Common/Categories/Colors')
|
110
|
+
when 'swift'
|
111
|
+
prompt.ask(prompt_text, default: './Common/Extensions/UIColorExtension.swift')
|
88
112
|
end
|
113
|
+
end
|
89
114
|
|
90
|
-
|
115
|
+
# Tests
|
116
|
+
|
117
|
+
def create_tests_path_prompt?(bundle)
|
118
|
+
prompt.yes?("Would you like to create tests for bundle #{bundle}?")
|
119
|
+
end
|
91
120
|
|
92
|
-
|
93
|
-
|
121
|
+
def images_tests_path_prompt(bundle, language)
|
122
|
+
prompt_text = "Where would you like to store tests for bundle #{bundle}?"
|
123
|
+
case language
|
124
|
+
when 'objc'
|
125
|
+
prompt.ask(prompt_text, default: './Common/Categories/ImagesTest')
|
126
|
+
when 'swift'
|
127
|
+
prompt.ask(prompt_text, default: './Common/Extensions/UIImageExtensionTest.swift')
|
94
128
|
end
|
129
|
+
end
|
95
130
|
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
131
|
+
def colors_tests_path_prompt(bundle, language)
|
132
|
+
prompt_text = "Where would you like to store tests for bundle #{bundle}?"
|
133
|
+
case language
|
134
|
+
when 'objc'
|
135
|
+
prompt.ask(prompt_text, default: './Common/Categories/ColorsTest')
|
136
|
+
when 'swift'
|
137
|
+
prompt.ask(prompt_text, default: './Common/Extensions/UIColorExtensionTest.swift')
|
103
138
|
end
|
139
|
+
end
|
104
140
|
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
end
|
141
|
+
def testable_import_prompt(bundle, app_name, language)
|
142
|
+
case language
|
143
|
+
when 'objc'
|
144
|
+
nil
|
145
|
+
when 'swift'
|
146
|
+
prompt.ask("Please enter a name that will be used for testable import in #{bundle} bundle?", default: "#{app_name}", required: true)
|
112
147
|
end
|
148
|
+
end
|
149
|
+
|
150
|
+
# Application name propmt
|
151
|
+
|
152
|
+
def app_name_prompt
|
153
|
+
prompt.ask('Please enter application name')
|
154
|
+
end
|
155
|
+
|
156
|
+
# Assets type prompt
|
113
157
|
|
158
|
+
def assets_types_prompt
|
159
|
+
types = { 'Images' => 0, 'Colors' => 1, 'Both' => 2 }
|
160
|
+
prompt.select('Choose a type: ', types)
|
114
161
|
end
|
115
162
|
end
|
116
|
-
end
|
163
|
+
end
|
164
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Redbreast
|
2
|
+
module Crawler
|
3
|
+
# Class used for finding colors
|
4
|
+
class Color
|
5
|
+
def self.color_names_uniq(assets_search_path)
|
6
|
+
Dir.glob(assets_search_path).flat_map do |asset_folder|
|
7
|
+
Dir.glob("#{asset_folder}/**/*.colorset").map do |color_name|
|
8
|
+
name_to_split = color_name
|
9
|
+
split_name = name_to_split.split('.xcassets/')
|
10
|
+
current_color_name = split_name[0] + '.xcassets/'
|
11
|
+
current_iterating_name = split_name[0] + '.xcassets/'
|
12
|
+
|
13
|
+
split_name[1].split('/').each do |folder|
|
14
|
+
if folder.include? '.colorset'
|
15
|
+
current_color_name += folder
|
16
|
+
next
|
17
|
+
end
|
18
|
+
|
19
|
+
current_iterating_name += folder + '/'
|
20
|
+
|
21
|
+
Dir.glob("#{current_iterating_name}*.json").map do |path_name|
|
22
|
+
File.open path_name do |file|
|
23
|
+
unless file.find { |line| line =~ /provides/ }.nil?
|
24
|
+
current_color_name += folder + '/'
|
25
|
+
next
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
current_color_name.split('.xcassets/')[-1].chomp('.colorset')
|
32
|
+
end
|
33
|
+
end
|
34
|
+
.uniq
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -1,18 +1,38 @@
|
|
1
1
|
module Redbreast
|
2
2
|
module Crawler
|
3
|
+
# Class for finding images
|
3
4
|
class Image
|
4
|
-
|
5
5
|
def self.image_names_uniq(assets_search_path)
|
6
|
-
Dir.glob(assets_search_path).flat_map
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
6
|
+
Dir.glob(assets_search_path).flat_map do |asset_folder|
|
7
|
+
Dir.glob("#{asset_folder}/**/*.imageset").map do |image_name|
|
8
|
+
name_to_split = image_name
|
9
|
+
split_name = name_to_split.split('.xcassets/')
|
10
|
+
current_image_name = split_name[0] + '.xcassets/'
|
11
|
+
current_iterating_name = split_name[0] + '.xcassets/'
|
12
|
+
|
13
|
+
split_name[1].split('/').each do |folder|
|
14
|
+
if folder.include? '.imageset'
|
15
|
+
current_image_name += folder
|
16
|
+
next
|
17
|
+
end
|
18
|
+
|
19
|
+
current_iterating_name += folder + '/'
|
13
20
|
|
21
|
+
Dir.glob("#{current_iterating_name}*.json").map do |path_name|
|
22
|
+
File.open path_name do |file|
|
23
|
+
unless file.find { |line| line =~ /provides/ }.nil?
|
24
|
+
current_image_name += folder + '/'
|
25
|
+
next
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
current_image_name.split('.xcassets/')[-1].chomp('.imageset')
|
32
|
+
end
|
33
|
+
end
|
34
|
+
.uniq
|
35
|
+
end
|
14
36
|
end
|
15
37
|
end
|
16
38
|
end
|
17
|
-
|
18
|
-
|
@@ -1,24 +1,25 @@
|
|
1
1
|
module Redbreast
|
2
|
+
# Class for handling errors that occurr
|
2
3
|
class ErrorHandler
|
3
4
|
extend Helper::Terminal
|
4
5
|
|
5
6
|
class << self
|
6
7
|
def rescuable
|
7
8
|
yield
|
8
|
-
rescue => e
|
9
|
+
rescue StandardError => e
|
9
10
|
handle(e)
|
10
11
|
end
|
11
12
|
|
12
|
-
def handle(
|
13
|
+
def handle(error)
|
13
14
|
prompt.error(
|
14
|
-
case
|
15
|
+
case error
|
15
16
|
when Errno::ENOENT
|
16
|
-
"We could not find a file that we need:\n\n#{
|
17
|
+
"We could not find a file that we need:\n\n#{error.message}"
|
17
18
|
else
|
18
|
-
"An error happened. This might help:\n\n#{
|
19
|
+
"An error happened. This might help:\n\n#{error.message}"
|
19
20
|
end
|
20
21
|
)
|
21
22
|
end
|
22
23
|
end
|
23
24
|
end
|
24
|
-
end
|
25
|
+
end
|
@@ -1,67 +1,77 @@
|
|
1
1
|
module Redbreast
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
2
|
+
module Helper
|
3
|
+
# Module with general metods used in creating files
|
4
|
+
module General
|
5
|
+
ESCAPE_KEYWORDS = ['associatedtype', 'class', 'deinit', 'enum', 'extension',
|
6
|
+
'fileprivate', 'func', 'import', 'init', 'inout',
|
7
|
+
'internal', 'let', 'operator', 'private', 'protocol',
|
8
|
+
'public', 'static', 'struct', 'subscript', 'typealias',
|
9
|
+
'var', 'break', 'case', 'continue', 'default',
|
10
|
+
'defer', 'do', 'else', 'fallthrough', 'for',
|
11
|
+
'guard', 'if', 'in', 'repeat', 'return',
|
12
|
+
'switch', 'where', 'while', 'as', 'Any',
|
13
|
+
'catch', 'false', 'is', 'nil', 'rethrows',
|
14
|
+
'super', 'self', 'Self', 'throw', 'throws',
|
15
|
+
'true', 'try', '_'].freeze
|
16
|
+
def config
|
17
|
+
@config ||= Redbreast::IO::Config.read
|
18
|
+
end
|
19
|
+
|
20
|
+
def programming_language
|
21
|
+
@programming_language ||= config[:language]
|
22
|
+
end
|
23
|
+
|
24
|
+
def bundles
|
25
|
+
@bundles ||= config[:bundles]
|
26
|
+
end
|
27
|
+
|
28
|
+
def app_name
|
29
|
+
@app_name ||= config[:app_name]
|
30
|
+
end
|
31
|
+
|
32
|
+
def indent(level = 0, initial = '')
|
33
|
+
(1..level)
|
34
|
+
.to_a.reduce('') { |result, _| result + ' ' }
|
35
|
+
.concat(initial)
|
36
|
+
end
|
37
|
+
|
38
|
+
def clean_enum_name(name)
|
39
|
+
clean_name = name
|
40
|
+
.split(/[^0-9a-zA-Z]/)
|
41
|
+
.reject(&:empty?)
|
42
|
+
.map(&:capitalize)
|
43
|
+
.join
|
44
|
+
|
45
|
+
escape_with_underscore_if_needed(clean_name)
|
46
|
+
end
|
47
|
+
|
48
|
+
def clean_case_name(name)
|
49
|
+
clean_variable_name(name)
|
50
|
+
end
|
51
|
+
|
52
|
+
def clean_variable_name(name)
|
53
|
+
clean_name = name
|
54
|
+
.split(/[^0-9a-zA-Z]/)
|
55
|
+
.reject(&:empty?)
|
56
|
+
.each_with_index
|
57
|
+
.map { |v, i| i.zero? ? v.tap { |char| char[0] = char[0].downcase } : v.capitalize }
|
58
|
+
.join
|
59
|
+
|
60
|
+
escaped_underscore = escape_with_underscore_if_needed(clean_name)
|
61
|
+
escape_keyword_if_needed(escaped_underscore)
|
62
|
+
end
|
63
|
+
|
64
|
+
def escape_with_underscore_if_needed(name)
|
65
|
+
return name if name.match(/^[A-Za-z_]/)
|
66
|
+
|
67
|
+
'_' + name
|
68
|
+
end
|
69
|
+
|
70
|
+
def escape_keyword_if_needed(name)
|
71
|
+
return name unless ESCAPE_KEYWORDS.include? name
|
18
72
|
|
19
|
-
|
20
|
-
@bundles ||= config[:bundles]
|
21
|
-
end
|
22
|
-
|
23
|
-
def indent(level = 0, initial = "")
|
24
|
-
(1..level)
|
25
|
-
.to_a.reduce("") { |result, value| result + " " }
|
26
|
-
.concat(initial)
|
27
|
-
end
|
28
|
-
|
29
|
-
def clean_enum_name(name)
|
30
|
-
clean_name = name
|
31
|
-
.split(/[^0-9a-zA-Z]/)
|
32
|
-
.reject { |c| c.empty? }
|
33
|
-
.map { |value| value.capitalize }
|
34
|
-
.join
|
35
|
-
|
36
|
-
escape_with_underscore_if_needed(clean_name)
|
37
|
-
end
|
38
|
-
|
39
|
-
def clean_case_name(name)
|
40
|
-
clean_variable_name(name)
|
41
|
-
end
|
42
|
-
|
43
|
-
def clean_variable_name(name)
|
44
|
-
clean_name = name
|
45
|
-
.split(/[^0-9a-zA-Z]/)
|
46
|
-
.reject { |c| c.empty? }
|
47
|
-
.each_with_index
|
48
|
-
.map { |value, index| index == 0 ? value.downcase : value.capitalize }
|
49
|
-
.join
|
50
|
-
|
51
|
-
escaped_underscore = escape_with_underscore_if_needed(clean_name)
|
52
|
-
escape_keyword_if_needed(escaped_underscore)
|
53
|
-
end
|
54
|
-
|
55
|
-
def escape_with_underscore_if_needed(name)
|
56
|
-
return name if name.match(/^[A-Za-z_]/)
|
57
|
-
"_" + name
|
58
|
-
end
|
59
|
-
|
60
|
-
def escape_keyword_if_needed(name)
|
61
|
-
return name if !ESCAPE_KEYWORDS.include? name
|
62
|
-
"`#{name}`"
|
63
|
-
end
|
64
|
-
|
73
|
+
"`#{name}`"
|
65
74
|
end
|
66
75
|
end
|
67
|
-
end
|
76
|
+
end
|
77
|
+
end
|