class LineTree

Attributes

to_a[R]

Public Class Methods

new(raw_s, level: nil, ignore_non_element: true, ignore_blank_lines: true, ignore_label: false, ignore_newline: true, root: nil, debug: false) click to toggle source
# File lib/line-tree.rb, line 26
def initialize(raw_s, level: nil, ignore_non_element: true, 
               ignore_blank_lines: true, ignore_label: false, 
               ignore_newline: true, root: nil, debug: false)
  
  
  puts 'inside linetree'.info if @debug
  
  @root = root
  s =  raw_s
  
  @ignore_non_element = ignore_non_element
  @ignore_label = ignore_label
  @ignore_blank_lines = ignore_blank_lines
  @ignore_newline = ignore_newline
  @debug = debug
  
  lines = ignore_blank_lines ? s.gsub(/^ *$\n/,'') : s
  puts ('lines : ' + lines.inspect).debug if @debug
  @to_a = scan_shift(lines.lstrip, level)
  
end

Public Instance Methods

make_tree_list(a) click to toggle source
# File lib/line-tree.rb, line 85
def make_tree_list(a)
  
  items = a.inject([]) do |r,x|    
    
    if x.is_a? Array then
      r << make_tree_list(x)
    else
      r + ['item', {title: x}]
    end
  end

end
to_doc(encapsulate: false) click to toggle source
# File lib/line-tree.rb, line 48
def to_doc(encapsulate: false)    
  
  a = @to_a
  
  a2 = if a[0].is_a? Array then      
    encapsulate ? encap(a) : scan_a(a)
  else
    puts 'before scan_a' if @debug
    scan_a(*a)
  end

  
  
  a3 = @root ? a2.unshift(@root, {}) : a2.flatten(1)
    
  puts 'a3: ' + a3.inspect if @debug  

  Rexle.new(a3)
  
end
to_h() click to toggle source
# File lib/line-tree.rb, line 69
def to_h()
  build_h(@to_a)
end
to_html(numbered: false) click to toggle source
# File lib/line-tree.rb, line 73
def to_html(numbered: false)
  
  @numbered = numbered
  s = "<ul>%s</ul>" % make_html_list(@to_a)
  puts ('s: ' + s.inspect).debug if @debug
  puts s if @debug
  Rexle.new(s).xml declaration: false
  
end
to_tree() click to toggle source
# File lib/line-tree.rb, line 83
def to_tree()
  
  def make_tree_list(a)
    
    items = a.inject([]) do |r,x|    
      
      if x.is_a? Array then
        r << make_tree_list(x)
      else
        r + ['item', {title: x}]
      end
    end

  end

  a = make_tree_list(@to_a)
  doc = Rexle.new(['tree', {}, *a])
  doc.xml    
  
end
to_xml(options={}) click to toggle source
# File lib/line-tree.rb, line 104
def to_xml(options={})
  to_doc.xml(options)
end

Private Instance Methods

build_h(a) click to toggle source
# File lib/line-tree.rb, line 110
def build_h(a)

  a.inject({}) do |r,x|

    h2 = if x.is_a? Array and x.length > 1 then

      {x[0] => {summary: {}, body: build_h(x[1..-1]) } }

    else

      {x[0] => {summary: {}}}
    end

    r.merge(h2)

  end
end
encap(a) click to toggle source
# File lib/line-tree.rb, line 128
def encap(a)
      
  a.each do |node|

    puts 'node: ' + node.inspect if @debug
    
    encap node[1..-1] if node[1].is_a? Array
    
    if node.is_a? Array then
      val = node[0]
      node.insert 1, {}, val
      node[0] = 'entry'
    end

  end
      
  if a.first.is_a? String then
    val = a[0]
    a.insert 1, {}, val
    a[0] = 'entry'
  end
  
  a

end
get_attributes(s) click to toggle source
# File lib/line-tree.rb, line 308
def get_attributes(s)
  
  a = s[1..-2].split(/(\w+:)/)[1..-1].each_slice(2).map do |label, val|
    [label[0..-2], val.strip.sub(/^['"]/,'').sub(/['"]$/,'')]
  end    

  Hash[*a.flatten]
end
get_xml_attributes(raw_attributes) click to toggle source
# File lib/line-tree.rb, line 317
def get_xml_attributes(raw_attributes)
  
  r1 = /([\w\-:]+\='[^']*)'/
  r2 = /([\w\-:]+\="[^"]*)"/
  
  r =  raw_attributes.scan(/#{r1}|#{r2}/).map(&:compact).flatten.inject({}) do |r, x|
    attr_name, val = x.split(/=/,2) 
    r.merge(attr_name.to_sym => val[1..-1])
  end

  return r
end
make_html_list(a, indent=-1, count=nil) click to toggle source
# File lib/line-tree.rb, line 154
def make_html_list(a, indent=-1, count=nil)

  puts 'inside make_html_list'.info if @debug
  
  items = a.map.with_index do |x, i|    
    
    puts ('x:'  + x.inspect).debug if @debug
    
    if x.is_a? Array then

      id, head, tail = if count then 
       
        [
          count.to_s + '.' + i.to_s, 
          i == 1 ? "<ul>\n" : '', 
          i == a.length - 1 ? "\n</ul>\n</li>" : ''
        ]

      else
        [i+1, '', '']
      end

      head + make_html_list(x, indent+1, id) + tail
      
    else

      #"%s%s %s" % ['  ' * indent, count, x]
      r = if @numbered then
        "%s<li id='n%s'>%s" % ['  ' * indent, count.to_s.gsub('.','-'), x]
      else
        "%s<li>%s" % ['  ' * indent, x]
      end
      
      i == 1 ? "<ul>" + r  : i == a.length - 1 ? r + "</li>" : r + ""

    end

  end

  items.join("\n")

end
parse_node(s) click to toggle source
# File lib/line-tree.rb, line 330
def parse_node(s)
  
  r = s.match(/('[^']+[']|[^ ]+) *(\{.*\})? *(.*)/m)
                                              .captures.values_at(0,1,-1)

  if r[1] then
    
    r[1] = get_attributes(r[1])
    
  elsif s[/(\w+ *= *["'])/]
    
    raw_attributes, value = s.split(/(?=[^'"]+$)/,2)
    r[1] = get_xml_attributes raw_attributes
    r[-1] = value.to_s.strip

  end      
  
  r
end
scan_a(a) click to toggle source
# File lib/line-tree.rb, line 261
def scan_a(a)
  
  puts 'a: ' + a.inspect if @debug    
  
  a.each do |node|
    
    puts 'node: ' + node.inspect if @debug
    
    if node.is_a? Array then      
      if node[1].is_a?(Array) and node[1][0] =~ /^<\w+/ then

        r = parse_node(node[0])
        node[0] = r[0]
        node[2] = node[1][0]
        node[1] = r[1]

      else
        
        scan_a node[1..-1] if node[1..-1].is_a?(Array)
      
        puts 'node2: ' + node.inspect if @debug

        r = parse_node(node[0])
        node[0] = r[0]; node.insert 1, r[1], r[2]        

      end
    end
  end
      
  if a.first.is_a? String then
    
    s = a[0]
    
    if @ignore_non_element then
      non_element = s[/^ *(\w+:)/,1]    
      return [nil,non_element] if non_element
    end      
    
    r = parse_node(s)
    a[0] = r[0]; a.insert 1, r[1], r[2]        
  end
  
  a

end
scan_shift(lines, level=nil) click to toggle source
# File lib/line-tree.rb, line 198
def scan_shift(lines, level=nil)

  level -= 1 if level

  return [] if lines.strip.empty?
  a = lines.split(/(?=^\S+)/)

  return [a] if a.length <= 1 and a.first.strip.empty?
  
  a.map do |x|      

    puts 'x: ' + x.inspect if @debug
    
    #jr240521 x.sub!(/ *$/,'')
    
    if @ignore_label == true or not x[/.*/][/^ *\w+:\S+/] then

      rlines = if @ignore_newline then
        x.lines.map {|x| x.sub(/(.)\n$/,'\1') }
      else
        x.lines
      end
    
      rlines = [x.gsub(/^ {2}/,'')] if level and level < 0

      label = [rlines.shift]
      new_lines = rlines.map{|x| x.sub(/^ {2}/,'')}

      if new_lines.length > 1 then
        separator = @ignore_newline ? "\n" : ''
        label + scan_shift(new_lines.join(separator),level)           

      else          

        #label = [] if label == ["\n"]
        
        if (new_lines.length > 0 and new_lines != [nil]) then
          
          if label == ["\n"] then
            [new_lines]
          else
            label + [new_lines]
          end
        else
          label
        end
      end
      
    else
      
      puts 'chomp' if @debug
      puts 'level: ' + level.inspect if @debug
      
      if level and level < 1 then
        [x]
      else
        [x.lines.map{|x| x.sub(/^ {2}/,'').chomp }.join]
      end
    end
  end

end