terminal-table 1.7.2 → 3.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/Rakefile CHANGED
@@ -1,8 +1,14 @@
1
- require "bundler/gem_tasks"
1
+ require 'bundler'
2
+ Bundler.setup
3
+ Bundler::GemHelper.install_tasks
2
4
 
3
- desc "Run specs"
4
- task :spec do
5
- sh "bundle exec rspec -f progress"
5
+ require 'rake'
6
+ require 'rspec/core/rake_task'
7
+
8
+ desc "Run all examples"
9
+ RSpec::Core::RakeTask.new(:spec) do |t|
10
+ t.ruby_opts = %w[-w]
11
+ t.rspec_opts = %w[--color]
6
12
  end
7
13
 
8
14
  desc "Default: Run specs"
data/examples/data.csv ADDED
@@ -0,0 +1,4 @@
1
+ First Name,Last Name,Email
2
+ TJ,Holowaychuk,tj@vision-media.ca
3
+ Bob,Someone,bob@vision-media.ca
4
+ Joe,Whatever,joe@vision-media.ca
data/examples/examples.rb CHANGED
File without changes
@@ -0,0 +1,89 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $:.unshift File.dirname(__FILE__) + '/../lib'
4
+ require 'terminal-table/import'
5
+
6
+ Terminal::Table::Style.defaults = { :border => :unicode_round }
7
+ # Terminal::Table::UnicodeThickEdgeBorder.new()
8
+
9
+ puts
10
+ puts table(['a', 'b'], [1, 2], [3, 4])
11
+
12
+ puts
13
+ puts table(['name', 'content'], ['ftp.example.com', '1.1.1.1'], ['www.example.com', '|lalalala|lalala|'])
14
+
15
+ puts
16
+ t = table ['a', 'b']
17
+ t.style = {:padding_left => 2, :width => 80}
18
+ t << [1, 2]
19
+ t << [3, 4]
20
+ t << :separator
21
+ t << [4, 6]
22
+ puts t
23
+
24
+ puts
25
+ user_table = table do |v|
26
+ v.title = "Contact Information"
27
+ v.headings = 'First Name', 'Last Name', 'Email'
28
+ v << %w( TJ Holowaychuk tj@vision-media.ca )
29
+ v << %w( Bob Someone bob@vision-media.ca )
30
+ v << %w( Joe Whatever bob@vision-media.ca )
31
+ end
32
+ puts user_table
33
+
34
+ puts
35
+ user_table = table do |v|
36
+ v.style.width = 80
37
+ v.headings = 'First Name', 'Last Name', 'Email'
38
+ v << %w( TJ Holowaychuk tj@vision-media.ca )
39
+ v << %w( Bob Someone bob@vision-media.ca )
40
+ v << %w( Joe Whatever bob@vision-media.ca )
41
+ end
42
+ puts user_table
43
+
44
+ puts
45
+ user_table = table do
46
+ self.headings = 'First Name', 'Last Name', 'Email'
47
+ add_row ['TJ', 'Holowaychuk', 'tj@vision-media.ca']
48
+ add_row ['Bob', 'Someone', 'bob@vision-media.ca']
49
+ add_row ['Joe', 'Whatever', 'joe@vision-media.ca']
50
+ add_separator
51
+ add_row ['Total', { :value => '3', :colspan => 2, :alignment => :right }]
52
+ align_column 1, :center
53
+ end
54
+ puts user_table
55
+
56
+ puts
57
+ user_table = table do
58
+ self.headings = ['First Name', 'Last Name', {:value => 'Phones', :colspan => 2, :alignment => :center}]
59
+ #add_row ['Bob', 'Someone', '123', '456']
60
+ add_row [{:value => "Bob Someone", :colspan => 3, :alignment => :center}, '123456']
61
+ add_row :separator
62
+ add_row ['TJ', 'Holowaychuk', {:value => "No phones\navaiable", :colspan => 2, :alignment => :center}]
63
+ add_row :separator
64
+ add_row ['Joe', 'Whatever', '4324', '343242']
65
+ end
66
+ puts user_table
67
+
68
+ rows = []
69
+ rows << ['Lines', 100]
70
+ rows << ['Comments', 20]
71
+ rows << ['Ruby', 70]
72
+ rows << ['JavaScript', 30]
73
+ puts table([nil, 'Lines'], *rows)
74
+
75
+ rows = []
76
+ rows << ['Lines', 100]
77
+ rows << ['Comments', 20]
78
+ rows << ['Ruby', 70]
79
+ rows << ['JavaScript', 30]
80
+ puts table(nil, *rows)
81
+
82
+ rows = []
83
+ rows << ['Lines', 100]
84
+ rows << ['Comments', 20]
85
+ rows << ['Ruby', 70]
86
+ rows << ['JavaScript', 30]
87
+ table = table([{ :value => 'Stats', :colspan => 2, :alignment => :center }], *rows)
88
+ table.align_column 1, :right
89
+ puts table
@@ -0,0 +1,34 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # Methods to suppress left/right borders using border_left & border_right
4
+
5
+ require_relative "../lib/terminal-table"
6
+ table = Terminal::Table.new do |t|
7
+ t.headings = ['id', 'name']
8
+ t.rows = [[1, 'One'], [2, 'Two'], [3, 'Three']]
9
+ t.style = { :border_left => false, :border_top => false, :border_bottom => false }
10
+ end
11
+
12
+ puts table
13
+ puts
14
+
15
+ # no right
16
+ table.style = {:border_right => false }
17
+ puts table
18
+ puts
19
+
20
+ # no right
21
+ table.style = {:border_left => true }
22
+ puts table
23
+ puts
24
+
25
+ table.style.border = Terminal::Table::UnicodeBorder.new
26
+ puts table
27
+
28
+
29
+ table.style = {:border_right => false, :border_left => true }
30
+ puts table
31
+
32
+ table.style = {:border_right => true, :border_left => false }
33
+ puts table
34
+
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+ require_relative "../lib/terminal-table"
3
+ puts Terminal::Table.new(headings: ['heading A', 'heading B'], rows: [['a', 'b'], ['a', 'b']], style: {border: Terminal::Table::MarkdownBorder.new})
4
+
@@ -0,0 +1,36 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require_relative '../lib/terminal-table'
4
+
5
+ puts Terminal::Table.new(headings: ['a', 'b', 'c', 'd'], style: { border: :unicode })
6
+
7
+ puts
8
+
9
+ tbl = Terminal::Table.new do |t|
10
+ t.style = { border: :unicode }
11
+ t.add_separator
12
+ t.add_separator
13
+ t.add_row ['x','y','z']
14
+ t.add_separator
15
+ t.add_separator
16
+ end
17
+ puts tbl
18
+
19
+ puts
20
+
21
+ puts Terminal::Table.new(headings: [['a', 'b', 'c', 'd'], ['cat','dog','frog','mouse']], style: { border: :unicode })
22
+
23
+ puts
24
+
25
+ puts Terminal::Table.new(headings: ['a', 'b', 'c', 'd'])
26
+
27
+ puts
28
+
29
+ tbl = Terminal::Table.new do |t|
30
+ t.add_separator
31
+ t.add_separator
32
+ t.add_row ['x','y','z']
33
+ t.add_separator
34
+ t.add_separator
35
+ end
36
+ puts tbl
@@ -0,0 +1,42 @@
1
+ #!/usr/bin/env ruby
2
+ require 'colorize'
3
+ require_relative '../lib/terminal-table.rb'
4
+
5
+ original_sample_data = [
6
+ ["Sep 2016", 33, [-38, -53.52], 46, [-25, -35.21]],
7
+ ["Oct 2016", 35, [2, 6.06], 50, [4, 8.69]]
8
+ ]
9
+
10
+ table = Terminal::Table.new headings: ["Month".cyan,"Monthly IT".cyan,"IT Difference OPM".cyan,
11
+ "Monthly OOT".cyan,"OOT Difference OPM".cyan], rows: original_sample_data
12
+
13
+ table.style = { padding_left: 2, padding_right: 2, border_x: "-".blue, border_y: "|".blue, border_i: "+".blue }
14
+
15
+ puts table
16
+
17
+ puts ""
18
+ puts "^ good table"
19
+ puts "v wonky table"
20
+ puts ""
21
+
22
+ split_column_sample_data = [
23
+ ["Sep 2016", 33, -38, -53.52, 46, -25, -35.21],
24
+ ["Oct 2016", 35, 2, 6.06, 50, 4, 8.69]
25
+ ]
26
+
27
+ table = Terminal::Table.new headings: ["Month".cyan,"Monthly IT".cyan,
28
+ {value: "IT Difference OPM".cyan, colspan: 2}, "Monthly OOT".cyan,
29
+ {value: "OOT Difference OPM".cyan, colspan: 2}], rows: split_column_sample_data
30
+
31
+ table.style = { padding_left: 2, padding_right: 2, border_x: "-".blue, border_y: "|".blue, border_i: "+".blue }
32
+
33
+ puts table
34
+
35
+
36
+ table = Terminal::Table.new headings: ["Month","Monthly IT",
37
+ {value: "IT Difference OPM", colspan: 2}, "Monthly OOT",
38
+ {value: "OOT Difference OPM", colspan: 2}], rows: split_column_sample_data
39
+
40
+ table.style = { padding_left: 2, padding_right: 2, border_x: "-".blue, border_y: "|".cyan, border_i: "+" }
41
+
42
+ puts table
@@ -0,0 +1,34 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "csv"
4
+ $LOAD_PATH << "#{__dir__}/../lib"
5
+ require "terminal-table"
6
+
7
+ #
8
+ # Usage:
9
+ # ./show_csv_table.rb data.csv
10
+ # cat data.csv | ./show_csv_table.rb
11
+ # cat data.csv | ./show_csv_table.rb -
12
+ #
13
+ #
14
+ # Reads a CSV from $stdin if no argument given, or argument is '-'
15
+ # otherwise interprets first cmdline argument as the CSV filename
16
+ #
17
+ use_stdin = ARGV[0].nil? || (ARGV[0] == '-')
18
+ io_object = use_stdin ? $stdin : File.open(ARGV[0], 'r')
19
+ csv = CSV.new(io_object)
20
+
21
+ #
22
+ # Convert to an array for use w/ terminal-table
23
+ # The assumption is that this is a pretty small spreadsheet.
24
+ #
25
+ csv_array = csv.to_a
26
+
27
+ user_table = Terminal::Table.new do |v|
28
+ v.style = { :border => :unicode_round } # >= v3.0.0
29
+ v.title = "Some Title"
30
+ v.headings = csv_array[0]
31
+ v.rows = csv_array[1..-1]
32
+ end
33
+
34
+ puts user_table
@@ -0,0 +1,23 @@
1
+ #!/usr/bin/env ruby
2
+ require_relative "../lib/terminal-table"
3
+
4
+ #
5
+ # An example of how to manually add separators with non-default
6
+ # border_type to enable a footer row.
7
+ #
8
+ table = Terminal::Table.new do |t|
9
+ # set the style
10
+ t.style = { border: :unicode_thick_edge }
11
+
12
+ # header row
13
+ t.headings = ['fruit', 'count']
14
+
15
+ # some row data
16
+ t.add_row ['apples', 7]
17
+ t.add_row ['bananas', 19]
18
+ t.add_separator border_type: :strong
19
+ # footer row
20
+ t.add_row ['total', 26]
21
+ end
22
+
23
+ puts table.render
@@ -21,6 +21,6 @@
21
21
  # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
22
  #++
23
23
 
24
- %w(cell row separator style table table_helper version).each do |file|
25
- require "terminal-table/#{file}"
24
+ %w(cell row separator style table table_helper util version).each do |file|
25
+ require_relative "./terminal-table/#{file}"
26
26
  end
@@ -57,7 +57,7 @@ module Terminal
57
57
  def render(line = 0)
58
58
  left = " " * @table.style.padding_left
59
59
  right = " " * @table.style.padding_right
60
- display_width = Unicode::DisplayWidth.of(escape(lines[line]))
60
+ display_width = Unicode::DisplayWidth.of(Util::ansi_escape(lines[line]))
61
61
  render_width = lines[line].to_s.size - display_width + width
62
62
  align("#{left}#{lines[line]}#{right}", alignment, render_width + @table.cell_padding)
63
63
  end
@@ -68,7 +68,7 @@ module Terminal
68
68
  # removes all ANSI escape sequences (e.g. color)
69
69
 
70
70
  def value_for_column_width_recalc
71
- lines.map{ |s| escape(s) }.max_by{ |s| Unicode::DisplayWidth.of(s) }
71
+ lines.map{ |s| Util::ansi_escape(s) }.max_by{ |s| Unicode::DisplayWidth.of(s) }
72
72
  end
73
73
 
74
74
  ##
@@ -82,12 +82,12 @@ module Terminal
82
82
  inner_width + padding
83
83
  end
84
84
 
85
- ##
86
- # removes all ANSI escape sequences (e.g. color)
87
- def escape(line)
88
- line.to_s.gsub(/\x1b(\[|\(|\))[;?0-9]*[0-9A-Za-z]/, '').
89
- gsub(/\x1b(\[|\(|\))[;?0-9]*[0-9A-Za-z]/, '').
90
- gsub(/(\x03|\x1a)/, '')
85
+ def inspect
86
+ fields = %i[alignment colspan index value width].map do |name|
87
+ val = self.instance_variable_get('@'+name.to_s)
88
+ "@#{name}=#{val.inspect}"
89
+ end.join(', ')
90
+ return "#<#{self.class} #{fields}>"
91
91
  end
92
92
  end
93
93
  end
@@ -12,7 +12,7 @@ module Terminal
12
12
  ##
13
13
  # Initialize with _width_ and _options_.
14
14
 
15
- def initialize table, array = []
15
+ def initialize table, array = [], **_kwargs
16
16
  @cell_index = 0
17
17
  @table = table
18
18
  @cells = []
@@ -36,17 +36,31 @@ module Terminal
36
36
  end
37
37
 
38
38
  def render
39
- y = @table.style.border_y
39
+ vleft, vcenter, vright = @table.style.vertical
40
40
  (0...height).to_a.map do |line|
41
- y + cells.map do |cell|
41
+ vleft + cells.map do |cell|
42
42
  cell.render(line)
43
- end.join(y) + y
43
+ end.join(vcenter) + vright
44
44
  end.join("\n")
45
45
  end
46
46
 
47
47
  def number_of_columns
48
48
  @cells.collect(&:colspan).inject(0, &:+)
49
49
  end
50
+
51
+ # used to find indices where we have table '+' crossings.
52
+ # in cases where the colspan > 1, then we will skip over some numbers
53
+ # if colspan is always 1, then the list should be incrementing by 1.
54
+ #
55
+ # skip 0 entry, because it's the left side.
56
+ # skip last entry, because it's the right side.
57
+ # we only care about "+/T" style crossings.
58
+ def crossings
59
+ idx = 0
60
+ @cells[0...-1].map { |c| idx += c.colspan }
61
+ end
62
+
50
63
  end
64
+
51
65
  end
52
66
  end
@@ -2,13 +2,65 @@ module Terminal
2
2
  class Table
3
3
  class Separator < Row
4
4
 
5
+ ##
6
+ # `prevrow`, `nextrow` contain references to adjacent rows.
7
+ #
8
+ # `border_type` is a symbol used to control which type of border is used
9
+ # on the separator (:top for top-edge, :bot for bottom-edge,
10
+ # :div for interior, and :strong for emphasized-interior)
11
+ #
12
+ # `implicit` is false for user-added separators, and true for
13
+ # implicit/auto-generated separators.
14
+
15
+ def initialize(*args, border_type: :div, implicit: false)
16
+ super
17
+ @prevrow, @nextrow = nil, nil
18
+ @border_type = border_type
19
+ @implicit = implicit
20
+ end
21
+
22
+ attr_accessor :border_type
23
+ attr_reader :implicit
24
+
5
25
  def render
6
- arr_x = (0...@table.number_of_columns).to_a.map do |i|
7
- @table.style.border_x * (@table.column_width(i) + @table.cell_padding)
26
+ left_edge, ctrflat, ctrud, right_edge, ctrdn, ctrup = @table.style.horizontal(border_type)
27
+
28
+ prev_crossings = @prevrow.respond_to?(:crossings) ? @prevrow.crossings : []
29
+ next_crossings = @nextrow.respond_to?(:crossings) ? @nextrow.crossings : []
30
+ rval = [left_edge]
31
+ numcols = @table.number_of_columns
32
+ (0...numcols).each do |idx|
33
+ rval << ctrflat * (@table.column_width(idx) + @table.cell_padding)
34
+ pcinc = prev_crossings.include?(idx+1)
35
+ ncinc = next_crossings.include?(idx+1)
36
+ border_center = if pcinc && ncinc
37
+ ctrud
38
+ elsif pcinc
39
+ ctrup
40
+ elsif ncinc
41
+ ctrdn
42
+ elsif !ctrud.empty?
43
+ # special case if the center-up-down intersection is empty
44
+ # which happens when verticals/intersections are removed. in that case
45
+ # we do not want to replace with a flat element so return empty-string in else block
46
+ ctrflat
47
+ else
48
+ ''
49
+ end
50
+ rval << border_center if idx < numcols-1
8
51
  end
9
- border_i = @table.style.border_i
10
- border_i + arr_x.join(border_i) + border_i
52
+
53
+ rval << right_edge
54
+ rval.join
55
+ end
56
+
57
+ # Save off neighboring rows, so that we can use them later in determining
58
+ # which types of table edges to use.
59
+ def save_adjacent_rows(prevrow, nextrow)
60
+ @prevrow = prevrow
61
+ @nextrow = nextrow
11
62
  end
63
+
12
64
  end
13
65
  end
14
66
  end