1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
|
module DBI
module Utils
# Formats a resultset in a textual table, suitable for printing.
module TableFormatter
def self.coerce(obj) # :nodoc:
# FIXME this is probably short-sighted.
obj = "NULL" if obj.nil?
obj = (obj.kind_of?(Array) or obj.kind_of?(Hash)) ? obj.inspect : obj.to_s
return obj
end
# Perform the formatting.
#
# * +header+: table headers, as you'd expect they correspond to each column in the row.
# * +rows+: array of array (or DBI::Row) which represent the data.
# * +header_orient+: jusification of the header. :left, :right, or :center.
# * +rows_orient+: justification of the rows. same as +header_orient+.
# * +indent+: number of spaces to indent each line in the output.
# * +cellspace+: number of spaces to pad the cell on the left and right.
# * +pagebreak_after+: introduce a pagebreak each +n+ rows.
# * +output+: object that responds to `<<` which will contain the output. Default is STDOUT.
#
# If a block is provided, +output+ will be yielded each row if
# +pagebreak+ is nil, otherwise it will be yielded when the output
# is complete.
#--
# TODO: add a nr-column where the number of the column is shown
#++
def self.ascii(header,
rows,
header_orient=:left,
rows_orient=:left,
indent=2,
cellspace=1,
pagebreak_after=nil,
output=STDOUT)
if rows.size == 0 or rows[0].size == 0
output.puts "No rows selected"
return
end
header_orient ||= :left
rows_orient ||= :left
indent ||= 2
cellspace ||= 1
# pagebreak_after n-rows (without counting header or split-lines)
# yield block with output as param after each pagebreak (not at the end)
col_lengths = (0...(header.size)).collect do |colnr|
[
(0...rows.size).collect { |rownr|
value = rows[rownr][colnr]
coerce(value).size
}.max,
header[colnr].size
].max
end
indent = " " * indent
split_line = indent + "+"
col_lengths.each {|col| split_line << "-" * (col+cellspace*2) + "+" }
cellspace = " " * cellspace
output_row = proc {|row, orient|
output << indent + "|"
row.each_with_index {|c,i|
output << cellspace
str = coerce(c)
output << case orient
when :left then str.ljust(col_lengths[i])
when :right then str.rjust(col_lengths[i])
when :center then str.center(col_lengths[i])
end
output << cellspace
output << "|"
}
output << "\n"
}
rownr = 0
loop do
output << split_line + "\n"
output_row.call(header, header_orient)
output << split_line + "\n"
if pagebreak_after.nil?
rows.each {|ar| output_row.call(ar, rows_orient)}
output << split_line + "\n"
break
end
rows[rownr,pagebreak_after].each {|ar| output_row.call(ar, rows_orient)}
output << split_line + "\n"
rownr += pagebreak_after
break if rownr >= rows.size
yield output if block_given?
end
end
end # module TableFormatter
end
end
|