netlinx-erb 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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