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.
Files changed (111) hide show
  1. checksums.yaml +4 -4
  2. data/bin/origen +1 -236
  3. data/config/application.rb +10 -1
  4. data/config/version.rb +1 -1
  5. data/lib/origen/{boot_api.rb → boot/api.rb} +2 -2
  6. data/lib/origen/boot/app.rb +324 -0
  7. data/lib/origen/boot.rb +287 -0
  8. data/lib/origen/commands/archive.rb +175 -0
  9. data/lib/origen/commands/extract.rb +43 -0
  10. data/lib/origen/commands/new.rb +33 -23
  11. data/lib/origen/commands.rb +4 -1
  12. data/lib/origen/commands_global.rb +3 -2
  13. data/lib/origen/operating_systems.rb +4 -0
  14. data/lib/origen/revision_control.rb +1 -1
  15. data/lib/origen/site_config.rb +4 -1
  16. data/lib/origen.rb +3 -2
  17. data/origen_app_generators/Gemfile +16 -0
  18. data/origen_app_generators/Gemfile.lock +147 -0
  19. data/origen_app_generators/LICENSE +21 -0
  20. data/origen_app_generators/README.md +368 -0
  21. data/origen_app_generators/Rakefile +10 -0
  22. data/origen_app_generators/bin/boot.rb +37 -0
  23. data/{bin → origen_app_generators/bin}/fix_my_workspace +0 -0
  24. data/origen_app_generators/config/application.rb +153 -0
  25. data/origen_app_generators/config/boot.rb +1 -0
  26. data/origen_app_generators/config/commands.rb +63 -0
  27. data/origen_app_generators/config/shared_commands.rb +172 -0
  28. data/origen_app_generators/config/version.rb +8 -0
  29. data/origen_app_generators/doc/history +213 -0
  30. data/origen_app_generators/lib/origen_app_generators/application.rb +62 -0
  31. data/origen_app_generators/lib/origen_app_generators/base.rb +231 -0
  32. data/origen_app_generators/lib/origen_app_generators/empty_application.rb +15 -0
  33. data/origen_app_generators/lib/origen_app_generators/empty_plugin.rb +15 -0
  34. data/origen_app_generators/lib/origen_app_generators/new.rb +162 -0
  35. data/origen_app_generators/lib/origen_app_generators/origen_infrastructure/app_generator_plugin.rb +109 -0
  36. data/origen_app_generators/lib/origen_app_generators/plugin.rb +58 -0
  37. data/origen_app_generators/lib/origen_app_generators/sub_block_parser.rb +81 -0
  38. data/origen_app_generators/lib/origen_app_generators/test_engineering/stand_alone_application.rb +236 -0
  39. data/origen_app_generators/lib/origen_app_generators/test_engineering/test_block.rb +162 -0
  40. data/origen_app_generators/lib/origen_app_generators.rb +123 -0
  41. data/origen_app_generators/lib/tasks/app_generators.rake +6 -0
  42. data/origen_app_generators/lib/tasks/new_app_tests.rake +8 -0
  43. data/origen_app_generators/origen_app_generators.gemspec +33 -0
  44. data/origen_app_generators/spec/spec_helper.rb +49 -0
  45. data/origen_app_generators/spec/sub_block_spec.rb +36 -0
  46. data/origen_app_generators/target/debug.rb +8 -0
  47. data/origen_app_generators/target/default.rb +8 -0
  48. data/origen_app_generators/target/production.rb +0 -0
  49. data/origen_app_generators/templates/app_generators/application/Gemfile +19 -0
  50. data/origen_app_generators/templates/app_generators/application/Rakefile +7 -0
  51. data/origen_app_generators/templates/app_generators/application/config/application.rb +125 -0
  52. data/origen_app_generators/templates/app_generators/application/config/boot.rb +4 -0
  53. data/origen_app_generators/templates/app_generators/application/config/commands.rb +79 -0
  54. data/origen_app_generators/templates/app_generators/application/config/maillist_dev.txt +4 -0
  55. data/origen_app_generators/templates/app_generators/application/config/maillist_prod.txt +3 -0
  56. data/origen_app_generators/templates/app_generators/application/config/version.rb +8 -0
  57. data/origen_app_generators/templates/app_generators/application/doc/history +0 -0
  58. data/origen_app_generators/templates/app_generators/application/dot_keep +0 -0
  59. data/origen_app_generators/templates/app_generators/application/lib/app.rake +6 -0
  60. data/origen_app_generators/templates/app_generators/application/lib/module.rb +22 -0
  61. data/origen_app_generators/templates/app_generators/application/lib/top_level.rb +12 -0
  62. data/origen_app_generators/templates/app_generators/application/origen_core_session +2 -0
  63. data/origen_app_generators/templates/app_generators/application/spec/spec_helper.rb +44 -0
  64. data/origen_app_generators/templates/app_generators/application/target/debug.rb +8 -0
  65. data/origen_app_generators/templates/app_generators/application/target/default.rb +1 -0
  66. data/origen_app_generators/templates/app_generators/application/target/production.rb +4 -0
  67. data/origen_app_generators/templates/app_generators/application/templates/web/index.md.erb +19 -0
  68. data/origen_app_generators/templates/app_generators/application/templates/web/layouts/_basic.html.erb +13 -0
  69. data/origen_app_generators/templates/app_generators/application/templates/web/partials/_navbar.html.erb +20 -0
  70. data/origen_app_generators/templates/app_generators/application/templates/web/release_notes.md.erb +5 -0
  71. data/origen_app_generators/templates/app_generators/new/generator.rb +102 -0
  72. data/origen_app_generators/templates/app_generators/new/info.md.erb +9 -0
  73. data/origen_app_generators/templates/app_generators/origen_infrastructure/app_generator_plugin/config/load_generators.rb +6 -0
  74. data/origen_app_generators/templates/app_generators/origen_infrastructure/app_generator_plugin/lib/application.rb +54 -0
  75. data/origen_app_generators/templates/app_generators/origen_infrastructure/app_generator_plugin/lib/base.rb +55 -0
  76. data/origen_app_generators/templates/app_generators/origen_infrastructure/app_generator_plugin/lib/module.rb +28 -0
  77. data/origen_app_generators/templates/app_generators/origen_infrastructure/app_generator_plugin/lib/plugin.rb +64 -0
  78. data/origen_app_generators/templates/app_generators/plugin/Gemfile +26 -0
  79. data/origen_app_generators/templates/app_generators/plugin/Rakefile +10 -0
  80. data/origen_app_generators/templates/app_generators/plugin/config/boot.rb +24 -0
  81. data/origen_app_generators/templates/app_generators/plugin/gemspec.rb +42 -0
  82. data/origen_app_generators/templates/app_generators/plugin/lib/README +4 -0
  83. data/origen_app_generators/templates/app_generators/plugin/lib_dev/README +5 -0
  84. data/origen_app_generators/templates/app_generators/plugin/templates/web/index.md.erb +37 -0
  85. data/origen_app_generators/templates/app_generators/plugin/templates/web/partials/_navbar_external.html.erb +20 -0
  86. data/origen_app_generators/templates/app_generators/plugin/templates/web/partials/_navbar_internal.html.erb +20 -0
  87. data/origen_app_generators/templates/app_generators/test_engineering/stand_alone_application/Gemfile +23 -0
  88. data/origen_app_generators/templates/app_generators/test_engineering/stand_alone_application/environment/j750.rb +1 -0
  89. data/origen_app_generators/templates/app_generators/test_engineering/stand_alone_application/environment/jlink.rb +1 -0
  90. data/origen_app_generators/templates/app_generators/test_engineering/stand_alone_application/environment/uflex.rb +1 -0
  91. data/origen_app_generators/templates/app_generators/test_engineering/stand_alone_application/environment/v93k.rb +1 -0
  92. data/origen_app_generators/templates/app_generators/test_engineering/stand_alone_application/lib/ip_block.rb +23 -0
  93. data/origen_app_generators/templates/app_generators/test_engineering/stand_alone_application/lib/ip_block_controller.rb +5 -0
  94. data/origen_app_generators/templates/app_generators/test_engineering/stand_alone_application/lib/top_level.rb +33 -0
  95. data/origen_app_generators/templates/app_generators/test_engineering/stand_alone_application/lib/top_level_controller.rb +21 -0
  96. data/origen_app_generators/templates/app_generators/test_engineering/stand_alone_application/pattern/example.rb +4 -0
  97. data/origen_app_generators/templates/app_generators/test_engineering/stand_alone_application/target/top_level.rb +4 -0
  98. data/origen_app_generators/templates/app_generators/test_engineering/test_block/environment/j750.rb +2 -0
  99. data/origen_app_generators/templates/app_generators/test_engineering/test_block/environment/ultraflex.rb +2 -0
  100. data/origen_app_generators/templates/app_generators/test_engineering/test_block/environment/v93k.rb +2 -0
  101. data/origen_app_generators/templates/app_generators/test_engineering/test_block/lib/controller.rb +12 -0
  102. data/origen_app_generators/templates/app_generators/test_engineering/test_block/lib/interface.rb +21 -0
  103. data/origen_app_generators/templates/app_generators/test_engineering/test_block/lib/model.rb +18 -0
  104. data/origen_app_generators/templates/app_generators/test_engineering/test_block/lib_dev/dut.rb +27 -0
  105. data/origen_app_generators/templates/app_generators/test_engineering/test_block/lib_dev/dut_controller.rb +26 -0
  106. data/origen_app_generators/templates/app_generators/test_engineering/test_block/pattern/example.rb +5 -0
  107. data/origen_app_generators/templates/app_generators/test_engineering/test_block/program/prb1.rb +11 -0
  108. data/origen_app_generators/templates/app_generators/test_engineering/test_block/target/default.rb +2 -0
  109. data/origen_site_config.yml +13 -2
  110. data/templates/git/gitignore.erb +0 -1
  111. 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
@@ -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