netlinx-erb 1.0.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 (49) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +9 -0
  3. data/doc/Array.html +213 -0
  4. data/doc/Hash.html +266 -0
  5. data/doc/HashHelpers.html +413 -0
  6. data/doc/Helpers.html +2154 -0
  7. data/doc/NetLinx.html +128 -0
  8. data/doc/NetLinx/ERB.html +233 -0
  9. data/doc/NetLinx/ERB/HashHelpers.html +413 -0
  10. data/doc/NetLinx/ERB/Helpers.html +2157 -0
  11. data/doc/NetLinx/Rake.html +117 -0
  12. data/doc/NetLinx/Rake/ERB.html +117 -0
  13. data/doc/NetLinx/Rake/ERB/Compile.html +354 -0
  14. data/doc/NetLinx/Rake/ERB/GenerateERB.html +419 -0
  15. data/doc/NetLinx/Rake/ERB/GenerateRPC.html +349 -0
  16. data/doc/NetLinx/Rake/ERB/Lines.html +381 -0
  17. data/doc/NetLinx/Rake/Lines.html +381 -0
  18. data/doc/RPC.html +683 -0
  19. data/doc/String.html +322 -0
  20. data/doc/_index.html +248 -0
  21. data/doc/class_list.html +58 -0
  22. data/doc/css/common.css +1 -0
  23. data/doc/css/full_list.css +57 -0
  24. data/doc/css/style.css +339 -0
  25. data/doc/file.README.html +84 -0
  26. data/doc/file.license.html +73 -0
  27. data/doc/file_list.html +63 -0
  28. data/doc/frames.html +26 -0
  29. data/doc/index.html +84 -0
  30. data/doc/js/app.js +219 -0
  31. data/doc/js/full_list.js +181 -0
  32. data/doc/js/jquery.js +4 -0
  33. data/doc/method_list.html +237 -0
  34. data/doc/top-level-namespace.html +114 -0
  35. data/lib/netlinx-erb.rb +14 -0
  36. data/lib/netlinx/erb/erb.rb +19 -0
  37. data/lib/netlinx/erb/hash_helpers.rb +42 -0
  38. data/lib/netlinx/erb/helpers.rb +399 -0
  39. data/lib/netlinx/erb/rpc.rb +270 -0
  40. data/lib/netlinx/rake/erb.rb +26 -0
  41. data/lib/netlinx/rake/erb/generate_erb.rb +66 -0
  42. data/lib/netlinx/rake/erb/generate_rpc.rb +31 -0
  43. data/lib/netlinx/rake/erb/lines.rb +47 -0
  44. data/license.txt +21 -0
  45. data/template/Gemfile +9 -0
  46. data/template/README.md +130 -0
  47. data/template/Rakefile +11 -0
  48. data/template/rpc.axi +148 -0
  49. metadata +234 -0
@@ -0,0 +1,14 @@
1
+
2
+ require 'erb'
3
+
4
+ require_relative 'netlinx/erb/erb'
5
+ require_relative 'netlinx/erb/hash_helpers'
6
+ require_relative 'netlinx/erb/helpers'
7
+ require_relative 'netlinx/erb/rpc'
8
+
9
+
10
+ # :nodoc:
11
+ module NetLinx
12
+ module ERB
13
+ end
14
+ end
@@ -0,0 +1,19 @@
1
+
2
+ require_relative 'helpers'
3
+
4
+ module NetLinx
5
+ module ERB
6
+
7
+ # @return a binding for ERB to evaluate code in.
8
+ # @example
9
+ # ERB.new(buffer, nil, '%<>-').result(NetLinx::ERB.binding)
10
+ def self.binding
11
+ @b ||= Module.new.instance_eval {
12
+ extend NetLinx::ERB::Helpers
13
+ # TODO: _config.rb instance variables should be injected here.
14
+ binding
15
+ }
16
+ end
17
+
18
+ end
19
+ end
@@ -0,0 +1,42 @@
1
+
2
+ module NetLinx
3
+ module ERB
4
+
5
+ # A collection of helper methods for use in Hash
6
+ module HashHelpers
7
+
8
+ # Template suffix (capitalized / unmodified).
9
+ def tmpl_suffix
10
+ Hash.instance_variable_get :@tmpl_suffix
11
+ end
12
+
13
+ # Template suffix for variables (lowercase).
14
+ def tmpl_var_suffix
15
+ Hash.instance_variable_get :@tmpl_var_suffix
16
+ end
17
+
18
+ # Append the @tmpl_suffix to each key in the hash.
19
+ def append_suffix
20
+ hash = self.map do |k,v|
21
+ key_name = "#{k}"
22
+ key_name += "_#{tmpl_suffix}" if tmpl_suffix and not tmpl_suffix.empty?
23
+
24
+ [key_name.to_sym, v]
25
+ end
26
+
27
+ Hash[hash]
28
+ end
29
+
30
+ # Append the @tmpl_suffix to each key in the hash and overwrite this
31
+ # hash with the result.
32
+ def append_suffix!
33
+ hash = append_suffix
34
+ self.clear
35
+ self.merge! hash
36
+ end
37
+
38
+ end
39
+ end
40
+ end
41
+
42
+ Hash.class_eval { include NetLinx::ERB::HashHelpers }
@@ -0,0 +1,399 @@
1
+
2
+ require_relative 'erb'
3
+ require_relative 'hash_helpers'
4
+
5
+ module NetLinx
6
+ module ERB
7
+
8
+ # A collection of code generation helper methods for use in NetLinx ERB files.
9
+ module Helpers
10
+
11
+
12
+ # @group Formatting
13
+
14
+
15
+ # Generate a group of lines for a given hash.
16
+ # @param hash [Hash]
17
+ # @param padding [String, Numeric] whitespace placed in front of the string.
18
+ # Can be a string of spaces, or a number representing the indentation level.
19
+ # @yield [key, value] elements from hash
20
+ # @return [String] lines of source code
21
+ def group hash, padding: nil, &block
22
+ padding = ' ' * (4 * padding) if padding.is_a?(Numeric)
23
+ hash.map { |key, value| block.call key, value }.compact.map { |str| padding.to_s + str }.join("\n")
24
+ end
25
+
26
+ # Left justify a block of code to line up on a type of character.
27
+ # Defaults to :equals (=).
28
+ #
29
+ # @param amount [Numeric] value of number of spaces, or the longest key in a hash.
30
+ # @param type [:equals, :colon, :comma, :comma_2, :semicolon] character to justify on.
31
+ # @return [String] a group of justified lines of source code.
32
+ def justify str, amount: nil, type: nil
33
+ # justification_amount = amount.is_a?(Numeric) ? amount : amount.map { |key, _| key.to_s.size }.max
34
+
35
+ lines = str.split "\n"
36
+
37
+ justify_types = {
38
+ equals: lines.map { |line| line.index "=" }.compact.max,
39
+ colon: lines.map { |line| line.index ":" }.compact.max,
40
+ comma: lines.map { |line| line.index "," }.compact.max,
41
+ comma_2: lines.map { |line| line.index "," }.compact.max,
42
+ semicolon: lines.map { |line| line.index ";" }.compact.max,
43
+ }
44
+
45
+ # Types that will be chosen from automatically if no type is specified
46
+ auto_justify_types = [:equals, :colon]
47
+
48
+ justify_by = justify_types.select { |k,v|
49
+ auto_justify_types.include?(k) && !v.nil?
50
+ }.min
51
+ justify_by = justify_by.first if justify_by
52
+ justify_by = type if type
53
+
54
+ justify_amount = amount || justify_types[justify_by] || 0
55
+
56
+ # Rebuild each line with the appropriate justification.
57
+ lines.map! { |line|
58
+ output = ''
59
+
60
+ case justify_by
61
+ when :equals
62
+ line =~ /(.*?)(=.*)/
63
+ output = $2.nil? ? line : $1.ljust(justify_amount) + $2
64
+ when :colon
65
+ line =~ /(.*?\:)\s*(.*)/
66
+ output = $2.nil? ? line : $1.ljust(justify_amount + 1) + ' ' + $2
67
+ when :comma
68
+ line =~ /(.*?\,)\s*(.*)/
69
+ output = $2.nil? ? line : $1.ljust(justify_amount + 1) + ' ' + $2
70
+ when :comma_2
71
+ line =~ /(.*?\,.*?\,)\s*(.*)/
72
+ output = $2.nil? ? line : $1.ljust(justify_amount + 1) + ' ' + $2
73
+ when :semicolon
74
+ line =~ /(.*?\;)\s*(.*)/
75
+ output = $2.nil? ? line : $1.ljust(justify_amount + 1) + ' ' + $2
76
+ else
77
+ line
78
+ end
79
+ }.join "\n"
80
+ end
81
+
82
+
83
+ # @group Code Generation
84
+
85
+
86
+ # Print the list of devices.
87
+ # @param h [Hash] device names as keys.
88
+ # @param justify [Numeric] column number to justify equals symbol (=) on.
89
+ # @return [String] a group of justified lines of source code.
90
+ def print_device_hash h, justify: nil
91
+ # TODO: Refactor to use #justify.
92
+ max_len = h.map { |name, value| name.size }.max
93
+ h.map { |name, value| "dv#{name.to_s.upcase.ljust justify || max_len} = #{value};" }.join("\n")
94
+ end
95
+
96
+ # Print the list of constants.
97
+ # @param h [Hash] constant names as keys.
98
+ # @param justify [Numeric] column number to justify equals symbol (=) on.
99
+ # @return [String] a group of justified lines of source code.
100
+ def print_constant_hash h, justify: nil
101
+ # TODO: Refactor to use #justify.
102
+ max_len = h.map { |name, value| name.size }.max
103
+ h.map { |name, value| "#{name.to_s.upcase.ljust justify || max_len} = #{value};" }.join("\n")
104
+ end
105
+
106
+ # Print the list of variables.
107
+ # Format:
108
+ # {
109
+ # var_name: { type: :integer, default: 0, comment: 'my var' }
110
+ # }
111
+ # @param h [Hash] variable names as keys.
112
+ # @return [String] a group of justified lines of source code.
113
+ def print_variable_hash h
114
+ justify group(h) { |name, params|
115
+ type = params.fetch :type, :integer
116
+ default = params.fetch :default, nil
117
+ comment = params.fetch :comment, nil
118
+
119
+ output = "#{type} #{name.to_s.downcase}"
120
+ output += " = #{default}" if default
121
+ output += ";"
122
+ output += " // #{comment}" if comment
123
+ output
124
+ }
125
+ end
126
+
127
+ # Generate instance variables for the DEFINE_CONSTANTS section
128
+ # from the given hash keys.
129
+ # Appends @tmpl_suffix if set.
130
+ # @see #print_variable_hash #print_variable_hash - for formatting
131
+ def generate_constant_ivars h, append_suffix: false
132
+ h.each_key do |key|
133
+ value = key.to_s.upcase
134
+ value = "#{value}_#{@tmpl_suffix.to_s.upcase}" if @tmpl_suffix and append_suffix
135
+
136
+ instance_variable_set :"@#{key.to_sym}", value
137
+ end
138
+
139
+ h
140
+ end
141
+
142
+ # Generate instance variables for the DEFINE_VARIABLES section
143
+ # from the given hash keys.
144
+ # Appends @tmpl_var_suffix if set.
145
+ # @see #print_variable_hash #print_variable_hash - for formatting
146
+ def generate_variable_ivars h, append_suffix: true
147
+ h.each_key do |key|
148
+ value = key.to_s.downcase
149
+ value = "#{value}_#{@tmpl_suffix.to_s.downcase}" if @tmpl_suffix and append_suffix
150
+
151
+ instance_variable_set :"@#{key.to_sym}", value
152
+ end
153
+
154
+ h
155
+ end
156
+
157
+ # Automatically comment out the input unless the condition is met.
158
+ # @param str [String] NetLinx source code string
159
+ # @param condition comments out the source code string if evaluates to false or nil
160
+ # @return [String] NetLinx source code
161
+ def auto_comment str, condition
162
+ condition ? str : str.split("\n").map { |line| "// " + line }.join("\n")
163
+ end
164
+
165
+ # Generate button events for the given hash of buttons.
166
+ # @param buttons [Hash] button constants
167
+ # @param device [String] touch panel device constant.
168
+ # @dvTP comes from ERB template.
169
+ # @return [String] \[dev, chan\] source code
170
+ def button_event buttons, device = @dvTP
171
+ buttons.map { |name, _| "button_event[#{device}, #{name}]" }.join("\n")
172
+ end
173
+
174
+ # Generate a button_event block for the given hash of buttons.
175
+ # @param buttons [Hash] button constants
176
+ # @param kwargs [Hash]
177
+ # @option kwargs [String] :function name of the function to call in the switch block
178
+ # @option kwargs [Symbol, nil] :remap name of symbol to use to {Hash#remap} the hash.
179
+ # This is a convenience arg for readability; the hash can also be remapped
180
+ # before passed into this method.
181
+ # @option kwargs [String] :device touch panel device constant.
182
+ # @dvTP comes from ERB template.
183
+ # @option kwargs [String, Numeric] :padding (3) whitespace placed in front of the string.
184
+ # Can be a string of spaces, or a number representing the indentation level.
185
+ # @option kwargs [Boolean] :momentary (false) adds a `to` statement for momentary button feedback
186
+ # @option kwargs [Boolean] :hold_block (false) create a hold block for the event
187
+ # @option kwargs [Boolean] :hold_time (0.6) repeat time for the hold block
188
+ # @yield [value, name] option to create a custom function call string.
189
+ # Modifies the function arguments if :function is set, otherwise modifies
190
+ # the entire function call string.
191
+ # @yieldparam value value of the buttons hash for the given key. Accounts for remap.
192
+ # @yieldparam name [Symbol] key of the buttons hash
193
+ # @yieldreturn [String] function string
194
+ #
195
+ # @example
196
+ # button_event_block bluray_key_constants.remap(:key),
197
+ # function: 'bluray_key', momentary: true
198
+ #
199
+ # button_event_block channel_strip_constants.select {|k,_| k.to_s.end_with? "_UP"},
200
+ # function: 'audio_increment_volume', remap: :audio, hold_block: true, momentary: true
201
+ #
202
+ # # Use block to create function string.
203
+ # # :function not set
204
+ # button_event_block(video_source_constants) { |h|
205
+ # "video_patch(#{h[:input]}, #{h[:dest]})"
206
+ # }
207
+ #
208
+ # # Use block to create parameters string.
209
+ # # :function is set
210
+ # button_event_block(video_source_constants, function: 'video_patch') { |h|
211
+ # "#{h[:input]}, #{h[:dest]}"
212
+ # }
213
+ #
214
+ # # Use block to specify an array of parameters.
215
+ # # :function is set
216
+ # button_event_block(video_source_constants, function: 'video_patch') { |h|
217
+ # [h[:input], h[:dest]]
218
+ # }
219
+ #
220
+ def button_event_block buttons, **kwargs, &block
221
+ function = kwargs.fetch :function, nil
222
+ device = kwargs.fetch :device, @dvTP
223
+ remap = kwargs.fetch :remap, nil
224
+ padding = kwargs.fetch :padding, 3
225
+ momentary = kwargs.fetch :momentary, false
226
+ hold_block = kwargs.fetch :hold_block, false
227
+ hold_time = kwargs.fetch :hold_time, 0.6
228
+
229
+ buttons = buttons.remap(remap) if remap
230
+
231
+ case_string = justify group(buttons, padding: padding) { |name, value|
232
+ str = if block_given?
233
+ block_val = block.call value, name
234
+ block_val = block_val.join ', ' if block_val.is_a? Array
235
+
236
+ if function
237
+ "#{function}(#{block_val})"
238
+ else
239
+ "#{block_val}"
240
+ end
241
+ else
242
+ "#{function}(#{value})"
243
+ end
244
+
245
+ auto_comment "case #{name}: #{str};", value
246
+ }
247
+
248
+ momentary_string = momentary ? "\n to[button.input];\n " : ''
249
+
250
+ output = <<EOS
251
+ #{button_event buttons, device}
252
+ {
253
+ push:
254
+ {#{momentary_string}
255
+ switch (button.input.channel)
256
+ {
257
+ #{ case_string }
258
+ }
259
+ }
260
+
261
+ EOS
262
+
263
+ if hold_block
264
+ hold_string = <<EOS
265
+ hold[#{hold_time}, repeat]:
266
+ {
267
+ switch (button.input.channel)
268
+ {
269
+ #{ case_string }
270
+ }
271
+ }
272
+
273
+ EOS
274
+ output += hold_string
275
+ end
276
+
277
+ output +=
278
+ <<EOS
279
+ release: {}
280
+ }
281
+ EOS
282
+ output.chomp
283
+ end
284
+
285
+ # Generate an empty HiQnet address string.
286
+ #
287
+ # @example
288
+ # # Generates:
289
+ # '0x000000000000'
290
+ def hiqnet_empty
291
+ '0x' + ('0' * 12)
292
+ end
293
+
294
+ # Send a touch panel command to show or hide a control.
295
+ # @param control [Symbol, String] address or constant of a control
296
+ # @param show [Boolean, Numeric, String] 0/1 print verbatim.
297
+ # true/fase convert to 0/1.
298
+ # string expression is wrapped in itoa().
299
+ #
300
+ # @example
301
+ # ^SHO-<control>,<0|1>
302
+ def show_control control, show, device: @dvTP
303
+ str = "send_command #{device}, \"'^SHO-', itoa(#{control}), ',"
304
+
305
+ if show.is_a? Fixnum
306
+ str += "#{show}'"
307
+ elsif show == true or show == false or show == nil
308
+ str += "#{show ? 1 : 0}'"
309
+ else
310
+ str += "', itoa(#{show})"
311
+ end
312
+
313
+ str += "\";"
314
+ end
315
+
316
+ # Run ERB on the given template file.
317
+ # @param template_file [String] file path
318
+ # @return [String] ERB output.
319
+ # @raise [LoadError] template not found
320
+ def execute_erb template_file
321
+ raise LoadError, "Template not found: #{template_file}" unless File.exists? template_file
322
+ $AUTOGEN_HEADER + ::ERB.new(File.read(template_file), nil, '%<>-')
323
+ .result(NetLinx::ERB.binding)
324
+ end
325
+
326
+
327
+ # @group Other
328
+
329
+
330
+ # Ensures button number constants haven't been unintentionally duplicated.
331
+ # @param hashes [*Hash]
332
+ # @raise if two keys have the same value.
333
+ def check_for_duplicate_values *hashes
334
+ raise NotImplementedError
335
+ end
336
+
337
+ end
338
+ end
339
+ end
340
+
341
+ # :nodoc:
342
+ class Hash
343
+
344
+ # Reconstructs a single level hash out of a hash with nested parameters.
345
+ # @param nested_key use the value associated with this key in the nested hash
346
+ # @return [Hash] keys mapped to the set of values specified
347
+ #
348
+ # @example
349
+ # buttons = {
350
+ # :TOUCH_PANEL_BUTTON_1 => { btn: 1, matrix_input: :MTX_IN_DVD },
351
+ # :TOUCH_PANEL_BUTTON_2 => { btn: 2, matrix_input: :MTX_IN_VCR }
352
+ # }
353
+ #
354
+ # # buttons.remap(:btn) will return a hash of touch panel button
355
+ # # symbols with the :btn numbers mapped as the values, and
356
+ # # :matrix_input will be discarded.
357
+ def remap nested_key
358
+ self.map { |k,v| [k, v[nested_key]] }.to_h
359
+ end
360
+
361
+ end
362
+
363
+ # Patch Array#to_h into Ruby 2.0
364
+ unless RUBY_VERSION >= '2.1.0'
365
+ # :nodoc:
366
+ class Array
367
+ # Convert array to hash.
368
+ def to_h
369
+ Hash[self]
370
+ end
371
+ end
372
+ end
373
+
374
+ # :nodoc:
375
+ class String
376
+
377
+ # Intended for initializing struct constants.
378
+ def remove_comma_after_last_item
379
+ self.gsub(/(?<=\}),(.*?)\z/, ' \1')
380
+ end
381
+
382
+ # Convert a string to a HiQnet address struct.
383
+ # Can include state variable.
384
+ # @param sv [String, Integer, nil], state variable
385
+ #
386
+ # @example
387
+ # '0x100203000103'.to_hiqnet(0x0000)
388
+ # # Generates:
389
+ # {$10, $02, $03, $00, $01, $03, $00, $00},
390
+ def to_hiqnet sv = nil
391
+ sv ||= ''
392
+ sv = sv.is_a?(Fixnum) ? sv.to_s(16) : sv.to_s
393
+ sv = sv.rjust(4, '0') unless sv.empty?
394
+
395
+ address = self + sv
396
+ "{#{address.gsub(/\A0x/, '').upcase.scan(/../).map {|s| '$' + s}.join(', ')}},"
397
+ end
398
+
399
+ end