Items templates with JRuby

Following up on my post on Dynamic sitemaps with JRuby - this post will show how to template and generate items files with JRuby.

I will use my Nuvo Home Audio system items file as the example:

Before:

Switch                   NuvoFavorite                                                      { channel="exec:command:nuvo_playlist:run"}            

String                   Music_Port_Source_A_URL                                                                                                  
String                   Music_Port_Source_B_URL                                                                                                  
String                   Music_Port_Source_C_URL                                                                                                  
String                   Music_Port_Source_D_URL                                                                                                  

Switch                   RestartMPS4                                                                                                              

Group:Switch:OR(ON, OFF) ZonePowers                                                                                                               
Group                    ZoneSources                                                                                                              


// system
Switch                   Nuvo_System_Alloff      "All Zones Off"                           { channel="nuvo:amplifier:nuvo:system#alloff" }        
Switch                   Nuvo_System_Allmute     "All Zones Mute"                          { channel="nuvo:amplifier:nuvo:system#allmute" }       
Switch                   Nuvo_System_Page        "Page All Zones"                          { channel="nuvo:amplifier:nuvo:system#page" }          

// zones
Switch                   Nuvo_Z1_Power           "Power"                    (ZonePowers)   { channel="nuvo:amplifier:nuvo:zone1#power" }          
Number                   Nuvo_Z1_Source          "Source Input [%s]"        (ZoneSources)  { channel="nuvo:amplifier:nuvo:zone1#source" }         
Dimmer                   Nuvo_Z1_Volume          "Volume [%d %%]"                          { channel="nuvo:amplifier:nuvo:zone1#volume" }         
Switch                   Nuvo_Z1_Mute            "Mute"                                    { channel="nuvo:amplifier:nuvo:zone1#mute" }           
Number                   Nuvo_Z1_Favorite        "Favorite"                                { channel="nuvo:amplifier:nuvo:zone1#favorite" }       
Player                   Nuvo_Z1_Control         "Control"                                 { channel="nuvo:amplifier:nuvo:zone2#control" }        
Number                   Nuvo_Z1_Treble          "Treble Adjustment [%s]"                  { channel="nuvo:amplifier:nuvo:zone1#treble" }         
Number                   Nuvo_Z1_Bass            "Bass Adjustment [%s]"                    { channel="nuvo:amplifier:nuvo:zone1#bass" }           
Number                   Nuvo_Z1_Balance         "Balance Adjustment [%s]"                 { channel="nuvo:amplifier:nuvo:zone1#balance" }        
Switch                   Nuvo_Z1_Loudness        "Loudness"                                { channel="nuvo:amplifier:nuvo:zone1#loudness" }       
Switch                   Nuvo_Z1_Dnd             "Do Not Disturb"                          { channel="nuvo:amplifier:nuvo:zone1#dnd" }            
Switch                   Nuvo_Z1_Lock            "Zone Locked [%s]"                        { channel="nuvo:amplifier:nuvo:zone1#lock" }           
Switch                   Nuvo_Z1_Party           "Party Mode"                              { channel="nuvo:amplifier:nuvo:zone1#party" }          

Switch                   Nuvo_Z2_Power           "Power"                    (ZonePowers)   { channel="nuvo:amplifier:nuvo:zone2#power" }          
Number                   Nuvo_Z2_Source          "Source Input [%s]"        (ZoneSources)  { channel="nuvo:amplifier:nuvo:zone2#source" }         
Dimmer                   Nuvo_Z2_Volume          "Volume [%d %%]"                          { channel="nuvo:amplifier:nuvo:zone2#volume" }         
Switch                   Nuvo_Z2_Mute            "Mute"                                    { channel="nuvo:amplifier:nuvo:zone2#mute" }           
Number                   Nuvo_Z2_Favorite        "Favorite"                                { channel="nuvo:amplifier:nuvo:zone2#favorite" }       
Player                   Nuvo_Z2_Control         "Control"                                 { channel="nuvo:amplifier:nuvo:zone2#control" }        
Number                   Nuvo_Z2_Treble          "Treble Adjustment [%s]"                  { channel="nuvo:amplifier:nuvo:zone2#treble" }         
Number                   Nuvo_Z2_Bass            "Bass Adjustment [%s]"                    { channel="nuvo:amplifier:nuvo:zone2#bass" }           
Number                   Nuvo_Z2_Balance         "Balance Adjustment [%s]"                 { channel="nuvo:amplifier:nuvo:zone2#balance" }        
Switch                   Nuvo_Z2_Loudness        "Loudness"                                { channel="nuvo:amplifier:nuvo:zone2#loudness" }       
Switch                   Nuvo_Z2_Dnd             "Do Not Disturb"                          { channel="nuvo:amplifier:nuvo:zone2#dnd" }            
Switch                   Nuvo_Z2_Lock            "Zone Locked [%s]"                        { channel="nuvo:amplifier:nuvo:zone2#lock" }           
Switch                   Nuvo_Z2_Party           "Party Mode"                              { channel="nuvo:amplifier:nuvo:zone2#party" }          

Switch                   Nuvo_Z3_Power           "Power"                    (ZonePowers)   { channel="nuvo:amplifier:nuvo:zone3#power" }          
Number                   Nuvo_Z3_Source          "Source Input [%s]"        (ZoneSources)  { channel="nuvo:amplifier:nuvo:zone3#source" }         
Dimmer                   Nuvo_Z3_Volume          "Volume [%d %%]"                          { channel="nuvo:amplifier:nuvo:zone3#volume" }         
Switch                   Nuvo_Z3_Mute            "Mute"                                    { channel="nuvo:amplifier:nuvo:zone3#mute" }           
Number                   Nuvo_Z3_Favorite        "Favorite"                                { channel="nuvo:amplifier:nuvo:zone3#favorite" }       
Player                   Nuvo_Z3_Control         "Control"                                 { channel="nuvo:amplifier:nuvo:zone3#control" }        
Number                   Nuvo_Z3_Treble          "Treble Adjustment [%s]"                  { channel="nuvo:amplifier:nuvo:zone3#treble" }         
Number                   Nuvo_Z3_Bass            "Bass Adjustment [%s]"                    { channel="nuvo:amplifier:nuvo:zone3#bass" }           
Number                   Nuvo_Z3_Balance         "Balance Adjustment [%s]"                 { channel="nuvo:amplifier:nuvo:zone3#balance" }        
Switch                   Nuvo_Z3_Loudness        "Loudness"                                { channel="nuvo:amplifier:nuvo:zone3#loudness" }       
Switch                   Nuvo_Z3_Dnd             "Do Not Disturb"                          { channel="nuvo:amplifier:nuvo:zone3#dnd" }            
Switch                   Nuvo_Z3_Lock            "Zone Locked [%s]"                        { channel="nuvo:amplifier:nuvo:zone3#lock" }           
Switch                   Nuvo_Z3_Party           "Party Mode"                              { channel="nuvo:amplifier:nuvo:zone3#party" }          

Switch                   Nuvo_Z4_Power           "Power"                    (ZonePowers)   { channel="nuvo:amplifier:nuvo:zone4#power" }          
Number                   Nuvo_Z4_Source          "Source Input [%s]"        (ZoneSources)  { channel="nuvo:amplifier:nuvo:zone4#source" }         
Dimmer                   Nuvo_Z4_Volume          "Volume [%d %%]"                          { channel="nuvo:amplifier:nuvo:zone4#volume" }         
Switch                   Nuvo_Z4_Mute            "Mute"                                    { channel="nuvo:amplifier:nuvo:zone4#mute" }           
Number                   Nuvo_Z4_Favorite        "Favorite"                                { channel="nuvo:amplifier:nuvo:zone4#favorite" }       
Player                   Nuvo_Z4_Control         "Control"                                 { channel="nuvo:amplifier:nuvo:zone4#control" }        
Number                   Nuvo_Z4_Treble          "Treble Adjustment [%s]"                  { channel="nuvo:amplifier:nuvo:zone4#treble" }         
Number                   Nuvo_Z4_Bass            "Bass Adjustment [%s]"                    { channel="nuvo:amplifier:nuvo:zone4#bass" }           
Number                   Nuvo_Z4_Balance         "Balance Adjustment [%s]"                 { channel="nuvo:amplifier:nuvo:zone4#balance" }        
Switch                   Nuvo_Z4_Loudness        "Loudness"                                { channel="nuvo:amplifier:nuvo:zone4#loudness" }       
Switch                   Nuvo_Z4_Dnd             "Do Not Disturb"                          { channel="nuvo:amplifier:nuvo:zone4#dnd" }            
Switch                   Nuvo_Z4_Lock            "Zone Locked [%s]"                        { channel="nuvo:amplifier:nuvo:zone4#lock" }           
Switch                   Nuvo_Z4_Party           "Party Mode"                              { channel="nuvo:amplifier:nuvo:zone4#party" }          

Switch                   Nuvo_Z5_Power           "Power"                    (ZonePowers)   { channel="nuvo:amplifier:nuvo:zone5#power" }          
Number                   Nuvo_Z5_Source          "Source Input [%s]"        (ZoneSources)  { channel="nuvo:amplifier:nuvo:zone5#source" }         
Dimmer                   Nuvo_Z5_Volume          "Volume [%d %%]"                          { channel="nuvo:amplifier:nuvo:zone5#volume" }         
Switch                   Nuvo_Z5_Mute            "Mute"                                    { channel="nuvo:amplifier:nuvo:zone5#mute" }           
Number                   Nuvo_Z5_Favorite        "Favorite"                                { channel="nuvo:amplifier:nuvo:zone5#favorite" }       
Player                   Nuvo_Z5_Control         "Control"                                 { channel="nuvo:amplifier:nuvo:zone5#control" }        
Number                   Nuvo_Z5_Treble          "Treble Adjustment [%s]"                  { channel="nuvo:amplifier:nuvo:zone5#treble" }         
Number                   Nuvo_Z5_Bass            "Bass Adjustment [%s]"                    { channel="nuvo:amplifier:nuvo:zone5#bass" }           
Number                   Nuvo_Z5_Balance         "Balance Adjustment [%s]"                 { channel="nuvo:amplifier:nuvo:zone5#balance" }        
Switch                   Nuvo_Z5_Loudness        "Loudness"                                { channel="nuvo:amplifier:nuvo:zone5#loudness" }       
Switch                   Nuvo_Z5_Dnd             "Do Not Disturb"                          { channel="nuvo:amplifier:nuvo:zone5#dnd" }            
Switch                   Nuvo_Z5_Lock            "Zone Locked [%s]"                        { channel="nuvo:amplifier:nuvo:zone5#lock" }           
Switch                   Nuvo_Z5_Party           "Party Mode"                              { channel="nuvo:amplifier:nuvo:zone5#party" }          

Switch                   Nuvo_Z6_Power           "Power"                    (ZonePowers)   { channel="nuvo:amplifier:nuvo:zone6#power" }          
Number                   Nuvo_Z6_Source          "Source Input [%s]"        (ZoneSources)  { channel="nuvo:amplifier:nuvo:zone6#source" }         
Dimmer                   Nuvo_Z6_Volume          "Volume [%d %%]"                          { channel="nuvo:amplifier:nuvo:zone6#volume" }         
Switch                   Nuvo_Z6_Mute            "Mute"                                    { channel="nuvo:amplifier:nuvo:zone6#mute" }           
Number                   Nuvo_Z6_Favorite        "Favorite"                                { channel="nuvo:amplifier:nuvo:zone6#favorite" }       
Player                   Nuvo_Z6_Control         "Control"                                 { channel="nuvo:amplifier:nuvo:zone6#control" }        
Number                   Nuvo_Z6_Treble          "Treble Adjustment [%s]"                  { channel="nuvo:amplifier:nuvo:zone6#treble" }         
Number                   Nuvo_Z6_Bass            "Bass Adjustment [%s]"                    { channel="nuvo:amplifier:nuvo:zone6#bass" }           
Number                   Nuvo_Z6_Balance         "Balance Adjustment [%s]"                 { channel="nuvo:amplifier:nuvo:zone6#balance" }        
Switch                   Nuvo_Z6_Loudness        "Loudness"                                { channel="nuvo:amplifier:nuvo:zone6#loudness" }       
Switch                   Nuvo_Z6_Dnd             "Do Not Disturb"                          { channel="nuvo:amplifier:nuvo:zone6#dnd" }            
Switch                   Nuvo_Z6_Lock            "Zone Locked [%s]"                        { channel="nuvo:amplifier:nuvo:zone6#lock" }           
Switch                   Nuvo_Z6_Party           "Party Mode"                              { channel="nuvo:amplifier:nuvo:zone6#party" }          

Switch                   Nuvo_Z7_Power           "Power"                    (ZonePowers)   { channel="nuvo:amplifier:nuvo:zone7#power" }          
Number                   Nuvo_Z7_Source          "Source Input [%s]"        (ZoneSources)  { channel="nuvo:amplifier:nuvo:zone7#source" }         
Dimmer                   Nuvo_Z7_Volume          "Volume [%d %%]"                          { channel="nuvo:amplifier:nuvo:zone7#volume" }         
Switch                   Nuvo_Z7_Mute            "Mute"                                    { channel="nuvo:amplifier:nuvo:zone7#mute" }           
Number                   Nuvo_Z7_Favorite        "Favorite"                                { channel="nuvo:amplifier:nuvo:zone7#favorite" }       
Player                   Nuvo_Z7_Control         "Control"                                 { channel="nuvo:amplifier:nuvo:zone7#control" }        
Number                   Nuvo_Z7_Treble          "Treble Adjustment [%s]"                  { channel="nuvo:amplifier:nuvo:zone7#treble" }         
Number                   Nuvo_Z7_Bass            "Bass Adjustment [%s]"                    { channel="nuvo:amplifier:nuvo:zone7#bass" }           
Number                   Nuvo_Z7_Balance         "Balance Adjustment [%s]"                 { channel="nuvo:amplifier:nuvo:zone7#balance" }        
Switch                   Nuvo_Z7_Loudness        "Loudness"                                { channel="nuvo:amplifier:nuvo:zone7#loudness" }       
Switch                   Nuvo_Z7_Dnd             "Do Not Disturb"                          { channel="nuvo:amplifier:nuvo:zone7#dnd" }            
Switch                   Nuvo_Z7_Lock            "Zone Locked [%s]"                        { channel="nuvo:amplifier:nuvo:zone7#lock" }           
Switch                   Nuvo_Z7_Party           "Party Mode"                              { channel="nuvo:amplifier:nuvo:zone7#party" }          

String                   Nuvo_S5_Display_Line1   "Track: [%s]"                             { channel="nuvo:amplifier:nuvo:source5#display_line1" }
String                   Nuvo_S5_Display_Line2   "Album: [%s]"                             { channel="nuvo:amplifier:nuvo:source5#display_line2" }
String                   Nuvo_S5_Display_Line3   "Artist: [%s]"                            { channel="nuvo:amplifier:nuvo:source5#display_line3" }
String                   Nuvo_S5_Display_Line4   "Title: [%s]"                             { channel="nuvo:amplifier:nuvo:source5#display_line4" }
String                   Nuvo_S5_Play_Mode       "Play Mode: [%s]"                         { channel="nuvo:amplifier:nuvo:source5#play_mode" }    
//Number:Time            Nuvo_S5_Track_Length    "Track Length: [%s s]"                    { channel="nuvo:amplifier:nuvo:source5#track_length" }
//Number:Time            Nuvo_S5_Track_Position  "Track Position: [%s s]"                  { channel="nuvo:amplifier:nuvo:source5#track_position" }
String                   Nuvo_S5_Button_Press    "Button: [%s]"                            { channel="nuvo:amplifier:nuvo:source5#button_press" } 

String                   Nuvo_S6_Display_Line1   "Track: [%s]"                             { channel="nuvo:amplifier:nuvo:source6#display_line1" }
String                   Nuvo_S6_Display_Line2   "Album: [%s]"                             { channel="nuvo:amplifier:nuvo:source6#display_line2" }
String                   Nuvo_S6_Display_Line3   "Artist: [%s]"                            { channel="nuvo:amplifier:nuvo:source6#display_line3" }
String                   Nuvo_S6_Display_Line4   "Title: [%s]"                             { channel="nuvo:amplifier:nuvo:source6#display_line4" }
String                   Nuvo_S6_Play_Mode       "Play Mode: [%s]"                         { channel="nuvo:amplifier:nuvo:source6#play_mode" }    
//Number:Time            Nuvo_S6_Track_Length    "Track Length: [%s s]"                    { channel="nuvo:amplifier:nuvo:source6#track_length" }
//Number:Time            Nuvo_S6_Track_Position  "Track Position: [%s s]"                  { channel="nuvo:amplifier:nuvo:source6#track_position" }
String                   Nuvo_S6_Button_Press    "Button: [%s]"                            { channel="nuvo:amplifier:nuvo:source6#button_press" }

Using templates

Switch                   NuvoFavorite                                                      { channel="exec:command:nuvo_playlist:run"}            

<% ('A'..'D').each do |source| -%>
<%= "String Music_Port_Source_#{source}_URL" %>
<% end -%>

Switch                   RestartMPS4                                                                                                              

Group:Switch:OR(ON, OFF) ZonePowers                                                                                                               
Group                    ZoneSources                                                                                                              


// system
Switch                   Nuvo_System_Alloff      "All Zones Off"                           { channel="nuvo:amplifier:nuvo:system#alloff" }        
Switch                   Nuvo_System_Allmute     "All Zones Mute"                          { channel="nuvo:amplifier:nuvo:system#allmute" }       
Switch                   Nuvo_System_Page        "Page All Zones"                          { channel="nuvo:amplifier:nuvo:system#page" }          

// zones
<% 1.upto(7).each do |zone| -%>
<% zone_channel = "nuvo:amplifier:nuvo:zone#{zone}" -%>
<%= %Q|Switch                   Nuvo_Z#{zone}_Power           "Power"                    (ZonePowers)   { channel="#{zone_channel}#power" }       |%>
<%= %Q|Number                   Nuvo_Z#{zone}_Source          "Source Input [%s]"        (ZoneSources)  { channel="#{zone_channel}#source" }      |%>
<%= %Q|Dimmer                   Nuvo_Z#{zone}_Volume          "Volume [%d %%]"                          { channel="#{zone_channel}#volume" }      |%>   
<%= %Q|Switch                   Nuvo_Z#{zone}_Mute            "Mute"                                    { channel="#{zone_channel}#mute" }        |%>   
<%= %Q|Number                   Nuvo_Z#{zone}_Favorite        "Favorite"                                { channel="#{zone_channel}#favorite" }    |%>   
<%= %Q|Player                   Nuvo_Z#{zone}_Control         "Control"                                 { channel="#{zone_channel}#control" }     |%>   
<%= %Q|Number                   Nuvo_Z#{zone}_Treble          "Treble Adjustment [%s]"                  { channel="#{zone_channel}#treble" }      |%>   
<%= %Q|Number                   Nuvo_Z#{zone}_Bass            "Bass Adjustment [%s]"                    { channel="#{zone_channel}#bass" }        |%>   
<%= %Q|Number                   Nuvo_Z#{zone}_Balance         "Balance Adjustment [%s]"                 { channel="#{zone_channel}#balance" }     |%>   
<%= %Q|Switch                   Nuvo_Z#{zone}_Loudness        "Loudness"                                { channel="#{zone_channel}#loudness" }    |%>   
<%= %Q|Switch                   Nuvo_Z#{zone}_Dnd             "Do Not Disturb"                          { channel="#{zone_channel}#dnd" }         |%>   
<%= %Q|Switch                   Nuvo_Z#{zone}_Lock            "Zone Locked [%s]"                        { channel="#{zone_channel}#lock" }        |%>   
<%= %Q|Switch                   Nuvo_Z#{zone}_Party           "Party Mode"                              { channel="#{zone_channel}#party" }       |%>   
<%= %>
<% end %>

// zones
<% [5,6].each do |source| -%>
<% source_channel = "nuvo:amplifier:nuvo:source#{source}" -%>
<%= %Q| String                   Nuvo_S#{source}_Display_Line1   "Track: [%s]"                             { channel="#{source_channel}#display_line1" } |%>
<%= %Q| String                   Nuvo_S#{source}_Display_Line2   "Album: [%s]"                             { channel="#{source_channel}#display_line2" } |%>
<%= %Q| String                   Nuvo_S#{source}_Display_Line3   "Artist: [%s]"                            { channel="#{source_channel}#display_line3" } |%>
<%= %Q| String                   Nuvo_S#{source}_Display_Line4   "Title: [%s]"                             { channel="#{source_channel}#display_line4" } |%>
<%= %Q| String                   Nuvo_S#{source}_Play_Mode       "Play Mode: [%s]"                         { channel="#{source_channel}#play_mode" }     |%>
<%= %Q| //Number:Time            Nuvo_S#{source}_Track_Length    "Track Length: [%s s]"                    { channel="#{source_channel}#track_length" } |%>
<%= %Q| //Number:Time            Nuvo_S#{source}_Track_Position  "Track Position: [%s s]"                  { channel="#{source_channel}#track_position" } |%>
<%= %Q| String                   Nuvo_S#{source}_Button_Press    "Button: [%s]"                            { channel="#{source_channel}#button_press" }  |%>
<%= %>
<% end %>

You may noticed the funny %Q| above. Rather than forcing you to escape double quotes with \ everywhere like other languages, ruby has an alternative syntax you can use where you can do %Q and then choose any character you want to start and end the string, so I selected ‘|’ since I don’t have a pipe anywhere in my item definitions.

Item template rendering rule

require 'openhab'
require 'erb'

ITEMS_DIR = __conf__/'items'

# Capture everything between and including the start/ending
def capture_between(name, start, ending = start)
  /(?<#{name}>#{Regexp.quote(start)}[^#{Regexp.quote(ending)}]+#{Regexp.quote(ending)})/
  # Capture name, find start, anything but the ending, then ending.  
end

def regex
  @regex ||= begin

    #Group[:itemtype[:function]] groupname ["labeltext"] [<iconname>] [(group1, group2, ...)]

    group_item = /Group(?::\w+(?::\w+(?:\(.*\))?)?)?/ # Find 'Group', maybe colon followed by word, maybe colon followed by word
                                                      # maybe open parens followed by anything and a closed parens
    item_type = /\S+/                                 # Any non whitepsace
    
    type = /(?<type>(?:#{group_item.source})|(?:#{item_type.source}))/

    name = /(?<name>[\S]+)/ # one or more non whitespace chars

    label = capture_between('label', '"')
    icon = capture_between('icon', '<', '>')
    groups = capture_between('groups', '(', ')')
    tags = capture_between('tags', '[', ']')
    binding_config = capture_between('binding_config', '{', '}')

    # itemtype itemname "labeltext [stateformat]" <iconname> (group1, group2, ...) ["tag1", "tag2", ...] {bindingconfig}
     optionals = [label, icon, groups, tags, binding_config].map do |optional|
       # zero or more whitespace 
       # maybe the optional
       /\s*#{optional.source}?/
     end.map(&:source).join('')

    # start of line
    # zero or more whitespace
    # do not match comment lines
    # type or group
    # one or more whitespace
    # all of the optionals
    # zero or more whitespace
    # end of line
    /^\s*#{type.source}\s+#{name.source}#{optionals}\s*$/
  end
end

def parse_item_line(line, maxes)
  return line.strip if line.strip.start_with? '//' #Ignore comment lines

  if (matches = regex.match(line))
    matches.named_captures.compact.each do |capture, value|
      maxes[capture.to_sym] = [maxes[capture.to_sym], value.length].max
    end
    matches
  else
    line.strip
  end
end

def format_line(line, maxes)
  return line unless line.is_a? MatchData

  # itemtype itemname "labeltext [stateformat]" <iconname> (group1, group2, ...) ["tag1", "tag2", ...] {bindingconfig}
  %i[type name label icon groups tags binding_config].map { |field| (line[field] || '').ljust(maxes[field] || 0) }.join(' ')
end

def format(string)
  maxes = Hash.new(0)
  formatted = string.lines
                    .map { |line| parse_item_line(line, maxes) }
                    .map { |line| format_line(line, maxes) }
                    .join("\n")
end

# Render a template 
# @param source template file in sitemap dir without the .erb extension
# @param variables optional list of bindings for template, if supplied template will not have access to openhab variables
def render(source, **variables)
  template = ERB.new(File.read(source), trim_mode: '-')
  variables ? template.result_with_hash(variables) : template.result 
end

rule 'Template Items' do
  watch __conf__/'items/templates/*.erb', for: [:created, :modified]
  run do |event|
    file = event.path
    logger.debug("Templating #{file}")
    items_content = format( render(file) ) 

    items_file = ITEMS_DIR/file.basename(file.extname)
    File.write(items_file, items_content)
    logger.debug("Wrote #{items_file}")
  end
end

The majority of the code is regular expressions for parsing a rendered items file and producing a file that will have all the columns line up. There is probably a better way to do that, but I suck at regular expressions… so suggestions welcome.

Going method by method:

capture_between / regex

regex generates the regular expression that can parse an item line, capture between is a regex that is reused to capture between a start and ending.

parse_item_line

This parses a line in an items file using the regex, ignoring comment lines, it also updates a hash that tracks the max length of all item fields.

format_line

If the line matched the regex, it generates a new line where each column is padded so the columns line up in the items file.

format

Ties together the line parsing with the formatting to generate the final output

render

This is the same as in the sitemap example and is the code that expands the templates into the rendered version.

‘Template Items’ rule

This is executed via the watch trigger whenever any file in the templates subdirectory of items is created or modified and then renders, formats and writes the output to a file in the items directory.

1 Like

Learnt something new about ruby object reference