swift-boiler 1.0

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: ae6e8acdb47998ccba7f7d369e45246852ac134d
4
+ data.tar.gz: 62dc57b257198487389f4ca88f7b80c191345f9d
5
+ SHA512:
6
+ metadata.gz: d28b9e6f66707174357fab342d4cb97e47d5c7f6069fec4e20c1951f438ec5dd9c0639815af870a6d32b08ab4a0b2ed58a5b803ee35e2412f6b3ea1dbd36e574
7
+ data.tar.gz: 190b8965ab0fbc9c39dd033f42dda7287cb4c9a0e7582f6f5165cf6dffaa272aeae72ee7a73bf0859466cea225d366a036031f3c0d731f145c71edba5c01fd98
data/README.md ADDED
@@ -0,0 +1,67 @@
1
+ # Swift-Boiler
2
+
3
+ Swift-Boiler is a tool developed for iOS developers to speed up the process of implementing views, models, controllers, and many other common patterns found in an iOS project. Inspired by the swift syntax and the simplicity of the Rails generate tool, Swift-Boiler is a simple to use boiler plate code generator that will get you up running in no time.
4
+
5
+ ## Installation
6
+
7
+ ### Install Swift-Boiler via [Homebrew](http://brew.sh):
8
+
9
+ ```sh
10
+ $ brew update
11
+ $ brew install swift-boiler
12
+ ```
13
+
14
+ <!-- ### Install it with [Homebrew](http://brew.sh):
15
+
16
+ ```sh
17
+ $ gem install swift-boiler
18
+ ``` -->
19
+
20
+ ## Usage
21
+
22
+ Swift-Boiler has only one swift-boil binary, and the command follow this specific syntax:
23
+ <summary>swi
24
+ ft-boil \<option\></summary>
25
+ ```sh
26
+ $ swift-boil --help
27
+ ```
28
+
29
+ <summary>swift-boil \<option\> \<template_path\> \<class_name\> \<options\> \<properties\></summary>
30
+ ```sh
31
+ $ swift-boil -t /Desktop/mytemplate.mustache MyView toplabel:UILabel bottomlabel:UILabel
32
+ $ swift-boil -t /Desktop/mytemplate.mustache MyView -d toplabel:UILabel bottomlabel:UILabel
33
+ ```
34
+
35
+ <summary>swift-boil \<command\> \<class_name\> \<options\> \<properties\></summary>
36
+ ```sh
37
+ $ swift-boil v MyView mainlabel:UILabel firstView:UIView secondView:CustomView
38
+ $ swift-boil view MyView -d mainlabel:UILabel firstView:UIView secondView:CustomView
39
+ ```
40
+
41
+ ### Commands:
42
+ - `view or v`: command to generate the boiler plate code for a view
43
+ - `model or m`: command to generate the boiler plate code for a model
44
+ - `controller or c`: command to generate the boiler plate code for a controller
45
+ - `tableViewCell or tvc`: command to generate the boiler plate code for a table view cell
46
+ - `singleton or s`: command to generate the boiler plate code for a singleton
47
+
48
+ ### Options:
49
+ - `--help or -h`: shows usage details
50
+ - `--delegate or -d`: it indicates that Swift-Boiler should add a delegate to the class being generated
51
+ - `--template or -t`: allows user to specify a custom template to be used to generate code
52
+
53
+ ## Development
54
+
55
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
56
+
57
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
58
+
59
+ ## Contributing
60
+
61
+ Bug reports and pull requests are welcome on GitHub at our [Bug Section](https://github.com/Boilerplate-Factory/swift-boiler/issues).
62
+
63
+
64
+ ## License
65
+
66
+ The gem is available as open source under the terms of the [MIT License](https://github.com/Boilerplate-Factory/swift-boiler/blob/master/LICENSE.txt).
67
+
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "swift/boiler"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
data/bin/swift-boil ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "swift/boiler"
4
+
5
+ Swift::Boiler.boil(ARGV)
@@ -0,0 +1,26 @@
1
+ module Swift
2
+ module Boiler
3
+ class Builder
4
+
5
+ def build_template(template)
6
+ Mustache.template_file = template.template_path
7
+ mustache_template = Mustache.new
8
+ mustache_template[:class_name] = template.class_name
9
+ #mustache_template[:dev_name] = template.developer_name
10
+ mustache_template[:date] = template.date
11
+ mustache_template[:options] = template.options
12
+ mustache_template[:properties] = template.properties
13
+ # puts template.inspect
14
+ create_file(mustache_template.render.to_s, mustache_template[:class_name])
15
+ end
16
+
17
+ def create_file(text, class_name)
18
+ puts text
19
+ out_file = File.new(class_name + ".swift", "w")
20
+ out_file.puts(text)
21
+ out_file.close
22
+ end
23
+
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,172 @@
1
+ require 'mustache'
2
+ require 'swift/boiler/template'
3
+ require 'swift/boiler/token'
4
+
5
+ module Swift
6
+ module Boiler
7
+ class Parser
8
+
9
+ TYPE = :type
10
+ NAME = :name
11
+ PROPERTY_NAME_INDEX = 0
12
+ PROPERTY_TYPE_INDEX = 1
13
+ CAPITALIZED_NAME = :capitalized_name
14
+ LABEL_TYPE = :ui_label
15
+ VIEW_TYPE = :ui_view
16
+ UNKNOWN_TYPE = :unknow_type
17
+ SHORTCUTS = { tableviewcell: 'table_view_cell', m: 'model', v: 'view', c: 'controller', s: 'singleton', tvc: 'table_view_cell' }
18
+
19
+ def create_template_from_tokens(tokens)
20
+ template = Template.new
21
+ template.template_path = get_template_path(tokens)
22
+ template.class_name = get_class_name(tokens)
23
+ template.options = get_options(tokens)
24
+ template.properties = get_properties(tokens)
25
+ template
26
+ end
27
+
28
+ def get_template_path(tokens)
29
+ tokens.each do |token|
30
+ if is_path_generation_possible_from_token(token)
31
+ return get_template_path_from_token(token)
32
+ end
33
+ end
34
+ end
35
+
36
+ def is_path_generation_possible_from_token(token)
37
+ is_template_path_token(token) || is_template_name_token(token)
38
+ end
39
+
40
+ def get_template_path_from_token(token)
41
+ if is_template_path_token(token)
42
+ return get_template_path_from_path_token(token)
43
+ elsif is_template_name_token(token)
44
+ return get_template_path_from_name_token(token)
45
+ end
46
+ end
47
+
48
+ def get_class_name(tokens)
49
+ tokens.each do |token|
50
+ if is_class_name_token(token)
51
+ return token.content
52
+ end
53
+ end
54
+ end
55
+
56
+ def get_options(tokens)
57
+ options = {}
58
+ tokens.each do |token|
59
+ options[:protocol] = is_protocol_token(token)
60
+ end
61
+ options
62
+ end
63
+
64
+ def get_properties(tokens)
65
+ properties = {}
66
+ properties[LABEL_TYPE] = Array.new
67
+ properties[VIEW_TYPE] = Array.new
68
+ properties[UNKNOWN_TYPE] = Array.new
69
+ tokens.each do |token|
70
+ if token.type == Token::PROPERTY
71
+ new_property = get_property_from_token(token)
72
+ case new_property[TYPE].to_s
73
+ when "UILabel"
74
+ properties[LABEL_TYPE] << new_property
75
+ when "UIView"
76
+ properties[VIEW_TYPE] << new_property
77
+ else
78
+ properties[UNKNOWN_TYPE] << new_property
79
+ end
80
+ end
81
+ end
82
+ properties
83
+ end
84
+
85
+ def get_template_path_from_path_token(token)
86
+ token.content
87
+ end
88
+
89
+ def get_template_path_from_name_token(token)
90
+ template_name = get_template_name_from_token(token)
91
+ File.dirname(__FILE__) + '/templates/' + template_name + ".mustache"
92
+ end
93
+
94
+ def get_template_name_from_token(template_name_token)
95
+ if is_abreviation(template_name_token)
96
+ get_name_from_abreviation(template_name_token.content.downcase)
97
+ else
98
+ get_name_from_name_token(template_name_token)
99
+ end
100
+ end
101
+
102
+ def get_property_from_token(token)
103
+ name = get_property_name_from_token(token)
104
+ type = get_property_type_from_token(token)
105
+ capitalized_name = capitalize_name(name)
106
+ create_property_dictionary(name, capitalized_name, type)
107
+ end
108
+
109
+ def create_property_dictionary(name, capitalized_name, type)
110
+ property = {}
111
+ property[NAME] = name
112
+ property[TYPE] = type
113
+ property[CAPITALIZED_NAME] = capitalized_name
114
+ property
115
+ end
116
+
117
+ def get_property_name_from_token(token)
118
+ argument_list = token.content.split(/:/)
119
+ name = argument_list[PROPERTY_NAME_INDEX]
120
+ downcase_name(name)
121
+ end
122
+
123
+ def get_property_type_from_token(token)
124
+ argument_list = token.content.split(/:/)
125
+ argument_list[PROPERTY_TYPE_INDEX]
126
+ end
127
+
128
+ def capitalize_name(name)
129
+ name.split.map(&:capitalize).join(' ')
130
+ end
131
+
132
+ def downcase_name(name)
133
+ place_holder = name.dup
134
+ first_letter = place_holder.slice!(0).downcase
135
+ first_letter + place_holder
136
+ end
137
+
138
+ def get_name_from_abreviation(abreviation)
139
+ print SHORTCUTS[abreviation.to_sym]
140
+ SHORTCUTS[abreviation.to_sym]
141
+ end
142
+
143
+ def get_name_from_name_token(template_name_token)
144
+ template_name_token.content.downcase
145
+ end
146
+
147
+ def is_abreviation(template_name_token)
148
+ template_name = template_name_token.content.downcase
149
+ template_name_token.type == Token::TEMPLATE_NAME && SHORTCUTS.has_key?(template_name.to_sym)
150
+ end
151
+
152
+ def is_protocol_token(token)
153
+ token.type == Token::OPTION && (token.content == "-p" || token.content == "--protocol")
154
+ end
155
+
156
+ private
157
+
158
+ def is_template_path_token(token)
159
+ token.type == Token::TEMPLATE_PATH
160
+ end
161
+
162
+ def is_template_name_token(token)
163
+ token.type == Token::TEMPLATE_NAME
164
+ end
165
+
166
+ def is_class_name_token(token)
167
+ token.type == Token::CLASS_NAME
168
+ end
169
+
170
+ end
171
+ end
172
+ end
@@ -0,0 +1,23 @@
1
+
2
+ require 'swift/boiler/token'
3
+ require 'swift/boiler/token_factory'
4
+ require 'swift/boiler/token_pattern_validator'
5
+
6
+ module Swift
7
+ module Boiler
8
+ class Scanner
9
+
10
+ def create_valid_token_pattern_from_arguments(arguments)
11
+ token_factory = Swift::Boiler::TokenFactory.new
12
+ token_pattern_validator = Swift::Boiler::TokenPatternValidator.new
13
+ tokens = token_factory.create_tokens_from_arguments(arguments)
14
+ if token_pattern_validator.validate(tokens)
15
+ return tokens
16
+ else
17
+ raise ArgumentError.new("The following sequence of arguments was not valid #{arguments}.")
18
+ end
19
+
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,12 @@
1
+ module Swift
2
+ module Boiler
3
+ class Template
4
+ attr_accessor :template_path, :class_name, :date, :properties, :options
5
+
6
+ def initialize
7
+ @date = Time.now.strftime("%d/%m/%Y")
8
+ end
9
+
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,59 @@
1
+ //
2
+ // {{class_name}}.swift
3
+ //
4
+ // Created by <# Developer Name #> on {{date}}.
5
+ //
6
+ //
7
+
8
+ import UIKit
9
+
10
+ class {{class_name}}: UIViewController {
11
+ private let mainView = {{class_name}}View()
12
+ {{#properties.ui_label}}
13
+
14
+ private let {{name}}:UILabel = {
15
+ let {{name}} = UILabel()
16
+ {{name}}.textColor = <# UIColor #>
17
+ {{name}}.font = <# UIFont #>
18
+ return {{name}}
19
+ }()
20
+ {{/properties.ui_label}}
21
+ {{#properties.ui_view}}
22
+
23
+ private let {{name}}:UIView = {
24
+ let {{name}} = UIView()
25
+ {{name}}.backgroundColor = <# UIColor #>
26
+ {{name}}.clipBounds = <# true or false #>
27
+ return {{name}}
28
+ }()
29
+ {{/properties.ui_view}}
30
+ {{#properties.unknow_type}}
31
+
32
+ private let {{name}} = {{type}}()
33
+
34
+ {{/properties.unknow_type}}
35
+
36
+ override func loadView() {
37
+ view = mainView
38
+ }
39
+
40
+ init() {
41
+ super.init(nibName: nil, bundle: nil)
42
+ }
43
+
44
+ required init?(coder aDecoder: NSCoder) {
45
+ fatalError("init(coder:) has not been implemented for {{class_name}}.swift")
46
+ }
47
+
48
+ override func viewDidLoad() {
49
+ super.viewDidLoad()
50
+ }
51
+
52
+ override func viewWillAppear(_ animated: Bool) {
53
+ super.viewWillAppear(animated)
54
+ }
55
+
56
+ override func viewDidAppear(_ animated: Bool) {
57
+ super.viewDidAppear(animated)
58
+ }
59
+ }
@@ -0,0 +1,31 @@
1
+ //
2
+ // {{class_name}}.swift
3
+ //
4
+ // Created by {{dev_name}} on {{date}}.
5
+ //
6
+ //
7
+
8
+ struct {{class_name}} {
9
+
10
+ {{#properties.ui_label}}
11
+ let {{name}}: {{type}} = {{type}}()
12
+ {{/properties.ui_label}}
13
+ {{#properties.ui_view}}
14
+ let {{name}}: {{type}} = {{type}}()
15
+ {{/properties.ui_view}}
16
+ {{#properties.unknow_type}}
17
+ let {{name}}: {{type}} = {{type}}()
18
+ {{/properties.unknow_type}}
19
+
20
+ public init({{#properties.unknow_type}}, {{name}}:{{type}}{{/properties.unknow_type}}{{#properties.ui_label}}, {{name}}:{{type}}{{/properties.ui_label}}{{#properties.ui_view}}, {{name}}:{{type}}{{/properties.ui_view}}) {
21
+ {{#properties.ui_label}}
22
+ self.{{name}} = {{name}}
23
+ {{/properties.ui_label}}
24
+ {{#properties.ui_view}}
25
+ self.{{name}} = {{name}}
26
+ {{/properties.ui_view}}
27
+ {{#properties.unknow_type}}
28
+ self.{{name}} = {{name}}
29
+ {{/properties.unknow_type}}
30
+ }
31
+ }
@@ -0,0 +1,17 @@
1
+ //
2
+ // {{class_name}}.swift
3
+ //
4
+ // Created by <# Developer Name #> on {{date}}.
5
+ //
6
+ //
7
+
8
+
9
+ class {{class_name}} {
10
+
11
+ static let shared: {{class_name}}
12
+
13
+ private init(_ shared: {{class_name}} = {{class_name}}()) {
14
+ self.shared = shared
15
+ }
16
+
17
+ }
@@ -0,0 +1,135 @@
1
+ //
2
+ // {{class_name}}.swift
3
+ //
4
+ // Created by <# Developer Name #> on {{date}}.
5
+ //
6
+ //
7
+
8
+ import UIKit
9
+ {{#options.protocol}}
10
+
11
+ protocol {{class_name}}Delegate: class {
12
+
13
+ }
14
+
15
+ protocol {{class_name}}DataSouce: class {
16
+
17
+ }
18
+ {{/options.protocol}}
19
+
20
+ class {{class_name}}: UITableViewCell {
21
+ {{#options.protocol}}
22
+ weak private var delegate: {{class_name}}Delegate?
23
+ weak private var datasource: {{class_name}}DataSource?
24
+ {{/options.protocol}}
25
+ {{#properties.ui_label}}
26
+
27
+ private let {{name}}:UILabel = {
28
+ let {{name}} = UILabel()
29
+ {{name}}.textColor = <# UIColor #>
30
+ {{name}}.font = <# UIFont #>
31
+ return {{name}}
32
+ }()
33
+ {{/properties.ui_label}}
34
+ {{#properties.ui_view}}
35
+
36
+ private let {{name}}:UIView = {
37
+ let {{name}} = UIView()
38
+ {{name}}.backgroundColor = <# UIColor #>
39
+ {{name}}.clipBounds = <# true or false #>
40
+ return {{name}}
41
+ }()
42
+ {{/properties.ui_view}}
43
+ {{#properties.unknow_type}}
44
+
45
+ private let {{name}}:{{type}} = {
46
+ return {{type}}()
47
+ }()
48
+ {{/properties.unknow_type}}
49
+
50
+ override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
51
+ super.init(style: .subtitle, reuseIdentifier: reuseIdentifier)
52
+ setupView()
53
+ }
54
+
55
+ required public init?(coder aDecoder: NSCoder) {
56
+ super.init(coder: aDecoder)
57
+ }
58
+
59
+ override func prepareForReuse() {
60
+ super.prepareForReuse()
61
+ {{#properties.ui_label}}
62
+ {{name}}.text = ""
63
+ {{/properties.ui_label}}
64
+ }
65
+
66
+ // MARK: - Identifier
67
+
68
+ class func identifier() -> String {
69
+ return String(describing: self)
70
+ }
71
+
72
+ // MARK: - Setup
73
+
74
+ private func setupView() {
75
+ addViewComponents()
76
+ setupConstraints()
77
+ }
78
+
79
+ private func addViewComponents() {
80
+ {{#properties.ui_label}}
81
+ contentView.addSubview({{name}})
82
+ {{/properties.ui_label}}
83
+ {{#properties.ui_view}}
84
+ contentView.addSubview({{name}})
85
+ {{/properties.ui_view}}
86
+ {{#properties.unknow_type}}
87
+ contentView.addSubview({{name}})
88
+ {{/properties.unknow_type}}
89
+ }
90
+
91
+ // MARK: - Constraints
92
+
93
+ private func setupConstraints() {
94
+ {{#properties.ui_label}}
95
+ setupConstraintsFor{{capitalized_name}}()
96
+ {{/properties.ui_label}}
97
+ {{#properties.ui_view}}
98
+ setupConstraintsFor{{capitalized_name}}()
99
+ {{/properties.ui_view}}
100
+ {{#properties.unknow_type}}
101
+ setupConstraintsFor{{capitalized_name}}()
102
+ {{/properties.unknow_type}}
103
+ }
104
+
105
+ {{#properties.ui_label}}
106
+ private func setupConstraintsFor{{capitalized_name}}() {
107
+ {{name}}.translatesAutoresizingMaskIntoConstraints = false
108
+ {{name}}.topAnchor.constraint(equalTo: <# topAnchor #>, constant: <# constant #>).isActive = true
109
+ {{name}}.leftAnchor.constraint(equalTo: <# leftAnchor #>, constant: <# constant #>).isActive = true
110
+ {{name}}.rightAnchor.constraint(equalTo: <# rightAnchor #>, constant: <# constant #>).isActive = true
111
+ {{name}}.bottomAnchor.constraint(equalTo: <# bottomAnchor #>, constant: <# constant #>).isActive = true
112
+ }
113
+
114
+ {{/properties.ui_label}}
115
+ {{#properties.ui_view}}
116
+ private func setupConstraintsFor{{capitalized_name}}() {
117
+ {{name}}.translatesAutoresizingMaskIntoConstraints = false
118
+ {{name}}.topAnchor.constraint(equalTo: <# topAnchor #>, constant: <# constant #>).isActive = true
119
+ {{name}}.leftAnchor.constraint(equalTo: <# leftAnchor #>, constant: <# constant #>).isActive = true
120
+ {{name}}.rightAnchor.constraint(equalTo: <# rightAnchor #>, constant: <# constant #>).isActive = true
121
+ {{name}}.bottomAnchor.constraint(equalTo: <# bottomAnchor #>, constant: <# constant #>).isActive = true
122
+ }
123
+
124
+ {{/properties.ui_view}}
125
+ {{#properties.unknow_type}}
126
+ private func setupConstraintsFor{{capitalized_name}}() {
127
+ {{name}}.translatesAutoresizingMaskIntoConstraints = false
128
+ {{name}}.topAnchor.constraint(equalTo: <# topAnchor #>, constant: <# constant #>).isActive = true
129
+ {{name}}.leftAnchor.constraint(equalTo: <# leftAnchor #>, constant: <# constant #>).isActive = true
130
+ {{name}}.rightAnchor.constraint(equalTo: <# rightAnchor #>, constant: <# constant #>).isActive = true
131
+ {{name}}.bottomAnchor.constraint(equalTo: <# bottomAnchor #>, constant: <# constant #>).isActive = true
132
+ }
133
+
134
+ {{/properties.unknow_type}}
135
+ }
@@ -0,0 +1,126 @@
1
+ //
2
+ // {{class_name}}.swift
3
+ //
4
+ // Created by <# Developer Name #> on {{date}}.
5
+ //
6
+ //
7
+
8
+ import UIKit
9
+ {{#options.protocol}}
10
+
11
+ protocol {{class_name}}Delegate: class {
12
+
13
+ }
14
+
15
+ protocol {{class_name}}DataSouce: class {
16
+
17
+ }
18
+ {{/options.protocol}}
19
+
20
+ class {{class_name}}: UIView {
21
+ {{#options.protocol}}
22
+ weak private var delegate: {{class_name}}Delegate?
23
+ weak private var datasource: {{class_name}}DataSource?
24
+ {{/options.protocol}}
25
+ {{#properties.ui_label}}
26
+
27
+ private let {{name}}:UILabel = {
28
+ let {{name}} = UILabel()
29
+ {{name}}.textColor = <# UIColor #>
30
+ {{name}}.font = <# UIFont #>
31
+ return {{name}}
32
+ }()
33
+ {{/properties.ui_label}}
34
+ {{#properties.ui_view}}
35
+
36
+ private let {{name}}:UIView = {
37
+ let {{name}} = UIView()
38
+ {{name}}.backgroundColor = <# UIColor #>
39
+ {{name}}.clipBounds = <# true or false #>
40
+ return {{name}}
41
+ }()
42
+ {{/properties.ui_view}}
43
+ {{#properties.unknow_type}}
44
+
45
+ private let {{name}}:{{type}} = {
46
+ return {{type}}()
47
+ }()
48
+ {{/properties.unknow_type}}
49
+
50
+ override init(frame: CGRect) {
51
+ super.init(frame: frame)
52
+ self.setupView()
53
+ }
54
+
55
+ convenience init() {
56
+ self.init(frame: CGRect.zero)
57
+ }
58
+
59
+ required init?(coder aDecoder: NSCoder) {
60
+ fatalError("init(coder:) has not been implemented for {{class_name}}.swift")
61
+ }
62
+
63
+ // MARK: - Setup
64
+
65
+ private func setupView() {
66
+ addViewComponents()
67
+ setupConstraints()
68
+ }
69
+
70
+ private func addViewComponents() {
71
+ {{#properties.ui_label}}
72
+ addSubview({{name}})
73
+ {{/properties.ui_label}}
74
+ {{#properties.ui_view}}
75
+ addSubview({{name}})
76
+ {{/properties.ui_view}}
77
+ {{#properties.unknow_type}}
78
+ addSubview({{name}})
79
+ {{/properties.unknow_type}}
80
+ }
81
+
82
+ // MARK: - Constraints
83
+
84
+ private func setupConstraints() {
85
+ {{#properties.ui_label}}
86
+ setupConstraintsFor{{capitalized_name}}()
87
+ {{/properties.ui_label}}
88
+ {{#properties.ui_view}}
89
+ setupConstraintsFor{{capitalized_name}}()
90
+ {{/properties.ui_view}}
91
+ {{#properties.unknow_type}}
92
+ setupConstraintsFor{{capitalized_name}}()
93
+ {{/properties.unknow_type}}
94
+ }
95
+
96
+ {{#properties.ui_label}}
97
+ private func setupConstraintsFor{{capitalized_name}}() {
98
+ {{name}}.translatesAutoresizingMaskIntoConstraints = false
99
+ {{name}}.topAnchor.constraint(equalTo: <# topAnchor #>, constant: <# constant #>).isActive = true
100
+ {{name}}.leftAnchor.constraint(equalTo: <# leftAnchor #>, constant: <# constant #>).isActive = true
101
+ {{name}}.rightAnchor.constraint(equalTo: <# rightAnchor #>, constant: <# constant #>).isActive = true
102
+ {{name}}.bottomAnchor.constraint(equalTo: <# bottomAnchor #>, constant: <# constant #>).isActive = true
103
+ }
104
+
105
+ {{/properties.ui_label}}
106
+ {{#properties.ui_view}}
107
+ private func setupConstraintsFor{{capitalized_name}}() {
108
+ {{name}}.translatesAutoresizingMaskIntoConstraints = false
109
+ {{name}}.topAnchor.constraint(equalTo: <# topAnchor #>, constant: <# constant #>).isActive = true
110
+ {{name}}.leftAnchor.constraint(equalTo: <# leftAnchor #>, constant: <# constant #>).isActive = true
111
+ {{name}}.rightAnchor.constraint(equalTo: <# rightAnchor #>, constant: <# constant #>).isActive = true
112
+ {{name}}.bottomAnchor.constraint(equalTo: <# bottomAnchor #>, constant: <# constant #>).isActive = true
113
+ }
114
+
115
+ {{/properties.ui_view}}
116
+ {{#properties.unknow_type}}
117
+ private func setupConstraintsFor{{capitalized_name}}() {
118
+ {{name}}.translatesAutoresizingMaskIntoConstraints = false
119
+ {{name}}.topAnchor.constraint(equalTo: <# topAnchor #>, constant: <# constant #>).isActive = true
120
+ {{name}}.leftAnchor.constraint(equalTo: <# leftAnchor #>, constant: <# constant #>).isActive = true
121
+ {{name}}.rightAnchor.constraint(equalTo: <# rightAnchor #>, constant: <# constant #>).isActive = true
122
+ {{name}}.bottomAnchor.constraint(equalTo: <# bottomAnchor #>, constant: <# constant #>).isActive = true
123
+ }
124
+
125
+ {{/properties.unknow_type}}
126
+ }
@@ -0,0 +1,16 @@
1
+ //
2
+ // {{class_name}}.swift
3
+ //
4
+ // Created by <# Developer Name #> on {{date}}.
5
+ //
6
+ //
7
+
8
+ import UIKit
9
+
10
+ class {{class_name}} {
11
+
12
+ init(model: Model) {
13
+
14
+ }
15
+
16
+ }
@@ -0,0 +1,15 @@
1
+ module Swift
2
+ module Boiler
3
+ class Token
4
+ attr_accessor :type, :content
5
+
6
+ TYPE = [ OPTION = :option_type, PROPERTY = :property_type, TEMPLATE_NAME = :template_name_type, TEMPLATE_PATH = :template_path_type, CLASS_NAME = :class_name_type ]
7
+
8
+ def initialize (type, content)
9
+ @type = type
10
+ @content = content
11
+ end
12
+
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,56 @@
1
+ require 'swift/boiler/token'
2
+
3
+ module Swift
4
+ module Boiler
5
+ class TokenFactory
6
+
7
+ def create_tokens_from_arguments(arguments)
8
+ tokens = Array.new
9
+
10
+ arguments.each do |argument|
11
+
12
+ if is_valid_option(argument)
13
+ tokens << Token.new(Token::OPTION, argument)
14
+
15
+ elsif is_valid_property(argument)
16
+ tokens << Token.new(Token::PROPERTY, argument)
17
+
18
+ elsif is_valid_template_name(argument)
19
+ tokens << Token.new(Token::TEMPLATE_NAME, argument)
20
+
21
+ elsif is_valid_template_path(argument)
22
+ tokens << Token.new(Token::TEMPLATE_PATH, argument)
23
+
24
+ elsif is_valid_class_name(argument)
25
+ tokens << Token.new(Token::CLASS_NAME, argument)
26
+
27
+ else
28
+ raise ArgumentError.new("Argument was not recognized: #{argument}")
29
+ end
30
+ end
31
+
32
+ tokens
33
+ end
34
+
35
+ def is_valid_option(argument)
36
+ argument =~ /\A--[a-z]{3,}\z|\A-[a-z]\z/
37
+ end
38
+
39
+ def is_valid_property(argument)
40
+ argument =~ /\A[a-zA-Z_][a-zA-Z_\d\-]*:[a-zA-Z][a-zA-Z_.\d\-]{2,}\z/
41
+ end
42
+
43
+ def is_valid_template_name(argument)
44
+ ["controller", "c", "model", "m" "singleton", "s", "table_view_cell", "tableviewcell", "tvc", "view", "v", "viewmodel"].include?(argument)
45
+ end
46
+
47
+ def is_valid_class_name(argument)
48
+ argument =~ /\A[a-zA-Z][a-zA-Z\d_]+\z/
49
+ end
50
+
51
+ def is_valid_template_path(argument)
52
+ argument =~ /\A[a-zA-Z\-.\/\\~\s_:]*[\/\\][\w\-\s]+.mustache\z|\A[\w\-\s]+.mustache\z/
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,73 @@
1
+ require 'swift/boiler/token'
2
+
3
+ module Swift
4
+ module Boiler
5
+ class TokenPatternValidator
6
+
7
+ def validate(tokens)
8
+ tokens.count > 0 && is_token_pattern_valid(tokens)
9
+ end
10
+
11
+ def is_token_pattern_valid(tokens)
12
+ is_help_pattern(tokens) || is_template_path_pattern(tokens) || is_template_name_pattern(tokens)
13
+ end
14
+
15
+ def is_template_path_pattern(tokens)
16
+ has_one_template_name = contains_unique_instace_of_type(tokens, Token::TEMPLATE_NAME)
17
+ has_one_template_path = contains_unique_instace_of_type(tokens, Token::TEMPLATE_PATH)
18
+ has_one_class_name = contains_unique_instace_of_type(tokens, Token::CLASS_NAME)
19
+ !has_one_template_name && has_one_template_path && has_one_class_name && is_first_token_template_option(tokens)
20
+ end
21
+
22
+ def is_template_name_pattern(tokens)
23
+ has_one_template_name = contains_unique_instace_of_type(tokens, Token::TEMPLATE_NAME)
24
+ has_one_template_path = contains_unique_instace_of_type(tokens, Token::TEMPLATE_PATH)
25
+ has_one_class_name = contains_unique_instace_of_type(tokens, Token::CLASS_NAME)
26
+ !has_one_template_path && has_one_class_name && has_one_template_name && is_first_token_template_name_type(tokens)
27
+ end
28
+
29
+ def is_help_pattern(tokens)
30
+ tokens.count == 1 && is_first_token_help_option(tokens)
31
+ end
32
+
33
+ def contains_unique_instace_of_type(tokens, type)
34
+ instance_counter = 0
35
+ tokens.each do |token|
36
+ if token.type == type
37
+ instance_counter += 1
38
+ end
39
+ end
40
+ instance_counter == 1
41
+ end
42
+
43
+ def is_first_token_template_name_type(tokens)
44
+ tokens.count > 0 && is_template_name_token(tokens[0])
45
+ end
46
+
47
+ def is_first_token_help_option(tokens)
48
+ tokens.count > 0 && is_help_token(tokens[0])
49
+ end
50
+
51
+ def is_first_token_help_option(tokens)
52
+ tokens.count > 0 && is_help_token(tokens[0])
53
+ end
54
+
55
+ def is_first_token_template_option(tokens)
56
+ tokens.count > 0 && is_template_token(tokens[0])
57
+ end
58
+
59
+ def is_template_name_token(token)
60
+ token.type == Token::TEMPLATE_NAME
61
+ end
62
+
63
+ def is_help_token(token)
64
+ token.type == Token::OPTION && (token.content == '-h' || token.content == '--help')
65
+ end
66
+
67
+ def is_template_token(token)
68
+ token.type == Token::OPTION && (token.content == '-t' || token.content == '--template')
69
+ end
70
+
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,5 @@
1
+ module Swift
2
+ module Boiler
3
+ VERSION = "1.0"
4
+ end
5
+ end
@@ -0,0 +1,37 @@
1
+ require 'swift/boiler/builder'
2
+ require 'swift/boiler/scanner'
3
+ require 'swift/boiler/parser'
4
+ require 'swift/boiler/template'
5
+ require 'swift/boiler/token'
6
+
7
+ module Swift
8
+ module Boiler
9
+ class << self
10
+
11
+ def boil(arguments)
12
+ begin
13
+ template = build_template_from_arguments(arguments)
14
+ create_file_from_template(template)
15
+ rescue ArgumentError => argumentError
16
+ print "swift-boiler: #{argumentError.message}. Please see 'swift-boil --help'."
17
+ end
18
+ end
19
+
20
+ private
21
+
22
+ def create_file_from_template(template)
23
+ builder = Swift::Boiler::Builder.new
24
+ builder.build_template(template)
25
+ end
26
+
27
+ def build_template_from_arguments(arguments)
28
+ scanner = Swift::Boiler::Scanner.new
29
+ parser = Swift::Boiler::Parser.new
30
+ tokens = scanner.create_valid_token_pattern_from_arguments(arguments)
31
+ template = parser.create_template_from_tokens(tokens)
32
+ template
33
+ end
34
+
35
+ end
36
+ end
37
+ end
metadata ADDED
@@ -0,0 +1,107 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: swift-boiler
3
+ version: !ruby/object:Gem::Version
4
+ version: '1.0'
5
+ platform: ruby
6
+ authors:
7
+ - Pedro Peres
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-07-16 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.12'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.12'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: minitest
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '5.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '5.0'
55
+ description: This gem generate swift boilter plate code
56
+ email:
57
+ - pedro.peres@weightwatchers.com
58
+ executables:
59
+ - swift-boil
60
+ extensions: []
61
+ extra_rdoc_files: []
62
+ files:
63
+ - bin/console
64
+ - bin/setup
65
+ - bin/swift-boil
66
+ - lib/swift/boiler/builder.rb
67
+ - lib/swift/boiler/parser.rb
68
+ - lib/swift/boiler/scanner.rb
69
+ - lib/swift/boiler/template.rb
70
+ - lib/swift/boiler/templates/controller.mustache
71
+ - lib/swift/boiler/templates/model.mustache
72
+ - lib/swift/boiler/templates/singleton.mustache
73
+ - lib/swift/boiler/templates/table_view_cell.mustache
74
+ - lib/swift/boiler/templates/view.mustache
75
+ - lib/swift/boiler/templates/viewmodel.mustache
76
+ - lib/swift/boiler/token.rb
77
+ - lib/swift/boiler/token_factory.rb
78
+ - lib/swift/boiler/token_pattern_validator.rb
79
+ - lib/swift/boiler/version.rb
80
+ - lib/swift/boiler.rb
81
+ - README.md
82
+ homepage: https://github.com/Boilerplate-Factory/swift-boiler
83
+ licenses:
84
+ - MIT
85
+ metadata:
86
+ allowed_push_host: Set to 'http://mygemserver.com'
87
+ post_install_message:
88
+ rdoc_options: []
89
+ require_paths:
90
+ - lib
91
+ required_ruby_version: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - ">="
94
+ - !ruby/object:Gem::Version
95
+ version: '0'
96
+ required_rubygems_version: !ruby/object:Gem::Requirement
97
+ requirements:
98
+ - - ">="
99
+ - !ruby/object:Gem::Version
100
+ version: '0'
101
+ requirements: []
102
+ rubyforge_project:
103
+ rubygems_version: 2.0.14.1
104
+ signing_key:
105
+ specification_version: 4
106
+ summary: This gem generate swift boilter plate code
107
+ test_files: []