origen 0.38.0 → 0.40.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 +4 -4
- data/bin/origen +1 -236
- data/config/application.rb +10 -1
- data/config/version.rb +1 -1
- data/lib/origen/{boot_api.rb → boot/api.rb} +2 -2
- data/lib/origen/boot/app.rb +324 -0
- data/lib/origen/boot.rb +287 -0
- data/lib/origen/commands/archive.rb +175 -0
- data/lib/origen/commands/extract.rb +43 -0
- data/lib/origen/commands/new.rb +33 -23
- data/lib/origen/commands.rb +4 -1
- data/lib/origen/commands_global.rb +3 -2
- data/lib/origen/operating_systems.rb +4 -0
- data/lib/origen/revision_control.rb +1 -1
- data/lib/origen/site_config.rb +4 -1
- data/lib/origen.rb +3 -2
- data/origen_app_generators/Gemfile +16 -0
- data/origen_app_generators/Gemfile.lock +147 -0
- data/origen_app_generators/LICENSE +21 -0
- data/origen_app_generators/README.md +368 -0
- data/origen_app_generators/Rakefile +10 -0
- data/origen_app_generators/bin/boot.rb +37 -0
- data/{bin → origen_app_generators/bin}/fix_my_workspace +0 -0
- data/origen_app_generators/config/application.rb +153 -0
- data/origen_app_generators/config/boot.rb +1 -0
- data/origen_app_generators/config/commands.rb +63 -0
- data/origen_app_generators/config/shared_commands.rb +172 -0
- data/origen_app_generators/config/version.rb +8 -0
- data/origen_app_generators/doc/history +213 -0
- data/origen_app_generators/lib/origen_app_generators/application.rb +62 -0
- data/origen_app_generators/lib/origen_app_generators/base.rb +231 -0
- data/origen_app_generators/lib/origen_app_generators/empty_application.rb +15 -0
- data/origen_app_generators/lib/origen_app_generators/empty_plugin.rb +15 -0
- data/origen_app_generators/lib/origen_app_generators/new.rb +162 -0
- data/origen_app_generators/lib/origen_app_generators/origen_infrastructure/app_generator_plugin.rb +109 -0
- data/origen_app_generators/lib/origen_app_generators/plugin.rb +58 -0
- data/origen_app_generators/lib/origen_app_generators/sub_block_parser.rb +81 -0
- data/origen_app_generators/lib/origen_app_generators/test_engineering/stand_alone_application.rb +236 -0
- data/origen_app_generators/lib/origen_app_generators/test_engineering/test_block.rb +162 -0
- data/origen_app_generators/lib/origen_app_generators.rb +123 -0
- data/origen_app_generators/lib/tasks/app_generators.rake +6 -0
- data/origen_app_generators/lib/tasks/new_app_tests.rake +8 -0
- data/origen_app_generators/origen_app_generators.gemspec +33 -0
- data/origen_app_generators/spec/spec_helper.rb +49 -0
- data/origen_app_generators/spec/sub_block_spec.rb +36 -0
- data/origen_app_generators/target/debug.rb +8 -0
- data/origen_app_generators/target/default.rb +8 -0
- data/origen_app_generators/target/production.rb +0 -0
- data/origen_app_generators/templates/app_generators/application/Gemfile +19 -0
- data/origen_app_generators/templates/app_generators/application/Rakefile +7 -0
- data/origen_app_generators/templates/app_generators/application/config/application.rb +125 -0
- data/origen_app_generators/templates/app_generators/application/config/boot.rb +4 -0
- data/origen_app_generators/templates/app_generators/application/config/commands.rb +79 -0
- data/origen_app_generators/templates/app_generators/application/config/maillist_dev.txt +4 -0
- data/origen_app_generators/templates/app_generators/application/config/maillist_prod.txt +3 -0
- data/origen_app_generators/templates/app_generators/application/config/version.rb +8 -0
- data/origen_app_generators/templates/app_generators/application/doc/history +0 -0
- data/origen_app_generators/templates/app_generators/application/dot_keep +0 -0
- data/origen_app_generators/templates/app_generators/application/lib/app.rake +6 -0
- data/origen_app_generators/templates/app_generators/application/lib/module.rb +22 -0
- data/origen_app_generators/templates/app_generators/application/lib/top_level.rb +12 -0
- data/origen_app_generators/templates/app_generators/application/origen_core_session +2 -0
- data/origen_app_generators/templates/app_generators/application/spec/spec_helper.rb +44 -0
- data/origen_app_generators/templates/app_generators/application/target/debug.rb +8 -0
- data/origen_app_generators/templates/app_generators/application/target/default.rb +1 -0
- data/origen_app_generators/templates/app_generators/application/target/production.rb +4 -0
- data/origen_app_generators/templates/app_generators/application/templates/web/index.md.erb +19 -0
- data/origen_app_generators/templates/app_generators/application/templates/web/layouts/_basic.html.erb +13 -0
- data/origen_app_generators/templates/app_generators/application/templates/web/partials/_navbar.html.erb +20 -0
- data/origen_app_generators/templates/app_generators/application/templates/web/release_notes.md.erb +5 -0
- data/origen_app_generators/templates/app_generators/new/generator.rb +102 -0
- data/origen_app_generators/templates/app_generators/new/info.md.erb +9 -0
- data/origen_app_generators/templates/app_generators/origen_infrastructure/app_generator_plugin/config/load_generators.rb +6 -0
- data/origen_app_generators/templates/app_generators/origen_infrastructure/app_generator_plugin/lib/application.rb +54 -0
- data/origen_app_generators/templates/app_generators/origen_infrastructure/app_generator_plugin/lib/base.rb +55 -0
- data/origen_app_generators/templates/app_generators/origen_infrastructure/app_generator_plugin/lib/module.rb +28 -0
- data/origen_app_generators/templates/app_generators/origen_infrastructure/app_generator_plugin/lib/plugin.rb +64 -0
- data/origen_app_generators/templates/app_generators/plugin/Gemfile +26 -0
- data/origen_app_generators/templates/app_generators/plugin/Rakefile +10 -0
- data/origen_app_generators/templates/app_generators/plugin/config/boot.rb +24 -0
- data/origen_app_generators/templates/app_generators/plugin/gemspec.rb +42 -0
- data/origen_app_generators/templates/app_generators/plugin/lib/README +4 -0
- data/origen_app_generators/templates/app_generators/plugin/lib_dev/README +5 -0
- data/origen_app_generators/templates/app_generators/plugin/templates/web/index.md.erb +37 -0
- data/origen_app_generators/templates/app_generators/plugin/templates/web/partials/_navbar_external.html.erb +20 -0
- data/origen_app_generators/templates/app_generators/plugin/templates/web/partials/_navbar_internal.html.erb +20 -0
- data/origen_app_generators/templates/app_generators/test_engineering/stand_alone_application/Gemfile +23 -0
- data/origen_app_generators/templates/app_generators/test_engineering/stand_alone_application/environment/j750.rb +1 -0
- data/origen_app_generators/templates/app_generators/test_engineering/stand_alone_application/environment/jlink.rb +1 -0
- data/origen_app_generators/templates/app_generators/test_engineering/stand_alone_application/environment/uflex.rb +1 -0
- data/origen_app_generators/templates/app_generators/test_engineering/stand_alone_application/environment/v93k.rb +1 -0
- data/origen_app_generators/templates/app_generators/test_engineering/stand_alone_application/lib/ip_block.rb +23 -0
- data/origen_app_generators/templates/app_generators/test_engineering/stand_alone_application/lib/ip_block_controller.rb +5 -0
- data/origen_app_generators/templates/app_generators/test_engineering/stand_alone_application/lib/top_level.rb +33 -0
- data/origen_app_generators/templates/app_generators/test_engineering/stand_alone_application/lib/top_level_controller.rb +21 -0
- data/origen_app_generators/templates/app_generators/test_engineering/stand_alone_application/pattern/example.rb +4 -0
- data/origen_app_generators/templates/app_generators/test_engineering/stand_alone_application/target/top_level.rb +4 -0
- data/origen_app_generators/templates/app_generators/test_engineering/test_block/environment/j750.rb +2 -0
- data/origen_app_generators/templates/app_generators/test_engineering/test_block/environment/ultraflex.rb +2 -0
- data/origen_app_generators/templates/app_generators/test_engineering/test_block/environment/v93k.rb +2 -0
- data/origen_app_generators/templates/app_generators/test_engineering/test_block/lib/controller.rb +12 -0
- data/origen_app_generators/templates/app_generators/test_engineering/test_block/lib/interface.rb +21 -0
- data/origen_app_generators/templates/app_generators/test_engineering/test_block/lib/model.rb +18 -0
- data/origen_app_generators/templates/app_generators/test_engineering/test_block/lib_dev/dut.rb +27 -0
- data/origen_app_generators/templates/app_generators/test_engineering/test_block/lib_dev/dut_controller.rb +26 -0
- data/origen_app_generators/templates/app_generators/test_engineering/test_block/pattern/example.rb +5 -0
- data/origen_app_generators/templates/app_generators/test_engineering/test_block/program/prb1.rb +11 -0
- data/origen_app_generators/templates/app_generators/test_engineering/test_block/target/default.rb +2 -0
- data/origen_site_config.yml +13 -2
- data/templates/git/gitignore.erb +0 -1
- metadata +99 -4
@@ -0,0 +1,231 @@
|
|
1
|
+
module OrigenAppGenerators
|
2
|
+
# This is the base generator used by all generators in this application
|
3
|
+
class Base < Origen::CodeGenerators::Base
|
4
|
+
include Origen::Utility::InputCapture
|
5
|
+
|
6
|
+
require 'gems'
|
7
|
+
|
8
|
+
def set_source_paths
|
9
|
+
# The base Origen generator puts the Origen core directory on the source path, in retrospect this
|
10
|
+
# was a bad idea and makes for hard to debug errors if an app generator resolves a template from
|
11
|
+
# outside of this app.
|
12
|
+
# So to keep things sane remove any inherited source paths.
|
13
|
+
self.class.source_paths.pop until self.class.source_paths.empty?
|
14
|
+
klass = self.class
|
15
|
+
|
16
|
+
until klass == OrigenAppGenerators::Base
|
17
|
+
if template_dir = OrigenAppGenerators.template_dirs[klass]
|
18
|
+
dir = []
|
19
|
+
last_class = nil
|
20
|
+
until klass.to_s =~ /^OrigenAppGenerators/
|
21
|
+
dir << "#{template_dir}/#{class_dir(klass)}"
|
22
|
+
last_class = klass
|
23
|
+
klass = klass.superclass
|
24
|
+
end
|
25
|
+
dir << "#{template_dir}/base"
|
26
|
+
klass = last_class
|
27
|
+
else
|
28
|
+
dir = "#{Origen.root!}/templates/app_generators/#{class_dir(klass)}"
|
29
|
+
end
|
30
|
+
Array(dir).each do |dir|
|
31
|
+
self.class.source_paths << dir if File.exist?(dir) && !self.class.source_paths.include?(dir)
|
32
|
+
end
|
33
|
+
klass = klass.superclass
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
# Just makes the type (:plugin or :application) available to all templates
|
38
|
+
def set_type
|
39
|
+
@type = type
|
40
|
+
end
|
41
|
+
|
42
|
+
def get_common_user_input
|
43
|
+
get_name_and_namespace
|
44
|
+
end
|
45
|
+
|
46
|
+
def get_lastest_origen_version
|
47
|
+
@latest_origen_version ||= begin
|
48
|
+
(Gems.info 'origen')['version']
|
49
|
+
rescue
|
50
|
+
# If the above fails, e.g. due to an SSL error in the runtime environment, try to fetch the
|
51
|
+
# latest Origen version from the Origen website, before finally falling back to the version
|
52
|
+
# we are currently running if all else fails
|
53
|
+
begin
|
54
|
+
require 'httparty'
|
55
|
+
response = HTTParty.get('http://origen-sdk.org/origen/release_notes/')
|
56
|
+
version = Origen::VersionString.new(response.body.match(/Tag: v(\d+\.\d+.\d+)</).to_a.last)
|
57
|
+
if version.valid?
|
58
|
+
version
|
59
|
+
else
|
60
|
+
fail "Can't get the latest version!"
|
61
|
+
end
|
62
|
+
rescue
|
63
|
+
Origen.version
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
protected
|
69
|
+
|
70
|
+
def class_dir(klass)
|
71
|
+
names = klass.to_s.split('::')
|
72
|
+
names.shift
|
73
|
+
names.map(&:underscore).join('/')
|
74
|
+
end
|
75
|
+
|
76
|
+
# def application_class?(klass)
|
77
|
+
# until klass == OrigenAppGenerators::Base
|
78
|
+
# end
|
79
|
+
|
80
|
+
def debugger
|
81
|
+
require 'byebug'
|
82
|
+
byebug # rubocop:disable Lint/Debugger
|
83
|
+
end
|
84
|
+
|
85
|
+
def plugin?
|
86
|
+
type == :plugin
|
87
|
+
end
|
88
|
+
|
89
|
+
def application?
|
90
|
+
!plugin?
|
91
|
+
end
|
92
|
+
|
93
|
+
def self.title
|
94
|
+
desc.sub(/^An? /, '').titleize
|
95
|
+
end
|
96
|
+
|
97
|
+
# Calling this will compile all files in filelist against the current instance
|
98
|
+
# variable values
|
99
|
+
def build_filelist
|
100
|
+
symlink_cmds = []
|
101
|
+
self.destination_root = args.first
|
102
|
+
filelist.each do |_name, file|
|
103
|
+
if file[:type] == :symlink
|
104
|
+
if Origen.running_on_windows?
|
105
|
+
dest = Pathname.new("#{destination_root}/#{file[:dest]}")
|
106
|
+
source = dest.dirname.to_s + "/#{file[:source]}"
|
107
|
+
symlink_cmds << "call mklink /h #{dest.to_s.gsub('/', '\\')} #{source.to_s.gsub('/', '\\')}"
|
108
|
+
else
|
109
|
+
create_link file[:dest], file[:source]
|
110
|
+
end
|
111
|
+
elsif file[:type] == :dir || file[:type] == :directory
|
112
|
+
if file[:copy]
|
113
|
+
if (file.key? :dest) && (file.key? :source)
|
114
|
+
directory(file[:source], file[:dest])
|
115
|
+
else
|
116
|
+
directory(file[:dest] || file[:source])
|
117
|
+
end
|
118
|
+
elsif file[:nokeep]
|
119
|
+
empty_directory(file[:dest] || file[:source])
|
120
|
+
else
|
121
|
+
copy_file('dot_keep', "#{file[:dest]}/.keep")
|
122
|
+
end
|
123
|
+
else
|
124
|
+
dest = file[:dest] || file[:source]
|
125
|
+
if file[:copy] || dest =~ /.erb$/
|
126
|
+
copy_file(file[:source], dest)
|
127
|
+
else
|
128
|
+
@options = file[:options] || {}
|
129
|
+
template(file[:source], dest)
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
symlink_cmds.each { |cmd| system(cmd) }
|
134
|
+
end
|
135
|
+
|
136
|
+
# Convenience method that is equivalent to calling get_name and then get_namespace
|
137
|
+
def get_name_and_namespace
|
138
|
+
get_name
|
139
|
+
get_namespace
|
140
|
+
end
|
141
|
+
|
142
|
+
# Prompts the user to confirm or enter the Ruby namespace to be used in the app.
|
143
|
+
#
|
144
|
+
# If @name is already defined a proposal will be generated from that, alternatively a proposal
|
145
|
+
# can be supplied. If not proposal is resolved the user will be prompted to input from scratch.
|
146
|
+
def get_namespace(proposal = nil)
|
147
|
+
puts
|
148
|
+
puts "SELECT YOUR #{type.to_s.upcase}'S NAMESPACE"
|
149
|
+
puts
|
150
|
+
puts "All #{type} code needs to reside in a unique namespace, this prevents naming collisions with 3rd party plugins."
|
151
|
+
puts 'By Ruby conventions, this must start with a capital letter and should ideally be CamelCased and not use underscores.'
|
152
|
+
# puts 'Some examples:: C40TFSNVMTester, CAPIOrigen, LS2080, ApacheOrigen'
|
153
|
+
[@namespace_advice].each { |l| puts l } if @namespace_advice
|
154
|
+
puts
|
155
|
+
if !proposal && @name
|
156
|
+
proposal = @name.to_s.camelize
|
157
|
+
end
|
158
|
+
proposal = nil if proposal.length < 3
|
159
|
+
|
160
|
+
valid = false
|
161
|
+
until valid
|
162
|
+
@namespace = get_text(single: true, default: proposal)
|
163
|
+
proposal = nil
|
164
|
+
unless @namespace.empty?
|
165
|
+
if @namespace.length >= 3
|
166
|
+
valid = valid_constant?(@namespace)
|
167
|
+
end
|
168
|
+
unless valid
|
169
|
+
puts 'That namespace is not valid :-('
|
170
|
+
puts
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
174
|
+
@namespace
|
175
|
+
end
|
176
|
+
|
177
|
+
# Returns true if the given string can be converted to a valid Ruby constant and one that
|
178
|
+
# does not already exist within the scope of this application and Origen Core
|
179
|
+
def valid_constant?(string)
|
180
|
+
valid = false
|
181
|
+
# Try and convert this to a constant to test for validity, this will also screen things
|
182
|
+
# like Origen since that will not trigger an error
|
183
|
+
begin
|
184
|
+
string.constantize
|
185
|
+
rescue NameError => e
|
186
|
+
if e.message =~ /^uninitialized constant/
|
187
|
+
valid = true
|
188
|
+
end
|
189
|
+
else
|
190
|
+
# Something else is wrong with it
|
191
|
+
end
|
192
|
+
valid
|
193
|
+
end
|
194
|
+
|
195
|
+
# Prompts the user to input a name for the new application, this will be screened to ensure
|
196
|
+
# that it can cleanly cast to a symbol for use in Origen.
|
197
|
+
#
|
198
|
+
# This should be unique within the whole Origen ecosystem, in future this method will be enhanced
|
199
|
+
# to check with the Origen server which will in future maintain a database of known app names.
|
200
|
+
#
|
201
|
+
# The final name is returned at the end and assigned to variable @name for use in templates.
|
202
|
+
def get_name
|
203
|
+
proposal = args.first.symbolize.to_s
|
204
|
+
proposal = nil if proposal.length < 3
|
205
|
+
puts
|
206
|
+
puts "WHAT DO YOU WANT TO CALL YOUR NEW #{type.to_s.upcase}?"
|
207
|
+
puts
|
208
|
+
puts "This should be lowercased and underscored and will be used to uniquely identify your #{type} within the Origen ecosystem."
|
209
|
+
[@name_advice].each { |l| puts l } if @name_advice
|
210
|
+
puts
|
211
|
+
valid = false
|
212
|
+
until valid
|
213
|
+
name = get_text(single: true, default: proposal)
|
214
|
+
proposal = nil
|
215
|
+
unless name.empty?
|
216
|
+
if name == name.symbolize.to_s
|
217
|
+
if name.symbolize.to_s.length >= 3
|
218
|
+
valid = true
|
219
|
+
@name = name
|
220
|
+
end
|
221
|
+
else
|
222
|
+
puts
|
223
|
+
puts 'That name is not valid, how about this?'
|
224
|
+
proposal = name.symbolize.to_s
|
225
|
+
end
|
226
|
+
end
|
227
|
+
end
|
228
|
+
@name
|
229
|
+
end
|
230
|
+
end
|
231
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module OrigenAppGenerators
|
2
|
+
# Generates a generic application shell
|
3
|
+
class EmptyApplication < Application
|
4
|
+
# Any methods that are not protected will get invoked in the order they are
|
5
|
+
# defined when the generator is run
|
6
|
+
|
7
|
+
def generate_files
|
8
|
+
build_filelist
|
9
|
+
end
|
10
|
+
|
11
|
+
def conclude
|
12
|
+
puts "New app created at: #{destination_root}"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module OrigenAppGenerators
|
2
|
+
# Generates a generic plugin shell
|
3
|
+
class EmptyPlugin < Plugin
|
4
|
+
# Any methods that are not protected will get invoked in the order they are
|
5
|
+
# defined when the generator is run
|
6
|
+
|
7
|
+
def generate_files
|
8
|
+
build_filelist
|
9
|
+
end
|
10
|
+
|
11
|
+
def conclude
|
12
|
+
puts "New app created at: #{destination_root}"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,162 @@
|
|
1
|
+
module OrigenAppGenerators
|
2
|
+
class New < Base
|
3
|
+
include Origen::Utility::InputCapture
|
4
|
+
|
5
|
+
desc 'Creates a new application generator within this application'
|
6
|
+
|
7
|
+
# Naming of this method is important here to override the default user input which
|
8
|
+
# does not apply to this generator
|
9
|
+
def get_common_user_input
|
10
|
+
get_domain
|
11
|
+
get_name
|
12
|
+
get_type
|
13
|
+
get_summary
|
14
|
+
@namespace = Origen.app.namespace
|
15
|
+
end
|
16
|
+
|
17
|
+
def set_type
|
18
|
+
# Type not applicable in for this generator
|
19
|
+
end
|
20
|
+
|
21
|
+
def generate_files
|
22
|
+
build_filelist
|
23
|
+
end
|
24
|
+
|
25
|
+
def enable
|
26
|
+
available = Origen.app.namespace.constantize::AVAILABLE
|
27
|
+
test_inputs = Origen.app.namespace.constantize::TEST_INPUTS
|
28
|
+
|
29
|
+
# **** Add require line ****
|
30
|
+
module_declaration = /\nmodule #{Origen.app.namespace}/
|
31
|
+
inject_into_file "lib/#{Origen.app.name}.rb", "require '#{Origen.app.name}/#{@domain_namespace.underscore}/#{@classname.underscore}'\n",
|
32
|
+
before: module_declaration
|
33
|
+
|
34
|
+
# **** Add to the AVAILABLE hash ****
|
35
|
+
if available[@domain_summary]
|
36
|
+
existing_domain = /\s*('|")#{@domain_summary}('|") => \[\s*\n/
|
37
|
+
inject_into_file "lib/#{Origen.app.name}.rb", " #{Origen.app.namespace}::#{@domain_namespace}::#{@classname},\n",
|
38
|
+
after: existing_domain
|
39
|
+
else
|
40
|
+
new_domain = <<-END
|
41
|
+
'#{@domain_summary}' => [
|
42
|
+
#{Origen.app.namespace}::#{@domain_namespace}::#{@classname},
|
43
|
+
],
|
44
|
+
END
|
45
|
+
available_hash = /AVAILABLE = {\s*\n/
|
46
|
+
inject_into_file "lib/#{Origen.app.name}.rb", new_domain, after: available_hash
|
47
|
+
end
|
48
|
+
|
49
|
+
# **** Add a starter set of test inputs ****
|
50
|
+
# First work out what the selection numbers will be for the new generator
|
51
|
+
if available[@domain_summary]
|
52
|
+
first = available.size - available.find_index { |k, _| k == @domain_summary }
|
53
|
+
second = available[@domain_summary].size
|
54
|
+
else
|
55
|
+
first = available.size + 1
|
56
|
+
second = 0
|
57
|
+
end
|
58
|
+
inputs = "\n # #{test_inputs.size} - #{@domain_namespace}::#{@classname}\n"
|
59
|
+
if @parentclass == 'Plugin'
|
60
|
+
inputs += " ['#{first}', '#{second}', :default, :default, 'A cool plugin', 'yes', :default]"
|
61
|
+
else
|
62
|
+
inputs += " ['#{first}', '#{second}', :default, :default, :default]"
|
63
|
+
end
|
64
|
+
inputs = ",#{inputs}" unless test_inputs.empty?
|
65
|
+
end_of_test_inputs = /\n\s*\]\s*#\s*END_OF_TEST_INPUTS/
|
66
|
+
inject_into_file "lib/#{Origen.app.name}.rb", inputs, before: end_of_test_inputs
|
67
|
+
end
|
68
|
+
|
69
|
+
# Can't compile this as contains some final ERB, so substitute instead
|
70
|
+
# def customize_doc_page
|
71
|
+
# file = filelist[:doc_info][:dest]
|
72
|
+
# gsub_file file, 'TITLE_GOES_HERE', @title
|
73
|
+
# if @type == :plugin
|
74
|
+
# gsub_file file, 'INTRO_GOES_HERE', "This generates a customized version of the [Generic Plugin](<%= path 'origen_app_generators/plugin' %>)."
|
75
|
+
# else
|
76
|
+
# gsub_file file, 'INTRO_GOES_HERE', "This generates a customized version of the [Generic Application](<%= path 'origen_app_generators/application' %>)."
|
77
|
+
# end
|
78
|
+
# end
|
79
|
+
|
80
|
+
def conclude
|
81
|
+
system "origen lint #{Origen.root}/lib/#{Origen.app.name}.rb"
|
82
|
+
puts
|
83
|
+
puts "New generator created at: #{filelist[:generator][:dest]}"
|
84
|
+
puts
|
85
|
+
puts "Create any template files you need for this generator in: #{filelist[:templates_dir][:dest]}"
|
86
|
+
puts
|
87
|
+
# puts "Before you go add some documentation about what this generates to: templates/web/origen_app_generators/origen_app_generators/#{@domain_namespace.underscore}/#{@classname.underscore}.md.erb"
|
88
|
+
# puts
|
89
|
+
end
|
90
|
+
|
91
|
+
protected
|
92
|
+
|
93
|
+
def get_summary
|
94
|
+
puts
|
95
|
+
puts 'DESCRIBE YOUR NEW GENERATOR IN A FEW WORDS'
|
96
|
+
puts
|
97
|
+
@summary = get_text(single: true)
|
98
|
+
@title = @summary.sub(/^An? /, '').titleize
|
99
|
+
end
|
100
|
+
|
101
|
+
def get_type
|
102
|
+
puts
|
103
|
+
puts 'WILL YOUR TEMPLATE GENERATE A PLUGIN OR A TOP-LEVEL APPLICATION?'
|
104
|
+
puts
|
105
|
+
type = get_text(single: true, accept: %w(application plugin)).downcase
|
106
|
+
@parentclass = type.capitalize
|
107
|
+
end
|
108
|
+
|
109
|
+
def get_name
|
110
|
+
puts
|
111
|
+
puts 'GIVE YOUR NEW GENERATOR CLASS A NAME'
|
112
|
+
puts
|
113
|
+
puts 'Your new generator needs a class name, this should be reasonably descriptive although it will not be displayed to end users'
|
114
|
+
puts 'Some examples: GenericTestBlock, IPBlock, MPGBOMApp'
|
115
|
+
puts
|
116
|
+
valid = false
|
117
|
+
until valid
|
118
|
+
@classname = get_text(single: true).split('::').last
|
119
|
+
unless @classname.empty?
|
120
|
+
if @classname.length >= 3
|
121
|
+
valid = valid_constant?("#{Origen.app.namespace}::#{@domain_namespace}::#{@classname}")
|
122
|
+
end
|
123
|
+
unless valid
|
124
|
+
puts 'That class name is not valid :-('
|
125
|
+
puts
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
@classname
|
130
|
+
end
|
131
|
+
|
132
|
+
def get_domain
|
133
|
+
puts
|
134
|
+
puts 'WHAT APPLICATION DOMAIN WILL YOUR NEW APP TEMPLATE APPLY TO?'
|
135
|
+
puts
|
136
|
+
puts "Enter something like 'Test Engineering', 'Design', etc."
|
137
|
+
puts
|
138
|
+
domain = get_text(single: true)
|
139
|
+
domain = domain.split(' ').map do |word|
|
140
|
+
# Ensure all first letters capitalized, but make sure something like
|
141
|
+
# 'NVM' remains 'NVM' and not 'Nvm'
|
142
|
+
letters = word.split('')
|
143
|
+
letters.first.upcase!
|
144
|
+
letters.join
|
145
|
+
end.join(' ')
|
146
|
+
|
147
|
+
@domain_summary = domain
|
148
|
+
@domain_namespace = @domain_summary.gsub(' ', '')
|
149
|
+
end
|
150
|
+
|
151
|
+
def filelist
|
152
|
+
@filelist ||= {
|
153
|
+
generator: { source: 'generator.rb',
|
154
|
+
dest: "lib/#{Origen.app.name}/#{@domain_namespace.underscore}/#{@classname.underscore}.rb" },
|
155
|
+
templates_dir: { dest: "templates/app_generators/#{@domain_namespace.underscore}/#{@classname.underscore}",
|
156
|
+
type: :directory },
|
157
|
+
# doc_info: { source: 'info.md.erb',
|
158
|
+
# dest: "templates/web/#{Origen.app.name}/#{@domain_namespace.underscore}/#{@classname.underscore}.md.erb" }
|
159
|
+
}
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
data/origen_app_generators/lib/origen_app_generators/origen_infrastructure/app_generator_plugin.rb
ADDED
@@ -0,0 +1,109 @@
|
|
1
|
+
module OrigenAppGenerators
|
2
|
+
module OrigenInfrastructure
|
3
|
+
# Generates a generic application shell
|
4
|
+
class AppGeneratorPlugin < Plugin
|
5
|
+
desc "A plugin to make your own application templates available through the 'origen new' command"
|
6
|
+
|
7
|
+
def initialize(*args)
|
8
|
+
@audience = :internal
|
9
|
+
@validate_release_tests = ['origen app_gen:test --regression']
|
10
|
+
super
|
11
|
+
end
|
12
|
+
|
13
|
+
# Any methods that are not protected will get invoked in the order that they are
|
14
|
+
# defined when the generator is run, method naming is irrelevant unless you want
|
15
|
+
# to override a method that is defined by the parent class
|
16
|
+
|
17
|
+
def get_user_input
|
18
|
+
# The methods to get the common user input that applies to all applications will
|
19
|
+
# get called at the start automatically, you have a chance here to ask any additional
|
20
|
+
# questions that are specific to the type of application being generated
|
21
|
+
end
|
22
|
+
|
23
|
+
def generate_files
|
24
|
+
@runtime_dependencies = [
|
25
|
+
['origen_app_generators', ">= #{Origen.app!.version}"]
|
26
|
+
]
|
27
|
+
@post_runtime_dependency_comments = [
|
28
|
+
'DO NOT ADD ANY ADDITIONAL RUNTIME DEPENDENCIES HERE, WHEN THESE GENERATORS',
|
29
|
+
'ARE INVOKED TO GENERATE A NEW APPLICATION IT WILL NOT BE LAUNCHED FROM WITHIN',
|
30
|
+
'A BUNDLED ENVIRONMENT.',
|
31
|
+
'',
|
32
|
+
'THEREFORE GENERATORS MUST NOT RELY ON ANY 3RD PARTY GEMS THAT ARE NOT',
|
33
|
+
'PRESENT AS PART OF A STANDARD ORIGEN INSTALLATION - I.E. YOU CAN ONLY RELY',
|
34
|
+
'ON THE GEMS THAT ORIGEN ITSELF DEPENDS ON.'
|
35
|
+
]
|
36
|
+
# Calling this will build all files, directories and symlinks contained in the
|
37
|
+
# hash returned by the filelist method
|
38
|
+
build_filelist
|
39
|
+
end
|
40
|
+
|
41
|
+
def modify_files
|
42
|
+
# If you want to modify any of the generated files you can do so now, you have access
|
43
|
+
# to all of the Thor Action methods described here:
|
44
|
+
# http://www.rubydoc.info/github/wycats/thor/Thor/Actions
|
45
|
+
# See the enable method in lib/app_generators/new.rb for some examples of using these.
|
46
|
+
end
|
47
|
+
|
48
|
+
def conclude
|
49
|
+
# Print out anything you think the user should know about their new application at the end
|
50
|
+
puts "New app created at: #{destination_root}"
|
51
|
+
puts
|
52
|
+
puts 'Create your first generator by running this command within your new app:'
|
53
|
+
puts ' origen app_gen:new'
|
54
|
+
puts
|
55
|
+
end
|
56
|
+
|
57
|
+
protected
|
58
|
+
|
59
|
+
# Defines the filelist for the generator, the default list is inherited from the
|
60
|
+
# parent class (Plugin).
|
61
|
+
# The filelist can contain references to generate files, directories or symlinks in the
|
62
|
+
# new application.
|
63
|
+
#
|
64
|
+
# Generally to make your generator more maintainable try and re-use as much as possible
|
65
|
+
# from the parent generator, this means that your generator will automatically stay up
|
66
|
+
# to date with the latest conventions
|
67
|
+
#
|
68
|
+
# The master templates live in templates/app_generators/plugin, but
|
69
|
+
# DO NOT MODIFY THESE FILES DIRECTLY.
|
70
|
+
# Either add or remove things post-generation in the modify_files method or copy the
|
71
|
+
# master file to the equivalent sub-directory of templates/app_generators/origen_infrastructure_engineering/app_generator_plugin
|
72
|
+
# which will override the version in the master directory.
|
73
|
+
#
|
74
|
+
# Additional files can be added or removed from the filelist as shown below.
|
75
|
+
def filelist
|
76
|
+
@filelist ||= begin
|
77
|
+
list = super # Always pick up the parent list
|
78
|
+
# Example of how to remove a file from the parent list
|
79
|
+
# list.delete(:web_doc_layout)
|
80
|
+
list.delete(:lib_readme)
|
81
|
+
list.delete(:lib_readme_dev)
|
82
|
+
list.delete(:templates_shared)
|
83
|
+
# Example of how to add a file, in this case the file will be compiled and copied to
|
84
|
+
# the same location in the new app
|
85
|
+
# list[:config_shared_commands] = { source: 'config/shared_commands.rb' }
|
86
|
+
list[:config_load_generators] = { source: 'config/load_generators.rb' }
|
87
|
+
list[:lib_base] = { source: 'lib/base.rb', dest: "lib/#{@name}/base.rb" }
|
88
|
+
list[:lib_plugin] = { source: 'lib/plugin.rb', dest: "lib/#{@name}/plugin.rb" }
|
89
|
+
list[:lib_application] = { source: 'lib/application.rb', dest: "lib/#{@name}/application.rb" }
|
90
|
+
# Alternatively specifying a different destination, typically you would do this when
|
91
|
+
# the final location is dynamic
|
92
|
+
# list[:gemspec] = { source: 'gemspec.rb', dest: "#{@name}.gemspec" }
|
93
|
+
# Example of how to create a directory
|
94
|
+
list[:templates_app] = { dest: 'templates/app_generators/application', type: :directory }
|
95
|
+
list[:templates_plugin] = { dest: 'templates/app_generators/plugin', type: :directory }
|
96
|
+
list[:templates_base] = { dest: 'templates/app_generators/base', type: :directory }
|
97
|
+
# By default, directories created in this way will contain a .keep file, to inhibit this:
|
98
|
+
# list[:pattern_dir] = { dest: "pattern", type: :directory, nokeep: true }
|
99
|
+
# Example of how to create a symlink
|
100
|
+
# list[:target_default] = { source: 'debug.rb', # Relative to the file being linked to
|
101
|
+
# dest: 'target/default.rb', # Relative to destination_root
|
102
|
+
# type: :symlink }
|
103
|
+
# Remember to return the final list
|
104
|
+
list
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
module OrigenAppGenerators
|
2
|
+
# The base generator class that should be used by all plugin generators
|
3
|
+
class Plugin < Application
|
4
|
+
def get_common_user_input
|
5
|
+
get_name_and_namespace
|
6
|
+
get_summary
|
7
|
+
get_audience unless @audience
|
8
|
+
end
|
9
|
+
|
10
|
+
protected
|
11
|
+
|
12
|
+
# See Application#filelist for more details
|
13
|
+
def filelist
|
14
|
+
@filelist ||= begin
|
15
|
+
list = super
|
16
|
+
list.delete(:web_doc_layout)
|
17
|
+
list.delete(:web_references)
|
18
|
+
list.delete(:web_defintions)
|
19
|
+
list.delete(:web_installation)
|
20
|
+
list.delete(:web_introduction)
|
21
|
+
list[:gemspec] = { source: 'gemspec.rb', dest: "#{@name}.gemspec" }
|
22
|
+
list[:templates_shared] = { dest: 'templates/shared', type: :directory }
|
23
|
+
if @audience == :external
|
24
|
+
list[:travis] = { source: '.travis.yml' }
|
25
|
+
list[:web_navbar] = { source: 'templates/web/partials/_navbar_external.html.erb', dest: 'templates/web/partials/_navbar.html.erb' }
|
26
|
+
else
|
27
|
+
list[:web_navbar] = { source: 'templates/web/partials/_navbar_internal.html.erb', dest: 'templates/web/partials/_navbar.html.erb' }
|
28
|
+
end
|
29
|
+
list[:lib_readme] = { source: 'lib/README', dest: "lib/#{@name}/README" }
|
30
|
+
list[:lib_readme_dev] = { source: 'lib_dev/README', dest: "lib/#{@name}_dev/README" }
|
31
|
+
list
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def get_summary
|
36
|
+
puts
|
37
|
+
puts 'DESCRIBE YOUR NEW PLUGIN IN A FEW WORDS'
|
38
|
+
puts
|
39
|
+
@summary = get_text(single: true)
|
40
|
+
end
|
41
|
+
|
42
|
+
# Prompts the user to say whether the new plugin is intended for an internal
|
43
|
+
# or external audience (meaning it will published to rubygems.org)
|
44
|
+
def get_audience(proposal = nil)
|
45
|
+
puts
|
46
|
+
puts 'IS THIS PLUGIN GOING TO BE RELEASED TO AN EXTERNAL AUDIENCE?'
|
47
|
+
puts
|
48
|
+
puts 'By answering yes, this plugin will be pushed to rubygems.org when it is released and it will be available outside of your company.'
|
49
|
+
puts
|
50
|
+
confirm_external = get_text(confirm: :return_boolean, default: 'no')
|
51
|
+
@audience = :external if confirm_external
|
52
|
+
end
|
53
|
+
|
54
|
+
def type
|
55
|
+
:plugin
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
module OrigenAppGenerators
|
2
|
+
require 'strscan'
|
3
|
+
# Responsible for parsing something like this:
|
4
|
+
#
|
5
|
+
# "ram, osc, pll, atd(2), comms[ram(2), osc](3)"
|
6
|
+
#
|
7
|
+
# into this:
|
8
|
+
#
|
9
|
+
# {
|
10
|
+
# "RAM"=>{}, "Osc"=>{}, "PLL"=>{}, "ATD"=> {:instances=>2},
|
11
|
+
# "Comms"=>{:instances=>3, :children=>{"RAM"=>{:instances=>2}, "Osc"=>{}}}
|
12
|
+
# }
|
13
|
+
#
|
14
|
+
class SubBlockParser
|
15
|
+
def parse(str)
|
16
|
+
r = {}
|
17
|
+
split(str).each do |tag|
|
18
|
+
tag, i = extract_instances(tag)
|
19
|
+
name, children = extract_children(tag)
|
20
|
+
name = camelize(name)
|
21
|
+
r[name] = {}
|
22
|
+
r[name][:instances] = i if i
|
23
|
+
r[name][:children] = children if children
|
24
|
+
end
|
25
|
+
r
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
# Splits the given string by comma, but understands that nested
|
31
|
+
# commas should not be split on
|
32
|
+
def split(str)
|
33
|
+
r = []
|
34
|
+
str = StringScanner.new(str)
|
35
|
+
r << next_tag(str) until str.eos?
|
36
|
+
r
|
37
|
+
end
|
38
|
+
|
39
|
+
def next_tag(str)
|
40
|
+
v = str.scan_until(/,|\[|$/)
|
41
|
+
if v[-1] == ','
|
42
|
+
v.chop.strip
|
43
|
+
elsif v[-1] == '['
|
44
|
+
open = 1
|
45
|
+
while open > 0
|
46
|
+
v += str.scan_until(/\[|\]/)
|
47
|
+
if v[-1] == '['
|
48
|
+
open += 1
|
49
|
+
else
|
50
|
+
open -= 1
|
51
|
+
end
|
52
|
+
end
|
53
|
+
v += next_tag(str)
|
54
|
+
# End of line
|
55
|
+
else
|
56
|
+
v.strip
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def extract_children(tag)
|
61
|
+
# http://rubular.com/r/plGILY2e2U
|
62
|
+
if tag.strip =~ /([^\[]*)\[(.*)\]/
|
63
|
+
[Regexp.last_match(1), parse(Regexp.last_match(2))]
|
64
|
+
else
|
65
|
+
[tag.strip, nil]
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def extract_instances(tag)
|
70
|
+
if tag.strip =~ /(.*)\((\d+)\)$/
|
71
|
+
[Regexp.last_match(1), Regexp.last_match(2).to_i]
|
72
|
+
else
|
73
|
+
[tag.strip, nil]
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def camelize(val)
|
78
|
+
val.strip.gsub(/\s+/, '_').camelize
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|