Module: Columnize

Defined in:
lib/columnize.rb,
lib/columnize/version.rb

Overview

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

Constant Summary collapse

DEFAULT_OPTS =

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

{
  :arrange_array     => false,
  :arrange_vertical  => true,
  :array_prefix      => '',
  :array_suffix      => '',
  :colsep            => '  ',
  :displaywidth      => 80,
  :lineprefix        => '',
  :ljust             => :auto,
  :term_adjust       => false
}
VERSION =

The current version of this package

'0.3.6'

Class Method Summary collapse

Class Method Details

.cell_size(cell, term_adjust) ⇒ Object

Return the length of String cell. If Boolean term_adjust is true, ignore terminal sequences in cell.



89
90
91
92
93
94
95
# 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) ⇒ Object

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.



113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
# 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) ⇒ Object

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.



62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# 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
    %w(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