tty 0.0.4 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
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