Retab changes for PR #1681
parent
a231e85293
commit
3c1df47314
|
@ -14,203 +14,203 @@ module Text
|
|||
###
|
||||
class Table
|
||||
|
||||
#
|
||||
# Initializes a text table instance using the supplied properties. The
|
||||
# Table class supports the following hash attributes:
|
||||
#
|
||||
# Header
|
||||
#
|
||||
# The string to display as a heading above the table. If none is
|
||||
# specified, no header will be displayed.
|
||||
#
|
||||
# HeaderIndent
|
||||
#
|
||||
# The amount of space to indent the header. The default is zero.
|
||||
#
|
||||
# Columns
|
||||
#
|
||||
# The array of columns that will exist within the table.
|
||||
#
|
||||
# Rows
|
||||
#
|
||||
# The array of rows that will exist.
|
||||
#
|
||||
# Width
|
||||
#
|
||||
# The maximum width of the table in characters.
|
||||
#
|
||||
# Indent
|
||||
#
|
||||
# The number of characters to indent the table.
|
||||
#
|
||||
# CellPad
|
||||
#
|
||||
# The number of characters to put between each horizontal cell.
|
||||
#
|
||||
# Prefix
|
||||
#
|
||||
# The text to prefix before the table.
|
||||
#
|
||||
# Postfix
|
||||
#
|
||||
# The text to affix to the end of the table.
|
||||
#
|
||||
# Sortindex
|
||||
#
|
||||
# The column to sort the table on, -1 disables sorting.
|
||||
#
|
||||
def initialize(opts = {})
|
||||
self.header = opts['Header']
|
||||
self.headeri = opts['HeaderIndent'] || 0
|
||||
self.columns = opts['Columns'] || []
|
||||
# updated below if we got a "Rows" option
|
||||
self.rows = []
|
||||
#
|
||||
# Initializes a text table instance using the supplied properties. The
|
||||
# Table class supports the following hash attributes:
|
||||
#
|
||||
# Header
|
||||
#
|
||||
# The string to display as a heading above the table. If none is
|
||||
# specified, no header will be displayed.
|
||||
#
|
||||
# HeaderIndent
|
||||
#
|
||||
# The amount of space to indent the header. The default is zero.
|
||||
#
|
||||
# Columns
|
||||
#
|
||||
# The array of columns that will exist within the table.
|
||||
#
|
||||
# Rows
|
||||
#
|
||||
# The array of rows that will exist.
|
||||
#
|
||||
# Width
|
||||
#
|
||||
# The maximum width of the table in characters.
|
||||
#
|
||||
# Indent
|
||||
#
|
||||
# The number of characters to indent the table.
|
||||
#
|
||||
# CellPad
|
||||
#
|
||||
# The number of characters to put between each horizontal cell.
|
||||
#
|
||||
# Prefix
|
||||
#
|
||||
# The text to prefix before the table.
|
||||
#
|
||||
# Postfix
|
||||
#
|
||||
# The text to affix to the end of the table.
|
||||
#
|
||||
# Sortindex
|
||||
#
|
||||
# The column to sort the table on, -1 disables sorting.
|
||||
#
|
||||
def initialize(opts = {})
|
||||
self.header = opts['Header']
|
||||
self.headeri = opts['HeaderIndent'] || 0
|
||||
self.columns = opts['Columns'] || []
|
||||
# updated below if we got a "Rows" option
|
||||
self.rows = []
|
||||
|
||||
self.width = opts['Width'] || 80
|
||||
self.indent = opts['Indent'] || 0
|
||||
self.cellpad = opts['CellPad'] || 2
|
||||
self.prefix = opts['Prefix'] || ''
|
||||
self.postfix = opts['Postfix'] || ''
|
||||
self.colprops = []
|
||||
self.width = opts['Width'] || 80
|
||||
self.indent = opts['Indent'] || 0
|
||||
self.cellpad = opts['CellPad'] || 2
|
||||
self.prefix = opts['Prefix'] || ''
|
||||
self.postfix = opts['Postfix'] || ''
|
||||
self.colprops = []
|
||||
|
||||
self.sort_index = opts['SortIndex'] || 0
|
||||
self.sort_index = opts['SortIndex'] || 0
|
||||
|
||||
# Default column properties
|
||||
self.columns.length.times { |idx|
|
||||
self.colprops[idx] = {}
|
||||
self.colprops[idx]['MaxWidth'] = self.columns[idx].length
|
||||
}
|
||||
# Default column properties
|
||||
self.columns.length.times { |idx|
|
||||
self.colprops[idx] = {}
|
||||
self.colprops[idx]['MaxWidth'] = self.columns[idx].length
|
||||
}
|
||||
|
||||
# ensure all our internal state gets updated with the given rows by
|
||||
# using add_row instead of just adding them to self.rows. See #3825.
|
||||
opts['Rows'].each { |row| add_row(row) } if opts['Rows']
|
||||
# ensure all our internal state gets updated with the given rows by
|
||||
# using add_row instead of just adding them to self.rows. See #3825.
|
||||
opts['Rows'].each { |row| add_row(row) } if opts['Rows']
|
||||
|
||||
# Merge in options
|
||||
if (opts['ColProps'])
|
||||
opts['ColProps'].each_key { |col|
|
||||
idx = self.columns.index(col)
|
||||
# Merge in options
|
||||
if (opts['ColProps'])
|
||||
opts['ColProps'].each_key { |col|
|
||||
idx = self.columns.index(col)
|
||||
|
||||
if (idx)
|
||||
self.colprops[idx].merge!(opts['ColProps'][col])
|
||||
end
|
||||
}
|
||||
end
|
||||
if (idx)
|
||||
self.colprops[idx].merge!(opts['ColProps'][col])
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
# Converts table contents to a string.
|
||||
#
|
||||
def to_s
|
||||
str = prefix.dup
|
||||
str << header_to_s || ''
|
||||
str << columns_to_s || ''
|
||||
str << hr_to_s || ''
|
||||
#
|
||||
# Converts table contents to a string.
|
||||
#
|
||||
def to_s
|
||||
str = prefix.dup
|
||||
str << header_to_s || ''
|
||||
str << columns_to_s || ''
|
||||
str << hr_to_s || ''
|
||||
|
||||
sort_rows
|
||||
rows.each { |row|
|
||||
if (is_hr(row))
|
||||
str << hr_to_s
|
||||
else
|
||||
str << row_to_s(row)
|
||||
end
|
||||
}
|
||||
sort_rows
|
||||
rows.each { |row|
|
||||
if (is_hr(row))
|
||||
str << hr_to_s
|
||||
else
|
||||
str << row_to_s(row)
|
||||
end
|
||||
}
|
||||
|
||||
str << postfix
|
||||
str << postfix
|
||||
|
||||
return str
|
||||
end
|
||||
return str
|
||||
end
|
||||
|
||||
#
|
||||
# Converts table contents to a csv
|
||||
#
|
||||
def to_csv
|
||||
str = ''
|
||||
str << ( columns.join(",") + "\n" )
|
||||
rows.each { |row|
|
||||
next if is_hr(row)
|
||||
str << ( row.map{|x|
|
||||
x = x.to_s
|
||||
#
|
||||
# Converts table contents to a csv
|
||||
#
|
||||
def to_csv
|
||||
str = ''
|
||||
str << ( columns.join(",") + "\n" )
|
||||
rows.each { |row|
|
||||
next if is_hr(row)
|
||||
str << ( row.map{|x|
|
||||
x = x.to_s
|
||||
|
||||
x.gsub(/[\r\n]/, ' ').gsub(/\s+/, ' ').gsub('"', '""')
|
||||
}.map{|x| "\"#{x}\"" }.join(",") + "\n" )
|
||||
}
|
||||
str
|
||||
end
|
||||
x.gsub(/[\r\n]/, ' ').gsub(/\s+/, ' ').gsub('"', '""')
|
||||
}.map{|x| "\"#{x}\"" }.join(",") + "\n" )
|
||||
}
|
||||
str
|
||||
end
|
||||
|
||||
#
|
||||
#
|
||||
# Returns the header string.
|
||||
#
|
||||
def header_to_s # :nodoc:
|
||||
if (header)
|
||||
pad = " " * headeri
|
||||
#
|
||||
#
|
||||
# Returns the header string.
|
||||
#
|
||||
def header_to_s # :nodoc:
|
||||
if (header)
|
||||
pad = " " * headeri
|
||||
|
||||
return pad + header + "\n" + pad + "=" * header.length + "\n\n"
|
||||
end
|
||||
return pad + header + "\n" + pad + "=" * header.length + "\n\n"
|
||||
end
|
||||
|
||||
return ''
|
||||
end
|
||||
return ''
|
||||
end
|
||||
|
||||
#
|
||||
# Prints the contents of the table.
|
||||
#
|
||||
def print
|
||||
puts to_s
|
||||
end
|
||||
#
|
||||
# Prints the contents of the table.
|
||||
#
|
||||
def print
|
||||
puts to_s
|
||||
end
|
||||
|
||||
#
|
||||
# Adds a row using the supplied fields.
|
||||
#
|
||||
def <<(fields)
|
||||
add_row(fields)
|
||||
end
|
||||
#
|
||||
# Adds a row using the supplied fields.
|
||||
#
|
||||
def <<(fields)
|
||||
add_row(fields)
|
||||
end
|
||||
|
||||
#
|
||||
# Adds a row with the supplied fields.
|
||||
#
|
||||
def add_row(fields = [])
|
||||
if fields.length != self.columns.length
|
||||
raise RuntimeError, 'Invalid number of columns!'
|
||||
end
|
||||
fields.each_with_index { |field, idx|
|
||||
if (colprops[idx]['MaxWidth'] < field.to_s.length)
|
||||
colprops[idx]['MaxWidth'] = field.to_s.length
|
||||
end
|
||||
}
|
||||
#
|
||||
# Adds a row with the supplied fields.
|
||||
#
|
||||
def add_row(fields = [])
|
||||
if fields.length != self.columns.length
|
||||
raise RuntimeError, 'Invalid number of columns!'
|
||||
end
|
||||
fields.each_with_index { |field, idx|
|
||||
if (colprops[idx]['MaxWidth'] < field.to_s.length)
|
||||
colprops[idx]['MaxWidth'] = field.to_s.length
|
||||
end
|
||||
}
|
||||
|
||||
rows << fields
|
||||
end
|
||||
rows << fields
|
||||
end
|
||||
|
||||
#
|
||||
# Sorts the rows based on the supplied index of sub-arrays
|
||||
# If the supplied index is an IPv4 address, handle it differently, but
|
||||
# avoid actually resolving domain names.
|
||||
#
|
||||
def sort_rows(index=sort_index)
|
||||
return if index == -1
|
||||
return unless rows
|
||||
rows.sort! do |a,b|
|
||||
if a[index].nil?
|
||||
-1
|
||||
elsif b[index].nil?
|
||||
1
|
||||
elsif Rex::Socket.dotted_ip?(a[index]) and Rex::Socket.dotted_ip?(b[index])
|
||||
Rex::Socket::addr_atoi(a[index]) <=> Rex::Socket::addr_atoi(b[index])
|
||||
elsif a[index] =~ /^[0-9]+$/ and b[index] =~ /^[0-9]+$/
|
||||
a[index].to_i <=> b[index].to_i
|
||||
else
|
||||
a[index] <=> b[index] # assumes otherwise comparable.
|
||||
end
|
||||
end
|
||||
end
|
||||
#
|
||||
# Sorts the rows based on the supplied index of sub-arrays
|
||||
# If the supplied index is an IPv4 address, handle it differently, but
|
||||
# avoid actually resolving domain names.
|
||||
#
|
||||
def sort_rows(index=sort_index)
|
||||
return if index == -1
|
||||
return unless rows
|
||||
rows.sort! do |a,b|
|
||||
if a[index].nil?
|
||||
-1
|
||||
elsif b[index].nil?
|
||||
1
|
||||
elsif Rex::Socket.dotted_ip?(a[index]) and Rex::Socket.dotted_ip?(b[index])
|
||||
Rex::Socket::addr_atoi(a[index]) <=> Rex::Socket::addr_atoi(b[index])
|
||||
elsif a[index] =~ /^[0-9]+$/ and b[index] =~ /^[0-9]+$/
|
||||
a[index].to_i <=> b[index].to_i
|
||||
else
|
||||
a[index] <=> b[index] # assumes otherwise comparable.
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
# Adds a horizontal line.
|
||||
#
|
||||
def add_hr
|
||||
rows << '__hr__'
|
||||
end
|
||||
#
|
||||
# Adds a horizontal line.
|
||||
#
|
||||
def add_hr
|
||||
rows << '__hr__'
|
||||
end
|
||||
|
||||
#
|
||||
# Returns new sub-table with headers and rows maching column names submitted
|
||||
|
@ -230,13 +230,13 @@ class Table
|
|||
end
|
||||
|
||||
|
||||
alias p print
|
||||
alias p print
|
||||
|
||||
attr_accessor :header, :headeri # :nodoc:
|
||||
attr_accessor :columns, :rows, :colprops # :nodoc:
|
||||
attr_accessor :width, :indent, :cellpad # :nodoc:
|
||||
attr_accessor :prefix, :postfix # :nodoc:
|
||||
attr_accessor :sort_index # :nodoc:
|
||||
attr_accessor :header, :headeri # :nodoc:
|
||||
attr_accessor :columns, :rows, :colprops # :nodoc:
|
||||
attr_accessor :width, :indent, :cellpad # :nodoc:
|
||||
attr_accessor :prefix, :postfix # :nodoc:
|
||||
attr_accessor :sort_index # :nodoc:
|
||||
|
||||
protected
|
||||
|
||||
|
|
Loading…
Reference in New Issue