Adapted from the routine of the same name in cmd.py
or arranged horizontally:
['1', '2,', '3', '4'] => '1 2\n3 4\n'
Each column is only as wide possible, no larger than +displaywidth'. If list is not an array, the empty string, ", is returned. By default, columns are separated by two spaces - one was not legible enough. Set colsep to adjust the string separate columns. If arrange_vertical is set false, consecutive items will go across, left to right, top to bottom.
# File lib/columnize.rb, line 56 def columnize(list, displaywidth=80, colsep = ' ', arrange_vertical=true, ljust=true, lineprefix='') # Some degenerate cases if not list.is_a?(Array) return '' end if list.size == 0 return "<empty>\n" end l = list.map{|li| li.to_s} if 1 == l.size return "#{l[0]}\n" end nrows = ncols = 0 # Make nrows, ncols have more global scope colwidths = [] # Same for colwidths displaywidth = [4, displaywidth - lineprefix.length].max if arrange_vertical array_index = lambda {|nrows, row, col| nrows*col + row } # Try every row count from 1 upwards 1.upto(l.size-1) do |_nrows| nrows = _nrows ncols = (l.size + nrows-1) / nrows colwidths = [] totwidth = -colsep.length 0.upto(ncols-1) do |_col| col = _col # get max column width for this column colwidth = 0 0.upto(nrows-1) do |_row| row = _row i = array_index.call(nrows, row, col) if i >= l.size break end colwidth = [colwidth, l[i].size].max end colwidths << colwidth totwidth += colwidth + colsep.length if totwidth > displaywidth ncols = col break end end if totwidth <= displaywidth break end end # The smallest number of rows computed and the # max widths for each column has been obtained. # Now we just have to format each of the # rows. s = '' 0.upto(nrows-1) do |_row| row = _row texts = [] 0.upto(ncols-1) do |_col| col = _col i = array_index.call(nrows, row, col) if i >= l.size x = "" else x = l[i] end texts << x end while texts and texts[-1] == '' texts = texts[0..-2] end if texts.size > 0 0.upto(texts.size-1) do |_col| col = _col if ljust texts[col] = texts[col].ljust(colwidths[col]) else texts[col] = texts[col].rjust(colwidths[col]) end end s += "%s%s\n" % [lineprefix, texts.join(colsep)] end end return s else array_index = lambda {|nrows, row, col| ncols*(row-1) + col } # Try every column count from size downwards # Assign to make enlarge scope of loop variables totwidth = i = rounded_size = 0 l.size.downto(0) do |_ncols| ncols = _ncols # Try every row count from 1 upwards min_rows = (l.size+ncols-1) / ncols min_rows.upto(l.size) do |_nrows| nrows = _nrows rounded_size = nrows * ncols colwidths = [] totwidth = -colsep.length colwidth = row = 0 0.upto(ncols-1) do |_col| col = _col # get max column width for this column 1.upto(nrows) do |_row| row = _row i = array_index.call(nrows, row, col) if i >= rounded_size break elsif i < l.size colwidth = [colwidth, l[i].size].max end end colwidths << colwidth totwidth += colwidth + colsep.length if totwidth > displaywidth break end end if totwidth <= displaywidth # Found the right nrows and ncols nrows = row break elsif totwidth >= displaywidth # Need to reduce ncols break end end if totwidth <= displaywidth and i >= rounded_size-1 break end end # The smallest number of rows computed and the # max widths for each column has been obtained. # Now we just have to format each of the # rows. s = '' 1.upto(nrows) do |row| texts = [] 0.upto(ncols-1) do |col| i = array_index.call(nrows, row, col) if i >= l.size break else x = l[i] end texts << x end 0.upto(texts.size-1) do |col| if ljust texts[col] = texts[col].ljust(colwidths[col]) else texts[col] = texts[col].rjust(colwidths[col]) end end s += "%s%s\n" % [lineprefix, texts.join(colsep)] end return s end end
Generated with the Darkfish Rdoc Generator 2.