Class/Module Index [+]

Quicksearch

Columnize

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


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 <rockyb@rubyforge.net>

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.

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
def cell_size(cell, term_adjust)
  if term_adjust
    cell.gsub(/\e\[.*?m/, '')
  else
    cell
  end.size
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
def columnize(*args)

  list, opts = parse_columnize_options(args)

  # Some degenerate cases
  return '' if not list.is_a?(Array)
  return  "<empty>\n" if list.empty?
  l = list.map{|li| li.to_s}
  return "%s%s%s\n" % [opts[:array_prefix], l[0], 
                       opts[:array_suffix]] if 1 == l.size

  nrows = ncols = 0  # Make nrows, ncols have more global scope
  colwidths = []     # Same for colwidths
  if opts[:displaywidth] - opts[:lineprefix].length < 4
    opts[:displaywidth] = opts[:lineprefix].length + 4
  else
    opts[:displaywidth] -= opts[:lineprefix].length
  end
  if opts[:arrange_vertical]
    array_index = lambda {|num_rows, row, col| num_rows*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 = -opts[:colsep].length

      0.upto(ncols-1) do |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)
          break if i >= l.size
          colwidth = [colwidth, cell_size(l[i], opts[:term_adjust])].max
        end
        colwidths.push(colwidth)
        totwidth += colwidth + opts[:colsep].length
        if totwidth > opts[:displaywidth]
          ncols = col
          break
        end
      end
      break if totwidth <= opts[:displaywidth]
    end
    ncols = 1 if ncols < 1
    nrows = l.size if ncols == 1
    # 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|
        i = array_index.call(nrows, row, col)
        if i >= l.size
          x = ''
        else
          x = l[i]
        end
        texts.push(x)
      end
      texts.pop while !texts.empty? and texts[-1] == ''
      if texts.size > 0
        0.upto(texts.size-1) do |col|
          unless ncols == 1 && opts[:ljust]
            if opts[:ljust]
              texts[col] = texts[col].ljust(colwidths[col])
            else
              texts[col] = texts[col].rjust(colwidths[col])
            end
          end
        end
        s += "%s%s\n" % [opts[:lineprefix], texts.join(opts[:colsep])]
      end
    end
    return s
  else
    array_index = lambda {|num_rows, row, col| ncols*(row-1) + col }
    # Assign to make enlarge scope of loop variables.
    totwidth = i = rounded_size = 0  
    # Try every column count from size downwards.
    l.size.downto(1) 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 = -opts[:colsep].length
        colwidth = row = 0
        0.upto(ncols-1) do |col|
          # get max column width for this column
          1.upto(nrows) do |_row|
            row = _row
            i = array_index.call(nrows, row, col)
            break if i >= l.size
            colwidth = [colwidth, cell_size(l[i], opts[:term_adjust])].max
          end
          colwidths.push(colwidth)
          totwidth += colwidth + opts[:colsep].length
          break if totwidth > opts[:displaywidth];
        end
        if totwidth <= opts[:displaywidth]
          # Found the right nrows and ncols
          nrows  = row
          break
        elsif totwidth >= opts[:displaywidth]
          # Need to reduce ncols
          break
        end
      end
      break if totwidth <= opts[:displaywidth] and i >= rounded_size-1
    end
    ncols = 1 if ncols < 1
    nrows = l.size if ncols == 1
    # 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 = ''
    prefix = if opts[:array_prefix].empty?
               opts[:lineprefix] 
             else 
               opts[:array_prefix]
             end
    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.push(x)
      end
      0.upto(texts.size-1) do |col|
        unless ncols == 1 && opts[:ljust]
          if opts[:ljust]
            texts[col] = texts[col].ljust(colwidths[col]) if ncols != 1
          else
            texts[col] = texts[col].rjust(colwidths[col])
          end
        end
      end
      s += "%s%s\n" % [prefix, texts.join(opts[:colsep])]
      prefix = opts[:lineprefix]
    end
    s += opts[:array_suffix]
    return s
  end
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
def parse_columnize_options(args)
  list = args.shift
  if 1 == args.size && args[0].kind_of?(Hash)
    opts = DEFAULT_OPTS.merge(args[0])
    if opts[:arrange_array]
      opts[:array_prefix] = '['
      opts[:lineprefix]   = ' '
      opts[:array_suffix] = "]\n"
      opts[:colsep]       = ', '
      opts[:arrange_vertical] = false
    end
    opts[:ljust] = !(list.all?{|datum| datum.kind_of?(Numeric)}) if 
      opts[:ljust] == :auto
    return list, opts
  else      
    opts = DEFAULT_OPTS.dup
    %(displaywidth colsep arrange_vertical ljust lineprefix
      ).each do |field|
      break if args.empty?
      opts[field.to_sym] = args.shift
    end
    return list, opts
  end
end

[Validate]

Generated with the Darkfish Rdoc Generator 2.