Class: LatexTools::LatexTable

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

Overview

The LatexTable class represents a table in Latex. It provides multiple means of creating, formatting, and outputting Latex tables.

Basic Examples

The easiest way to create tables programmatically is to use the #<< method.

:include:examples/table/example1.rb

This produces

:include:examples/table/example1.rb.out

More documentation to come in the future, but hopefully this is enough to get you started.

Defined Under Namespace

Classes: Cline, MultiColumn, Row

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(*args) ⇒ LatexTable

Returns a new instance of LatexTable.



130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
# File 'lib/latex_table.rb', line 130

def initialize(*args)
  @col_dividers = Array.new
  @v_bordered = false
  @h_borders = 0
  @auto_add_columns = false
  @format = Hash.new{ Array.new }
  @strict = true
  case args.size
    when 0
      @rows = 0
      @columns = 0
      @data = Array.new
      add_row(:provisional)
    when 1
      arg = args.shift
      if(arg.kind_of?(Integer))
        @columns = arg
        @rows = 0
        @data = Array.new
        add_row(:provisional)
      else
        raise TypeError, "Invalid argument type in LatexTable#initialize"
      end
    else
      raise ArgumentError, "Invalid argument count"
  end
end

Instance Attribute Details

#auto_add_columnsObject

Returns the value of attribute auto_add_columns.



48
49
50
# File 'lib/latex_table.rb', line 48

def auto_add_columns
  @auto_add_columns
end

#col_dividerObject

Returns the value of attribute col_divider.



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

def col_divider
  @col_divider
end

#col_dividersObject

Returns the value of attribute col_dividers.



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

def col_dividers
  @col_dividers
end

#columnsObject (readonly)

Returns the value of attribute columns.



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

def columns
  @columns
end

#float_number_formatObject

Returns the value of attribute float_number_format.



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

def float_number_format
  @float_number_format
end

#formatObject (readonly)

Returns the value of attribute format.



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

def format
  @format
end

#h_bordersObject (readonly)

Returns the value of attribute h_borders.



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

def h_borders
  @h_borders
end

#rowsObject (readonly)

Returns the value of attribute rows.



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

def rows
  @rows
end

#strictObject

Returns the value of attribute strict.



48
49
50
# File 'lib/latex_table.rb', line 48

def strict
  @strict
end

#v_borderedObject (readonly)

Returns the value of attribute v_bordered.



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

def v_bordered
  @v_bordered
end

#v_double_borderedObject (readonly)

Returns the value of attribute v_double_bordered.



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

def v_double_bordered
  @v_double_bordered
end

Instance Method Details

#<<(element) ⇒ Object



335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
# File 'lib/latex_table.rb', line 335

def << (element)
  if(element == :endl)
    add_row(:provisional)
  elsif(element.kind_of?(Cline))
    lastnon = _last_non_provisional_row
    if(lastnon && lastnon.tag != :cline && @data.last.tag != :provisional)
      raise "Invalid cline addition:  Can't add a cline to a row that already has non-cline content.  Use #add_row or #<<(:endl)"
    end
    self.c_line(element.begin_col, element.end_col)
  elsif(element == :hline || element == :h_line)
    h_line
  else
    add_element(element)
  end
  return self
end

#add_borderObject Also known as: add_borders



483
484
485
486
# File 'lib/latex_table.rb', line 483

def add_border
  add_h_border
  add_v_border
end

#add_columnObject



276
277
278
279
280
281
282
283
# File 'lib/latex_table.rb', line 276

def add_column
  @columns = @columns + 1
  if(!@col_dividers.empty?)
    border = @col_dividers.pop
    @col_dividers.push(@col_divider.nil? ? "" : @col_divider)
    @col_dividers.push(border)
  end
end

#add_element(element) ⇒ Object



321
322
323
324
325
326
327
328
329
330
331
332
333
# File 'lib/latex_table.rb', line 321

def add_element(element)
  _cline_check
  _provisional_remove

  @data.last.push(element)
  if(@data.last.size > @columns)
    if(@auto_add_columns)
      add_column
    else
      _cant_add_column("add_element")
    end
  end
end

#add_element_spanning(num, text, alignment = :c) ⇒ Object

Raises:

  • (TypeError)


307
308
309
310
311
312
313
314
315
316
317
318
319
# File 'lib/latex_table.rb', line 307

def add_element_spanning(num, text, alignment = :c)
  _cline_check
  _provisional_remove
  raise TypeError.new unless num.kind_of?(Integer) || num == :fill
  if(@data.last.num_columns + num >= @columns)
    if(@auto_add_columns)
      @columns.upto(@data.last.num_columns + num - 1) { add_column }
    else
      _cant_add_column("add_element_spanning")
    end
  end
  @data.last.push(MultiColumn.new(num, alignment, text))
end

#add_element_spanning_to_end(text, alignment = :c) ⇒ Object



300
301
302
303
304
305
# File 'lib/latex_table.rb', line 300

def add_element_spanning_to_end(text, alignment = :c)
  _cline_check
  _provisional_remove
  @data.last.push(MultiColumn.new(:fill, alignment, text))
  add_row(:provisional)
end

#add_h_borderObject



479
480
481
# File 'lib/latex_table.rb', line 479

def add_h_border
  @h_borders = @h_borders + 1
end

#add_row(tag = nil) ⇒ Object



243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
# File 'lib/latex_table.rb', line 243

def add_row(tag = nil)
  if(@strict)
    spot = @rows - 1
    lastrow = nil
    lastrow = @data[spot] if spot >= 0
    skip_tags = [:hline,:cline,:provisional]
    while(lastrow && skip_tags.include?(lastrow.tag))
      spot -= 1
      if(spot >= 0)
        lastrow = @data[spot]
      else
        lastrow = nil
      end
    end
    ncols = nil
    if(lastrow && (ncols = lastrow.num_columns) != @columns && ncols != -1)
      last_non = _last_non_provisional_row
      unless(last_non && last_non.tag == :cline && @auto_add_columns && lastrow.num_columns < last_non.num_columns)
        raise RuntimeError, "Tried to add new row when previous row had #{ncols} columns which is not the same as #{@columns} columns.  Turn #strict off to ignore this, although your latex output may not compile."
      end
    end
  end
  add = !_provisional_remove
  if(add)
    @data.push(Row.new(tag))
  else
    @data.last.tag = tag
  end
  unless(tag == :provisional)
    @rows += 1 if(add)
  end
end

#add_spanning_row(text, alignment = :c) ⇒ Object



285
286
287
288
289
290
291
292
293
294
295
296
297
298
# File 'lib/latex_table.rb', line 285

def add_spanning_row(text, alignment = :c)
  _cline_check
  tmp = nil
  add = !(_provisional_remove)
  if(!add)
    tmp = @data.last
  else
    tmp = Row.new
    @rows += 1
    @data.push(tmp)
  end
  tmp.push(MultiColumn.new(:fill, alignment, text))
  add_row(:provisional)
end

#add_v_borderObject



447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
# File 'lib/latex_table.rb', line 447

def add_v_border
  if(@v_bordered)
    add_v_double_border
  elsif(@col_dividers.empty?)
    @col_dividers[0] = "|"
    1.upto(@columns - 1) do |i|
      @col_dividers[i] = @col_divider.nil? ? " " : @col_divider
    end
    @col_dividers[@columns] = "|"
  else
    @col_dividers[0] = "|"
    @col_dividers[@columns] = "|"
  end
  @v_bordered = true
end

#add_v_double_borderObject Also known as: add_double_v_border



463
464
465
466
467
468
469
470
471
472
473
474
475
476
# File 'lib/latex_table.rb', line 463

def add_v_double_border
  raise "Too many vertical borders.  A maximum of two is allowed" if @v_bordered && @col_dividers[0] == "||"
  if(@col_dividers.empty?)
    @col_dividers[0] = "||"
    1.upto(@columns - 1) do |i|
      @col_dividers[i] = @col_divider.nil? ? '' : @col_divider
    end
    @col_dividers[@columns] = "||"
  else
    @col_dividers[0] = "||"
    @col_dividers[@columns] = "||"
  end
  @v_double_bordered = true
end

#c_line(begincol, endcol) ⇒ Object Also known as: cline

This method ends the current row NOTE that the numbering is 1 based, just as in Latex itself



410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
# File 'lib/latex_table.rb', line 410

def c_line(begincol, endcol)
  last_row = _last_non_provisional_row
  if(last_row.nil? || last_row.tag != :cline)
    add_row(:cline)
  end
  last_row = _last_non_provisional_row

  last_element = last_row.last
  if(last_element)
    if(last_element.end_col >= begincol)
      raise ArgumentError, "Overlapping clines.  Check the start of the LatexTable#cline call in your code and the end of the previous call"
    end
  end
  if(endcol > @columns)
    if(@auto_add_columns)
      (@columns + 1).upto(endcol) { add_column }
    else
      _cant_add_column("c_line")
    end
  end

  if(begincol < 1)
    raise "Invalid cline specification (Begin column less than 1).  Note that the cline column specification is one-based, just as in Latex"
  end

  last_row.push(Cline.new(begincol, endcol))
end

#h_lineObject Also known as: hline

This method ends the current row



402
403
404
405
# File 'lib/latex_table.rb', line 402

def h_line
  add_row(:hline)
  add_row(:provisional)
end

#tabular_stringObject



158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
# File 'lib/latex_table.rb', line 158

def tabular_string
  ret_val = ""
  unless(@col_dividers.empty?)
    ret_val += @col_dividers[0]
  end
  1.upto(@columns) do |i|
    ret_val += "c"
    if(@col_dividers.empty?)
      unless(@col_divider.nil? || i == @columns)
        ret_val += @col_divider
      end
    else
      ret_val += @col_dividers[i]
    end
  end
  return ret_val
end

#to_latex(fontsize = "") ⇒ Object



176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
# File 'lib/latex_table.rb', line 176

def to_latex(fontsize = "")
  ret_val = ""
  ret_val = ret_val + "\\begin{table}#{fontsize}\n  \\begin{tabular}{"
  ret_val += tabular_string
  ret_val = ret_val + "}\n"
  1.upto(@h_borders) { ret_val = ret_val + "    \\hline\n" }
  ret_val += "    "
  ret_val += to_latex_fragment
  if(@h_borders != 0)
    ret_val += "\\\\"
  end
  1.upto(@h_borders) { ret_val = ret_val + "    \n \\hline" }
  ret_val = ret_val + "\n  \\end{tabular}\n"
  ret_val = ret_val + "\\end{table}\n"
  ret_val
end

#to_latex_fragmentObject



193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
# File 'lib/latex_table.rb', line 193

def to_latex_fragment
  ret_val = ""
  indent = "    "
  @data.each_with_index do |row, row_num|
    cols_so_far = 0
    if(row.tag == :hline)
      ret_val = ret_val + "\\hline"
      ret_val += " \n" + indent unless row_num == @rows - 1
    elsif(row.tag == :cline)
      row.each do |cline|
        ret_val += "\\cline{" + cline.begin_col.to_s + "-" + cline.end_col.to_s + "}  "
      end
      ret_val += " \n" + indent unless row_num == @rows - 1
    elsif(row.tag == :provisional)
      raise RuntimeError, "Programmer needs more coffee: Unhandled provisional" unless row_num == @data.size - 1
    else
      row.each_with_index do |entry, index|
        if(entry)
          content = entry.kind_of?(MultiColumn) ? entry.content : entry
          if(!@format[row_num].nil? && !@format[row_num][index].nil? && content.respond_to?(:to_f))
            content = @format[row_num][index] % content.to_f
          elsif(content.respond_to?(:to_f) && (content.to_f.to_s == content.to_s || content.to_i.to_s == content.to_s) && !@float_number_format.nil?)
            content = @float_number_format % content.to_f
          end
          val = content

          if(entry.kind_of?(MultiColumn))
            if(entry.width == :fill)
              val = "\\multicolumn{#{@columns - cols_so_far}}{#{entry.alignment.to_s}}{#{val}}"
              raise "Columns spanning to the end must be the last entry in a row." unless entry === row.last
              cols_so_far = @columns
            else
              val = "\\multicolumn{#{entry.width}}{#{entry.alignment.to_s}}{#{val}}"
              cols_so_far += entry.width
            end
          else
            cols_so_far += 1
          end

          ret_val = ret_val + val.to_s + ((cols_so_far == @columns) ? _end_of_line(row_num, indent) : " & ")
        end
      end
      (cols_so_far + 1).upto(@columns) do |index|
        ret_val = ret_val + " " + ((index == @columns) ? _end_of_line(row_num, indent) : " & ")
      end
    end
  end
  return ret_val
end

#to_sObject



439
440
441
# File 'lib/latex_table.rb', line 439

def to_s
  to_latex
end

#to_strObject



443
444
445
# File 'lib/latex_table.rb', line 443

def to_str
  to_latex
end