TODO: change colfmt to cell_format; change colsep to something else
# File lib/columnize/columnize.rb, line 14 def initialize(list=[], opts={}) self.list = list self.opts = DEFAULT_OPTS.merge(opts) end
Given list
, ncols
, nrows
, arrange
the one-dimensional array into a 2-dimensional lists of lists organized by
columns.
In either horizontal or vertical arrangement, we will need to access this for the list data or for the width information.
Here is an example: #arrange_by_column((1..5).to_a, 2, 3) =>
[[1,3,5], [2,4]]
# File lib/columnize/columnize.rb, line 133 def arrange_by_column(list, nrows, ncols) (0...ncols).map do |i| (0..nrows-1).inject([]) do |row, j| k = i + (j * ncols) k < list.length ? row << list[k] : row end end end
Given list
, ncols
, nrows
, arrange
the one-dimensional array into a 2-dimensional lists of lists organized by
rows.
In either horizontal or vertical arrangement, we will need to access this for the list data or for the width information.
Here is an example: #arrange_by_row((1..5).to_a, 3, 2) =>
[[1,2], [3,4], [5]],
# File lib/columnize/columnize.rb, line 119 def arrange_by_row(list, nrows, ncols) (0...nrows).map {|r| list[r*ncols, ncols] }.compact end
# File lib/columnize/columnize.rb, line 41 def columnize return @short_circuit if @short_circuit rows, colwidths = min_rows_and_colwidths ncols = colwidths.length justify = lambda {|t, c| @ljust ? t.ljust(colwidths[c]) : t.rjust(colwidths[c]) } textify = lambda do |row| row.map!.with_index(&justify) unless ncols == 1 && @ljust "#{@line_prefix}#{row.join(@colsep)}#{@line_suffix}" end text = rows.map(&textify) text.first.sub!(/^#{@line_prefix}/, @array_prefix) unless @array_prefix.empty? text.last.sub!(/#{@line_suffix}$/, @array_suffix) unless @array_suffix.empty? text.join("\n") # + "\n" # if we want extra separation end
# File lib/columnize/columnize.rb, line 19 def list=(list) @list = list if @list.is_a? Array @short_circuit = @list.empty? ? "<empty>\n" : nil else @short_circuit = '' @list = [] end end
TODO: make this a method, rather than a function (?) compute the smallest number of rows and the max widths for each column
# File lib/columnize/columnize.rb, line 62 def min_rows_and_colwidths list = @list.map &@stringify cell_widths = list.map(&@term_adjuster).map(&:size) # Set default arrangement: one atom per row cell_width_max = cell_widths.max result = [arrange_by_row(list, list.size, 1), [cell_width_max]] # If any atom > @displaywidth, stop and use one atom per row. return result if cell_width_max > @displaywidth # For horizontal arrangement, we want to *maximize* the number # of columns. Thus the candidate number of rows (+sizes+) starts # at the minumum number of rows, 1, and increases. # For vertical arrangement, we want to *minimize* the number of # rows. So here the candidate number of columns (+sizes+) starts # at the maximum number of columns, list.length, and # decreases. Also the roles of columns and rows are reversed # from horizontal arrangement. # Loop from most compact arrangement to least compact, stopping # at the first successful packing. The below code is tricky, # but very cool. # # FIXME: In the below code could be DRY'd. (The duplication got # introduced when I revised the code - rocky) if @arrange_vertical (1..list.length).each do |size| other_size = (list.size + size - 1) / size colwidths = arrange_by_row(cell_widths, other_size, size).map(&:max) totwidth = colwidths.inject(&:+) + ((colwidths.length-1) * @colsep.length) return [arrange_by_column(list, other_size, size), colwidths] if totwidth <= @displaywidth end else list.length.downto(1).each do |size| other_size = (list.size + size - 1) / size colwidths = arrange_by_column(cell_widths, other_size, size).map(&:max) totwidth = colwidths.inject(&:+) + ((colwidths.length-1) * @colsep.length) return [arrange_by_row(list, other_size, size), colwidths] if totwidth <= @displaywidth end end result end
TODO: freeze @opts
# File lib/columnize/columnize.rb, line 30 def opts=(opts) @opts = opts OLD_AND_NEW_KEYS.each {|old, new| @opts[new] = @opts.delete(old) if @opts.keys.include?(old) and !@opts.keys.include?(new) } @opts.merge!(ARRANGE_ARRAY_OPTS) if @opts[:arrange_array] set_attrs_from_opts end
# File lib/columnize/columnize.rb, line 142 def set_attrs_from_opts ATTRS.each {|attr| self.instance_variable_set "@#{attr}", @opts[attr] } @ljust = !@list.all? {|datum| datum.kind_of?(Numeric)} if @ljust == :auto @displaywidth -= @line_prefix.length @displaywidth = @line_prefix.length + 4 if @displaywidth < 4 @stringify = @colfmt ? lambda {|li| @colfmt % li } : lambda {|li| li.to_s } @term_adjuster = @opts[:term_adjust] ? lambda {|c| c.gsub(/\e\[.*?m/, '') } : lambda {|c| c } end
# File lib/columnize/columnize.rb, line 37 def update_opts(opts) self.opts = @opts.merge(opts) end