Class: Archieml::Loader
- Inherits:
-
Object
- Object
- Archieml::Loader
- Defined in:
- lib/archieml/loader.rb
Constant Summary collapse
- NEXT_LINE =
/.*((\r|\n)+)/
- START_KEY =
/^\s*([A-Za-z0-9\-_\.]+)[ \t\r]*:[ \t\r]*(.*(?:\n|\r|$))/
- COMMAND_KEY =
/^\s*:[ \t\r]*(endskip|ignore|skip|end)/i
- ARRAY_ELEMENT =
/^\s*\*[ \t\r]*(.*(?:\n|\r|$))/
- SCOPE_PATTERN =
/^\s*(\[|\{)[ \t\r]*([A-Za-z0-9\-_\.]*)[ \t\r]*(?:\]|\})[ \t\r]*.*?(\n|\r|$)/
Instance Method Summary collapse
- #flush_buffer! ⇒ Object
- #flush_buffer_into(key, options = {}) ⇒ Object
- #flush_scope! ⇒ Object
-
#format_value(value, type) ⇒ Object
type can be either :replace or :append.
-
#initialize ⇒ Loader
constructor
A new instance of Loader.
- #load(stream) ⇒ Object
- #parse_array_element(value) ⇒ Object
- #parse_command_key(command) ⇒ Object
- #parse_scope(scope_type, scope_key) ⇒ Object
- #parse_start_key(key, rest_of_line) ⇒ Object
Constructor Details
#initialize ⇒ Loader
Returns a new instance of Loader.
10 11 12 13 14 15 16 17 18 19 20 |
# File 'lib/archieml/loader.rb', line 10 def initialize @data = @scope = {} @buffer_scope = @buffer_key = nil @buffer_string = '' @is_skipping = false @done_parsing = false self.flush_scope! end |
Instance Method Details
#flush_buffer! ⇒ Object
133 134 135 136 137 |
# File 'lib/archieml/loader.rb', line 133 def flush_buffer! result = @buffer_string.dup @buffer_string = '' return result end |
#flush_buffer_into(key, options = {}) ⇒ Object
139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 |
# File 'lib/archieml/loader.rb', line 139 def flush_buffer_into(key, = {}) value = self.flush_buffer! if [:replace] value = self.format_value(value, :replace).sub(/^\s*/, '') @buffer_string = value.match(/\s*\Z/)[0] else value = self.format_value(value, :append) end if key.class == Array key[key.length - 1] = '' if [:replace] key[key.length - 1] += value.sub(/\s*\Z/, '') else key_bits = key.split('.') @buffer_scope = @scope key_bits[0...-1].each do |bit| @buffer_scope[bit] = {} if @buffer_scope[bit].class == String # reset @buffer_scope = @buffer_scope[bit] ||= {} end @buffer_scope[key_bits.last] = '' if [:replace] @buffer_scope[key_bits.last] += value.sub(/\s*\Z/, '') end end |
#flush_scope! ⇒ Object
167 168 169 |
# File 'lib/archieml/loader.rb', line 167 def flush_scope! @array = @array_type = @array_first_key = nil end |
#format_value(value, type) ⇒ Object
type can be either :replace or :append. If it’s :replace, then the string is assumed to be the first line of a value, and no escaping takes place. If we’re appending to a multi-line string, escape special punctuation by prepending the line with a backslash. (:, [, {, *, ) surrounding the first token of any line.
177 178 179 180 181 182 183 184 185 186 |
# File 'lib/archieml/loader.rb', line 177 def format_value(value, type) value.gsub!(/(?:^\\)?\[[^\[\]\n\r]*\](?!\])/, '') # remove comments value.gsub!(/\[\[([^\[\]\n\r]*)\]\]/, '[\1]') # [[]] => [] if type == :append value.gsub!(/^(\s*)\\/, '\1') end value end |
#load(stream) ⇒ Object
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
# File 'lib/archieml/loader.rb', line 22 def load(stream) stream.each_line do |line| return @data if @done_parsing if match = line.match(COMMAND_KEY) self.parse_command_key(match[1].downcase) elsif !@is_skipping && (match = line.match(START_KEY)) && (!@array || @array_type != 'simple') self.parse_start_key(match[1], match[2] || '') elsif !@is_skipping && (match = line.match(ARRAY_ELEMENT)) && @array && @array_type != 'complex' self.parse_array_element(match[1]) elsif !@is_skipping && match = line.match(SCOPE_PATTERN) self.parse_scope(match[1], match[2]) else @buffer_string += line end end self.flush_buffer! return @data end |
#parse_array_element(value) ⇒ Object
69 70 71 72 73 74 75 76 77 78 79 80 81 |
# File 'lib/archieml/loader.rb', line 69 def parse_array_element(value) self.flush_buffer! @array_type ||= 'simple' # Ignore simple array elements inside complex arrays return if @array_type == 'complex' @array << '' @buffer_key = @array @buffer_string = value self.flush_buffer_into(@array, replace: true) end |
#parse_command_key(command) ⇒ Object
83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 |
# File 'lib/archieml/loader.rb', line 83 def parse_command_key(command) if @is_skipping && !%w(endskip ignore).include?(command) return self.flush_buffer! end case command when "end" self.flush_buffer_into(@buffer_key, replace: false) if @buffer_key return when "ignore" return @done_parsing = true when "skip" @is_skipping = true when "endskip" @is_skipping = false end self.flush_buffer! end |
#parse_scope(scope_type, scope_key) ⇒ Object
106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 |
# File 'lib/archieml/loader.rb', line 106 def parse_scope(scope_type, scope_key) self.flush_buffer! self.flush_scope! if scope_key == '' @scope = @data elsif %w([ {).include?(scope_type) key_scope = @data key_bits = scope_key.split('.') key_bits[0...-1].each do |bit| key_scope = key_scope[bit] ||= {} end if scope_type == '[' @array = key_scope[key_bits.last] ||= [] if @array.length > 0 @array_type = @array.first.class == String ? 'simple' : 'complex' end elsif scope_type == '{' @scope = key_scope[key_bits.last] ||= {} end end end |
#parse_start_key(key, rest_of_line) ⇒ Object
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
# File 'lib/archieml/loader.rb', line 47 def parse_start_key(key, rest_of_line) self.flush_buffer! if @array @array_type ||= 'complex' # Ignore complex keys inside simple arrays return if @array_type == 'simple' if [nil, key].include?(@array_first_key) @array << (@scope = {}) end @array_first_key ||= key end @buffer_key = key @buffer_string = rest_of_line self.flush_buffer_into(key, replace: true) end |