Class: BoxLayout

Inherits:
Object
  • Object
show all
Defined in:
lib/box_layout.rb

Constant Summary collapse

VERSION =
'1.0.0'

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeBoxLayout

Returns a new instance of BoxLayout.



35
36
37
38
# File 'lib/box_layout.rb', line 35

def initialize
  @grid = []
  @boxes = []
end

Instance Attribute Details

#boxesObject (readonly)

Returns the value of attribute boxes.



34
35
36
# File 'lib/box_layout.rb', line 34

def boxes
  @boxes
end

#gridObject (readonly)

Returns the value of attribute grid.



34
35
36
# File 'lib/box_layout.rb', line 34

def grid
  @grid
end

Class Method Details

.html(str) ⇒ Object



28
29
30
31
32
# File 'lib/box_layout.rb', line 28

def self.html(str)
  layout = self.new
  layout.parse(str)
  layout.to_s
end

Instance Method Details

#[](x, y) ⇒ Object

Rendering and parsing tables.



119
120
121
# File 'lib/box_layout.rb', line 119

def [](x, y)
  grid[y][x].chr rescue " "
end

#box_bottom(x, y) ⇒ Object



131
132
133
134
135
136
137
# File 'lib/box_layout.rb', line 131

def box_bottom(x, y)
  # todo: find
  (y..grid.size).each do |bottom|
    return bottom if self[x + 1, bottom + 1] == '-'
  end
  raise "Unterminated box. c=#{self[x, y].inspect}"
end

#box_colspansObject



95
96
97
98
99
100
101
102
103
104
105
106
# File 'lib/box_layout.rb', line 95

def box_colspans
  colspans = Hash.new(0)
  boxes.each do |box| colspans[box] = 0 end

  box_x_delimeters.each do |delim|
    boxes.each do |box|
      colspans[box] += 1 if box.x < delim and box.right >= delim
    end
  end

  colspans
end

#box_right(x, y) ⇒ Object



123
124
125
126
127
128
129
# File 'lib/box_layout.rb', line 123

def box_right(x, y)
  # todo: find
  (x..grid[y+1].size).each do |right|
    return right if self[right + 1, y + 1] == '|'
  end
  raise "Unterminated box. c=#{self[x, y].inspect}"
end

#box_rowsObject



108
109
110
111
112
113
114
115
# File 'lib/box_layout.rb', line 108

def box_rows
  rows, boxes_left = [], boxes.uniq
  box_y_delimeters.each do |delim|
    boxes_in_row, boxes_left = boxes_left.partition { |box| box.y < delim }
    rows.push(boxes_in_row.sort_by { |box| box.x })
  end
  rows
end

#box_rowspansObject



82
83
84
85
86
87
88
89
90
91
92
93
# File 'lib/box_layout.rb', line 82

def box_rowspans
  rowspans = Hash.new(0)
  boxes.each do |box| rowspans[box] = 0 end

  box_y_delimeters.each do |delim|
    boxes.each do |box|
      rowspans[box] += 1 if box.y < delim and box.bottom >= delim
    end
  end

  rowspans
end

#box_x_delimetersObject



74
75
76
# File 'lib/box_layout.rb', line 74

def box_x_delimeters
  boxes.map { |box| box.right }.uniq.sort
end

#box_y_delimetersObject



78
79
80
# File 'lib/box_layout.rb', line 78

def box_y_delimeters
  boxes.map { |box| box.bottom }.uniq.sort
end

#parse(str) ⇒ Object



40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/box_layout.rb', line 40

def parse(str)
  @grid = str.strip.split(/\n/)
  @boxes = [] # in case some dork is calling parse multiple times

  grid.size.times do |y|
    grid[y].size.times do |x|
      if %w(- |).include? self[x, y] and
          self[x, y + 1] == '|' and
          self[x + 1, y] == '-' then
        boxes << Box.new(x, y, box_right(x, y), box_bottom(x, y))
      end
    end
  end
  return boxes
end

#parse_ascii_table(table) ⇒ Object



139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
# File 'lib/box_layout.rb', line 139

def parse_ascii_table(table)
  grid = table.strip.split(/\n/)
  boxes = []

  grid.size.times do |y|
    grid[y].size.times do |x|
      if %w(- |).include? self[x, y] and
          self[x, y + 1] == '|' and
          self[x + 1, y] == '-' then
        boxes << Box.new(x, y, box_right(x, y), box_bottom(x, y))
      end
    end
  end
  return boxes
end

#to_sObject



56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/box_layout.rb', line 56

def to_s
  rowspans, colspans = box_rowspans, box_colspans
  table = "<table border=\"border\">\n"
  box_rows.each do |row|
    table += "  <tr>\n"
    row.each do |box|
      r, c = rowspans[box], colspans[box]
      table += "    <td"
      table += " rowspan=\"%d\"" % r if r > 1
      table += " colspan=\"%d\"" % c if c > 1
      table += ">%s</td>\n"
    end
    table += "  </tr>\n"
  end
  table += "</table>"
  table
end