class DOST::Data
Attributes
headers_delimiters[R]
key_modifier[R]
lines[R]
values_delimiters[R]
Public Class Methods
new(lines:, headers_delimiters:, values_delimiters:, key_modifier: nil)
click to toggle source
# File lib/dost.rb, line 5 def initialize(lines:, headers_delimiters:, values_delimiters:, key_modifier: nil) @lines = lines.map(&:chomp) @headers_delimiters = headers_delimiters @values_delimiters = values_delimiters @key_modifier = key_modifier end
Public Instance Methods
dynamic_offseted_values(left_dynamic_bound_headers = [])
click to toggle source
# File lib/dost.rb, line 20 def dynamic_offseted_values(left_dynamic_bound_headers = []) values_lines.map do |line| headers.reverse.map do |(name, range)| is_dynamic = left_dynamic_bound_headers.include?(name) str = line[range] if is_dynamic && range.first > 0 i = range.first - 1 while present?(line[i]) && i >= 0 do str.prepend(line[i]) line[i] = ' ' i -= 1 end end [name, str.strip] end.reverse.to_h end end
headers()
click to toggle source
# File lib/dost.rb, line 12 def headers @headers ||= parse_headers end
values()
click to toggle source
# File lib/dost.rb, line 16 def values @values ||= parse_values end
Private Instance Methods
blank?(str)
click to toggle source
# File lib/dost.rb, line 119 def blank?(str) str !~ /[^[:space:]]/ end
calc_ranges(header_line)
click to toggle source
# File lib/dost.rb, line 77 def calc_ranges(header_line) header_line.split(%r{(^\s*\S*\s*)|(\S*\s*)}).reject(&:empty?).reduce([]) do |acc, key| index = acc.last&.last&.last || -1; acc.push([key, (index + 1)..(index + key.length)]) end end
delimiter?(line)
click to toggle source
# File lib/dost.rb, line 111 def delimiter?(line) line.chars.uniq.count == 1 && present?(delimiter_char(line)) end
delimiter_char(line)
click to toggle source
# File lib/dost.rb, line 115 def delimiter_char(line) line.chars.uniq.first end
header_lines()
click to toggle source
# File lib/dost.rb, line 88 def header_lines lines_between_delimiters(headers_delimiters.first, headers_delimiters.last) end
lines_between_delimiters(delimiter_start, delimiter_end)
click to toggle source
# File lib/dost.rb, line 92 def lines_between_delimiters(delimiter_start, delimiter_end) lines.reduce([]) do |acc, line| if acc.empty? acc.push(line) if delimiter?(line) && delimiter_char(line) == delimiter_start else if delimiter?(line) if delimiter_char(line) == delimiter_end return acc[1..-1] else acc = [line] end else acc.push(line) end end acc end end
modify_key(key)
click to toggle source
# File lib/dost.rb, line 132 def modify_key(key) key_modifier.nil? ? keyа : key_modifier.call(key) end
overlaps?(orig, other)
click to toggle source
from apidock.com/rails/Range/overlaps
# File lib/dost.rb, line 128 def overlaps?(orig, other) orig.cover?(other.first) || other.cover?(orig.first) end
parse_headers()
click to toggle source
# File lib/dost.rb, line 38 def parse_headers raw_headers = header_lines.map { |header_line| calc_ranges(header_line) } first_row = raw_headers.first second_row = raw_headers[1] first_row.map.with_index do |(first_key, first_range)| values_inside = second_row.select do |(second_key, second_range)| overlaps?( ((second_range.first + second_key.index(/(\S)/))..(second_key.strip.length + second_range.first)), (first_range.first..(first_key.strip.length + first_range.first)) ) end if values_inside.empty? [[modify_key(first_key), first_range]] else values_inside.map.with_index do |(second_item_key, second_item_range), index| key = (first_key.strip + second_item_key.strip.prepend('_')) is_last_item = (index == values_inside.count - 1) second_item_left_bound = second_item_range.first + second_item_key.index(/(\S)/) left_bound = index.zero? ? [second_item_left_bound, first_range.first].min : second_item_range.first right_bound = is_last_item ? [second_item_range.last, first_range.last].min : second_item_range.last range = left_bound..right_bound [modify_key(key), range] end end end.flatten(1) end
parse_values()
click to toggle source
# File lib/dost.rb, line 69 def parse_values values_lines.map do |line| headers.map do |(name, range)| [name, line[range].strip] end.to_h end end
present?(str)
click to toggle source
# File lib/dost.rb, line 123 def present?(str) !blank?(str) end
values_lines()
click to toggle source
# File lib/dost.rb, line 84 def values_lines lines_between_delimiters(values_delimiters.first, values_delimiters.last) end