Last active
October 12, 2015 21:57
-
-
Save mevansam/4092474 to your computer and use it in GitHub Desktop.
Ruby method to format a text table that resizes to the screen width
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require "set" | |
require "highline" | |
# | |
# Prints a 2-d array as a table formatted to terminal size | |
# | |
def print_table(table, format = true, cols = nil) | |
# Apply column filter | |
unless cols.nil? | |
headings = cols.split(",").to_set | |
cols_to_delete = [ ] | |
i = 0 | |
table[0].each do |col| | |
cols_to_delete << i unless headings.include?(col) | |
i = i + 1 | |
end | |
table.each do |row| | |
cols_to_delete.reverse_each { |j| row.delete_at(j) } | |
end | |
end | |
if format | |
# Calculate widths | |
widths = [] | |
table.each do |line| | |
c = 0 | |
line.each do |col| | |
len = col.length | |
widths[c] = (widths[c] && widths[c] > len) ? widths[c] : len | |
c += 1 | |
end | |
end | |
max_scr_cols = HighLine::SystemExtensions.terminal_size[0] - (widths.length * 3) - 1 | |
max_tbl_cols = 0 | |
width_map = {} | |
c = 0 | |
widths.each do |n| | |
max_tbl_cols += n | |
width_map[c] = n | |
c += 1 | |
end | |
c = nil | |
# Shrink columns that have too much space to try and fit table into visible console | |
if max_tbl_cols > max_scr_cols | |
width_map = width_map.sort_by { |col,width| -width } | |
last_col = widths.length - 1 | |
c = 0 | |
while max_tbl_cols > max_scr_cols && c < last_col | |
while width_map[c][1] > width_map[c + 1][1] | |
i = c | |
while i >= 0 | |
width_map[i][1] -= 1 | |
widths[width_map[i][0]] -= 1 | |
max_tbl_cols -= 1 | |
i -= 1 | |
break if max_tbl_cols == max_scr_cols | |
end | |
break if max_tbl_cols == max_scr_cols | |
end | |
c += 1 | |
end | |
end | |
border1 = "" | |
border2 = "" | |
format = "" | |
widths.each do |n| | |
border1 += "+#{'-' * (n + 2)}" | |
border2 += "+#{'=' * (n + 2)}" | |
format += "| %#{n}s " | |
end | |
border1 += "+\n" | |
border2 += "+\n" | |
format += "|\n" | |
else | |
c = nil | |
border1 = nil | |
border2 = nil | |
format = Array.new(table[0].size, "%s,").join.chop! + "\n" | |
# Delete column headings for unformatted output | |
table.delete_at(0) | |
end | |
# Print each line. | |
write_header_border = !border2.nil? | |
printf border1 if border1 | |
table.each do |line| | |
if c | |
# Check if cell needs to be truncated | |
i = 0 | |
while i < c | |
j = width_map[i][0] | |
width = width_map[i][1] | |
cell = line[j] | |
len = cell.length | |
if len > width | |
line[j] = cell[0, width - 2] + ".." | |
end | |
i += 1 | |
end | |
end | |
printf format, *line | |
if write_header_border | |
printf border2 | |
write_header_border = false | |
end | |
end | |
printf border1 if border1 | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment