ngi 0.2.1 → 0.2.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +49 -5
- data/bin/ngi +24 -21
- data/lib/ngi.rb +10 -7
- data/lib/ngi/configure.rb +117 -122
- data/lib/ngi/delegate.rb +3 -5
- data/lib/ngi/generator.rb +180 -186
- data/lib/ngi/utils/command_parser.rb +93 -96
- data/lib/ngi/utils/jser.rb +36 -36
- data/lib/ngi/utils/utils.rb +22 -20
- data/lib/ngi/version.rb +10 -2
- data/ngi.gemspec +1 -0
- data/ngi_example.gif +0 -0
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c3e2d5d2fceb01e3e06c14c3580561bd3a15329f
|
4
|
+
data.tar.gz: 3fa569d585f690a60ee5bb6c52567620d167310b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 114412c6662f27aebef62423bdf4d91b9b4bafec03b4938fefa9789470e44f4c1ffda7f9468c1e2072b85113bf91421ced34add0dd39587ff0fdeb024b5f8bce
|
7
|
+
data.tar.gz: 5dc112cf93b96791658c9100656d3c0f37513bab2f49c68a67e87e7b9a7b375c10b7cbd1ea45598587caa3dc67da3a6e4cba6e22546dbdbe774c36b4fe0b6825
|
data/README.md
CHANGED
@@ -1,8 +1,26 @@
|
|
1
|
-
# angular_init 0.2.
|
1
|
+
# angular_init 0.2.2
|
2
|
+
|
3
|
+
## Quick Start
|
4
|
+
|
5
|
+
ngi creates AngularJS templates for you from the command line.
|
6
|
+
|
7
|
+
**Get up and running in seconds:**
|
8
|
+
|
9
|
+
[![Gem Version](https://badge.fury.io/rb/ngi.svg)](http://badge.fury.io/rb/ngi)
|
10
|
+
|
11
|
+
```shell
|
12
|
+
$ gem install ngi
|
13
|
+
$ cd ~/MyAwesomeApp # => go to your app
|
14
|
+
$ ngi controller # => creates a new AngularJS controller
|
15
|
+
```
|
16
|
+
|
17
|
+
## Know everything
|
2
18
|
|
3
19
|
<a href="http://joshbeam.github.io/angular_init">Website</a>
|
4
20
|
|
5
|
-
**
|
21
|
+
**Having issues?** Email me (Josh) at <a href="mailto:frontendcollisionblog@gmail.com">frontendcollisionblog@gmail.com</a>. I'll usually respond within an hour or so. You can also report a bug by opening a new issue through GitHub, or if you want to add a feature yourself, just fork and submit a pull request!
|
22
|
+
|
23
|
+
**What's new in 0.2.x?**
|
6
24
|
- Install it as a gem (`gem install ngi`)
|
7
25
|
- You can now make an `index` boilerplate HTML page (`ngi index`)
|
8
26
|
- Use `ngi -h` to see all commands
|
@@ -46,7 +64,7 @@ After you [do the 1-step installation][install] of `ngi` (the short-name for the
|
|
46
64
|
# all done!
|
47
65
|
```
|
48
66
|
|
49
|
-
## Output (
|
67
|
+
## Output (new boilerplate code)
|
50
68
|
|
51
69
|
```javascript
|
52
70
|
// ~/MyAwesomeApp/myAwesome.controller.js
|
@@ -78,6 +96,7 @@ By the way, the output of this little tool is meant to follow [John Papa's Angul
|
|
78
96
|
## Coming soon
|
79
97
|
|
80
98
|
- Add custom templates and languages
|
99
|
+
- Possible Node.js version
|
81
100
|
|
82
101
|
Feel free to fork the project or get <a href="http://frontendcollisionblog.com/about">in touch with Josh (me)</a> with any feature requests!
|
83
102
|
|
@@ -142,7 +161,7 @@ The command line tool itself is written in <a href="https://www.ruby-lang.org/en
|
|
142
161
|
|
143
162
|
# Technical Information
|
144
163
|
|
145
|
-
**Version** 0.2.
|
164
|
+
**Version** 0.2.2 (uses <a href="http://semver.org/">Semantic Versioning</a>)
|
146
165
|
|
147
166
|
**Language** Ruby
|
148
167
|
|
@@ -150,7 +169,32 @@ The command line tool itself is written in <a href="https://www.ruby-lang.org/en
|
|
150
169
|
|
151
170
|
<hr>
|
152
171
|
|
153
|
-
|
172
|
+
**Disclaimer**
|
173
|
+
|
174
|
+
`angular_init` and `ngi` and the author (Joshua Beam) are not directly associated with <a href="http://angularjs.org">AngularJS</a>.
|
175
|
+
|
176
|
+
**Copyright (c) 2015 Joshua Beam** — <a href="http://frontendcollisionblog.com">Front End Collision</a>
|
177
|
+
|
178
|
+
MIT License
|
179
|
+
|
180
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
181
|
+
a copy of this software and associated documentation files (the
|
182
|
+
"Software"), to deal in the Software without restriction, including
|
183
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
184
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
185
|
+
permit persons to whom the Software is furnished to do so, subject to
|
186
|
+
the following conditions:
|
187
|
+
|
188
|
+
The above copyright notice and this permission notice shall be
|
189
|
+
included in all copies or substantial portions of the Software.
|
190
|
+
|
191
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
192
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
193
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
194
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
195
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
196
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
197
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
154
198
|
|
155
199
|
[install]: #installation-in-1-step
|
156
200
|
[sample-usage]: #sample-usage
|
data/bin/ngi
CHANGED
@@ -9,27 +9,30 @@
|
|
9
9
|
require_relative '../lib/ngi'
|
10
10
|
require_relative '../lib/ngi/utils/utils'
|
11
11
|
|
12
|
+
# This class is just a wrapper for the main process
|
13
|
+
# of ngi
|
12
14
|
class Parser
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
15
|
+
def self.parse(args)
|
16
|
+
p = Utils::CommandParser.new do |parser|
|
17
|
+
config = Ngi::Delegate::Configure.new.from_json
|
18
|
+
components = config['global']['components'].collect { |t| t['name'] }
|
19
|
+
types = Ngi::UserInput.new(valid_inputs: components)
|
20
|
+
|
21
|
+
parser.name = 'ngi'
|
22
|
+
parser.version = Ngi::VERSION
|
23
|
+
parser.banner << "\n(<command> can be one of the following)"
|
24
|
+
|
25
|
+
parser.on(types.valid_inputs, 'Create a new component') do |command|
|
26
|
+
Ngi::Delegate::Generator.run(type: command, config: config)
|
27
|
+
end
|
28
|
+
|
29
|
+
parser.on(['-o', '--options'], 'Configure ngi') do
|
30
|
+
Ngi::Delegate::Configure.run
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
p.parse(args)
|
35
|
+
end
|
33
36
|
end
|
34
37
|
|
35
|
-
Parser.parse(ARGV)
|
38
|
+
Parser.parse(ARGV)
|
data/lib/ngi.rb
CHANGED
@@ -5,12 +5,15 @@
|
|
5
5
|
|
6
6
|
CURRENT_DIR = File.dirname(__FILE__)
|
7
7
|
|
8
|
-
require_relative
|
9
|
-
require_relative
|
10
|
-
require_relative
|
8
|
+
require_relative 'ngi/delegate'
|
9
|
+
require_relative 'ngi/utils/utils'
|
10
|
+
require_relative 'ngi/version'
|
11
11
|
|
12
|
+
# This module wraps the basic classes
|
13
|
+
# of the tool ngi (in other words, this
|
14
|
+
# module simply provides namespace)
|
12
15
|
module Ngi
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
end
|
16
|
+
# REVIEW: Is this the best way to do it?
|
17
|
+
Delegate = ::Delegate
|
18
|
+
UserInput = ::Utils::UserInput
|
19
|
+
end
|
data/lib/ngi/configure.rb
CHANGED
@@ -5,161 +5,156 @@
|
|
5
5
|
|
6
6
|
# CURRENT_DIR is defined in angualr_init.rb
|
7
7
|
|
8
|
-
#
|
9
|
-
|
10
|
-
|
11
|
-
require_relative '../dep/json'
|
8
|
+
# require_relative '../dep/json'
|
9
|
+
require 'json'
|
12
10
|
require_relative 'utils/utils'
|
13
11
|
|
12
|
+
# Run the user through an interactive
|
13
|
+
# session of configuring ngi
|
14
14
|
class Configure
|
15
|
-
|
16
|
-
|
17
|
-
Utils = ::Utils
|
18
|
-
JSArray = Utils::JSArray
|
19
|
-
JSHash = Utils::JSHash
|
20
|
-
|
21
|
-
# Make Questioner accesible as in: Configure::Questioner.run()
|
22
|
-
# "Questioner" simply starts an interactive prompt to guide
|
23
|
-
# the user in configuring src/config/agular_init.config.json,
|
24
|
-
# which is a JSON file that holds all the global configurable
|
25
|
-
# options (like language to use, templates, etc.)
|
26
|
-
class Questioner
|
27
|
-
attr_accessor :file
|
28
|
-
|
29
|
-
def initialize(file)
|
30
|
-
@file = file
|
15
|
+
attr_accessor :file, :location
|
31
16
|
|
32
|
-
|
33
|
-
|
17
|
+
Utils = ::Utils
|
18
|
+
JSArray = Utils::JSArray
|
19
|
+
JSHash = Utils::JSHash
|
34
20
|
|
35
|
-
|
36
|
-
|
21
|
+
# Make Questioner accesible as in: Configure::Questioner.run()
|
22
|
+
# "Questioner" simply starts an interactive prompt to guide
|
23
|
+
# the user in configuring src/config/agular_init.config.json,
|
24
|
+
# which is a JSON file that holds all the global configurable
|
25
|
+
# options (like language to use, templates, etc.)
|
26
|
+
class Questioner
|
27
|
+
attr_accessor :file
|
37
28
|
|
38
|
-
|
39
|
-
|
29
|
+
def initialize(file)
|
30
|
+
@file = file
|
40
31
|
|
41
|
-
|
42
|
-
|
43
|
-
@CONFIGURABLE_PROPERTIES = @CONFIGURABLE.collect{ |k,v| v }
|
32
|
+
@GLOBAL = @file['global']
|
33
|
+
# TODO: extend array with this inject function?
|
44
34
|
|
45
|
-
|
46
|
-
|
47
|
-
end
|
48
|
-
end
|
35
|
+
# The options for languages to use
|
36
|
+
@LANGUAGES = @GLOBAL['languages']
|
49
37
|
|
50
|
-
|
51
|
-
|
38
|
+
# The properties in key => value format of the properties the user can configure
|
39
|
+
@CONFIGURABLE = @GLOBAL['configurable']
|
52
40
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
end
|
41
|
+
# An array of the properties that the user is allowed to configure,
|
42
|
+
# according to src/config/angular_init.config.json
|
43
|
+
@CONFIGURABLE_PROPERTIES = @CONFIGURABLE.collect { |_k, v| v }
|
57
44
|
|
58
|
-
|
59
|
-
|
60
|
-
end
|
45
|
+
yield(self) if block_given?
|
46
|
+
end
|
61
47
|
|
62
|
-
|
63
|
-
|
64
|
-
when @CONFIGURABLE['language']
|
65
|
-
language_types = @LANGUAGES.collect{|type,languages| type if languages.size > 1 }.reject{|t| t.nil?}
|
48
|
+
def choose_configurable_property
|
49
|
+
line_break = "\n------------------"
|
66
50
|
|
67
|
-
|
51
|
+
puts "\nCurrent settings #{line_break}"
|
52
|
+
@CONFIGURABLE.each_with_index do |(_k, v), i|
|
53
|
+
puts "#{i + 1}) " + v.capitalize + ': ' + JSHash.new(@GLOBAL[v]).to_str
|
54
|
+
end
|
68
55
|
|
69
|
-
|
56
|
+
# return
|
57
|
+
AskLoop.ask(check: @CONFIGURABLE_PROPERTIES, valid: JSArray.new(@CONFIGURABLE_PROPERTIES).to_str)
|
58
|
+
end
|
70
59
|
|
71
|
-
|
60
|
+
def configure_property(property)
|
61
|
+
case property
|
62
|
+
when @CONFIGURABLE['language']
|
63
|
+
language_types = @LANGUAGES.collect { |type, languages| type if languages.size > 1 }.reject(&:nil?)
|
72
64
|
|
73
|
-
|
65
|
+
type = AskLoop.ask(check: language_types, valid: JSArray.new(language_types).to_str)
|
74
66
|
|
75
|
-
|
76
|
-
end
|
67
|
+
language_opts = @LANGUAGES.reject { |t, languages| languages if t != type }[type].reject { |l| l == @GLOBAL['language'][type] }
|
77
68
|
|
78
|
-
|
69
|
+
language = AskLoop.ask(check: language_opts, valid: JSArray.new(language_opts).to_str)
|
79
70
|
|
80
|
-
|
81
|
-
end
|
71
|
+
answer = @GLOBAL['language']
|
82
72
|
|
73
|
+
answer[type] = language
|
74
|
+
end
|
83
75
|
|
84
|
-
|
85
|
-
q = Questioner.new(file) do |q|
|
86
|
-
configurable_property = q.choose_configurable_property
|
76
|
+
# TODO: add ability to add templates
|
87
77
|
|
88
|
-
|
78
|
+
answer
|
79
|
+
end
|
89
80
|
|
90
|
-
|
81
|
+
def self.run(file)
|
82
|
+
questioner = Questioner.new(file) do |q|
|
83
|
+
configurable_property = q.choose_configurable_property
|
91
84
|
|
92
|
-
|
93
|
-
end
|
85
|
+
result = q.configure_property(configurable_property)
|
94
86
|
|
95
|
-
|
96
|
-
end
|
97
|
-
end
|
87
|
+
q.file['global'][configurable_property] = result
|
98
88
|
|
99
|
-
|
100
|
-
|
101
|
-
# This implementation just creates a loop that asks
|
102
|
-
# for user input
|
103
|
-
class AskLoop < Utils::AskLoop
|
104
|
-
def self.ask(args)
|
105
|
-
puts "\n"
|
106
|
-
puts 'Choose from: '+args[:valid]
|
89
|
+
puts configurable_property.capitalize + ' set to: ' + JSHash.new(result).to_str
|
90
|
+
end
|
107
91
|
|
108
|
-
|
92
|
+
questioner.file
|
93
|
+
end
|
94
|
+
end
|
109
95
|
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
end
|
96
|
+
# Here, we implement the virtual class "Utils::AskLoop"
|
97
|
+
# (see src/ruby/utils/utils.rb)
|
98
|
+
# This implementation just creates a loop that asks
|
99
|
+
# for user input
|
100
|
+
class AskLoop < Utils::AskLoop
|
101
|
+
def self.ask(args)
|
102
|
+
puts "\n"
|
103
|
+
puts 'Choose from: ' + args[:valid]
|
119
104
|
|
120
|
-
|
121
|
-
end
|
122
|
-
end
|
105
|
+
answer = $stdin.gets.strip
|
123
106
|
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
107
|
+
loop do
|
108
|
+
if args[:check].include?(answer)
|
109
|
+
break
|
110
|
+
else
|
111
|
+
puts 'Choose from: ' + args[:valid]
|
112
|
+
puts '(or press ctrl+c to exit)'
|
113
|
+
answer = $stdin.gets.strip
|
114
|
+
end
|
115
|
+
end
|
130
116
|
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
end
|
117
|
+
answer
|
118
|
+
end
|
119
|
+
end
|
135
120
|
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
121
|
+
# The only thing we do here is load the JSON config file basically
|
122
|
+
# as just a string in JSON format.
|
123
|
+
# It will be converted to a Ruby hash in from_json below
|
124
|
+
def initialize
|
125
|
+
@location = CURRENT_DIR + '/config/angular_init.config.json'
|
126
|
+
@file = IO.read(@location)
|
140
127
|
|
141
|
-
|
142
|
-
|
143
|
-
def to_json
|
144
|
-
JSON.pretty_generate(@file)
|
145
|
-
end
|
146
|
-
|
147
|
-
# Here we actually write the new JSON config file
|
148
|
-
# to src/config/angular_init.config.json
|
149
|
-
def write
|
150
|
-
new_file = to_json
|
128
|
+
yield(self) if block_given?
|
129
|
+
end
|
151
130
|
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
end
|
131
|
+
# Convert the file to a Ruby hash
|
132
|
+
def from_json
|
133
|
+
JSON.parse(@file)
|
134
|
+
end
|
157
135
|
|
158
|
-
|
159
|
-
|
160
|
-
|
136
|
+
# Generate a "prettified" JSON version of our
|
137
|
+
# newly updated Ruby hash with the user's options
|
138
|
+
def to_json
|
139
|
+
JSON.pretty_generate(@file)
|
140
|
+
end
|
141
|
+
|
142
|
+
# Here we actually write the new JSON config file
|
143
|
+
# to src/config/angular_init.config.json
|
144
|
+
def write
|
145
|
+
new_file = to_json
|
161
146
|
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
end
|
147
|
+
File.open(@location, 'w') do |f|
|
148
|
+
f.write(new_file)
|
149
|
+
f.close
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
def self.run
|
154
|
+
Configure.new do |c|
|
155
|
+
c.file = Configure::Questioner.run(c.from_json)
|
156
|
+
|
157
|
+
c.write
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
data/lib/ngi/delegate.rb
CHANGED
@@ -16,9 +16,7 @@ require_relative 'configure'
|
|
16
16
|
# the flow of control to either the Generator class
|
17
17
|
# or the Configure class, based on the argument passed
|
18
18
|
# in (which is handled by bin/ngi)
|
19
|
-
|
20
19
|
class Delegate
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
end
|
20
|
+
Generator = ::Generator
|
21
|
+
Configure = ::Configure
|
22
|
+
end
|
data/lib/ngi/generator.rb
CHANGED
@@ -3,197 +3,191 @@
|
|
3
3
|
# github.com/joshbeam/angular_init
|
4
4
|
# MIT License
|
5
5
|
|
6
|
-
require_relative
|
6
|
+
require_relative 'utils/utils'
|
7
7
|
|
8
8
|
# This class generates templates (hence the name "Generator")
|
9
9
|
class Generator
|
10
|
-
|
10
|
+
Utils = ::Utils
|
11
11
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
12
|
+
class AskLoop < Utils::AskLoop
|
13
|
+
def self.ask(args)
|
14
|
+
puts "\n"
|
15
|
+
print args[:prompt]
|
16
16
|
|
17
|
-
|
17
|
+
answer = $stdin.gets.strip.downcase
|
18
18
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
19
|
+
loop do
|
20
|
+
if args[:check] == answer
|
21
|
+
break
|
22
|
+
else
|
23
|
+
puts 'Exited!'
|
24
|
+
exit
|
25
|
+
end
|
26
|
+
end
|
27
27
|
|
28
|
-
|
29
|
-
|
30
|
-
|
28
|
+
answer
|
29
|
+
end
|
30
|
+
end
|
31
31
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
g.write
|
195
|
-
end
|
196
|
-
|
197
|
-
puts 'All done!'
|
198
|
-
end
|
199
|
-
end
|
32
|
+
WHITESPACE = /\s*/
|
33
|
+
EMPTY = ''
|
34
|
+
CURRENT_DIR = File.dirname(__FILE__)
|
35
|
+
|
36
|
+
################################
|
37
|
+
|
38
|
+
# SET UP ALL THE CONFIG OPTIONS
|
39
|
+
# Generator.new (the initialization function) is called in self.run
|
40
|
+
|
41
|
+
def initialize(args)
|
42
|
+
@type = args[:type]
|
43
|
+
@config = args[:config]['global']
|
44
|
+
|
45
|
+
all_components = @config['components']
|
46
|
+
component = all_components.find { |t| t['name'] == @type }
|
47
|
+
|
48
|
+
# basically just rebuilding the object so we can use it here
|
49
|
+
@component = {
|
50
|
+
of_type: component['type'],
|
51
|
+
language: @config['language'][component['type']],
|
52
|
+
using: component['using'],
|
53
|
+
template: component['template']
|
54
|
+
}
|
55
|
+
|
56
|
+
template_dir = "#{CURRENT_DIR}/../templates/"
|
57
|
+
template_dir << "#{@component[:of_type]}/#{@component[:language]}/#{@component[:using]}/#{@component[:template]}"
|
58
|
+
|
59
|
+
@template_file = IO.read(template_dir)
|
60
|
+
|
61
|
+
yield(self) if block_given?
|
62
|
+
end
|
63
|
+
|
64
|
+
###############################
|
65
|
+
|
66
|
+
def new_file_name
|
67
|
+
print '[?] New file name: '
|
68
|
+
|
69
|
+
@new_file = $stdin.gets.gsub(WHITESPACE, EMPTY)
|
70
|
+
end
|
71
|
+
|
72
|
+
def module_name
|
73
|
+
print '[?] Module name: '
|
74
|
+
|
75
|
+
@module_name = $stdin.gets.gsub(WHITESPACE, EMPTY)
|
76
|
+
end
|
77
|
+
|
78
|
+
def name
|
79
|
+
print "[?] #{@type.capitalize} name: "
|
80
|
+
|
81
|
+
@name = $stdin.gets.gsub(WHITESPACE, EMPTY)
|
82
|
+
end
|
83
|
+
|
84
|
+
def inject
|
85
|
+
# REVIEW: use symbols instead of strings?
|
86
|
+
special = %w(routes controller).include?(@type)
|
87
|
+
auto_injections = [
|
88
|
+
{
|
89
|
+
for_type: 'routes',
|
90
|
+
service: '$routeProvider'
|
91
|
+
},
|
92
|
+
{
|
93
|
+
for_type: 'controller',
|
94
|
+
service: '$scope'
|
95
|
+
}
|
96
|
+
]
|
97
|
+
|
98
|
+
injection = special ? auto_injections.select { |inj| inj[:for_type] == @type }[0][:service] : nil
|
99
|
+
|
100
|
+
auto_injection_statement = special ? " (already injected #{injection})" : ''
|
101
|
+
|
102
|
+
print "[?] Inject#{auto_injection_statement}: "
|
103
|
+
|
104
|
+
# accepts a comma-delimited list
|
105
|
+
# EXAMPLE: testService, testService2
|
106
|
+
# => [testService,testService2]
|
107
|
+
@dependencies = $stdin.gets.split(',').map(&:strip).reject(&:empty?)
|
108
|
+
|
109
|
+
# automatically inject $scope into a controller
|
110
|
+
# FIXME: don't use index accessors (numbers are confusing)
|
111
|
+
@dependencies << auto_injections[1][:service] if @type == 'controller' && !@dependencies.include?(auto_injections[1][:service])
|
112
|
+
|
113
|
+
# automatically insert $routeProvider into a routes config
|
114
|
+
@dependencies << auto_injections[0][:service] if @type == 'routes' && !@dependencies.include?(auto_injections[0][:service])
|
115
|
+
end
|
116
|
+
|
117
|
+
def replace
|
118
|
+
# inject may or may not have run... if it wasn't run, then @dependencies was never set
|
119
|
+
# for example, for html templates, we don't run the inject function
|
120
|
+
# @dependencies = @dependencies || []
|
121
|
+
@dependencies ||= []
|
122
|
+
has_dependencies = @dependencies.size > 0
|
123
|
+
|
124
|
+
# Use 'config' as the type, since 'routes' is really an alias for a specific type of 'config'.
|
125
|
+
# TODO: map aliases from config file
|
126
|
+
@type = 'config' if @type == 'routes'
|
127
|
+
|
128
|
+
# Regex replacements to generate the template
|
129
|
+
@template_file = @template_file
|
130
|
+
.gsub(/\{\{type\}\}/, @type)
|
131
|
+
.gsub(/\{\{name\}\}/, @name || '')
|
132
|
+
.gsub(/\{\{module\}\}/, "#{@module_name}")
|
133
|
+
.gsub(
|
134
|
+
/\{\{inject\s\|\sarray_string\}\}/,
|
135
|
+
has_dependencies ?
|
136
|
+
@dependencies.to_s.gsub(/"/, '\'') : '[]'
|
137
|
+
)
|
138
|
+
.gsub(
|
139
|
+
/\{\{inject\s\|\scomma_delimited_variables\}\}/,
|
140
|
+
has_dependencies ?
|
141
|
+
@dependencies.each_with_index.inject('') { |str, (dep, i)| str += dep.to_s + (i == @dependencies.size - 1 ? '' : ', ') } : ''
|
142
|
+
)
|
143
|
+
end
|
144
|
+
|
145
|
+
def tag
|
146
|
+
# If Liquid-style tags are used in a template that can be used
|
147
|
+
# for multiple components, remove those parts that don't
|
148
|
+
# belong to the type of component user wants to generate
|
149
|
+
@template_file = @template_file
|
150
|
+
.gsub(/\{\%\sif\s#{@type}\s\%\}(.*)\{\%\sendif\s#{@type}\s\%\}/m, '\1')
|
151
|
+
.gsub(/\s\{\%\sif\s.*\s\%\}.*\{\%\sendif\s.*\s\%\}/m, '')
|
152
|
+
end
|
153
|
+
|
154
|
+
def write
|
155
|
+
# create the new file
|
156
|
+
def overwrite?
|
157
|
+
AskLoop.ask(check: 'y', prompt: 'File exists already, overwrite it? (y/n) ')
|
158
|
+
end
|
159
|
+
|
160
|
+
overwrite? if File.exist?(@new_file)
|
161
|
+
|
162
|
+
File.open(@new_file, 'w') do |file|
|
163
|
+
file.write(@template_file)
|
164
|
+
file.close
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
# Use this function to be able to say AngularInit::Delegate::Generator.run() inside the executable file
|
169
|
+
# This function simply goes through all of the methods in order to interactively
|
170
|
+
# prompt the user to generate a new template
|
171
|
+
def self.run(args)
|
172
|
+
Generator.new(args) do |g|
|
173
|
+
g.new_file_name
|
174
|
+
|
175
|
+
# we don't need to define the module if we're creating a module
|
176
|
+
g.module_name unless args[:type] == 'module'
|
177
|
+
|
178
|
+
# 'run', 'config', and 'routes' don't have custom names in AngularJS
|
179
|
+
# REVIEW: use symbols instead of strings?
|
180
|
+
g.name unless %w(run config routes index).include? args[:type]
|
181
|
+
|
182
|
+
g.inject unless ['index'].include? args[:type]
|
183
|
+
|
184
|
+
g.replace
|
185
|
+
|
186
|
+
g.tag
|
187
|
+
|
188
|
+
g.write
|
189
|
+
end
|
190
|
+
|
191
|
+
puts 'All done!'
|
192
|
+
end
|
193
|
+
end
|
@@ -3,102 +3,99 @@
|
|
3
3
|
# github.com/joshbeam/angular_init
|
4
4
|
# MIT License
|
5
5
|
|
6
|
-
|
7
6
|
# Similar to Ruby's OptionParser
|
8
7
|
# However, this is customized for angular_init
|
9
|
-
|
10
8
|
class CommandParser
|
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
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
end
|
9
|
+
attr_reader :args
|
10
|
+
attr_accessor :banner, :version, :separator, :name
|
11
|
+
|
12
|
+
def initialize
|
13
|
+
# TODO: to "Usage #{file_name}", etc.
|
14
|
+
@name = '<CLI>'
|
15
|
+
@banner = "Usage: #{@name} <command>"
|
16
|
+
@version = '0.0.0'
|
17
|
+
@separator = '===================='
|
18
|
+
@listeners = []
|
19
|
+
|
20
|
+
# automatically register some listeners
|
21
|
+
register_help
|
22
|
+
register_version
|
23
|
+
|
24
|
+
# be able to pass in a block for setup
|
25
|
+
yield(self) if block_given?
|
26
|
+
end
|
27
|
+
|
28
|
+
def name=(name)
|
29
|
+
# need to also replace the name in the banner
|
30
|
+
@banner = @banner.gsub(@name, name)
|
31
|
+
|
32
|
+
@name = name
|
33
|
+
end
|
34
|
+
|
35
|
+
# register the listeners
|
36
|
+
def on(options, description = '', &block)
|
37
|
+
listener = {}
|
38
|
+
|
39
|
+
# be able to pass in a single argument, or an array of arguments
|
40
|
+
options = *options unless options.is_a? Array
|
41
|
+
|
42
|
+
listener[:options] = options.map do |opt|
|
43
|
+
opt.strip.split(' ')
|
44
|
+
end
|
45
|
+
|
46
|
+
listener[:block] = block
|
47
|
+
listener[:description] = description
|
48
|
+
|
49
|
+
@listeners << listener
|
50
|
+
end
|
51
|
+
|
52
|
+
def parse(args)
|
53
|
+
# puts @listeners
|
54
|
+
matched_listener = {
|
55
|
+
options: nil,
|
56
|
+
block: nil
|
57
|
+
}
|
58
|
+
|
59
|
+
@listeners.each do |listener|
|
60
|
+
listener[:options].each do |opt_arr|
|
61
|
+
if opt_arr == args
|
62
|
+
matched_listener[:options] = opt_arr
|
63
|
+
matched_listener[:block] = listener[:block]
|
64
|
+
break
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
if !matched_listener[:options].nil?
|
70
|
+
# matched_listener[:options] should always be an array
|
71
|
+
# when we call, we can each member of that array to be
|
72
|
+
# passed separately
|
73
|
+
matched_listener[:block].call(*matched_listener[:options])
|
74
|
+
else
|
75
|
+
# if there was no match, show the help menu
|
76
|
+
parse(['-h'])
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def register_help
|
81
|
+
# automaticaly register this listener
|
82
|
+
on(['-h', '--help'], 'Show the help menu') do
|
83
|
+
puts @separator
|
84
|
+
puts @banner
|
85
|
+
|
86
|
+
@listeners.each_with_index do |listener, i|
|
87
|
+
desc = "\n" << "(#{i + 1}) #{listener[:description]}: "
|
88
|
+
desc << "#{listener[:options].join(', ')}"
|
89
|
+
puts desc
|
90
|
+
end
|
91
|
+
puts @separator
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def register_version
|
96
|
+
# automaticaly register this listener
|
97
|
+
on(['-v', '--version'], 'Show the version') do
|
98
|
+
puts "#{@name} #{@version}"
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
data/lib/ngi/utils/jser.rb
CHANGED
@@ -3,44 +3,44 @@
|
|
3
3
|
# github.com/joshbeam/angular_init
|
4
4
|
# MIT License
|
5
5
|
|
6
|
+
# Since ngi is an AngularJS tool and the users
|
7
|
+
# are familiar with JavaScript, this module of classes
|
8
|
+
# prints a string version of a Ruby hash or array
|
9
|
+
# as it would appear in normal JavaScript syntax
|
10
|
+
# For example:
|
11
|
+
# { "hello" => "world" }
|
12
|
+
# becomes:
|
13
|
+
# { 'hello': 'world' }
|
14
|
+
# and ["some","array"]
|
15
|
+
# becomes:
|
16
|
+
# ['some','array']
|
6
17
|
module JSer
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
# as it would appear in normal JavaScript syntax
|
11
|
-
# For example:
|
12
|
-
# { "hello" => "world" }
|
13
|
-
# becomes:
|
14
|
-
# { 'hello': 'world' }
|
15
|
-
# and ["some","array"]
|
16
|
-
# becomes:
|
17
|
-
# ['some','array']
|
18
|
-
def to_str
|
19
|
-
self.to_s.gsub(/\"/,"'").gsub(/\=\>/,": ")
|
20
|
-
end
|
18
|
+
def to_str
|
19
|
+
to_s.gsub(/\"/, "'").gsub(/\=\>/, ': ')
|
20
|
+
end
|
21
21
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
22
|
+
# A JSer class
|
23
|
+
# Usage:
|
24
|
+
# JSHash.new({"hello" => "world"}).to_str
|
25
|
+
class JSHash < Hash
|
26
|
+
def initialize(hash)
|
27
|
+
super
|
28
|
+
hash.each do |key, val|
|
29
|
+
self[key] = val
|
30
|
+
end
|
31
|
+
end
|
32
32
|
|
33
|
-
|
34
|
-
|
33
|
+
include JSer
|
34
|
+
end
|
35
35
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
36
|
+
# Another JSer class
|
37
|
+
# Usage:
|
38
|
+
# JSArray.new(["some","array"]).to_str
|
39
|
+
class JSArray < Array
|
40
|
+
def initialize(array)
|
41
|
+
super
|
42
|
+
end
|
43
43
|
|
44
|
-
|
45
|
-
|
46
|
-
end
|
44
|
+
include JSer
|
45
|
+
end
|
46
|
+
end
|
data/lib/ngi/utils/utils.rb
CHANGED
@@ -3,28 +3,30 @@
|
|
3
3
|
# github.com/joshbeam/angular_init
|
4
4
|
# MIT License
|
5
5
|
|
6
|
-
require_relative
|
7
|
-
require_relative
|
6
|
+
require_relative 'command_parser'
|
7
|
+
require_relative 'jser'
|
8
8
|
|
9
|
+
# This module holds classes of basic utility
|
10
|
+
# functions used throughout Ngi
|
9
11
|
module Utils
|
10
|
-
|
11
|
-
|
12
|
-
|
12
|
+
CommandParser = ::CommandParser
|
13
|
+
JSArray = JSer::JSArray
|
14
|
+
JSHash = JSer::JSHash
|
13
15
|
|
14
|
-
|
16
|
+
class AskLoop; end
|
15
17
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
def initialize(args)
|
23
|
-
@valid_inputs = args[:valid_inputs]
|
24
|
-
end
|
18
|
+
# This class is just a way to meaningfully
|
19
|
+
# collect an array of valid user inputs
|
20
|
+
# for use with OptionParser in bin/ngi
|
21
|
+
class UserInput
|
22
|
+
attr_reader :valid_inputs
|
25
23
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
24
|
+
def initialize(args)
|
25
|
+
@valid_inputs = args[:valid_inputs]
|
26
|
+
end
|
27
|
+
|
28
|
+
def valid?(input)
|
29
|
+
@valid_inputs.include?(input)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
data/lib/ngi/version.rb
CHANGED
@@ -1,3 +1,11 @@
|
|
1
|
+
# angular_init (short-name: ngi)
|
2
|
+
# Copyright 2015 Joshua Beam
|
3
|
+
# github.com/joshbeam/angular_init
|
4
|
+
# MIT License
|
5
|
+
|
6
|
+
# The current version of Ngi.
|
7
|
+
# This uses semantic versioning.
|
8
|
+
# See http://semver.org/
|
1
9
|
module Ngi
|
2
|
-
VERSION =
|
3
|
-
end
|
10
|
+
VERSION = '0.2.2'
|
11
|
+
end
|
data/ngi.gemspec
CHANGED
@@ -12,6 +12,7 @@ Gem::Specification.new do |spec|
|
|
12
12
|
spec.description = %q{This tool can make (for example) an AngularJS controller template file for you (.js), so that whenever you want to make a new controller for your app, you don't have to type the same starting code over and over again (by the way, this tool doesn't only create controllers. It does directives, filters... almost anything). ngi has one task, and one task only, which makes it lightweight and specialized. Most AngularJS developers are probably using the command line already (Gulp, Bower, npm, Git, etc.), so why not use the command line to streamline your code-writing too? Type less, write more AngularJS!}
|
13
13
|
spec.homepage = "https://github.com/joshbeam/angular_init"
|
14
14
|
spec.license = "MIT"
|
15
|
+
spec.required_ruby_version = ">= 2.1"
|
15
16
|
|
16
17
|
spec.files = `git ls-files -z`.split("\x0")
|
17
18
|
spec.executables = ["ngi"]
|
data/ngi_example.gif
ADDED
Binary file
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ngi
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Joshua Beam
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-04-
|
11
|
+
date: 2015-04-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -101,6 +101,7 @@ files:
|
|
101
101
|
- lib/templates/script/es5/default/constant.js
|
102
102
|
- lib/templates/script/es5/default/module.js
|
103
103
|
- ngi.gemspec
|
104
|
+
- ngi_example.gif
|
104
105
|
homepage: https://github.com/joshbeam/angular_init
|
105
106
|
licenses:
|
106
107
|
- MIT
|
@@ -113,7 +114,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
113
114
|
requirements:
|
114
115
|
- - ">="
|
115
116
|
- !ruby/object:Gem::Version
|
116
|
-
version: '
|
117
|
+
version: '2.1'
|
117
118
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
118
119
|
requirements:
|
119
120
|
- - ">="
|