Module: Columnize

### Home Classes Methods

### In Files

- lib/columnize.rb
- lib/columnize/version.rb

### Methods

- #cell_size
- #columnize
- #parse_columnize_options

### Files

- COPYING
- Makefile
- Makefile

### Class/Module Index

Quicksearch

- Columnize
- Object

No matching classes.

# 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

- 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

## 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`.

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