tty 0.0.4 → 0.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. data/.travis.yml +1 -1
  2. data/README.md +19 -7
  3. data/lib/tty.rb +10 -0
  4. data/lib/tty/support/equatable.rb +1 -0
  5. data/lib/tty/support/unicode.rb +36 -0
  6. data/lib/tty/table.rb +3 -3
  7. data/lib/tty/table/border.rb +104 -0
  8. data/lib/tty/table/border/ascii.rb +41 -0
  9. data/lib/tty/table/border/null.rb +49 -0
  10. data/lib/tty/table/border/unicode.rb +41 -0
  11. data/lib/tty/table/column_set.rb +77 -0
  12. data/lib/tty/table/operation/alignment.rb +2 -0
  13. data/lib/tty/table/operation/alignment_set.rb +4 -58
  14. data/lib/tty/table/operation/truncation.rb +15 -19
  15. data/lib/tty/table/operation/wrapped.rb +34 -0
  16. data/lib/tty/table/renderer.rb +8 -11
  17. data/lib/tty/table/renderer/ascii.rb +15 -0
  18. data/lib/tty/table/renderer/basic.rb +21 -34
  19. data/lib/tty/table/renderer/unicode.rb +2 -2
  20. data/lib/tty/vector.rb +117 -0
  21. data/lib/tty/version.rb +1 -1
  22. data/spec/tty/table/border/ascii/rendering_spec.rb +49 -0
  23. data/spec/tty/table/border/new_spec.rb +21 -0
  24. data/spec/tty/table/border/null/rendering_spec.rb +49 -0
  25. data/spec/tty/table/border/unicode/rendering_spec.rb +49 -0
  26. data/spec/tty/table/column_set/extract_widths_spec.rb +26 -0
  27. data/spec/tty/table/operation/alignment_set/align_rows_spec.rb +4 -4
  28. data/spec/tty/table/operation/alignment_set/new_spec.rb +1 -1
  29. data/spec/tty/table/operation/wrapped/wrap_spec.rb +22 -0
  30. data/spec/tty/table/properties_spec.rb +3 -0
  31. data/spec/tty/table/renderer/basic/render_spec.rb +144 -33
  32. data/spec/tty/table/renderer/pick_renderer_spec.rb +25 -0
  33. data/spec/tty/table/to_s_spec.rb +51 -0
  34. data/spec/tty/vector/new_spec.rb +47 -0
  35. metadata +35 -8
@@ -3,6 +3,8 @@
3
3
  module TTY
4
4
  class Table
5
5
  module Operation
6
+
7
+ # A class representing an alignment of cell data.
6
8
  class Alignment
7
9
  include TTY::Coercion
8
10
 
@@ -5,34 +5,7 @@ module TTY
5
5
  module Operation
6
6
 
7
7
  # A class which responsiblity is to align table rows and header.
8
- class AlignmentSet
9
- include Enumerable
10
-
11
- # Initialize an AlignmentSet
12
- #
13
- # @param [Array] alignments
14
- #
15
- # @api public
16
- def initialize(alignments = nil)
17
- @alignments = alignments || []
18
- end
19
-
20
- # Iterate over each alignment in the set
21
- #
22
- # @example
23
- # alignment_set = AlignmentSet.new alignments
24
- # alignment_set.each { |alignment| ... }
25
- #
26
- # @yield [alignment]
27
- #
28
- # @return [self]
29
- #
30
- # @api public
31
- def each
32
- return to_enum unless block_given?
33
- to_ary.each { |alignment| yield alignment }
34
- self
35
- end
8
+ class AlignmentSet < Vector
36
9
 
37
10
  # Lookup an alignment by index
38
11
  #
@@ -42,9 +15,7 @@ module TTY
42
15
  #
43
16
  # @api public
44
17
  def [](index)
45
- @alignments.fetch(index) do |alignment_index|
46
- :left
47
- end
18
+ elements.fetch(index, :left)
48
19
  end
49
20
 
50
21
  # Return each alignment in an Array
@@ -56,28 +27,7 @@ module TTY
56
27
  map { |alignment| alignment }
57
28
  end
58
29
 
59
- # @return [Array]
60
- #
61
- # @api public
62
- def to_ary
63
- @alignments
64
- end
65
-
66
- # @return [Array[Alignment]]
67
- #
68
- # @api public
69
- def to_a
70
- @alignments
71
- end
72
-
73
- # @return [Boolean]
74
- #
75
- # @api public
76
- def empty?
77
- to_ary.empty?
78
- end
79
-
80
- # Aligns table header
30
+ # Align table header
81
31
  #
82
32
  # @return [Array[String]]
83
33
  #
@@ -115,11 +65,7 @@ module TTY
115
65
  column_width = options[:column_widths][index]
116
66
  alignment = Alignment.new self[index]
117
67
 
118
- if index == row.size - 1
119
- line << alignment.format(cell, column_width)
120
- else
121
- line << alignment.format(cell, column_width, ' ')
122
- end
68
+ line << alignment.format(cell, column_width)
123
69
  end
124
70
  line
125
71
  end
@@ -6,36 +6,32 @@ module TTY
6
6
 
7
7
  # A class responsible for shortening text.
8
8
  class Truncation
9
+ include Unicode
9
10
 
10
- def truncate(string, width, options={})
11
- trailing = options.fetch :trailing, '…'
12
-
11
+ # Shorten given string with traling character.
12
+ #
13
+ # @param [String] string
14
+ # the string to truncate
15
+ # @param [Integer] width
16
+ # the maximum width
17
+ # @param [String] trailing
18
+ # the trailing character
19
+ #
20
+ # @return [String]
21
+ #
22
+ # @api public
23
+ def truncate(string, width, trailing = '…')
13
24
  as_unicode do
14
25
  chars = string.chars.to_a
15
- print 'CHARS '
16
- p chars
17
26
  if chars.length < width
18
27
  chars.join
19
28
  else
20
29
  traling_size = trailing.chars.to_a.size
21
- ( chars[0, width-traling_size].join ) + trailing
30
+ ( chars[0, width - traling_size].join ) + trailing
22
31
  end
23
32
  end
24
33
  end
25
34
 
26
- if "".respond_to?(:encode)
27
- def as_unicode
28
- yield
29
- end
30
- else
31
- def as_unicode
32
- old, $KCODE = $KCODE, "U"
33
- yield
34
- ensure
35
- $KCODE = old
36
- end
37
- end
38
-
39
35
  end # Truncation
40
36
  end # Operation
41
37
  end # Table
@@ -0,0 +1,34 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ module TTY
4
+ class Table
5
+ module Operation
6
+
7
+ # A class responsible for wrapping text.
8
+ class Wrapped
9
+ include Unicode
10
+
11
+ # Wrap a long string according to the width.
12
+ #
13
+ # @param [String] string
14
+ # the string to wrap
15
+ # @param [Integer] width
16
+ # the maximum width
17
+ # @param [Boolean] addnewline
18
+ # add new line add the end
19
+ #
20
+ # @api public
21
+ def wrap(string, width)
22
+ as_unicode do
23
+ chars = string.chars.to_a
24
+ return string if chars.length <= width
25
+ idx = width
26
+ return chars[0, idx].join + "\n" + wrap(chars[idx..-1].join, width)
27
+ end
28
+ end
29
+
30
+ end # Wrapped
31
+ end # Operation
32
+ end # Table
33
+ end # TTY
34
+
@@ -29,13 +29,15 @@ module TTY
29
29
  module Renderer
30
30
  extend TTY::Delegatable
31
31
 
32
+ autoload :ASCII, 'tty/table/renderer/ascii'
32
33
  autoload :Basic, 'tty/table/renderer/basic'
33
34
  autoload :Color, 'tty/table/renderer/color'
34
35
  autoload :Unicode, 'tty/table/renderer/unicode'
35
36
 
36
- RENDERER_DELEGATED_METHODS = [ :render, :extract_column_widths, :total_width]
37
+ RENDERER_DELEGATED_METHODS = [ :render, :total_width]
37
38
 
38
39
  RENDERER_MAPPER = {
40
+ :ascii => TTY::Table::Renderer::ASCII,
39
41
  :basic => TTY::Table::Renderer::Basic,
40
42
  :color => TTY::Table::Renderer::Color,
41
43
  :unicode => TTY::Table::Renderer::Unicode
@@ -45,24 +47,19 @@ module TTY
45
47
  #
46
48
  # @api private
47
49
  def initialize(options={})
48
- super
49
- self.renderer = RENDERER_MAPPER[:"#{options[:renderer]}"].new
50
+ super()
50
51
  end
51
52
 
52
53
  # Determine renderer class based on string name
53
54
  #
54
- # @param [TTY::Table::Renderer] renderer
55
- # the renderer used for displaying table
55
+ # @param [Symbol] renderer
56
+ # the renderer used for displaying table out of [:basic, :color, :unicode]
56
57
  #
57
58
  # @return [TTY::Table::Renderer]
58
59
  #
59
60
  # @api private
60
- def pick_renderer(renderer)
61
- if renderer
62
- RENDERER_MAPPER[renderer].new
63
- else
64
- self.renderer
65
- end
61
+ def pick_renderer(type=nil)
62
+ type ? RENDERER_MAPPER[type].new : self.renderer
66
63
  end
67
64
 
68
65
  # Return the default renderer
@@ -0,0 +1,15 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ module TTY
4
+ class Table
5
+ module Renderer
6
+ class ASCII < Basic
7
+
8
+ def render(table, border=nil)
9
+ super table, TTY::Table::Border::ASCII
10
+ end
11
+
12
+ end # ASCII
13
+ end # Renderer
14
+ end # Table
15
+ end # TTY
@@ -19,6 +19,14 @@ module TTY
19
19
  # @api public
20
20
  attr_reader :table
21
21
 
22
+
23
+ # Table border to be rendered
24
+ #
25
+ # @return [TTY::Table::Border]
26
+ #
27
+ # @api private
28
+ attr_reader :border_class
29
+
22
30
  TABLE_DELEGATED_METHODS = [:column_widths, :alignments]
23
31
 
24
32
  delegatable_method :table, *TABLE_DELEGATED_METHODS
@@ -77,13 +85,15 @@ module TTY
77
85
  # @return [String] string representation of table
78
86
  #
79
87
  # @api public
80
- def render(table)
88
+ def render(table, border_class=Border::Null)
81
89
  @table = table
90
+ @border_class = border_class
91
+
82
92
  return if table.to_a.empty?
83
93
  # setup(options)
84
94
  body = []
85
95
  unless table.length.zero?
86
- extract_column_widths
96
+ ColumnSet.new(table).extract_widths!
87
97
  # TODO: throw an error if too many columns as compared to terminal width
88
98
  # and then change table.orientation from vertical to horizontal
89
99
  # TODO: Decide about table orientation
@@ -94,38 +104,8 @@ module TTY
94
104
  body.compact.join("\n")
95
105
  end
96
106
 
97
- # Calcualte total table width
98
- #
99
- # @return [Integer]
100
- #
101
- # @api public
102
- def total_width
103
- column_widths.reduce(:+)
104
- end
105
-
106
107
  private
107
108
 
108
- # Calcualte maximum column widths
109
- #
110
- # @return [Array] column widths
111
- #
112
- # @api private
113
- def extract_column_widths
114
- return column_widths unless column_widths.empty?
115
- data = table.header ? table.to_a + [table.header] : table.to_a
116
- colcount = data.max{ |a,b| a.size <=> b.size }.size
117
- maximas = []
118
- start = 0
119
-
120
- start.upto(colcount - 1) do |index|
121
- maximum = data.map { |row|
122
- row[index] ? (row[index].to_s.size) : 0
123
- }.max
124
- maximas << maximum
125
- end
126
- table.column_widths = maximas
127
- end
128
-
129
109
  # Format the header
130
110
  #
131
111
  # @return [Array[String]]
@@ -136,7 +116,8 @@ module TTY
136
116
  if header
137
117
  aligned = alignments.align_header header,
138
118
  :column_widths => column_widths
139
- [aligned.join]
119
+ border = border_class.new(aligned)
120
+ [border.top_line, border.row_line].compact
140
121
  else
141
122
  []
142
123
  end
@@ -150,7 +131,13 @@ module TTY
150
131
  def render_rows
151
132
  aligned = alignments.align_rows table.to_a,
152
133
  :column_widths => column_widths
153
- aligned.map { |row| row.join }
134
+
135
+ first_row_border = border_class.new(aligned.first)
136
+ aligned_border = aligned.map { |row| border_class.new(row).row_line }
137
+
138
+ [ table.header ? first_row_border.separator : first_row_border.top_line,
139
+ aligned_border,
140
+ first_row_border.bottom_line ].compact
154
141
  end
155
142
 
156
143
  end # Basic
@@ -5,8 +5,8 @@ module TTY
5
5
  module Renderer
6
6
  class Unicode < Basic
7
7
 
8
- def initialize
9
-
8
+ def render(table, border=nil)
9
+ super table, TTY::Table::Border::Unicode
10
10
  end
11
11
 
12
12
  end # Unicode
@@ -0,0 +1,117 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ module TTY
4
+
5
+ # This class represents a mathematical vector.
6
+ class Vector
7
+ include Enumerable, Equatable, Conversion
8
+
9
+ attr_reader :elements
10
+ protected :elements
11
+
12
+ # Utility method to instantiate a Vector
13
+ #
14
+ # @param [Array] *array
15
+ #
16
+ # @return [Vector]
17
+ #
18
+ # @api public
19
+ def self.[](*array)
20
+ new convert_to_array(array)
21
+ end
22
+
23
+ # Instantiate a Vector
24
+ #
25
+ # @param [Array] array
26
+ #
27
+ # @return [undefined]
28
+ #
29
+ # @api public
30
+ def initialize(array=[])
31
+ @elements = convert_to_array(array)
32
+ end
33
+
34
+ # Return element at index.
35
+ #
36
+ # @param [Integer] indx
37
+ # index of an element
38
+ #
39
+ # @return [Object]
40
+ # a value of an element
41
+ #
42
+ # @api public
43
+ def [](indx)
44
+ elements[i]
45
+ end
46
+ alias at []
47
+ alias element []
48
+
49
+ # Set a value of the element for the given index.
50
+ #
51
+ # @param [Integer] indx
52
+ # an index of an element
53
+ #
54
+ # @param [Object] value
55
+ # a value to be set
56
+ #
57
+ # @return [Object]
58
+ #
59
+ # @api public
60
+ def []=(indx, value)
61
+ elements[index] = value
62
+ end
63
+ alias set_element []=
64
+
65
+ # Iterate over each element in the vector
66
+ #
67
+ # @example
68
+ # vec = Vector[1,2,3]
69
+ # vec.each { |element| ... }
70
+ #
71
+ # @return [self]
72
+ #
73
+ # @api public
74
+ def each(&block)
75
+ return to_enum(:each) unless block_given?
76
+ to_ary.each(&block)
77
+ self
78
+ end
79
+
80
+ # Convert to array
81
+ #
82
+ # @return [Array]
83
+ #
84
+ # @api public
85
+ def to_ary
86
+ elements
87
+ end
88
+
89
+ # Check if there are not elements.
90
+ #
91
+ # @return [Boolean]
92
+ #
93
+ # @api public
94
+ def empty?
95
+ to_ary.empty?
96
+ end
97
+
98
+ # Check number of elements.
99
+ #
100
+ # @return [Integer]
101
+ #
102
+ # @api public
103
+ def size
104
+ to_ary.size
105
+ end
106
+
107
+ # Return the vector elements in an array.
108
+ #
109
+ # @return [Array]
110
+ #
111
+ # @api public
112
+ def to_a
113
+ elements.dup
114
+ end
115
+
116
+ end # Vector
117
+ end # TTY