Module to format an Array as an Array of String aligned in columns.
Display a list of strings as a compact set of columns.
For example, for a line width of 4 characters (arranged vertically): ['1', '2,', '3', '4'] => '1 3\n2 4\n' or arranged horizontally: ['1', '2,', '3', '4'] => '1 2\n3 4\n'
Each column is only as wide as necessary. By default, columns are separated by two spaces. Options are avalable for setting
the display width
the column separator
the line prefix
whether to ignore terminal codes in text size calculation
whether to left justify text instead of right justify
Columnize is copyright (C) 2007, 2008, 2009,
2010, 2011 Rocky Bernstein
All rights reserved. You can redistribute and/or modify it under the same terms as Ruby.
Adapted from the routine of the same name in Python cmd.py.
Sets constant Columnize::VERSION, the version number of this package. It is used in Gem creation but can also be consulted after require’ing ‘columnize’.
When an option is not specified for the below keys, these are the defaults.
The current version of this package
Return the length of String cell. If Boolean term_adjust is true, ignore terminal sequences in cell.
# File lib/columnize.rb, line 89 89: def cell_size(cell, term_adjust) 90: if term_adjust 91: cell.gsub(/\e\[.*?m/, '') 92: else 93: cell 94: end.size 95: end
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 113 113: def columnize(*args) 114: 115: list, opts = parse_columnize_options(args) 116: 117: # Some degenerate cases 118: return '' if not list.is_a?(Array) 119: return "<empty>\n" if list.empty? 120: l = list.map{|li| li.to_s} 121: return "%s%s%s\n" % [opts[:array_prefix], l[0], 122: opts[:array_suffix]] if 1 == l.size 123: 124: nrows = ncols = 0 # Make nrows, ncols have more global scope 125: colwidths = [] # Same for colwidths 126: if opts[:displaywidth] - opts[:lineprefix].length < 4 127: opts[:displaywidth] = opts[:lineprefix].length + 4 128: else 129: opts[:displaywidth] -= opts[:lineprefix].length 130: end 131: if opts[:arrange_vertical] 132: array_index = lambda {|num_rows, row, col| num_rows*col + row } 133: # Try every row count from 1 upwards 134: 1.upto(l.size-1) do |_nrows| 135: nrows = _nrows 136: ncols = (l.size + nrows-1) / nrows 137: colwidths = [] 138: totwidth = -opts[:colsep].length 139: 140: 0.upto(ncols-1) do |col| 141: # get max column width for this column 142: colwidth = 0 143: 0.upto(nrows-1) do |_row| 144: row = _row 145: i = array_index.call(nrows, row, col) 146: break if i >= l.size 147: colwidth = [colwidth, cell_size(l[i], opts[:term_adjust])].max 148: end 149: colwidths.push(colwidth) 150: totwidth += colwidth + opts[:colsep].length 151: if totwidth > opts[:displaywidth] 152: ncols = col 153: break 154: end 155: end 156: break if totwidth <= opts[:displaywidth] 157: end 158: ncols = 1 if ncols < 1 159: nrows = l.size if ncols == 1 160: # The smallest number of rows computed and the max widths for 161: # each column has been obtained. Now we just have to format 162: # each of the rows. 163: s = '' 164: 0.upto(nrows-1) do |_row| 165: row = _row 166: texts = [] 167: 0.upto(ncols-1) do |col| 168: i = array_index.call(nrows, row, col) 169: if i >= l.size 170: x = '' 171: else 172: x = l[i] 173: end 174: texts.push(x) 175: end 176: texts.pop while !texts.empty? and texts[1] == '' 177: if texts.size > 0 178: 0.upto(texts.size-1) do |col| 179: unless ncols == 1 && opts[:ljust] 180: if opts[:ljust] 181: texts[col] = texts[col].ljust(colwidths[col]) 182: else 183: texts[col] = texts[col].rjust(colwidths[col]) 184: end 185: end 186: end 187: s += "%s%s\n" % [opts[:lineprefix], texts.join(opts[:colsep])] 188: end 189: end 190: return s 191: else 192: array_index = lambda {|num_rows, row, col| ncols*(row-1) + col } 193: # Assign to make enlarge scope of loop variables. 194: totwidth = i = rounded_size = 0 195: # Try every column count from size downwards. 196: l.size.downto(1) do |_ncols| 197: ncols = _ncols 198: # Try every row count from 1 upwards 199: min_rows = (l.size+ncols-1) / ncols 200: min_rows.upto(l.size) do |_nrows| 201: nrows = _nrows 202: rounded_size = nrows * ncols 203: colwidths = [] 204: totwidth = -opts[:colsep].length 205: colwidth = row = 0 206: 0.upto(ncols-1) do |col| 207: # get max column width for this column 208: 1.upto(nrows) do |_row| 209: row = _row 210: i = array_index.call(nrows, row, col) 211: break if i >= l.size 212: colwidth = [colwidth, cell_size(l[i], opts[:term_adjust])].max 213: end 214: colwidths.push(colwidth) 215: totwidth += colwidth + opts[:colsep].length 216: break if totwidth > opts[:displaywidth]; 217: end 218: if totwidth <= opts[:displaywidth] 219: # Found the right nrows and ncols 220: nrows = row 221: break 222: elsif totwidth >= opts[:displaywidth] 223: # Need to reduce ncols 224: break 225: end 226: end 227: break if totwidth <= opts[:displaywidth] and i >= rounded_size-1 228: end 229: ncols = 1 if ncols < 1 230: nrows = l.size if ncols == 1 231: # The smallest number of rows computed and the max widths for 232: # each column has been obtained. Now we just have to format 233: # each of the rows. 234: s = '' 235: prefix = if opts[:array_prefix].empty? 236: opts[:lineprefix] 237: else 238: opts[:array_prefix] 239: end 240: 1.upto(nrows) do |row| 241: texts = [] 242: 0.upto(ncols-1) do |col| 243: i = array_index.call(nrows, row, col) 244: if i >= l.size 245: break 246: else 247: x = l[i] 248: end 249: texts.push(x) 250: end 251: 0.upto(texts.size-1) do |col| 252: unless ncols == 1 && opts[:ljust] 253: if opts[:ljust] 254: texts[col] = texts[col].ljust(colwidths[col]) if ncols != 1 255: else 256: texts[col] = texts[col].rjust(colwidths[col]) 257: end 258: end 259: end 260: s += "%s%s\n" % [prefix, texts.join(opts[:colsep])] 261: prefix = opts[:lineprefix] 262: end 263: s += opts[:array_suffix] 264: return s 265: end 266: end
Options parsing routine for Columnize::columnize. In the preferred newer style, args is either a hash where each key is one of the option names:
Arrange list vertically rather than horizontally. This is the default
String used to separate columns
Maximum width of each line
Boolean or :auto: Left-justify fields in a column? The default is true. If
the :auto, then right-justify if every element of the data is a kind of Numeric.
String: string to prepend to each line. The default is ’’.
In the older style positional arguments are used and the positions are in the order: displaywidth, colsep, arrange_vertical, ljust, and lineprefix.
# File lib/columnize.rb, line 62 62: def parse_columnize_options(args) 63: list = args.shift 64: if 1 == args.size && args[0].kind_of?(Hash) 65: opts = DEFAULT_OPTS.merge(args[0]) 66: if opts[:arrange_array] 67: opts[:array_prefix] = '[' 68: opts[:lineprefix] = ' ' 69: opts[:array_suffix] = "]\n" 70: opts[:colsep] = ', ' 71: opts[:arrange_vertical] = false 72: end 73: opts[:ljust] = !(list.all?{|datum| datum.kind_of?(Numeric)}) if 74: opts[:ljust] == :auto 75: return list, opts 76: else 77: opts = DEFAULT_OPTS.dup 78: %(displaywidth colsep arrange_vertical ljust lineprefix 79: ).each do |field| 80: break if args.empty? 81: opts[field.to_sym] = args.shift 82: end 83: return list, opts 84: end 85: end
Disabled; run with --debug to generate this.
Generated with the Darkfish Rdoc Generator 1.1.6.