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.
Files changed (43) hide show
  1. checksums.yaml +5 -5
  2. data/.DS_Store +0 -0
  3. data/.rubocop.yml +5 -0
  4. data/README.md +102 -4
  5. data/Rakefile +3 -3
  6. data/bin/console +3 -3
  7. data/exe/redbreast +17 -5
  8. data/lib/.DS_Store +0 -0
  9. data/lib/redbreast.rb +25 -17
  10. data/lib/redbreast/.DS_Store +0 -0
  11. data/lib/redbreast/commands/color_generator.rb +54 -0
  12. data/lib/redbreast/commands/color_test_generator.rb +57 -0
  13. data/lib/redbreast/commands/configuration_installer.rb +37 -0
  14. data/lib/redbreast/commands/image_generator.rb +49 -47
  15. data/lib/redbreast/commands/image_test_generator.rb +57 -0
  16. data/lib/redbreast/commands/setup.rb +139 -91
  17. data/lib/redbreast/crawlers/color_crawler.rb +38 -0
  18. data/lib/redbreast/crawlers/image_crawler.rb +30 -10
  19. data/lib/redbreast/error_handler.rb +7 -6
  20. data/lib/redbreast/helpers/general.rb +73 -63
  21. data/lib/redbreast/helpers/hash.rb +8 -8
  22. data/lib/redbreast/helpers/terminal.rb +2 -3
  23. data/lib/redbreast/io/config.rb +14 -15
  24. data/lib/redbreast/serializers/objc_serializer.rb +66 -19
  25. data/lib/redbreast/serializers/serializer.rb +17 -16
  26. data/lib/redbreast/serializers/swift_serializer.rb +90 -2
  27. data/lib/redbreast/template_generators/.DS_Store +0 -0
  28. data/lib/redbreast/template_generators/colors/objc_colors_template_generator.rb +35 -0
  29. data/lib/redbreast/template_generators/colors/swift_colors_template_generator.rb +22 -0
  30. data/lib/redbreast/template_generators/images/objc_images_template_generator.rb +27 -41
  31. data/lib/redbreast/template_generators/images/swift_images_template_generator.rb +16 -21
  32. data/lib/redbreast/template_generators/objc_template_generator.rb +19 -19
  33. data/lib/redbreast/template_generators/swift_template_generator.rb +9 -10
  34. data/lib/redbreast/template_generators/tests/colors/objc_colors_tests_template_generator.rb +35 -0
  35. data/lib/redbreast/template_generators/tests/colors/swift_colors_tests_template_generator.rb +27 -0
  36. data/lib/redbreast/template_generators/tests/images/objc_images_tests_template_generator.rb +36 -0
  37. data/lib/redbreast/template_generators/tests/images/swift_images_tests_template_generator.rb +27 -0
  38. data/lib/redbreast/version.rb +1 -1
  39. data/redbreast.gemspec +22 -22
  40. metadata +54 -15
  41. data/lib/redbreast/commands/test_generator.rb +0 -56
  42. data/lib/redbreast/template_generators/tests/objc_tests_template_generator.rb +0 -39
  43. 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
- module Command
6
- class Setup
7
- include Helper::Terminal
8
- include Helper::General
9
- include Helper::Hash
10
-
11
- def self.init(options = Commander::Command::Options.new)
12
- new(options).call
13
- end
14
-
15
- def initialize(options = Commander::Command::Options.new)
16
- @options = options
17
- end
18
-
19
- def call
20
- language = language_prompt
21
- bundle_names = bundle_names_prompt(language).split(" ")
22
- bundles = bundle_names.map do |bundle|
23
- reference = bundle_reference(bundle, language)
24
- assets_search_path = assets_search_path_prompt(bundle)
25
- output_source_path = images_sources_path_prompt(bundle, language)
26
- include_tests = create_tests_path_prompt?(bundle)
27
- {
28
- name: bundle,
29
- reference: reference,
30
- assetsSearchPath: assets_search_path,
31
- outputSourcePath: output_source_path,
32
- outputTestPath: include_tests ? tests_path_prompt(bundle, language) : nil,
33
- testableImport: include_tests ? testable_import_prompt(bundle, language) : nil
34
- }.compact
35
- end
36
- config = {
37
- language: language,
38
- bundles: bundles
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
- Redbreast::IO::Config.write(config)
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
- # Assets source path
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
- def assets_search_path_prompt(bundle)
56
- prompt.ask("Please enter assets folder search paths for bundle #{bundle}?", default: '**/*.xcassets')
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
- # Bundle names promt
60
-
61
- def bundle_names_prompt(language)
62
- case language
63
- when "objc"
64
- prompt.ask('Please enter bundle names that you use separated by spaces', default: 'mainBundle')
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
- def bundle_reference(bundle_name, language)
71
- case language
72
- when "objc"
73
- "[NSBundle #{bundle_name}]"
74
- when "swift"
75
- ".#{bundle_name}"
76
- end
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
- # Images source path
103
+ # Colors source path
80
104
 
81
- def images_sources_path_prompt(bundle, language)
82
- case language
83
- when "objc"
84
- prompt.ask("Where would you like to store images resources files for bundle #{bundle}?", default: './Common/Categories/Images')
85
- when "swift"
86
- prompt.ask("Where would you like to store images resources files for bundle #{bundle}?", default: './Common/Extensions/UIImageExtension.swift')
87
- end
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
- # Tests
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
- def create_tests_path_prompt?(bundle)
93
- prompt.yes?("Would you like to create tests for bundle #{bundle}?")
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
- def tests_path_prompt(bundle, language)
97
- case language
98
- when "objc"
99
- prompt.ask("Where would you like to store tests for bundle #{bundle}?", default: './Common/Categories/ImagesTest')
100
- when "swift"
101
- prompt.ask("Where would you like to store tests for bundle #{bundle}?", default: './Common/Extensions/UIImageExtensionTest.swift')
102
- end
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
- def testable_import_prompt(bundle, language)
106
- case language
107
- when "objc"
108
- nil
109
- when "swift"
110
- prompt.ask("Please enter testable import name for bundle #{bundle}?", required: true)
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 { |asset_folder|
7
- Dir.glob("#{asset_folder}/**/*.imageset").map { |image_name|
8
- image_name.split("/")[-1].chomp(".imageset")
9
- }
10
- }
11
- .uniq
12
- end
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(e)
13
+ def handle(error)
13
14
  prompt.error(
14
- case e
15
+ case error
15
16
  when Errno::ENOENT
16
- "We could not find a file that we need:\n\n#{e.message}"
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#{e.message}"
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
- module Helper
3
- module General
4
- ESCAPE_KEYWORDS = ["associatedtype", "class", "deinit", "enum", "extension", "fileprivate", "func",
5
- "import", "init", "inout", "internal", "let", "operator", "private", "protocol",
6
- "public", "static", "struct", "subscript", "typealias", "var", "break", "case",
7
- "continue", "default", "defer", "do", "else", "fallthrough", "for", "guard", "if",
8
- "in", "repeat", "return", "switch", "where", "while", "as", "Any", "catch", "false",
9
- "is", "nil", "rethrows", "super", "self", "Self", "throw", "throws", "true", "try", "_"]
10
-
11
- def config
12
- @config ||= Redbreast::IO::Config.read
13
- end
14
-
15
- def programming_language
16
- @programming_language ||= config[:language]
17
- end
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
- def bundles
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