roku_builder_generator 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: b0204f922e4434a1a0c814410ba2d655c82e771edbd1175a1705a689185a0819
4
+ data.tar.gz: 36650f221ae40b8903153f840536254853362d3e207e06f6e52d5d0fb8e3b8a0
5
+ SHA512:
6
+ metadata.gz: 4bf23c381e6473c46bdfb0866cc6f5f252948f0da310cee0b18fcecf7508f5a12662f355acbc1446cbac20ac704163137a55a7119dee394cc1c2c7813c244497
7
+ data.tar.gz: a17b132d2a5035afa12522e87e14710b6c239df97fc6143925849120c4e5e1aabf26c9042db4173f0be3528073160c204aed452af927a2007feefd592eb42eaa
data/.gitignore ADDED
@@ -0,0 +1,11 @@
1
+
2
+ /.bundle/
3
+ /.yardoc
4
+ /Gemfile.lock
5
+ /_yardoc/
6
+ /coverage/
7
+ /doc/
8
+ /pkg/
9
+ /spec/reports/
10
+ /tmp/
11
+ *.gem
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source "https://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in roku_builder_generator.gemspec
4
+ gemspec
5
+
6
+ gem 'solargraph', group: :development
data/LICENSE.txt ADDED
@@ -0,0 +1,13 @@
1
+ Copyright 2020 Viacom, Inc.
2
+
3
+ Licensed under the Apache License, Version 2.0 (the "License");
4
+ you may not use this file except in compliance with the License.
5
+ You may obtain a copy of the License at
6
+
7
+ http://www.apache.org/licenses/LICENSE-2.0
8
+
9
+ Unless required by applicable law or agreed to in writing, software
10
+ distributed under the License is distributed on an "AS IS" BASIS,
11
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ See the License for the specific language governing permissions and
13
+ limitations under the License.
data/README.md ADDED
@@ -0,0 +1,66 @@
1
+ # RokuBuilderGenerator
2
+
3
+ ## Installation
4
+
5
+ Add this line to your application's Gemfile:
6
+
7
+ ```ruby
8
+ gem 'roku_builder_generator'
9
+ ```
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install roku_builder_generator
18
+
19
+ ## Usage
20
+
21
+ The generator plugin has the following commands:
22
+
23
+ ```
24
+ Options for RokuBuilder::Generator:
25
+ Commands:
26
+ --generate COMPONENT_TYPE Generate a component: manager, module, task, screen
27
+ --name COMPONENT_NAME Name of the component
28
+ --extends COMPONENT_NAME A component to extend
29
+ --base-dir Base directory for generated code (eg.: 'brands/core/components/<type>s')
30
+ --with-config Add empty config JSON
31
+ --config-dir Use custom directory for config json (eg.: 'brands/core/region/US/configs/<type>s')
32
+ ```
33
+
34
+ ### Examples
35
+
36
+ Generate a manager called "FooManager", with an empty configuration JSON file:
37
+
38
+ `roku --generate manager --name foo --with-config`
39
+
40
+ Generate a task ("Bar"), but just display the output on screen:
41
+
42
+ `roku --generate task --name bar --dry-run -V`
43
+
44
+ ### Config
45
+
46
+ You can supplement the default configuration using a local file `.roku_builder_generator.json`
47
+
48
+ Format of config file:
49
+
50
+ ```js
51
+ {
52
+ "component_dir": "base/directory/for/components", // default: "./brands/core/components"
53
+ "config_dir": "base/directory/for/config/json/files", // default: "./brands/core/region/US/configs"
54
+ "template_dir": "directory/for/templates" // default: "./roku_builder_generator"
55
+ }
56
+ ```
57
+
58
+ ### Custom Templates
59
+
60
+ You can add custom templates for different component types by adding [ERB](https://www.stuartellis.name/articles/erb/) files to the template directory (either `./roku_builder_generator` or whatever was defined in the config).
61
+
62
+ The template file name must be of the form `<component_name>.<file_extension>.erb`
63
+
64
+ For example, to add a custom template for module SceneGraph XML files, create the file:
65
+
66
+ `./roku_builder_generator/module.xml.erb`
@@ -0,0 +1,211 @@
1
+ require 'erb'
2
+ require 'fileutils'
3
+ require_relative '../../roku_builder_generator'
4
+
5
+
6
+ def default_config()
7
+ return {
8
+ :component_dir => "brands/core/components",
9
+ :config_dir => "brands/core/region/US/configs",
10
+ :template_dir => "roku_builder_generator"
11
+ }
12
+ end
13
+
14
+ def default_output_dir(component_type, base_dir = nil)
15
+ base_dir = base_dir || default_config[:component_dir]
16
+ return "#{base_dir}/#{component_type.capitalize()}s"
17
+ end
18
+
19
+ def default_config_dir(component_type, base_dir = nil)
20
+ base_dir = base_dir || default_config[:config_dir]
21
+ return "#{base_dir}/#{component_type.capitalize()}s"
22
+ end
23
+
24
+
25
+ module RokuBuilder
26
+
27
+ class Generator < Util
28
+ extend Plugin
29
+
30
+
31
+
32
+ # Hash of commands
33
+ # Each command defines a hash with three optional values
34
+ # Setting device to true will require that there is an avaiable device
35
+ # Setting source to true will require that the user passes a source option
36
+ # with the command
37
+ # Setting stage to true will require that the user passes a stage option
38
+ # with the command
39
+ def self.commands
40
+ {
41
+ generate: {}
42
+ }
43
+ end
44
+
45
+
46
+ def get_output_dir( component_type, component_name, parent_dir = nil, custom_dir = nil, base_component_dir = nil )
47
+ output_dir = get_directory_name(component_type, component_name)
48
+ unless parent_dir.nil? || "" === parent_dir
49
+ output_dir = parent_dir+"/"+output_dir
50
+ end
51
+ base_dir = custom_dir ? custom_dir : default_output_dir(component_type, base_component_dir)
52
+ return "./#{base_dir}/#{output_dir}"
53
+
54
+ end
55
+
56
+ def get_config_output_dir( component_type, custom_dir = nil, base_config_dir = nil )
57
+ base_dir = custom_dir ? custom_dir : default_config_dir(component_type, base_config_dir)
58
+ return "./#{base_dir}"
59
+
60
+ end
61
+
62
+ # Hook to add options to the parser
63
+ # The keys set in options for commands must match the keys in the commands
64
+ # hash
65
+ def self.parse_options(parser:, options:)
66
+ parser.separator "Commands:"
67
+ parser.on("--generate COMPONENT_TYPE", "Generate a component: manager, module, task, screen") do |component_type|
68
+ options[:generate] = component_type
69
+ end
70
+ parser.on("--name COMPONENT_NAME", "Name of the component") do |component_name|
71
+ options[:name] = component_name
72
+ end
73
+ parser.on("--extends COMPONENT_NAME", "A component to extend") do |component_name|
74
+ options[:extends] = component_name
75
+ end
76
+ parser.on("--base-dir", "Base directory for generated code (eg.: '#{default_output_dir('<type>')}')") do |base_dir|
77
+ options[:custom_dir] = base_dir
78
+ end
79
+ parser.on("--with-config", "Add empty config JSON") do |d|
80
+ options[:with_config] = true
81
+ end
82
+ parser.on("--config-dir", "Use custom directory for config json (eg.: '#{default_config_dir('<type>')}')") do |d|
83
+ options[:config_dir] = d
84
+ end
85
+ parser.on("--dry-run", "Do not write files, just output") do |d|
86
+ options[:dry_run] = true
87
+ end
88
+ end
89
+
90
+ # Array of plugins the this plugin depends on
91
+ def self.dependencies
92
+ []
93
+ end
94
+
95
+ def init
96
+ #Setup
97
+ end
98
+
99
+
100
+ def get_file_name(component_type, name)
101
+ name = name.slice(0,1).capitalize + name.slice(1..-1)
102
+ if(component_type == 'screen' && !name.end_with?("Screen"))
103
+ return name+ "Screen"
104
+ end
105
+ if(component_type === 'manager'&& !name.end_with?("Manager"))
106
+ return name+'Manager'
107
+ end
108
+ return name
109
+ end
110
+
111
+ def get_directory_name(component_type, name)
112
+ name = name.slice(0,1).capitalize + name.slice(1..-1)
113
+ if(component_type === 'manager'&& !name.end_with?("Manager"))
114
+ return name+'Manager'
115
+ end
116
+ return name
117
+ end
118
+
119
+ def component_has_config_json(component_type)
120
+ ['module', 'screen', 'manager'].include? component_type
121
+
122
+ end
123
+
124
+ def generate(options:)
125
+ if(!options[:name])
126
+ raise InvalidOptions, "Missing component name"
127
+ end
128
+ if(!options[:generate])
129
+ raise InvalidOptions, "Missing component type"
130
+ end
131
+ config = read_config()
132
+ component_type = options[:generate].downcase
133
+ component_name_parts = options[:name].split('/')
134
+ component_proper_name = component_name_parts.last
135
+ component_parent_dir = component_name_parts.first(component_name_parts.size-1).join('/')
136
+
137
+ component_name = get_file_name(component_type, component_proper_name)
138
+ component = RokuBuilderGenerator::BrsComponent.new(component_name, options[:extends], component_type, @logger)
139
+ xml_text = component.render("xml")
140
+ brs_text = component.render("brs")
141
+ json_text = options[:with_config] && component_has_config_json(component_type) ? component.render("json") : nil
142
+
143
+ output_dir = get_output_dir(component_type, component_name, component_parent_dir, options[:custom_dir], config[:component_dir])
144
+ output_config_dir = get_config_output_dir(component_type, options[:config_dir], config[:config_dir])
145
+ output_file_name = File.join(output_dir, component_name)
146
+ output_config_file_name = File.join(output_config_dir, component_proper_name)
147
+
148
+ if(options[:dry_run])
149
+ @logger.unknown "Dry Run, not writing files"
150
+ show_line()
151
+ display_file(output_file_name+".xml", xml_text)
152
+ display_file(output_file_name+".brs", brs_text)
153
+ display_file(output_config_file_name+".json", json_text)
154
+ else
155
+ @logger.unknown "Writing files"
156
+ show_line()
157
+ FileUtils.mkdir_p output_dir
158
+ unless json_text.nil?
159
+ FileUtils.mkdir_p output_config_dir
160
+ end
161
+ write_file(output_file_name+".xml", xml_text)
162
+ write_file(output_file_name+".brs", brs_text)
163
+ write_file(output_config_file_name+".json", json_text)
164
+ end
165
+ end
166
+
167
+
168
+ def display_file(output_file_name, contents)
169
+ unless contents.nil?
170
+ @logger.unknown output_file_name
171
+ @logger.info "\n"+ contents
172
+ show_line
173
+ end
174
+ end
175
+
176
+ def write_file(output_file_name, contents)
177
+ unless contents.nil?
178
+ @logger.unknown output_file_name
179
+ File.open(output_file_name, "w") { |f| f.write contents }
180
+ end
181
+ end
182
+
183
+ def show_line
184
+ @logger.info "------"
185
+ end
186
+
187
+ def config_path()
188
+ config_json_file = "./.roku_builder_generator.json"
189
+ unless File.exist?(config_json_file)
190
+ @logger.warn "Missing Generator Config File (#{config_json_file}) - using default values"
191
+ return nil
192
+ end
193
+ return config_json_file
194
+ end
195
+
196
+ def read_config()
197
+ config = default_config
198
+ unless config_path.nil?
199
+ File.open(config_path) do |io|
200
+ config.merge!(JSON.parse(io.read, {symbolize_names: true}))
201
+ end
202
+ end
203
+ config
204
+ end
205
+
206
+ end
207
+
208
+
209
+ # Register your plugin
210
+ RokuBuilder.register_plugin(Generator)
211
+ end
@@ -0,0 +1,62 @@
1
+ require 'erb'
2
+ require_relative "./utils"
3
+
4
+ module RokuBuilderGenerator
5
+
6
+ class BrsComponent
7
+ include ERB::Util
8
+
9
+ attr_accessor :name, :extends, :template_type
10
+
11
+
12
+ def initialize(name, extends, template_type, logger = nil, local_file_dir = nil)
13
+ @name = name
14
+ @extends = extends
15
+ @template_type = template_type
16
+ @logger = logger
17
+ @local_file_dir = local_file_dir || RokuBuilderGenerator::NAME
18
+ end
19
+
20
+ def render(file_type)
21
+ file_name = get_template_name(@template_type, file_type)
22
+
23
+ unless file_name.nil?
24
+ template = File.read(file_name)
25
+ return render_template(template)
26
+ end
27
+ return nil
28
+ end
29
+
30
+ def log(message)
31
+ unless @logger.nil?
32
+ @logger.info message
33
+ else
34
+ puts message
35
+ end
36
+ end
37
+
38
+ def get_template_name(template_type, file_type)
39
+ file_name = "#{template_type}.#{file_type}.erb"
40
+ local_file = "./#{@local_file_dir}/#{file_name}"
41
+ gem_file = RokuBuilderGenerator::Utils.gem_libdir+"/templates/#{file_name}"
42
+ if File.exist?(local_file)
43
+ log "#{file_type}: Using local version of template - #{local_file}"
44
+ return local_file
45
+ elsif File.exist?(gem_file)
46
+ log "#{file_type}: Using gem version of template - #{gem_file}"
47
+ return gem_file
48
+ end
49
+ if template_type === "default"
50
+ return nil
51
+ end
52
+ return get_template_name("default", file_type)
53
+ end
54
+
55
+ def render_template(template)
56
+ return ERB.new(template).result(binding)
57
+ end
58
+
59
+
60
+ end
61
+
62
+ end
@@ -0,0 +1,10 @@
1
+ '##COPYRIGHT HEADER##
2
+
3
+
4
+ ' <%= name %>
5
+ '
6
+ ' @since version
7
+
8
+ sub init()
9
+
10
+ end sub
@@ -0,0 +1,4 @@
1
+ {
2
+ "<%= name %>": {
3
+ }
4
+ }
@@ -0,0 +1,10 @@
1
+ <?xml version="1.0" encoding="utf-8" ?>
2
+ <!-- ##COPYRIGHT HEADER## -->
3
+
4
+ <component name="<%= name %>"<% if !extends.nil? %> extends="<%= extends %>"<% end %>>
5
+ <script type="text/brightscript" uri="<%= name %>.brs" />
6
+
7
+ <interface>
8
+ </interface>
9
+
10
+ </component>
@@ -0,0 +1,10 @@
1
+ '##COPYRIGHT HEADER##
2
+
3
+
4
+ ' <%= name %>
5
+ '
6
+ ' @since version
7
+
8
+ sub completeSetup()
9
+
10
+ end sub
@@ -0,0 +1,13 @@
1
+ <?xml version="1.0" encoding="utf-8" ?>
2
+ <!-- ##COPYRIGHT HEADER## -->
3
+
4
+ <component name="<%= name %>"<% if !extends.nil? %> extends="<%= extends %>"<% end %>>
5
+ <script type="text/brightscript" uri="<%= name %>.brs" />
6
+
7
+ <interface>
8
+ </interface>
9
+
10
+ <children>
11
+ </children>
12
+
13
+ </component>
@@ -0,0 +1,15 @@
1
+ <?xml version="1.0" encoding="utf-8" ?>
2
+ <!-- ##COPYRIGHT HEADER## -->
3
+
4
+ <component name="<%= name %>"<% if !extends.nil? %> extends="<%= extends %>"<% end %>>
5
+ <script type="text/brightscript" uri="<%= name %>.brs" />
6
+
7
+ <interface>
8
+ </interface>
9
+
10
+ <children>
11
+ <Group id="screenContainer">
12
+ </Group>
13
+ </children>
14
+
15
+ </component>
@@ -0,0 +1,16 @@
1
+ module RokuBuilderGenerator
2
+ module Utils
3
+
4
+ # Return a directory with the project libraries.
5
+ def self.gem_libdir
6
+
7
+ t = ["#{File.dirname(__FILE__)}",
8
+ "#{File.dirname(File.expand_path($0))}/../lib/#{RokuBuilderGenerator::NAME}",
9
+ "#{Gem.dir}/gems/#{RokuBuilderGenerator::NAME}-#{RokuBuilderGenerator::VERSION}/lib/#{RokuBuilderGenerator::NAME}"]
10
+ t.each {|i| return i if File.readable?(i) }
11
+ raise "All paths are invalid: #{t}"
12
+ end
13
+
14
+ # [...]
15
+ end
16
+ end
@@ -0,0 +1,4 @@
1
+ module RokuBuilderGenerator
2
+ NAME = "roku_builder_generator"
3
+ VERSION = "0.1.0"
4
+ end
@@ -0,0 +1,8 @@
1
+
2
+ require_relative "roku_builder_generator/version"
3
+ require_relative "roku_builder_generator/utils"
4
+ require_relative "roku_builder_generator/brs_component"
5
+
6
+
7
+ module RokuBuilderGenerator
8
+ end
@@ -0,0 +1,24 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path("../lib", __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require "roku_builder_generator/version"
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "roku_builder_generator"
8
+ spec.version = RokuBuilderGenerator::VERSION
9
+ spec.authors = ["Mark Pearce"]
10
+ spec.email = ["mark.pearce@redspace.com"]
11
+
12
+ spec.summary = %q{RokuBuilder Generator Plugin}
13
+ spec.description = %q{Plugin for RokuBuilder to do code generation for Brightscript}
14
+ spec.homepage = ""
15
+
16
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
17
+ f.match(%r{^(test|spec|features)/})
18
+ end
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_dependency "roku_builder", "~> 4.4"
22
+
23
+ spec.add_development_dependency "bundler", "~> 2.1"
24
+ end
metadata ADDED
@@ -0,0 +1,86 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: roku_builder_generator
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Mark Pearce
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2020-05-13 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: roku_builder
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '4.4'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '4.4'
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '2.1'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '2.1'
41
+ description: Plugin for RokuBuilder to do code generation for Brightscript
42
+ email:
43
+ - mark.pearce@redspace.com
44
+ executables: []
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - ".gitignore"
49
+ - Gemfile
50
+ - LICENSE.txt
51
+ - README.md
52
+ - lib/roku_builder/plugins/generator.rb
53
+ - lib/roku_builder_generator.rb
54
+ - lib/roku_builder_generator/brs_component.rb
55
+ - lib/roku_builder_generator/templates/default.brs.erb
56
+ - lib/roku_builder_generator/templates/default.json.erb
57
+ - lib/roku_builder_generator/templates/default.xml.erb
58
+ - lib/roku_builder_generator/templates/manager.brs.erb
59
+ - lib/roku_builder_generator/templates/module.xml.erb
60
+ - lib/roku_builder_generator/templates/screen.xml.erb
61
+ - lib/roku_builder_generator/utils.rb
62
+ - lib/roku_builder_generator/version.rb
63
+ - roku_builder_generator.gemspec
64
+ homepage: ''
65
+ licenses: []
66
+ metadata: {}
67
+ post_install_message:
68
+ rdoc_options: []
69
+ require_paths:
70
+ - lib
71
+ required_ruby_version: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ required_rubygems_version: !ruby/object:Gem::Requirement
77
+ requirements:
78
+ - - ">="
79
+ - !ruby/object:Gem::Version
80
+ version: '0'
81
+ requirements: []
82
+ rubygems_version: 3.0.8
83
+ signing_key:
84
+ specification_version: 4
85
+ summary: RokuBuilder Generator Plugin
86
+ test_files: []