grouik 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/src/bin/grouik +36 -0
- data/src/lib/grouik/cli.rb +172 -0
- data/src/lib/grouik/concerns/helpable.rb +19 -0
- data/src/lib/grouik/concerns.rb +16 -0
- data/src/lib/grouik/formatter.rb +67 -0
- data/src/lib/grouik/helpers/cli.rb +102 -0
- data/src/lib/grouik/helpers/loader.rb +72 -0
- data/src/lib/grouik/helpers/process.rb +82 -0
- data/src/lib/grouik/helpers.rb +50 -0
- data/src/lib/grouik/loadable.rb +51 -0
- data/src/lib/grouik/loader.rb +156 -0
- data/src/lib/grouik/output/message.rb +54 -0
- data/src/lib/grouik/output/messager.rb +86 -0
- data/src/lib/grouik/output.rb +13 -0
- data/src/lib/grouik/process.rb +195 -0
- data/src/lib/grouik/types.rb +46 -0
- data/src/lib/grouik/version_info.yml +16 -0
- data/src/lib/grouik.rb +101 -0
- metadata +216 -0
@@ -0,0 +1,156 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright (C) 2017 Dimitri Arrigoni <dimitri@arrigoni.me>
|
4
|
+
# License GPLv3+: GNU GPL version 3 or later
|
5
|
+
# <http://www.gnu.org/licenses/gpl.html>.
|
6
|
+
# This is free software: you are free to change and redistribute it.
|
7
|
+
# There is NO WARRANTY, to the extent permitted by law.
|
8
|
+
|
9
|
+
require 'benchmark'
|
10
|
+
require 'pathname'
|
11
|
+
require 'ostruct'
|
12
|
+
|
13
|
+
require 'grouik/concerns'
|
14
|
+
|
15
|
+
# Main class loader
|
16
|
+
#
|
17
|
+
# loads files during ``Grouik::Loader#load_all``
|
18
|
+
class Grouik::Loader
|
19
|
+
attr_accessor :basedir
|
20
|
+
attr_accessor :ignores
|
21
|
+
attr_reader :paths
|
22
|
+
|
23
|
+
attr_reader :attempts
|
24
|
+
attr_reader :errors
|
25
|
+
attr_reader :stats
|
26
|
+
|
27
|
+
include Grouik::Concerns::Helpable
|
28
|
+
|
29
|
+
def initialize
|
30
|
+
self.basedir = '.'
|
31
|
+
self.ignores = []
|
32
|
+
|
33
|
+
@loadeds = []
|
34
|
+
@errors = {}
|
35
|
+
@loadables = []
|
36
|
+
@attempts = 0
|
37
|
+
@stats = nil
|
38
|
+
|
39
|
+
return self unless block_given?
|
40
|
+
|
41
|
+
yield self
|
42
|
+
register
|
43
|
+
end
|
44
|
+
|
45
|
+
# @param [Array<String|Regexp>] ignores
|
46
|
+
def ignores=(ignores)
|
47
|
+
@ignores = helpers.get(:loader).make_ignores(ignores)
|
48
|
+
end
|
49
|
+
|
50
|
+
# @param [Array<String>] paths
|
51
|
+
def paths=(paths)
|
52
|
+
@paths = paths.to_a.map { |path| Pathname.new(path.to_s) }
|
53
|
+
end
|
54
|
+
|
55
|
+
# @return [Array<Pathname>]
|
56
|
+
def paths
|
57
|
+
(@paths || (@paths.empty? ? ['.'] : @paths)).clone
|
58
|
+
end
|
59
|
+
|
60
|
+
# Register paths
|
61
|
+
#
|
62
|
+
# @return [self]
|
63
|
+
def register
|
64
|
+
helpers.get(:loader).register_paths(basedir, @paths)
|
65
|
+
|
66
|
+
self
|
67
|
+
end
|
68
|
+
|
69
|
+
# Get loadables
|
70
|
+
#
|
71
|
+
# @return [Array<Grouik::Loadable>]
|
72
|
+
def loadables
|
73
|
+
if @loadables.empty?
|
74
|
+
self.basedir do
|
75
|
+
@loadables = helpers.get(:loader)
|
76
|
+
.collect_loadables(paths)
|
77
|
+
.ignores(ignores)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
@loadables.clone
|
82
|
+
end
|
83
|
+
|
84
|
+
# @return [Pathname]
|
85
|
+
def basedir
|
86
|
+
Dir.chdir(helpers.get(:loader).pwd.join(basedir)) { yield } if block_given?
|
87
|
+
|
88
|
+
Pathname.new(@basedir)
|
89
|
+
end
|
90
|
+
|
91
|
+
# @return [self]
|
92
|
+
def load_all
|
93
|
+
return @loadeds.clone unless @loadeds.empty?
|
94
|
+
|
95
|
+
loadables = self.loadables
|
96
|
+
@loadeds = []
|
97
|
+
@errors = {}
|
98
|
+
|
99
|
+
@stats = Benchmark.measure do
|
100
|
+
loop do
|
101
|
+
loadables = process_loadables(loadables)
|
102
|
+
break if loadables.nil? or (loadables and loadables.empty?)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
@loadeds.compact
|
106
|
+
self
|
107
|
+
end
|
108
|
+
|
109
|
+
# Format using a formatter
|
110
|
+
#
|
111
|
+
# @param [Hash] options
|
112
|
+
# @return [String]
|
113
|
+
def format(options = {})
|
114
|
+
Grouik.get(:formatter).format(load_all.loadables, options).to_s
|
115
|
+
end
|
116
|
+
|
117
|
+
def loaded?
|
118
|
+
self.loadables.size == @loadeds.size
|
119
|
+
end
|
120
|
+
|
121
|
+
# @return [Fixnum]
|
122
|
+
def attempts_maxcount
|
123
|
+
(self.loadables.size**2) + 1
|
124
|
+
end
|
125
|
+
|
126
|
+
protected
|
127
|
+
|
128
|
+
def process_loadables(processables)
|
129
|
+
processables.each_with_index do |loadable, index|
|
130
|
+
return [] if attempts >= attempts_maxcount or processables.empty?
|
131
|
+
|
132
|
+
@attempts += 1
|
133
|
+
loaded = nil
|
134
|
+
begin
|
135
|
+
loaded = loadable.load(helpers.get(:loader).pwd.join(basedir))
|
136
|
+
rescue StandardError => e
|
137
|
+
unless @errors[loadable.to_s]
|
138
|
+
@errors[loadable.to_s] = OpenStruct.new(
|
139
|
+
source: loadable.to_s,
|
140
|
+
message: e.message.lines[0].strip.freeze,
|
141
|
+
line: e.backtrace[0].split(':')[1],
|
142
|
+
error: e
|
143
|
+
).freeze
|
144
|
+
end
|
145
|
+
next
|
146
|
+
end
|
147
|
+
|
148
|
+
next if loaded.nil?
|
149
|
+
|
150
|
+
@loadeds.push(processables.delete_at(index))
|
151
|
+
# when loadable is loaded, then error is removed
|
152
|
+
@errors.delete(loadable.to_s)
|
153
|
+
end
|
154
|
+
processables
|
155
|
+
end
|
156
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright (C) 2017 Dimitri Arrigoni <dimitri@arrigoni.me>
|
4
|
+
# License GPLv3+: GNU GPL version 3 or later
|
5
|
+
# <http://www.gnu.org/licenses/gpl.html>.
|
6
|
+
# This is free software: you are free to change and redistribute it.
|
7
|
+
# There is NO WARRANTY, to the extent permitted by law.
|
8
|
+
|
9
|
+
# Describe a message (sent on a IO as STDOUT/STDERR)
|
10
|
+
class Grouik::Output::Message
|
11
|
+
attr_accessor :content
|
12
|
+
attr_accessor :type
|
13
|
+
attr_accessor :stream
|
14
|
+
|
15
|
+
def initialize
|
16
|
+
yield self if block_given?
|
17
|
+
end
|
18
|
+
|
19
|
+
# @param content [String]
|
20
|
+
def content=(content)
|
21
|
+
@content = content.to_s.empty? ? nil : content.to_s
|
22
|
+
end
|
23
|
+
|
24
|
+
# @param stream [IO]
|
25
|
+
def stream=(stream)
|
26
|
+
@stream = stream.clone
|
27
|
+
end
|
28
|
+
|
29
|
+
# @return [IO]
|
30
|
+
def stream
|
31
|
+
@stream || STDOUT.clone
|
32
|
+
end
|
33
|
+
|
34
|
+
# @raise [RuntimeError]
|
35
|
+
# @return [self]
|
36
|
+
def send
|
37
|
+
attrs = [:stream, :content, :type]
|
38
|
+
attrs.each do |attr|
|
39
|
+
raise 'attributes %s must be set' % attrs if public_send(attr).nil?
|
40
|
+
end
|
41
|
+
|
42
|
+
messager_class.new(stream, content.to_s).output(type)
|
43
|
+
self
|
44
|
+
end
|
45
|
+
|
46
|
+
protected
|
47
|
+
|
48
|
+
# @return [Grouik::Output::Messager]
|
49
|
+
def messager_class
|
50
|
+
require '%s/messager' % __dir__
|
51
|
+
|
52
|
+
Grouik::Output::Messager
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright (C) 2017 Dimitri Arrigoni <dimitri@arrigoni.me>
|
4
|
+
# License GPLv3+: GNU GPL version 3 or later
|
5
|
+
# <http://www.gnu.org/licenses/gpl.html>.
|
6
|
+
# This is free software: you are free to change and redistribute it.
|
7
|
+
# There is NO WARRANTY, to the extent permitted by law.
|
8
|
+
|
9
|
+
# Provide a wrapper over ``Rainbow``
|
10
|
+
class Grouik::Output::Messager
|
11
|
+
attr_accessor :stream
|
12
|
+
attr_accessor :content
|
13
|
+
|
14
|
+
def initialize(stream = STDOUT, content = nil)
|
15
|
+
@stream = stream
|
16
|
+
self.content = content
|
17
|
+
end
|
18
|
+
|
19
|
+
def content=(content)
|
20
|
+
@content = content.to_s
|
21
|
+
end
|
22
|
+
|
23
|
+
# @todo Catch ``NoMethodError`` or similar error
|
24
|
+
# @return [self]
|
25
|
+
def output(type)
|
26
|
+
stream.puts self.format_as(type)
|
27
|
+
|
28
|
+
self
|
29
|
+
end
|
30
|
+
|
31
|
+
class << self
|
32
|
+
# @return [self]
|
33
|
+
def output(stream, type)
|
34
|
+
self.new(stream, content).output(type)
|
35
|
+
end
|
36
|
+
|
37
|
+
# Defines available formats
|
38
|
+
#
|
39
|
+
# @return [Hash]
|
40
|
+
def formats
|
41
|
+
{
|
42
|
+
status_success: {
|
43
|
+
background: :green,
|
44
|
+
color: :black,
|
45
|
+
},
|
46
|
+
status_failure: {
|
47
|
+
background: :red,
|
48
|
+
color: :black,
|
49
|
+
},
|
50
|
+
error: {
|
51
|
+
color: :red,
|
52
|
+
}
|
53
|
+
}
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
# @param type [Symbol|String]
|
58
|
+
# @return [Rainbow::Presenter, Rainbow::NullPresenter]
|
59
|
+
def format_as(type)
|
60
|
+
colorize(self.class.formats[type.to_sym])
|
61
|
+
end
|
62
|
+
|
63
|
+
# Denote output is colorizable (``tty?``)
|
64
|
+
def colorizable?
|
65
|
+
stream.tty?
|
66
|
+
end
|
67
|
+
|
68
|
+
protected
|
69
|
+
|
70
|
+
# Get a colorizable (almost a wrapper over ``Rainbow``) content instance
|
71
|
+
#
|
72
|
+
# @return [Rainbow::Presenter, Rainbow::NullPresenter]
|
73
|
+
def colorizable
|
74
|
+
require 'rainbow'
|
75
|
+
|
76
|
+
Rainbow.enabled = colorizable?
|
77
|
+
Rainbow::Wrapper.new(colorizable?).wrap(content)
|
78
|
+
end
|
79
|
+
|
80
|
+
def colorize(format = {})
|
81
|
+
colorizable = self.colorizable.clone
|
82
|
+
format.to_h.each { |k, v| colorizable = colorizable.public_send(k, v) }
|
83
|
+
|
84
|
+
colorizable
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright (C) 2017 Dimitri Arrigoni <dimitri@arrigoni.me>
|
4
|
+
# License GPLv3+: GNU GPL version 3 or later
|
5
|
+
# <http://www.gnu.org/licenses/gpl.html>.
|
6
|
+
# This is free software: you are free to change and redistribute it.
|
7
|
+
# There is NO WARRANTY, to the extent permitted by law.
|
8
|
+
|
9
|
+
module Grouik::Output
|
10
|
+
[:message].each do |req|
|
11
|
+
require '%s/output/%s' % [__dir__, req]
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,195 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright (C) 2017 Dimitri Arrigoni <dimitri@arrigoni.me>
|
4
|
+
# License GPLv3+: GNU GPL version 3 or later
|
5
|
+
# <http://www.gnu.org/licenses/gpl.html>.
|
6
|
+
# This is free software: you are free to change and redistribute it.
|
7
|
+
# There is NO WARRANTY, to the extent permitted by law.
|
8
|
+
|
9
|
+
require 'pathname'
|
10
|
+
|
11
|
+
require 'grouik/concerns'
|
12
|
+
|
13
|
+
# Intended to wrap ``Grouik::Loader``
|
14
|
+
#
|
15
|
+
# Easify reusability through ``Grouik::Cli``
|
16
|
+
# or as standalone (for example in a Rake task)
|
17
|
+
#
|
18
|
+
# Sample of use:
|
19
|
+
#
|
20
|
+
# ~~~~
|
21
|
+
# task 'src/ceres.rb' do
|
22
|
+
# require 'grouik'
|
23
|
+
#
|
24
|
+
# Grouik.process do |process|
|
25
|
+
# process.verbose = false
|
26
|
+
# process.paths = ['lib']
|
27
|
+
# process.basedir = 'src'
|
28
|
+
# process.output = 'src/ceres.rb'
|
29
|
+
# process.template = 'src/ceres.tpl'
|
30
|
+
# end.on_failure { exit Errno::ECANCELED::Errno }
|
31
|
+
# end
|
32
|
+
# ~~~~
|
33
|
+
class Grouik::Process
|
34
|
+
attr_accessor :template
|
35
|
+
attr_accessor :bootstrap
|
36
|
+
attr_accessor :verbose
|
37
|
+
attr_reader :output
|
38
|
+
|
39
|
+
include Grouik::Concerns::Helpable
|
40
|
+
|
41
|
+
def initialize
|
42
|
+
@output = nil
|
43
|
+
@template = nil
|
44
|
+
@bootstrap = nil
|
45
|
+
@verbose = false
|
46
|
+
|
47
|
+
@loader = Grouik::Loader.new
|
48
|
+
yield self if block_given?
|
49
|
+
@loader.register
|
50
|
+
end
|
51
|
+
|
52
|
+
def verbose?
|
53
|
+
!!@verbose
|
54
|
+
end
|
55
|
+
|
56
|
+
# @param [Pathname|String] output
|
57
|
+
# @return [Object]
|
58
|
+
def output=(output)
|
59
|
+
@output = output.is_a?(String) ? Pathname.new(output) : output
|
60
|
+
end
|
61
|
+
|
62
|
+
# @return [self]
|
63
|
+
# @todo Do not suppress exceptions
|
64
|
+
def process
|
65
|
+
@output.write('') if @output.respond_to?(:file?) and !@output.exist?
|
66
|
+
if bootstrap
|
67
|
+
begin
|
68
|
+
require bootstrap if bootstrap
|
69
|
+
rescue NameError
|
70
|
+
rescue LoadError
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
output = @loader.format(template: @template)
|
75
|
+
display_errors
|
76
|
+
# avoid to break previouly written file in case of failure
|
77
|
+
@output.write(output) if success?
|
78
|
+
|
79
|
+
self
|
80
|
+
end
|
81
|
+
|
82
|
+
# @param [Hash] options
|
83
|
+
def format(options = {})
|
84
|
+
@loader.format(options)
|
85
|
+
end
|
86
|
+
|
87
|
+
# Errors encountered during process
|
88
|
+
#
|
89
|
+
# @return [Hash]
|
90
|
+
def errors
|
91
|
+
loader.errors
|
92
|
+
end
|
93
|
+
|
94
|
+
# Denote errors encountered
|
95
|
+
#
|
96
|
+
# @return [Boolean]
|
97
|
+
def errors?
|
98
|
+
errors.empty? ? false : true
|
99
|
+
end
|
100
|
+
|
101
|
+
# Display encountered errors
|
102
|
+
#
|
103
|
+
# @return [self]
|
104
|
+
def display_errors
|
105
|
+
helpers.get(:process).display_errors(self)
|
106
|
+
|
107
|
+
self
|
108
|
+
end
|
109
|
+
|
110
|
+
# Display status
|
111
|
+
#
|
112
|
+
# @return [self]
|
113
|
+
def display_status
|
114
|
+
helpers.get(:process).display_status(self)
|
115
|
+
|
116
|
+
self
|
117
|
+
end
|
118
|
+
|
119
|
+
# Denote process is a success
|
120
|
+
#
|
121
|
+
# @return [Boolean]
|
122
|
+
def success?
|
123
|
+
loader.loaded? and !errors?
|
124
|
+
end
|
125
|
+
|
126
|
+
# Denote process is a failure
|
127
|
+
#
|
128
|
+
# @return [Boolean]
|
129
|
+
def failure?
|
130
|
+
!success?
|
131
|
+
end
|
132
|
+
|
133
|
+
# Block executed on failure
|
134
|
+
#
|
135
|
+
# @yield [self] Block executed when errors have been encountered
|
136
|
+
# @return [self]
|
137
|
+
def on_failure
|
138
|
+
yield(self) if failure?
|
139
|
+
|
140
|
+
self
|
141
|
+
end
|
142
|
+
|
143
|
+
# Block executed on success
|
144
|
+
#
|
145
|
+
# @yield [self] Block executed when process is a success
|
146
|
+
# @return [self]
|
147
|
+
def on_success
|
148
|
+
yield(self) if success?
|
149
|
+
|
150
|
+
self
|
151
|
+
end
|
152
|
+
|
153
|
+
# Provides access to public accessors
|
154
|
+
def method_missing(method, *args, &block)
|
155
|
+
if respond_to_missing?(method)
|
156
|
+
@loader.public_send(method, *args, &block)
|
157
|
+
else
|
158
|
+
super
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
def respond_to_missing?(method, include_private = false)
|
163
|
+
result = loader_accessors.include?(method.to_sym)
|
164
|
+
unless result
|
165
|
+
return super if include_private
|
166
|
+
end
|
167
|
+
|
168
|
+
result
|
169
|
+
end
|
170
|
+
|
171
|
+
# Get loader
|
172
|
+
#
|
173
|
+
# @return [Grouik::Loader]
|
174
|
+
def loader
|
175
|
+
@loader.clone.freeze
|
176
|
+
end
|
177
|
+
|
178
|
+
protected
|
179
|
+
|
180
|
+
# Get loader public attributes
|
181
|
+
#
|
182
|
+
# @return [Array]
|
183
|
+
def loader_attributes
|
184
|
+
loader.public_methods
|
185
|
+
.grep(/^\w+=$/)
|
186
|
+
.map { |m| m.to_s.gsub(/=$/, '').to_sym }
|
187
|
+
end
|
188
|
+
|
189
|
+
# Get loader public accessors
|
190
|
+
#
|
191
|
+
# @return [Array]
|
192
|
+
def loader_accessors
|
193
|
+
loader_attributes + loader_attributes.map { |m| ('%s=' % m).to_sym }
|
194
|
+
end
|
195
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright (C) 2017 Dimitri Arrigoni <dimitri@arrigoni.me>
|
4
|
+
# License GPLv3+: GNU GPL version 3 or later
|
5
|
+
# <http://www.gnu.org/licenses/gpl.html>.
|
6
|
+
# This is free software: you are free to change and redistribute it.
|
7
|
+
# There is NO WARRANTY, to the extent permitted by law.
|
8
|
+
|
9
|
+
# Special types in use
|
10
|
+
module Grouik::Types
|
11
|
+
end
|
12
|
+
|
13
|
+
# Get filtered loadables, using ignores regexp
|
14
|
+
#
|
15
|
+
# @return [Array<Grouik::Loadable>]
|
16
|
+
class Grouik::Types::Loadables < Array
|
17
|
+
# Removes ignored patterns (regexps)
|
18
|
+
#
|
19
|
+
# @param [Array<Regexp>] regexps
|
20
|
+
# @return [self]
|
21
|
+
def ignores(regexps)
|
22
|
+
filter = lambda do |loadable, regexps|
|
23
|
+
regexps.each do |regexp|
|
24
|
+
return true if loadable and regexp.match(loadable.to_s)
|
25
|
+
end
|
26
|
+
|
27
|
+
false
|
28
|
+
end
|
29
|
+
|
30
|
+
self.clone.delete_if do |loadable|
|
31
|
+
filter.call(loadable, regexps)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# @return [self]
|
36
|
+
def add_file(file, basedir = nil)
|
37
|
+
self.push(make_loadable(basedir, file))
|
38
|
+
|
39
|
+
self
|
40
|
+
end
|
41
|
+
|
42
|
+
# @return [Grouik::Loadable]
|
43
|
+
def make_loadable(*args)
|
44
|
+
Grouik.get(:loadable_factory).call(*args)
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
---
|
2
|
+
major: 1
|
3
|
+
minor: 0
|
4
|
+
patch: 0
|
5
|
+
authors: ['Dimitri Arrigoni']
|
6
|
+
email: 'dimitri@arrigoni.me'
|
7
|
+
date: '2017-03-28'
|
8
|
+
summary: 'Grouik!'
|
9
|
+
description: 'Simple require file generator'
|
10
|
+
licenses: ['GPL-3.0']
|
11
|
+
license: 'Copyright (C) 2017 Dimitri Arrigoni <dimitri@arrigoni.me>
|
12
|
+
License GPLv3+: GNU GPL version 3 or later
|
13
|
+
<http://www.gnu.org/licenses/gpl.html>.
|
14
|
+
This is free software: you are free to change and redistribute it.
|
15
|
+
There is NO WARRANTY, to the extent permitted by law.'
|
16
|
+
homepage: 'https://github.com/SwagDevOps/ruby-grouik'
|
data/src/lib/grouik.rb
ADDED
@@ -0,0 +1,101 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright (C) 2017 Dimitri Arrigoni <dimitri@arrigoni.me>
|
4
|
+
# License GPLv3+: GNU GPL version 3 or later
|
5
|
+
# <http://www.gnu.org/licenses/gpl.html>.
|
6
|
+
# This is free software: you are free to change and redistribute it.
|
7
|
+
# There is NO WARRANTY, to the extent permitted by law.
|
8
|
+
|
9
|
+
require 'pathname'
|
10
|
+
require 'active_support/inflector'
|
11
|
+
require 'version_info'
|
12
|
+
|
13
|
+
$LOAD_PATH.unshift Pathname.new(__dir__)
|
14
|
+
|
15
|
+
# Produce a ``require`` file, resolving classes dependencies
|
16
|
+
#
|
17
|
+
# Sample of use:
|
18
|
+
#
|
19
|
+
# ~~~~
|
20
|
+
# Grouik.process do |process|
|
21
|
+
# process.basedir = './path/to/my/project'
|
22
|
+
# process.paths = ['lib']
|
23
|
+
# process.ignores = []
|
24
|
+
# process.output = '/dev/stdout'
|
25
|
+
# process.template = 'lib/main'
|
26
|
+
# process.bootstrap = nil
|
27
|
+
# process.verbose = true
|
28
|
+
# end.success? ? 0 : 1
|
29
|
+
# ~~~~
|
30
|
+
#
|
31
|
+
# or using command line.
|
32
|
+
module Grouik
|
33
|
+
require 'grouik/helpers'
|
34
|
+
|
35
|
+
class << self
|
36
|
+
# @return [Hash]
|
37
|
+
def version_info
|
38
|
+
unless self.const_defined?(:VERSION)
|
39
|
+
include VersionInfo
|
40
|
+
|
41
|
+
VersionInfo.file_format = :yaml
|
42
|
+
VERSION.file_name = self.version_filepath
|
43
|
+
VERSION.load
|
44
|
+
end
|
45
|
+
|
46
|
+
VERSION.to_hash.freeze
|
47
|
+
end
|
48
|
+
|
49
|
+
protected
|
50
|
+
|
51
|
+
# Get path to the ``version`` file
|
52
|
+
#
|
53
|
+
# @return [Pathname]
|
54
|
+
def version_filepath
|
55
|
+
name = ActiveSupport::Inflector.underscore(self.name)
|
56
|
+
|
57
|
+
Pathname.new(__dir__).join(name, 'version_info.yml')
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
# registers version_info
|
62
|
+
self.version_info
|
63
|
+
# loads sub(modules|classes)
|
64
|
+
[:loader, :loadable, :formatter, :process, :output].each do |r|
|
65
|
+
require '%s/%s' % [ActiveSupport::Inflector.underscore(name), r]
|
66
|
+
end
|
67
|
+
|
68
|
+
@components = {
|
69
|
+
process_class: Process,
|
70
|
+
formatter: Formatter,
|
71
|
+
helpers: Grouik::Helpers,
|
72
|
+
inflector: ActiveSupport::Inflector,
|
73
|
+
messager_factory: ->(&block) { Output::Message.new(&block) },
|
74
|
+
loadable_factory: ->(base, path) { Loadable.new(base, path) },
|
75
|
+
}
|
76
|
+
|
77
|
+
class << self
|
78
|
+
attr_accessor :components
|
79
|
+
|
80
|
+
# Access to components
|
81
|
+
#
|
82
|
+
# @param name [String, Symbol] name of component
|
83
|
+
# @return [Object]
|
84
|
+
# @see Grouik.components
|
85
|
+
def get(name)
|
86
|
+
components.fetch(name.to_sym)
|
87
|
+
end
|
88
|
+
|
89
|
+
# Initialize a Process and process it
|
90
|
+
#
|
91
|
+
# @return [Grouik::Process]
|
92
|
+
def process(&block)
|
93
|
+
self.get(:process_class).new(&block).process
|
94
|
+
end
|
95
|
+
|
96
|
+
def message(&block)
|
97
|
+
self.get(:messager_factory).call(&block).send
|
98
|
+
self
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|