Giter Club home page Giter Club logo

tty-table's Introduction

TTY Toolkit logo

TTY::Table Gitter

Gem Version Actions CI Build status Code Climate Coverage Status Inline docs

A flexible and intuitive table formatting.

TTY::Table provides independent table formatting component for TTY toolkit.

Features

  • Table behaves like an array with familiar API see
  • Create table once and render using custom view renderers see
  • Rendering provides many display options see
  • Easy custom border creation see
  • Supports multibyte character encodings

Installation

Add this line to your application's Gemfile:

gem "tty-table"

And then execute:

$ bundle

Or install it yourself as:

$ gem install tty-table

Contents

1. Usage

First, provide TTY::Table with data, for example, two headers and two rows:

table = TTY::Table.new(["header1","header2"], [["a1", "a2"], ["b1", "b2"]])

Then to print to the console, call the render method with border type as a first argument:

puts table.render(:ascii)
# =>
#  +-------+-------+
#  |header1|header2|
#  +-------+-------+
#  |a1     |a2     |
#  +-------+-------+
#  |b1     |b2     |
#  +-------+-------+

2. Interface

2.1 Initialization

TTY::Table can be created in variety of ways. The easiest way is to pass 2-dimensional array:

table = TTY::Table[["a1", "a2"], ["b1", "b2"]]
table = TTY::Table.new([["a1", "a2"], ["b1", "b2"]])
table = TTY::Table.new(rows: [["a1", "a2"], ["b1", "b2"]])

Alternatively you can specify the rows one by one inside a block:

table = TTY::Table.new do |t|
  t << ["a1", "a2"]
  t << ["b1", "b2"]
end

You can add rows of data after initialization with << operator:

table = TTY::Table.new
table << ["a1","a2"]
table << ["b1","b2"]

In addition to rows, you can specify table header:

table = TTY::Table.new(["h1", "h2"], [["a1", "a2"], ["b1", "b2"]])
table = TTY::Table.new(header: ["h1", "h2"], rows: [["a1", "a2"], ["b1", "b2"]])

You can also mix header with rows inside a hash like so:

table = TTY::Table.new([{"h1" => ["a1", "a2"], "h2" => ["b1", "b2"]}])

2.2 Iteration

Table behaves like an Array so <<, each and familiar methods can be used:

table << ["a1", "a2", "a3"]
table << ["b1", "b2", "b3"]
table << ["a1", "a2"] << ["b1", "b2"]  # chain rows assignment

In order to iterate over table rows including headers do:

table.each { |row| ... }                       # iterate over rows
table.each_with_index  { |row, index| ... }    # iterate over rows with an index

2.3 Access

In order to reference the row at index do:

table = TTY::Table.new [["a1","a2"], ["b1","b2"]]
table[0]                    # => ["a1","a2"]
table.row(0)                # => ["a1","a2"]
table.row(i) { |row| ... }  # return array for row(i)

Negative indices count backwards from the end of table data (-1 is the last element):

table[-1]   # => ["b1","b2"]

To reference element at given row(i) and column(j) do:

table[i, j]   # return element at row(i) and column(j)
table[0,0]    # => "a1"

To specifically reference column(j) do:

table.column(j) { ... }   # return array for column(j)
table.column(0)           # => ["a1","b1"]
table.column(name)        # return array for column(name), name of header

An IndexError is raised for indexes outside of data range.

2.4 Size

In order to query the number of rows, columns or size do:

table.rows_size        # return row size
table.columns_size     # return column size
table.size             # return an array of [row_size, column_size]

2.5 Orientation

3 Rendering

TTY-Table rendering process means you can create tabular data once and then create different renderers to match your needs for formatting the data.

3.1 Render

Given a table:

table = TTY::Table.new(["header1","header2"], [["a1", "a2"], ["b1", "b2"]])

Once you have an instance of TTY::Table you can decorate the content using the render method. In order to display a basic whitespace delimited view do:

table.render(:basic)
# =>
#  header1 header2
#  a1      a2
#  b1      b2

This will use so called :basic renderer with default options. The other renderers are :ascii and :unicode.

The render method can accept as a second argument the rendering options either as hash value:

table.render(:basic, alignments: [:left, :center])

or inside a block:

table.render(:basic) do |renderer|
  renderer.alignments= [:left, :center]
end

3.2 Renderer

TTY::Table has a definition of TTY::Table::Renderer which allows you to provide different view for your tabular data. It comes with few initial renderers built in such as TTY::Table::Renderer::Basic, TTY::Table::Renderer::ASCII and TTY::Table::Renderer:Unicode.

Given a table of data:

table = TTY::Table.new ["header1","header2"], [["a1", "a2"], ["b1", "b2"]]

You can create a special renderer for it:

multi_renderer = TTY::Table::Renderer::Basic.new(table, multiline: true)

and then call render

multi_renderer.render

This way, you create tabular data once and then create different renderers to match your needs for formatting the data.

3.2.1 Basic Renderer

The basic render allows for formatting table with whitespace without any border:

renderer = TTY::Table::Renderer::Basic.new(table)
renderer.render
# =>
#  header1 header2
#  a1      a2
#  b1      b2

This is the same as calling render directly on table:

table.render

3.2.2 ASCII Renderer

The ascii renderer allows for formatting table with ASCII type border.

Create an instance of ASCII renderer:

renderer = TTY::Table::Renderer::ASCII.new(table)

and then call render to get the formatted data:

renderer.render
# =>
#  +-------+-------+
#  |header1|header2|
#  +-------+-------+
#  |a1     |a2     |
#  |b1     |b2     |
#  +-------+-------+

This is the same as calling render directly on table instance with :ascii as the first argument:

table.render(:ascii)

3.2.3 Unicode Renderer

The uniocde renderer allows for formatting table with Unicode type border.

Create an instance of Unicode renderer:

renderer = TTY::Table::Renderer::Unicode.new(table)

and then call render to get the formatted data:

renderer.render
# =>
#  ┌───────┬───────┐
#  │header1│header2│
#  ├───────┼───────┤
#  │a1     │a2     │
#  │b1     │b2     │
#  └───────┴───────┘

This is the same as calling render directly on table instance with :unicode as the first argument:

table.render(:unicode)

3.3 Options

Rendering of TTY-Table includes numerous customization options:

  • :alignments - array of cell alignments out of :left, :center and :right. Defaults to :left.
  • :border - hash of border options out of :characters, :style and :separator
  • :border_class - a type of border to use such as TTY::Table::Border::Null, TTY::Table::Border::ASCII and TTY::Table::Border::Unicode
  • :column_widths - array of maximum column widths
  • :filter - a proc object that is applied to every field in a row
  • :indent - indentation applied to rendered table, by default 0
  • :multiline - when true will wrap text at new line or column width, when false will escape special characters
  • :padding - array of integers to set table fields padding. Defaults to [0,0,0,0].
  • :resize - when true will expand/shrink table column sizes to match the terminal width, otherwise when false will rotate table vertically. Defaults to false.
  • :width - constrains the table total width. Defaults to value automatically calculated based on the content and terminal size.

The render method can accept as a second argument the above options either as hash value:

table.render(:basic, alignments: [:left, :center])

Or inside a block as a property:

table.render(:basic) do |renderer|
  renderer.alignments = [:left, :center]
end

3.4 Alignment

By default all columns are :left aligned.

You can align each column individually by passing :alignments option to table renderer:

table.render(:ascii, alignments: [:center, :right])
# =>
#  +-------+-------+
#  |header1|header2|
#  +-------+-------+
#  |  a1   |     a2|
#  |  b1   |     b2|
#  +-------+-------+

Alternatively you can align all columns with :alignment option:

table.render(:ascii, alignment: [:center])
# =>
#  +-------+-------+
#  |header1|header2|
#  +-------+-------+
#  |  a1   |  a2   |
#  |  b1   |  b2   |
#  +-------+-------+

If you require a more granular alignment you can align individual fields in a row by passing :alignment option like so:

table = TTY::Table.new(header: ["header1", "header2"])
table << [{value: "a1", alignment: :right}, "a2"]
table << ["b1", {value: "b2", alignment: :center}]

and then simply render:

table.render(:ascii)
# =>
#  +-------+-------+
#  |header1|header2|
#  +-------+-------+
#  |     a1|a2     |
#  |b1     |  b2   |
#  +-------+-------+

3.5 Border

To print border around data table you need to specify renderer type out of basic, ascii, unicode. By default basic is used. For instance, to output unicode border:

table = TTY::Table.new ["header1", "header2"], [["a1", "a2"], ["b1", "b2"]]
table.render :unicode
# =>
#  ┌───────┬───────┐
#  │header1│header2│
#  ├───────┼───────┤
#  │a1     │a2     │
#  │b1     │b2     │
#  └───────┴───────┘

or by creating unicode renderer:

renderer = TTY::Table::Renderer::Unicode.new(table)
renderer.render

3.5.1 Parts

The following are available border parts:

Part ASCII Unicode
top -
top_mid +
top_left +
top_right +
bottom -
bottom_mid +
bottom_left +
bottom_right +
mid -
mid_mid +
mid_left +
mid_right +
left ` `
center ` `
right ` `

Using the above border parts you can create your own border with the border helper:

table = TTY::Table.new ["header1", "header2"], [["a1", "a2"], ["b1", "b2"]
table.render do |renderer|
  renderer.border do
    mid          "="
    mid_mid      " "
  end
end
# =>
#  header1 header2
#  ======= =======
#  a1      a2
#  b1      b2

3.5.2 Custom

You can also create your own custom border by subclassing TTY::Table::Border and implementing the def_border method using internal DSL methods like so:

class MyBorder < TTY::Table::Border
  def_border do
    left         "$"
    center       "$"
    right        "$"
    bottom       " "
    bottom_mid   "*"
    bottom_left  "*"
    bottom_right "*"
  end
end

Next pass the border class to your table instance render_with method

table = TTY::Table.new ["header1", "header2"], [["a1", "a2"], ["b1", "b2"]
table.render_with MyBorder
# =>
#  $header1$header2$
#  $a1     $a2     $
#  *       *       *

3.5.3 Separator

In addition to specifying border characters you can force the table to render a separator line on each row like:

table = TTY::Table.new ["header1", "header2"], [["a1", "a2"], ["b1", "b2"]]
table.render do |renderer|
  renderer.border.separator = :each_row
end
# =>
#  +-------+-------+
#  |header1|header2|
#  +-------+-------+
#  |a1     |a2     |
#  +-------+-------+
#  |b1     |b2     |
#  +-------+-------+

If you want more control you can provide an array of rows after which a separator will be added:

table = TTY::Table.new ["header1", "header2"], [["a1", "a2"], ["b1", "b2"], ["c1", "c2"]]
table.render do |renderer|
  renderer.border.separator = [0, 2]
end
# =>
#  +-------+-------+
#  |header1|header2|
#  +-------+-------+
#  |a1     |a2     |
#  |b1     |b2     |
#  +-------+-------+
#  |c1     |c2     |
#  +-------+-------+

Note: if you supply a detailed list of rows to separate, then the separator between the header and the rows will not be automatically added.

You can also give the separator option a proc to control where the separators are:

table = TTY::Table.new ["header1", "header2"],
                       [["a1", "a2"], ["b1", "b2"], ["c1", "c2"], ["d1", "d2"]]
table.render do |renderer|
  renderer.border.separator = ->(row) { row == 0 || (row+1) % 2 == 0} # separate every two rows
end
# =>
#  +-------+-------+
#  |header1|header2|
#  +-------+-------+
#  |a1     |a2     |
#  |b1     |b2     |
#  +-------+-------+
#  |c1     |c2     |
#  |d1     |d2     |
#  +-------+-------+

Finally you can also position a separator using the :separator key word in place of a row:

table = TTY::Table.new ["header1", "header2"],
                       [:separator, ["a1", "a2"], ["b1", "b2"]]
table << :separator << ["c1", "c2"]  # you can push separators on too!
table.render
# =>
#  +-------+-------+
#  |header1|header2|
#  +-------+-------+
#  |a1     |a2     |
#  |b1     |b2     |
#  +-------+-------+
#  |c1     |c2     |
#  +-------+-------+

3.5.4 Style

If you want to change the display color of your border do:

table.render do |renderer|
  renderer.border.style = :green
end

All supported colors are provided by the Pastel dependency.

3.6 Filter

You can define filters that will modify individual table field value before it is rendered. A filter can be a callable such as proc.

Here's an example that formats capitalizes each field in second column skipping the header:

table = TTY::Table.new(["header1", "header2"], [["a1", "a2"], ["b1", "b2"]])
table.render do |renderer|
  renderer.filter = ->(val, row_index, col_index) do
    if col_index == 1 and !(row_index == 0)
      val.capitalize
    else
      val
    end
  end
end
# =>
#  +-------+-------+
#  |header1|header2|
#  +-------+-------+
#  |a1     |A2     |
#  +-------+-------+
#  |b1     |B2     |
#  +-------+-------+

To color even fields red on green background add filter like so:

pastel = Pastel.new

table.render do |renderer|
  renderer.filter = ->(val, row_index, col_index) do
    col_index % 2 == 1 ? pastel.red.on_green(val) : val
  end
end

3.7 Multiline

Renderer options may include :multiline parameter. When set to true, table fields will wrap at their natural line breaks or the column widths(if provided).

table = TTY::Table.new([["First", "1"], ["Multi\nLine\nContent", "2"], ["Third", "3"]])
table.render(:ascii, multiline: true)
# =>
#  +-------+-+
#  |First  |1|
#  |Multi  |2|
#  |Line   | |
#  |Content| |
#  |Third  |3|
#  +-------+-+

When multiline is set to false, all line break characters will be escaped. In cases when the column widths are set, the content will be truncated.

table = TTY::Table.new [["First", "1"], ["Multiline\nContent", "2"], ["Third", "3"]]
table.render :ascii, multiline: false
# =>
#  +------------------+-+
#  |First             |1|
#  |Multiline\nContent|2|
#  |Third             |3|
#  +------------------+-+

3.8 Padding

Renderer also accepts padding option which accepts array with arguments similar to CSS padding.

[2,2,2,2]  # => pad left and right with 2 characters, add 2 lines above and below
[1,2]      # => pad left and right with 2 characters, add 1 line above and below
1          # => pad left and right with 1 character, and 1 lines above and below

Therefore, to apply padding to the example table do:

table.render(:ascii, padding: [1,2,1,2])
# =>
#  +---------+---------+
#  |         |         |
#  | header1 | header2 |
#  |         |         |
#  +---------+---------+
#  |         |         |
#  | a1      | a2      |
#  |         |         |
#  |         |         |
#  | b1      | b2      |
#  |         |         |
#  +---------+---------+

However, when adding top or bottom padding to content with line breaks, the multiline option needs to be set to true to allow for rows to span multiple lines. For example:

table = TTY::Table.new(header: ["head1", "head2"])
table << ["Multi\nLine", "Text\nthat\nwraps"]
table << ["Some\nother\ntext", "Simple"]

This would render as:

table.render(:ascii, multiline: true, padding: [1,2,1,2])
# =>
#  +---------+----------+
#  |         |          |
#  |  h1     |  head2   |
#  |         |          |
#  +---------+----------+
#  |         |          |
#  |  Multi  |  Text    |
#  |  Line   |  that    |
#  |         |  wraps   |
#  |         |          |
#  |         |          |
#  |  Some   |  Simple  |
#  |  other  |          |
#  |  text   |          |
#  |         |          |
#  +---------+----------+

3.9 Resize

You can force table to resize to the terminal full width using the :resize option:

table.render(:ascii, resize: true)

3.10 Width

To control table's column sizes pass width, resize options. By default table's natural column widths are calculated from the content. If the total table width does not fit in terminal window then the table is rotated vertically to preserve content.

The resize property will force the table to expand/shrink to match the terminal width or custom width. On its own the width property will not resize table but only enforce table vertical rotation if content overspills.

For example, given the following table:

header = ["h1", "h2", "h3"]
rows   = [["aaa1", "aa2", "aaaaaaa3"], ["b1", "b2", "b3"]]
table = TTY::Table.new(header, rows)

The result of rending to 80 columns width will produce:

table.render(width: 80, resize: true)
# =>
#  +---------+-------+------------+
#  |h1       |h2     |h3          |
#  +---------+-------+------------+
#  |aaa1     |aa2    |aaaaaaa3    |
#  |b1       |b2     |b3          |
#  +---------+-------+------------+

Contributing

  1. Fork it ( https://github.com/piotrmurach/tty-table/fork )
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am 'Add some feature')
  4. Push to the branch (git push origin my-new-feature)
  5. Create a new Pull Request

This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the Contributor Covenant code of conduct.

Copyright

Copyright (c) 2015 Piotr Murach. See LICENSE for further details.

tty-table's People

Contributors

ameir avatar catmando avatar deemytch avatar emsk avatar gstark avatar olleolleolle avatar piotrmurach avatar slowbro avatar tibra avatar timcraft avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

tty-table's Issues

Top border is not indented correctly when table has no headers

Describe the problem

When rendering a table with an indent, if the table has no headers then the top border is not indented.

Steps to reproduce the problem

require 'tty-table'

ok = TTY::Table.new(header: ["H1","H2","H3"])
ok << ["a1","a2","a3"]
ok << ["b1","b2","b3"]

puts ok.render(:ascii, indent: 12)

broken = TTY::Table.new
broken << ["a1","a2","a3"]
broken << ["b1","b2","b3"]

puts broken.render(:ascii, indent: 12)

Actual behaviour

            +--+--+--+
            |H1|H2|H3|
            +--+--+--+
            |a1|a2|a3|
            |b1|b2|b3|
            +--+--+--+
+--+--+--+
            |a1|a2|a3|
            |b1|b2|b3|
            +--+--+--+

Expected behaviour

            +--+--+--+
            |H1|H2|H3|
            +--+--+--+
            |a1|a2|a3|
            |b1|b2|b3|
            +--+--+--+
            +--+--+--+
            |a1|a2|a3|
            |b1|b2|b3|
            +--+--+--+

Describe your environment

  • OS version: Darwin Kernel Version 23.2.0
  • Ruby version: v3.2.1
  • TTY::Table version: 0.12.0

Streaming of rows for table.

Creating tables where you know the desired column widths (number of characters or percentages) but you don't know the number of rows yet, because you'd like to stream the rows, not wait for all the data until rendering.

Forced vertical tables to not respect terminal width or multiline render option

When rendering a table whose width forces a vertical rotation, tables will always render to their non-multiline-wrapping widths, regardless of whether the terminal can accommodate this.

puts TTY::Table.new(rows: [['Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam volu',12930,'blah',4325678,23456789]],header:['header number one','header number two','header number three','header number four','header number five']).render(:unicode,multiline:true)

Example:

Leading space stripped from cells

Peter,
First off, excellent update. This tty-table split has solved a number of small bugs and annoyances and has made the library generally nicer to use. I'm very pleased with it!

That said, I've noticed an annoying behaviour. When printing a table, cells whose strings contain leading whitespace are stripped. This would make sense in some contexts, but when getting back information from a database it can be important to know exactly the contents of something being printed in the table. I wish there were a way to change this behaviour.

In the past, I've noticed that coloring and stripping of fields have both had slightly different quirks in multiline and non-multiline mode, but I'm not sure if that's the case anymore.

Add Separator at position

Hello,

I read from the doc that it is possible to have a separator for each row:

table.render do |renderer|
  renderer.border.separator = :each_row
end

Is it possible to be able to specify where the separators apply.

For instance, being able to draw something like:

+---------------+----------+-----+
|white_name     |created_at|count|
+---------------+----------+-----+
|mommyville     |01/2016   |123  |
|mommyville     |02/2016   |17   |
|--------------------------------|
|alike          |01/2016   |38   |
|alike          |02/2016   |106  |
|--------------------------------|
|stephanefeugere|02/2016   |65   |
|--------------------------------|
|whysoserious   |02/2016   |126  |
|--------------------------------|
|hallcouture    |02/2016   |25   |
|--------------------------------|
|reinh          |02/2016   |3    |
|reinh          |03/2016   |1    |
+---------------+----------+-----+

This could be really useful also to display totals and/or subtotals rows for a table.

Cheers. TTY::Table is SO COOL.

Create table directly from Hash

It would be great to add support for data saved in array of hash. Eg:

users = [
  { name: "Foo", city: "XYZ", admin: true },
  { name: "Bar", zip: 987654, city: "ABC"}
]

table = TTY::Table.new(users)
renderer = TTY::Table::Renderer::Unicode.new(table)
renderer.render

Output:

#  ┌─────┬───────┬─────┬─────┐
#  │name │zip    │city │admin│
#  ├─────┼───────┼─────┼─────┤
#  │Foo  │       │XYZ  │✔    │
#  │Bar  │987654 │ABC  │     │
#  └─────┴───────┴─────┴─────┘

Current implementation expects each header to have value defined for each row. If values are not available then it is to be replaced by nil. For above example sample input would be:

users = [ {
  name:  ["Foo", "Bar"],
  zip:   [nil, 987654],
  city:  ["XYZ", "ABC"],
  admin: [true, nil]
} ]

I can submit a PR if required.

Multiline render option breaks multi coloured cell data

Spotted an odd bug trying to render multicoloured strings in a cell, tty-tables looks to be getting confused by the end and start of colour codes generated by pastel. Can see it most clearly in :unicode render but it also fails with :basic render.

require "tty-table"

p = Pastel.new
hello = p.decorate("hello",:black, :on_green)
world = p.decorate("world",:black, :on_red)

["#{hello}", "#{hello}#{world}", "#{hello} #{world}"].each do |cell|
  puts cell
  puts cell.inspect
  puts
  tab = TTY::Table.new [:head], [[cell]]
  puts tab.render :unicode, multiline: false
  puts
  puts tab.render :unicode, multiline: true
  puts
end

screen shot 2018-10-22 at 22 13 03

The middle one shows the problem. multiline: true seems to cause tty-table to split hello\e[0m\e[30;41mworld with a newline after [30; but (the 3rd image) it is ok with hello\e[0m \e[30;41mworld (space between coloured bits).

Rotated table missing line separator

When resize is set to false and the table rotate, how do I get a line between each row ?

I am trying this

        table.render do |renderer|
          renderer.border.separator = :each_row
        end

        puts table.render(:unicode)

but not working :(

Dependency conflict on necromancer 0.4.0, tty-screen 0.6.4

Looks like a copy of #13, but for necromancer 0.4.0->0.5.0 and tty-screen 0.6.4->0.7.0

$ pry
[1] pry(main)> require 'tty-prompt'
=> true
[2] pry(main)> require 'tty-table'
Gem::ConflictError: Unable to activate tty-table-0.10.0, because necromancer-0.5.0 conflicts with necromancer (~> 0.4.0), tty-screen-0.7.0 conflicts with tty-screen (~> 0.6.4)
from /usr/home/kschiesser/.rvm/rubies/ruby-2.6.3/lib/ruby/site_ruby/2.6.0/rubygems/specification.rb:2299:in `raise_if_conflicts'
  • OS version: FreeBSD 11.2
  • Ruby version: 2.6.3
$ gem list tty

*** LOCAL GEMS ***

tty-color (0.4.3)
tty-cursor (0.7.0, 0.5.0)
tty-progressbar (0.14.0)
tty-prompt (0.19.0)
tty-reader (0.6.0, 0.3.0)
tty-screen (0.7.0, 0.6.5)
tty-spinner (0.8.0)
tty-table (0.10.0)

Dependency conflict with tty-prompt `necromancer`

require 'tty-prompt'
# => true
require 'tty-table'

Gem::ConflictError: Unable to activate tty-table-0.7.0, because necromancer-0.4.0 conflicts with necromancer (~> 0.3.0)
	from /usr/share/rvm/rubies/ruby-2.4.0/lib/ruby/site_ruby/2.4.0/rubygems/specification.rb:2288:in `raise_if_conflicts'
	from /usr/share/rvm/rubies/ruby-2.4.0/lib/ruby/site_ruby/2.4.0/rubygems/specification.rb:1408:in `activate'
	from /usr/share/rvm/rubies/ruby-2.4.0/lib/ruby/site_ruby/2.4.0/rubygems.rb:220:in `rescue in try_activate'
	from /usr/share/rvm/rubies/ruby-2.4.0/lib/ruby/site_ruby/2.4.0/rubygems.rb:213:in `try_activate'
	from /usr/share/rvm/rubies/ruby-2.4.0/lib/ruby/site_ruby/2.4.0/rubygems/core_ext/kernel_require.rb:126:in `rescue in require'
	from /usr/share/rvm/rubies/ruby-2.4.0/lib/ruby/site_ruby/2.4.0/rubygems/core_ext/kernel_require.rb:40:in `require'
	from (irb):2
	from /usr/share/rvm/rubies/ruby-2.4.0/bin/irb:11:in `<main>'

How to force table to rotate vertically

Maybe I'm missing something here, but when I try to render a table that is larger than the terminal window, tty-table throws Table's width is too small to contain the content (min width 3999, currently set 3999). When I mess with resize and width options, the table still does not want to rotate.

If I try

table.render width: 4000, resize: true

it throws NoMethodError: undefined method 'rindex' for nil:NilClass.

How do I get the table to flip vertically if it is too large? Also, can I have it so that the content overflows horizontally?

Columns are not rendered when the table width exceeds the currently set width.Defaulting

N trailing columns are hidden when the table size exceeds the currently set width. I would assume that they should be vertically rendered as it is already happening with the non hidden columns.

Steps to reproduce the problem

Case 1

require 'tty-table'
rows = [(1..15).to_a.map(&:to_s)]
table = TTY::Table.new rows
puts table.render(width: 30)

Case 2

rows = [(1..15).to_a.map(&:to_s) * 10]
table = TTY::Table.new rows
puts table.render(width: 30)

The width of 30 is artifical. You can also resize your terminal window to a size smaller than all rows combined.

Actual behaviour

Case 1

The table size exceeds the currently set width.Defaulting to vertical orientation.
1 1
2 2

Case 2

The table size exceeds the currently set width.Defaulting to vertical orientation.
1 1
2 2
3 3
4 4
1 1
2 2
3 3
4 4
1 1
2 2
3 3
4 4

I do not see the reason for this behaviour in the code yet. It does not make sense to render more or less columns depending on the amount of given rows and columns.

Expected behaviour

Case 1

The table size exceeds the currently set width.Defaulting to vertical orientation.
1 1
2 2
3 3
4 4
5 5
6 6
7 7
8 8
9 9
10 10
11 11
12 12
13 13
14 14
15 15

Case 2

1 1
2 2
3 3
4 4
5 5
6 6
7 7
8 8
9 9
10 10
11 11
12 12
13 13
14 14
15 15
1 1
2 2
3 3
4 4
5 5
6 6
7 7
8 8
9 9
10 10
11 11
12 12
13 13
14 14
15 15
1 1
2 2
3 3
4 4
5 5
6 6
7 7
8 8
9 9
10 10
11 11
12 12
13 13
14 14
15 15
...  # total 10 times

Describe your environment

  • OS version: Redhat, MacOS Catalina
  • Ruby version: 2.7.0
  • TTY::Table version: 0.12.0 & master

Thanks

Thank you for your great tty gems. I truly love them all and they provide joy to my job. I do not expect a bugfix but merely want to provide a report of the bug.

table.render outputs nothing when used inside Thor

Describe the problem

When using TTY::Table inside a Thor based CLI application the .render method outputs nothing.

table = TTY::Table.new(rows: [[1,2], [3,4])
table.render(:unicode)

results in


If you execute

puts table.render(:unicode)

You see the table as expected. However all cell formatting via renderer.filter lamba, as described in the docs is lost. Specifically the Color coding is lost. For instance

table = TTY::Table.new(rows: [[1,2], [3,4])
say table.render(:unicode) do |render|
  render.filter = ->(val, row_index, col_index) do
    pastel = Pastel.new
    paste.green(val)
  end
end

This renders the table, but only in black and white.

Expected behaviour

I expected a the cells to have green text.

Describe your environment

  • OS version: alpine 3.12.3 (ruby docker version ruby3-alpine)
  • Ruby version: 3.0
  • TTY::Table version: 0.12.0

CSV/JSON/YAML renderers would be nice

In a CLI app it would be kind of neat to have something like: foo service list --format csv. This would be super easy if tty-table had such renderers, just do something like table.render(opts.format || :basic)

Please release version with pastel 0.8 dependency

Describe the problem

There's some gem conflicts accross the various TTY gems that make it really hard to consume the latest (ruby 2.7 compatible) releases of all the gems. Most things depend on pastel 0.8 now, but this gem is still hard pinned to the 0.7 series.

Steps to reproduce the problem

Use this gem along with the latest version of tty-box or tty-prompt

Actual behaviour

Conflicts such as this:

Bundler could not find compatible versions for gem "pastel":
  In Gemfile:
    chef was resolved to 16.5.53, which depends on
      tty-prompt (~> 0.22) was resolved to 0.22.0, which depends on
        pastel (~> 0.8)

    chef was resolved to 16.5.53, which depends on
      tty-table (~> 0.11.0) was resolved to 0.11.0, which depends on
        pastel (~> 0.7.2)

Expected behaviour

Happy bundle updates

Describe your environment

  • OS version: macOS
  • Ruby version: 2.7
  • TTY::Table version: 0.11.0

RangeError: Invalid array length

Describe the problem

node_modules/tty-table/src/format.js:172
            + Array(padBoth + 1 + padRemainder).join(" ")
              ^
RangeError: Invalid array length

  at /node_modules/tty-table/src/format.js:172:15
    at Array.map (<anonymous>)
    at module.exports.wrapCellText (/node_modules/tty-table/src/format.js:156:35)
    at module.exports.buildCell (/node_modules/tty-table/src/render.js:287:39)
    at /node_modules/tty-table/src/render.js:171:26
    at Array.map (<anonymous>)
    at module.exports.buildRow (/node_modules/tty-table/src/render.js:170:13)
    at /node_modules/tty-table/src/render.js:47:24
    at Array.map (<anonymous>)
    at module.exports.stringifyData (/node_modules/tty-table/src/render.js:46:45)

Node.js v18.17.1

The version of tty-table I use is: "tty-table": "^4.1.3"

Steps to reproduce the problem

Your code here to reproduce the issue

Actual behaviour

What happened? This could be a description, log output, error raised etc.

Expected behaviour

What did you expect to happen?

Describe your environment

  • OS version:
  • Ruby version:
  • TTY::Table version:

Headless table fails

I was planning to use a one row table for the alignment I can get from using it. But it doesn't seem to work that way.

require 'tty-table'
# => true
TTY::Table.new ['left', 'center', 'right']
/home/danielpclark/.rvm/gems/ruby-2.4.0/gems/necromancer-0.3.0/lib/necromancer/conversion_target.rb:69: warning: constant ::Fixnum is deprecated
/home/danielpclark/.rvm/gems/ruby-2.4.0/gems/necromancer-0.3.0/lib/necromancer/conversion_target.rb:69: warning: constant ::Bignum is deprecated
NoMethodError: undefined method `zip' for nil:NilClass
	from /home/danielpclark/.rvm/gems/ruby-2.4.0/gems/tty-table-0.7.0/lib/tty/table/row.rb:78:in `initialize'
	from /home/danielpclark/.rvm/gems/ruby-2.4.0/gems/tty-table-0.7.0/lib/tty/table/row.rb:14:in `new'
	from /home/danielpclark/.rvm/gems/ruby-2.4.0/gems/tty-table-0.7.0/lib/tty/table/row.rb:14:in `to_row'
	from /home/danielpclark/.rvm/gems/ruby-2.4.0/gems/tty-table-0.7.0/lib/tty/table.rb:466:in `block in coerce'
	from /home/danielpclark/.rvm/gems/ruby-2.4.0/gems/tty-table-0.7.0/lib/tty/table.rb:466:in `map'
	from /home/danielpclark/.rvm/gems/ruby-2.4.0/gems/tty-table-0.7.0/lib/tty/table.rb:466:in `coerce'
	from /home/danielpclark/.rvm/gems/ruby-2.4.0/gems/tty-table-0.7.0/lib/tty/table.rb:119:in `initialize'
	from /home/danielpclark/.rvm/gems/ruby-2.4.0/gems/tty-table-0.7.0/lib/tty/table.rb:95:in `new'
	from /home/danielpclark/.rvm/gems/ruby-2.4.0/gems/tty-table-0.7.0/lib/tty/table.rb:95:in `new'
	from (irb):2
	from /usr/share/rvm/rubies/ruby-2.4.0/bin/irb:11:in `<main>'

I wrote the following code to solve what I was going for:

def draw left=nil, center=nil, right=nil
  width = SUBMENUWIDTH
  str = left.to_s
  str = str + center.to_s.rjust(width/2 - str.length + center.to_s.length/2)
  str + right.to_s.rjust(width - str.length)
end 

The above lets me use the same method for both left and right alignment, or for centered text. I haven't mixed the two/three yet as I've only needed one or the other.

Render-time options are not consistent

It seems like rendering a table changes some of the properties of the table itself based on the context of the render, rather than simply changing the properties for that render output only.

For instance, if I instantiate a table too wide for the terminal and it defaults to vertical display, I can add a render-time line to make note of this and force separation between each line. However, it only works the first time I render it. If I instantiate a table and then run the same render twice in a row, it will produce different results.

    1.9.3-p392 :088 > table = TTY::Table.new({rows: [['deeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeh','swaaaaaaaaaaaaag','deeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeh','deeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeh','deeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeh'], ['next','row',3,4,5]], header:['derp','deh',3,4,5]})
     => #<TTY::Table header=#<TTY::Table::Header attributes=[#<TTY::Table::Field value="derp" name=nil width=4 colspan=1 rowspan=1 align=nil>, #<TTY::Table::Field value="deh" name=nil width=3 colspan=1 rowspan=1 align=nil>, #<TTY::Table::Field value=3 name=nil width=1 colspan=1 rowspan=1 align=nil>, #<TTY::Table::Field value=4 name=nil width=1 colspan=1 rowspan=1 align=nil>, #<TTY::Table::Field value=5 name=nil width=1 colspan=1 rowspan=1 align=nil>]> rows=[#<TTY::Table::Row fields=["deeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeh", "swaaaaaaaaaaaaag", "deeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeh", "deeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeh", "deeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeh"]>, #<TTY::Table::Row fields=["next", "row", 3, 4, 5]>] orientation=#<TTY::Table::Orientation::Horizontal:0x007f87ca912db0 @name=:horizontal> original_rows=nil original_columns=nil>
    1.9.3-p392 :089 > puts table.render(:unicode) { |renderer| renderer.border.separator = :each_row unless table.orientation.vertical?; puts table.orientation.vertical? }false
    The table size exceeds the currently set width.To avoid error either. Defaulting to vertical orientation.
    ┌────┬────────────────────────────────────────────────────────────────────────┐
    │derp│deeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeh│
    ├────┼────────────────────────────────────────────────────────────────────────┤
    │deh │swaaaaaaaaaaaaag                                                        │
    ├────┼────────────────────────────────────────────────────────────────────────┤
    │3   │deeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeh│
    ├────┼────────────────────────────────────────────────────────────────────────┤
    │4   │deeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeh│
    ├────┼────────────────────────────────────────────────────────────────────────┤
    │5   │deeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeh│
    ├────┼────────────────────────────────────────────────────────────────────────┤
    │derp│next                                                                    │
    ├────┼────────────────────────────────────────────────────────────────────────┤
    │deh │row                                                                     │
    ├────┼────────────────────────────────────────────────────────────────────────┤
    │3   │3                                                                       │
    ├────┼────────────────────────────────────────────────────────────────────────┤
    │4   │4                                                                       │
    ├────┼────────────────────────────────────────────────────────────────────────┤
    │5   │5                                                                       │
    └────┴────────────────────────────────────────────────────────────────────────┘
     => nil
    1.9.3-p392 :090 > puts table.render(:unicode) { |renderer| renderer.border.separator = :each_row unless table.orientation.vertical?; puts table.orientation.vertical? }
    true
    ┌────┬────────────────────────────────────────────────────────────────────────┐
    │derp│deeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeh│
    │deh │swaaaaaaaaaaaaag                                                        │
    │3   │deeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeh│
    │4   │deeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeh│
    │5   │deeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeh│
    │derp│next                                                                    │
    │deh │row                                                                     │
    │3   │3                                                                       │
    │4   │4                                                                       │
    │5   │5                                                                       │
    └────┴────────────────────────────────────────────────────────────────────────┘
     => nil

undefined method `rindex' for nil:NilClass when using resize: true

Hello! Thanks for creating this gem, it's been very useful for our team.

We are experiencing a bug where table resize raises an exception. The bug only occurs when terminal size is small enough that table resize is required:

$ stty size
21 81
$ ruby /tmp/test2.rb 
/usr/local/rvm/gems/ruby-2.3.6/gems/strings-0.1.1/lib/strings/truncate.rb:59:in `truncate': undefined method `rindex' for nil:NilClass (NoMethodError)
    from /usr/local/rvm/gems/ruby-2.3.6/gems/strings-0.1.1/lib/strings.rb:98:in `truncate'
    from /usr/local/rvm/gems/ruby-2.3.6/gems/tty-table-0.10.0/lib/tty/table/operation/truncation.rb:38:in `call'
    from /usr/local/rvm/gems/ruby-2.3.6/gems/tty-table-0.10.0/lib/tty/table/operations.rb:59:in `block (4 levels) in apply_to'
    from /usr/local/rvm/gems/ruby-2.3.6/gems/tty-table-0.10.0/lib/tty/table/operations.rb:58:in `each'
    from /usr/local/rvm/gems/ruby-2.3.6/gems/tty-table-0.10.0/lib/tty/table/operations.rb:58:in `block (3 levels) in apply_to'
    from /usr/local/rvm/gems/ruby-2.3.6/gems/tty-table-0.10.0/lib/tty/table/operations.rb:57:in `each'
    from /usr/local/rvm/gems/ruby-2.3.6/gems/tty-table-0.10.0/lib/tty/table/operations.rb:57:in `block (2 levels) in apply_to'
    from /usr/local/rvm/gems/ruby-2.3.6/gems/tty-table-0.10.0/lib/tty/table/operations.rb:55:in `each'
    from /usr/local/rvm/gems/ruby-2.3.6/gems/tty-table-0.10.0/lib/tty/table/operations.rb:55:in `each_with_index'
    from /usr/local/rvm/gems/ruby-2.3.6/gems/tty-table-0.10.0/lib/tty/table/operations.rb:55:in `block in apply_to'
    from /usr/local/rvm/gems/ruby-2.3.6/gems/tty-table-0.10.0/lib/tty/table/operations.rb:54:in `each'
    from /usr/local/rvm/gems/ruby-2.3.6/gems/tty-table-0.10.0/lib/tty/table/operations.rb:54:in `each_with_index'
    from /usr/local/rvm/gems/ruby-2.3.6/gems/tty-table-0.10.0/lib/tty/table/operations.rb:54:in `apply_to'
    from /usr/local/rvm/gems/ruby-2.3.6/gems/tty-table-0.10.0/lib/tty/table/renderer/basic.rb:203:in `render'
    from /usr/local/rvm/gems/ruby-2.3.6/gems/tty-table-0.10.0/lib/tty/table/renderer.rb:77:in `render'
    from /usr/local/rvm/gems/ruby-2.3.6/gems/tty-table-0.10.0/lib/tty/table/renderer.rb:99:in `render_with'
    from /usr/local/rvm/gems/ruby-2.3.6/gems/tty-table-0.10.0/lib/tty/table.rb:452:in `render_with'
    from /usr/local/rvm/gems/ruby-2.3.6/gems/tty-table-0.10.0/lib/tty/table.rb:426:in `render'
    from /tmp/test2.rb:11:in `<main>'

Here is a script to reproduce:

#!/usr/bin/env ruby
require 'tty-table'
table = TTY::Table.new(header: ['my header', 'a', 'b', 'c', 'd'])
string = 'some long data that must be wrapped'
table << [string, '', 'data', string, string]
puts table.render(:unicode, resize: true)

:padding and :resize don't play nicely together

#!/usr/bin/env ruby
# encoding: UTF-8

require "tty"

table = TTY::Table.new(header: [ "Column 1", "Column 2", "Column 3"]) do |t|
  t << [ "11", "12", "13" ]
  t << [ "21", "22", "23" ]
  t << [ "31", "32", "33" ]
end

puts table.render(:ascii, resize: true)

puts table.render(:ascii, padding: [1, 1, 1, 1])

puts table.render(:ascii, resize: true, padding: [1, 1, 1, 1])
+--------------------------+-------------------------+-------------------------+
|Column 1                  |Column 2                 |Column 3                 |
+--------------------------+-------------------------+-------------------------+
|11                        |12                       |13                       |
|21                        |22                       |23                       |
|31                        |32                       |33                       |
+--------------------------+-------------------------+-------------------------+
+----------+----------+----------+
|          |          |          |
| Column 1 | Column 2 | Column 3 |
|          |          |          |
+----------+----------+----------+
|          |          |          |
| 11       | 12       | 13       |
|          |          |          |
|          |          |          |
| 21       | 22       | 23       |
|          |          |          |
|          |          |          |
| 31       | 32       | 33       |
|          |          |          |
+----------+----------+----------+
+----------------------------+---------------------------+----------------------
-----+
|                            |                           |                      
     |
| Column 1                   | Column 2                  | Column 3             
     |
|                            |                           |                      
     |
+----------------------------+---------------------------+----------------------
-----+
|                            |                           |                      
     |
| 11                         | 12                        | 13                   
     |
|                            |                           |                      
     |
|                            |                           |                      
     |
| 21                         | 22                        | 23                   
     |
|                            |                           |                      
     |
|                            |                           |                      
     |
| 31                         | 32                        | 33                   
     |
|                            |                           |                      
     |
+----------------------------+---------------------------+----------------------
-----+

Column width spacing does not account for ANSI color sequences

To reproduce:

1.9.3-p392 :038 > p = Pastel.new
1.9.3-p392 :039 > puts TTY::Table.new(rows:[['test'],['test']],header:[p.green('derp')]).render(:unicode)
┌─────────────┐
│derp         │
├─────────────┤
│test         │
│test         │
└─────────────┘

Compare header field width to:

1.9.3-p392 :042 > puts TTY::Table.new(rows:[['test'],['test']],header:['derp']).render(:unicode)
┌────┐
│derp│
├────┤
│test│
│test│
└────┘

Wrong table header width when using TTY::Link

Describe the problem

When tables contain a TTY::Link, the right margin is off.
It seems that header width accounts for the text size when links are not supported (which is larger).

Steps to reproduce the problem

require "bundler/inline"

gemfile do
  source "https://rubygems.org"
  gem "tty-table"
  gem "tty-link"
end

require "tty-table"
require "tty-link"

headers = ["header 1", "header 2"]
rows = [
  [TTY::Link.link_to("hello", "https://example.com"), "world"]
]

puts TTY::Table.new(headers, rows).render

Actual behaviour

Note that it fails with all rendering modes
image

Expected behaviour

In this example, the "header 1" column should be narrower.

Describe your environment

  • OS version: macOS Big Sur 11.6
  • Ruby version: ruby 3.0.3p157 (2021-11-24 revision 3fb7d2cadc) [x86_64-darwin20]
  • TTY::Table version: 0.12.0
  • TTY::Link version: 0.1.1

Align cells via filter

Given the ability to align a cell by replacing its value with a hash containing {value: val, alignment: align) of some sort, one would expect the ability to do this in filters at render-time as well. For instance,

table               = TTY::Table.new(table_data).render(*@render_info) do |renderer|
  renderer.border.style = @color
  renderer.filter       = Proc.new { |val, _, _| {:value => val, :alignment => :right} }
end

However, this produces the following:

1.9.3-p392 :028 > puts t.render(:unicode, multiline: true) do |renderer|
1.9.3-p392 :029 >     renderer.filter       = Proc.new { |val, _, _| {:value => val, :alignment => :right} }
1.9.3-p392 :030?>   end
┌───────────────┬────────────────┐
│host           │total           │
├───────────────┼────────────────┤
│test_value     │37              │
└───────────────┴────────────────┘

Strange separator inserting

I want to separate rows by differ type. portfolio_table << :separator is not working properly inside each-block.

portfolio_table << :separator << row_data(item) is not working properly also.

Steps to reproduce the problem

def portfolio_table
  @portfolio_table ||= TTY::Table.new(
    header: %w[Type Name Amount Avg.\ price Yield Yield\ %]
  )
end

prev_type = positions.first[:instrumentType]

positions.each do |item|
  portfolio_table << :separator if item[:instrumentType] != prev_type
  portfolio_table << row_data(item)
  prev_type = item[:instrumentType]
end

puts portfolio_table.render(:ascii, padding: [0, 1, 0, 1])

Actual behaviour

+---------
| Type    
| STOCK   
| STOCK   
| STOCK   
| STOCK   
| STOCK   
| STOCK   
+---------
| STOCK   
| STOCK   
| STOCK   
| STOCK   
| STOCK   
| STOCK   
| STOCK   
| STOCK   
| STOCK   
| STOCK   
| STOCK   
| BOND    
| ETF     
| ETF     
| ETF     
| ETF     
| ETF     
| ETF     
| CURRENCY
| CURRENCY
+----------

Expected behaviour

Type
------
Stock
Stock
Stock
Stock
Stock
Stock
Stock
Stock
Stock
Stock
Stock
Stock
Stock
Stock
Stock
Stock
Stock
------
Bond
------
Etf
Etf
Etf
Etf
Etf
Etf
------
Currency
Currency

Environment

  • OS version: macOS Catalina
  • Ruby version: 2.7.1
  • TTY::Table version: tty-table (0.11.0)

README Filter test code

When I used the example code, using tty version 0.4.0, and adding: require 'tty'.

3.6 Filter

table.render do |renderer|
  renderer.filter = proc do |val, row_index, col_index|
    col_index % 2 == 1 ? TTY.color.set(val, :red, :on_green) : val
  end
end

I was getting it raising an error.

undefined method 'color' for TTY:Module (NoMethodError)

Is this code correct? I have been using a work which gets me going:

col_index % 2 == 1 ? Pastel.new.on_green(val) : val

anyway to add a separator between arbitrary rows?

would be handy to be able to somehow indicate that there is a separator between two arbitrary rows.

perhaps if a row was not an array but instead the keyword :separator ??

(FYI this is a very nice gem! thanks!)

border.separator = :each_row

This option as documented in the README does not work. Here is my IRB session:

>> require 'tty-table' #=> true
>> table = TTY::Table.new ['header1', 'header2'], [['a1', 'a2'], ['b1', 'b2']]
=> #<TTY::Table header=#<TTY::Table::Header fields=["header1", "header2"]> rows=[#<TTY::Table::Row fields=["a1", "a2"]>, #<TTY::Table::Row fields=["b1", "b2"]>] orientation=#<TTY::Table::Orientation::Horizontal:0x00007f819b8be740 @name=:horizontal> original_rows=nil original_columns=nil>
>> puts table.render(:ascii) do |renderer|
 >       renderer.border.separator = :each_row
|    end #=> nil
+-------+-------+
|header1|header2|
+-------+-------+
|a1     |a2     |
|b1     |b2     |
+-------+-------+

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.