redbreast 0.1.2 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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 +9 -7
- data/lib/.DS_Store +0 -0
- data/lib/redbreast.rb +25 -18
- 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 +29 -29
- 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 -92
- 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 -7
- 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 +93 -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 +21 -22
- metadata +35 -11
- 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
@@ -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.tap { |char| char[0] = char[0].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
|
@@ -1,9 +1,10 @@
|
|
1
1
|
module Redbreast
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
2
|
+
module Helper
|
3
|
+
# Module used for creating compact dictionaries
|
4
|
+
module HashHelper
|
5
|
+
def compact(dictionary)
|
6
|
+
dictionary.delete_if { |_k, v| v.nil? }
|
7
|
+
end
|
8
8
|
end
|
9
|
-
end
|
9
|
+
end
|
10
|
+
end
|
@@ -2,8 +2,8 @@ require 'tty-prompt'
|
|
2
2
|
|
3
3
|
module Redbreast
|
4
4
|
module Helper
|
5
|
+
# Module used for communicatin with user via terminal
|
5
6
|
module Terminal
|
6
|
-
|
7
7
|
def success(message = 'Success!')
|
8
8
|
prompt.ok(message)
|
9
9
|
end
|
@@ -11,7 +11,6 @@ module Redbreast
|
|
11
11
|
def prompt
|
12
12
|
@prompt ||= TTY::Prompt.new(interrupt: :exit)
|
13
13
|
end
|
14
|
-
|
15
14
|
end
|
16
15
|
end
|
17
|
-
end
|
16
|
+
end
|
data/lib/redbreast/io/config.rb
CHANGED
@@ -1,19 +1,18 @@
|
|
1
1
|
module Redbreast
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
end
|
2
|
+
module IO
|
3
|
+
# Used for reading and writing to config file
|
4
|
+
class Config
|
5
|
+
CONFIG_FILE_PATH = "#{Dir.pwd}/.redbrest.yml"
|
6
|
+
|
7
|
+
class << self
|
8
|
+
def write(data)
|
9
|
+
File.open(CONFIG_FILE_PATH, 'w') { |file| YAML.dump(data, file) }
|
10
|
+
end
|
11
|
+
|
12
|
+
def read
|
13
|
+
YAML.load_file(CONFIG_FILE_PATH)
|
15
14
|
end
|
16
|
-
|
17
15
|
end
|
18
16
|
end
|
19
|
-
end
|
17
|
+
end
|
18
|
+
end
|
@@ -1,27 +1,74 @@
|
|
1
|
-
require_relative 'serializer'
|
1
|
+
require_relative 'serializer'
|
2
2
|
|
3
3
|
module Redbreast
|
4
4
|
module Serializer
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
5
|
+
# Used for saving and creating ObjC files
|
6
|
+
class ObjC < Base
|
7
|
+
include Helper::General
|
8
|
+
|
9
|
+
def save(output_source_path:, template_generator:, generate_colors:)
|
10
|
+
FileUtils.mkdir_p output_source_path unless File.exist? output_source_path
|
11
|
+
|
12
|
+
file_base_name = generate_colors ? 'UIColor' : 'UIImage'
|
13
|
+
name = app_name.nil? ? 'Common' : app_name
|
14
|
+
|
15
|
+
if template_generator.h_template
|
16
|
+
write(output_source_path, template_generator.h_template, "#{file_base_name}+#{name}.h")
|
17
|
+
end
|
18
|
+
|
19
|
+
return unless template_generator.m_template
|
20
|
+
|
21
|
+
write(output_source_path, template_generator.m_template, "#{file_base_name}+#{name}.m")
|
22
|
+
end
|
23
|
+
|
24
|
+
def write(output_source_path, template, file_name)
|
25
|
+
file = ERB.new(template, nil, '-').result(binding)
|
26
|
+
File.write(File.join(output_source_path, file_name), file)
|
27
|
+
end
|
28
|
+
|
29
|
+
def create_objc_test_cases(names:, variable:)
|
30
|
+
text = ''
|
31
|
+
names.each do |name|
|
32
|
+
temp_array = name.split('/')
|
33
|
+
variable_name = temp_array.length == 1 ? clean_variable_name(name) : temp_array.unshift(temp_array.shift.downcase).join('')
|
34
|
+
text += variable % variable_name
|
23
35
|
end
|
36
|
+
text
|
37
|
+
end
|
38
|
+
|
39
|
+
def generate_m_file_objc(names:, variable_declaration:, variable_implementation:, bundle_name:)
|
40
|
+
text = ''
|
41
|
+
|
42
|
+
names.each do |name|
|
43
|
+
temp_arr = name.split('/')
|
44
|
+
|
45
|
+
variable_name = temp_arr.length == 1 ? clean_variable_name(name) : temp_arr.unshift(temp_arr.shift.downcase).join('')
|
46
|
+
text += variable_declaration % variable_name + variable_implementation % [name, bundle_name[:reference]]
|
47
|
+
text += name == names.last ? '' : "\n"
|
48
|
+
end
|
49
|
+
|
50
|
+
text
|
51
|
+
end
|
52
|
+
|
53
|
+
def generate_h_file_objc(names:, variable:)
|
54
|
+
text = ''
|
55
|
+
|
56
|
+
names.each do |name|
|
57
|
+
temp_arr = name.split('/')
|
58
|
+
variable_name = temp_arr.length == 1 ? clean_variable_name(name) : temp_arr.unshift(temp_arr.shift.downcase).join('')
|
59
|
+
text += variable % variable_name
|
60
|
+
end
|
61
|
+
|
62
|
+
text
|
63
|
+
end
|
64
|
+
|
65
|
+
def generate_category(type, class_name, app_name)
|
66
|
+
text = "@#{type} #{class_name} ("
|
67
|
+
|
68
|
+
return text += 'Common)\n' if app_name.nil? || app_name.empty?
|
24
69
|
|
70
|
+
text + app_name + ")\n"
|
71
|
+
end
|
25
72
|
end
|
26
73
|
end
|
27
74
|
end
|
@@ -1,18 +1,19 @@
|
|
1
1
|
module Redbreast
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
2
|
+
module Serializer
|
3
|
+
# Used for initializing a serializer which will save files for respective languages
|
4
|
+
class Base
|
5
|
+
include ERB::Util
|
6
|
+
attr_accessor :asset_names, :bundle
|
7
|
+
|
8
|
+
def initialize(asset_names, bundle, app_name)
|
9
|
+
@asset_names = asset_names
|
10
|
+
@bundle = bundle
|
11
|
+
@app_name = app_name
|
12
|
+
end
|
13
|
+
|
14
|
+
def save(*)
|
15
|
+
raise NotImplementedError, 'Abstract Method'
|
16
|
+
end
|
17
17
|
end
|
18
|
-
end
|
18
|
+
end
|
19
|
+
end
|
@@ -1,11 +1,12 @@
|
|
1
|
-
require_relative 'serializer'
|
1
|
+
require_relative 'serializer'
|
2
2
|
|
3
3
|
module Redbreast
|
4
4
|
module Serializer
|
5
|
+
# Used to save swift files
|
5
6
|
class Swift < Base
|
6
7
|
include Helper::General
|
7
8
|
|
8
|
-
def save(output_source_path
|
9
|
+
def save(output_source_path:, template_generator:, generate_colors:)
|
9
10
|
directory = File.dirname(output_source_path)
|
10
11
|
FileUtils.mkdir_p directory unless File.exist? directory
|
11
12
|
|
@@ -13,6 +14,96 @@ module Redbreast
|
|
13
14
|
File.write(output_source_path, file)
|
14
15
|
end
|
15
16
|
|
17
|
+
def generate_file_swift(names:, spacing: "\t", indentation: '', variable:, bundle:)
|
18
|
+
return if names.empty?
|
19
|
+
|
20
|
+
text = ''
|
21
|
+
arr = []
|
22
|
+
|
23
|
+
text, arr = generate_variables(names: names, spacing: spacing, indentation: indentation, variable: variable, bundle: bundle, text: text, array: arr)
|
24
|
+
|
25
|
+
arr = arr.uniq
|
26
|
+
text += indentation.empty? && text.empty? ? "\n" : ''
|
27
|
+
arr.each do |enum_name|
|
28
|
+
names_new = []
|
29
|
+
names_new_enum = []
|
30
|
+
new_enum_name = enum_name
|
31
|
+
|
32
|
+
text += "\n" + spacing + 'enum ' + enum_name + ' {'
|
33
|
+
names_new, names_new_enum = separate_variables_from_folders(names: names, enum_name: enum_name, new_enum_name: new_enum_name, names_new_enum: names_new_enum, names_new: names_new)
|
34
|
+
|
35
|
+
if !names_new_enum.empty? && new_enum_name == enum_name
|
36
|
+
indentation += indentation.empty? || indentation[-1] == '/' ? '' : '/'
|
37
|
+
text += "\n" + generate_file_swift(names: names_new_enum, spacing: spacing + "\t", indentation: indentation + enum_name, variable: variable, bundle: bundle)
|
38
|
+
end
|
39
|
+
|
40
|
+
unless names_new.empty?
|
41
|
+
|
42
|
+
indentation += indentation.empty? || indentation[-1] == '/' ? '' : '/'
|
43
|
+
text += "\n" + generate_file_swift(names: names_new, spacing: spacing + "\t", indentation: indentation + enum_name, variable: variable, bundle: bundle)
|
44
|
+
end
|
45
|
+
|
46
|
+
text += "\n" + spacing + '}' + "\n"
|
47
|
+
end
|
48
|
+
text
|
49
|
+
end
|
50
|
+
|
51
|
+
def generate_extension(extended_class, app_name)
|
52
|
+
text = 'extension ' + extended_class + " {\n"
|
53
|
+
|
54
|
+
return text if app_name.nil? || app_name.empty?
|
55
|
+
|
56
|
+
text + "\tenum " + app_name + " {}\n}\n\nextension " + extended_class + '.' + app_name + " {\n"
|
57
|
+
end
|
58
|
+
|
59
|
+
def create_swift_test_cases(names:, declaration:, app_name:)
|
60
|
+
text = ''
|
61
|
+
app_name_text = app_name.nil? || app_name.empty? ? '' : app_name + '.'
|
62
|
+
|
63
|
+
names.each do |name|
|
64
|
+
temp_array = name.split('/')
|
65
|
+
variable = temp_array.pop
|
66
|
+
additional_text = temp_array.count.zero? ? '' : '.'
|
67
|
+
text += "\t\t" + declaration + app_name_text + temp_array.join('.') + additional_text + clean_variable_name(variable)
|
68
|
+
text += name == names.last ? '' : "\n"
|
69
|
+
end
|
70
|
+
|
71
|
+
text
|
72
|
+
end
|
73
|
+
|
74
|
+
def generate_variables(names:, spacing:, indentation:, bundle:, variable:, text:, array:)
|
75
|
+
names.each do |name|
|
76
|
+
temp_arr = name.split('/')
|
77
|
+
|
78
|
+
if temp_arr.length != 1
|
79
|
+
array.push(temp_arr.first)
|
80
|
+
else
|
81
|
+
name_prefix = indentation.empty? ? '' : '/'
|
82
|
+
text += spacing + variable % [clean_variable_name(name), indentation + name_prefix + name, bundle[:reference]]
|
83
|
+
#text += spacing + declaration + clean_variable_name(name) + type + indentation + name_prefix + name + var_end + bundle[:reference] + line_end
|
84
|
+
text += name == names.last ? '' : "\n"
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
[text, array]
|
89
|
+
end
|
90
|
+
|
91
|
+
def separate_variables_from_folders(names:, enum_name:, new_enum_name:, names_new_enum:, names_new:)
|
92
|
+
names.each do |name|
|
93
|
+
temp_arr = name.split('/')
|
94
|
+
|
95
|
+
next if temp_arr.length == 1
|
96
|
+
|
97
|
+
if temp_arr.length > 2
|
98
|
+
names_new_enum.push(temp_arr.drop(1).join('/')) if temp_arr.first == new_enum_name
|
99
|
+
next
|
100
|
+
end
|
101
|
+
|
102
|
+
names_new.push(temp_arr.drop(1).join('/')) if temp_arr[0] == enum_name
|
103
|
+
end
|
104
|
+
|
105
|
+
[names_new, names_new_enum]
|
106
|
+
end
|
16
107
|
end
|
17
108
|
end
|
18
109
|
end
|