Class Index [+]

Quicksearch

Columnize

Module to format an Array as an Array of String aligned in columns.

Summary

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

License

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’.

Constants

DEFAULT_OPTS

When an option is not specified for the below keys, these are the defaults.

VERSION

The current version of this package

Public Instance Methods

cell_size(cell, term_adjust) click to toggle source

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
columnize(*args) click to toggle source

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
parse_columnize_options(args) click to toggle source

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_vertical

Arrange list vertically rather than horizontally. This is the default

colsep

String used to separate columns

displaywidth

Maximum width of each line

ljust

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.

lineprefix

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.

[Validate]

Generated with the Darkfish Rdoc Generator 1.1.6.