tty 0.0.9 → 0.0.10

Sign up to get free protection for your applications and to get access to all the features.
Files changed (125) hide show
  1. data/.rspec +2 -1
  2. data/.travis.yml +3 -6
  3. data/README.md +232 -134
  4. data/lib/tty/plugins/plugin.rb +56 -0
  5. data/lib/tty/plugins.rb +75 -0
  6. data/lib/tty/shell/suggestion.rb +102 -0
  7. data/lib/tty/shell.rb +41 -14
  8. data/lib/tty/system/editor.rb +111 -0
  9. data/lib/tty/system/which.rb +13 -1
  10. data/lib/tty/system.rb +44 -28
  11. data/lib/tty/table/border/null.rb +0 -9
  12. data/lib/tty/table/border/row_line.rb +21 -0
  13. data/lib/tty/table/border.rb +63 -32
  14. data/lib/tty/table/border_dsl.rb +1 -1
  15. data/lib/tty/table/column_set.rb +16 -17
  16. data/lib/tty/table/field.rb +27 -7
  17. data/lib/tty/table/header.rb +18 -9
  18. data/lib/tty/table/operation/alignment_set.rb +20 -25
  19. data/lib/tty/table/operation/escape.rb +30 -0
  20. data/lib/tty/table/operation/filter.rb +36 -0
  21. data/lib/tty/table/operation/truncation.rb +22 -11
  22. data/lib/tty/table/operation/wrapped.rb +21 -10
  23. data/lib/tty/table/operations.rb +10 -8
  24. data/lib/tty/table/orientation/horizontal.rb +1 -1
  25. data/lib/tty/table/renderer/ascii.rb +3 -3
  26. data/lib/tty/table/renderer/basic.rb +135 -65
  27. data/lib/tty/table/renderer/color.rb +1 -4
  28. data/lib/tty/table/renderer/unicode.rb +3 -3
  29. data/lib/tty/table/renderer.rb +48 -61
  30. data/lib/tty/table/row.rb +30 -3
  31. data/lib/tty/table/transformation.rb +38 -0
  32. data/lib/tty/table/validatable.rb +7 -5
  33. data/lib/tty/table.rb +78 -99
  34. data/lib/tty/terminal/color.rb +2 -2
  35. data/lib/tty/terminal/echo.rb +1 -1
  36. data/lib/tty/terminal/pager/basic.rb +52 -0
  37. data/lib/tty/terminal/pager/system.rb +39 -0
  38. data/lib/tty/terminal/pager.rb +95 -0
  39. data/lib/tty/terminal.rb +30 -1
  40. data/lib/tty/version.rb +1 -1
  41. data/lib/tty.rb +41 -1
  42. data/spec/spec_helper.rb +20 -0
  43. data/spec/tty/plugins/find_spec.rb +28 -0
  44. data/spec/tty/plugins/load_spec.rb +20 -0
  45. data/spec/tty/plugins/plugin/load_spec.rb +30 -0
  46. data/spec/tty/plugins/plugin/new_spec.rb +18 -0
  47. data/spec/tty/shell/suggest_spec.rb +50 -0
  48. data/spec/tty/support/conversion_spec.rb +3 -3
  49. data/spec/tty/support/delegatable_spec.rb +1 -1
  50. data/spec/tty/support/equatable_spec.rb +6 -9
  51. data/spec/tty/system/editor/available_spec.rb +40 -0
  52. data/spec/tty/system/editor/build_spec.rb +40 -0
  53. data/spec/tty/system/editor/command_spec.rb +16 -0
  54. data/spec/tty/system/editor/executables_spec.rb +13 -0
  55. data/spec/tty/system/editor/invoke_spec.rb +38 -0
  56. data/spec/tty/system/editor/open_spec.rb +27 -0
  57. data/spec/tty/system/platform_spec.rb +4 -6
  58. data/spec/tty/system/which/which_spec.rb +48 -0
  59. data/spec/tty/system/which_spec.rb +8 -34
  60. data/spec/tty/table/border/ascii/rendering_spec.rb +19 -5
  61. data/spec/tty/table/border/new_spec.rb +1 -1
  62. data/spec/tty/table/border/null/rendering_spec.rb +24 -8
  63. data/spec/tty/table/border/unicode/rendering_spec.rb +19 -5
  64. data/spec/tty/table/column_set/extract_widths_spec.rb +4 -15
  65. data/spec/tty/table/column_set/total_width_spec.rb +15 -0
  66. data/spec/tty/table/data_spec.rb +14 -0
  67. data/spec/tty/table/each_spec.rb +17 -4
  68. data/spec/tty/table/each_with_index_spec.rb +34 -6
  69. data/spec/tty/table/field/length_spec.rb +21 -0
  70. data/spec/tty/table/field/lines_spec.rb +21 -0
  71. data/spec/tty/table/filter_spec.rb +23 -0
  72. data/spec/tty/table/header/call_spec.rb +1 -1
  73. data/spec/tty/table/header/height_spec.rb +27 -0
  74. data/spec/tty/table/initialize_spec.rb +6 -6
  75. data/spec/tty/table/operation/alignment_set/call_spec.rb +39 -0
  76. data/spec/tty/table/operation/escape/call_spec.rb +16 -0
  77. data/spec/tty/table/operation/filter/call_spec.rb +17 -0
  78. data/spec/tty/table/operation/truncation/call_spec.rb +15 -10
  79. data/spec/tty/table/operation/truncation/truncate_spec.rb +1 -1
  80. data/spec/tty/table/operation/wrapped/call_spec.rb +15 -10
  81. data/spec/tty/table/operation/wrapped/wrap_spec.rb +1 -1
  82. data/spec/tty/table/operations/new_spec.rb +4 -4
  83. data/spec/tty/table/options_spec.rb +0 -28
  84. data/spec/tty/table/orientation_spec.rb +5 -6
  85. data/spec/tty/table/properties_spec.rb +1 -4
  86. data/spec/tty/table/render_spec.rb +57 -0
  87. data/spec/tty/table/{renders_with_spec.rb → render_with_spec.rb} +29 -10
  88. data/spec/tty/table/renderer/ascii/render_spec.rb +68 -0
  89. data/spec/tty/table/renderer/ascii/separator_spec.rb +28 -0
  90. data/spec/tty/table/renderer/basic/alignment_spec.rb +18 -16
  91. data/spec/tty/table/renderer/basic/extract_column_widths_spec.rb +17 -12
  92. data/spec/tty/table/renderer/basic/filter_spec.rb +53 -0
  93. data/spec/tty/table/renderer/basic/multiline_content_spec.rb +135 -0
  94. data/spec/tty/table/renderer/basic/new_spec.rb +13 -2
  95. data/spec/tty/table/renderer/basic/options_spec.rb +48 -0
  96. data/spec/tty/table/renderer/basic/render_spec.rb +19 -121
  97. data/spec/tty/table/renderer/basic/separator_spec.rb +14 -48
  98. data/spec/tty/table/renderer/basic/truncation_spec.rb +35 -0
  99. data/spec/tty/table/renderer/basic/wrapping_spec.rb +40 -0
  100. data/spec/tty/table/{border_spec.rb → renderer/border_spec.rb} +17 -20
  101. data/spec/tty/table/renderer/select_spec.rb +22 -0
  102. data/spec/tty/table/{border → renderer}/style_spec.rb +13 -14
  103. data/spec/tty/table/renderer/unicode/render_spec.rb +68 -0
  104. data/spec/tty/table/renderer/unicode/separator_spec.rb +26 -0
  105. data/spec/tty/table/rotate_spec.rb +2 -3
  106. data/spec/tty/table/row/call_spec.rb +1 -1
  107. data/spec/tty/table/row/each_spec.rb +31 -0
  108. data/spec/tty/table/row/height_spec.rb +27 -0
  109. data/spec/tty/table/to_s_spec.rb +3 -3
  110. data/spec/tty/table/transformation/extract_tuples_spec.rb +35 -0
  111. data/spec/tty/table/validatable/validate_options_spec.rb +1 -2
  112. data/spec/tty/terminal/home_spec.rb +3 -3
  113. data/spec/tty/terminal/page_spec.rb +13 -0
  114. data/spec/tty/terminal/pager/available_spec.rb +40 -0
  115. data/spec/tty/terminal/pager/basic/page_spec.rb +54 -0
  116. data/spec/tty/terminal/pager/command_spec.rb +16 -0
  117. data/spec/tty/terminal/pager/executables_spec.rb +13 -0
  118. data/spec/tty/terminal/pager/page_spec.rb +47 -0
  119. data/spec/tty/terminal/pager/system/page_spec.rb +29 -0
  120. data/spec/tty/text/distance/distance_spec.rb +12 -0
  121. data/tty.gemspec +7 -3
  122. metadata +160 -27
  123. data/spec/tty/table/operation/alignment_set/align_rows_spec.rb +0 -53
  124. data/spec/tty/table/renderer/pick_renderer_spec.rb +0 -25
  125. data/spec/tty/table/renderer_spec.rb +0 -49
@@ -6,12 +6,12 @@ module TTY
6
6
  # A class that represents table columns properties.
7
7
  class ColumnSet
8
8
  include Equatable
9
- extend Delegatable
10
9
 
11
10
  attr_reader :table
12
11
 
13
- delegatable_method :table, :column_widths
14
-
12
+ # Initialize a ColumnSet
13
+ #
14
+ # @api public
15
15
  def initialize(table)
16
16
  @table = table
17
17
  end
@@ -22,7 +22,7 @@ module TTY
22
22
  #
23
23
  # @api public
24
24
  def total_width
25
- column_widths.reduce(:+)
25
+ extract_widths.reduce(:+)
26
26
  end
27
27
 
28
28
  # Calcualte maximum column widths
@@ -30,15 +30,11 @@ module TTY
30
30
  # @return [Array] column widths
31
31
  #
32
32
  # @api private
33
- def extract_widths!
34
- return column_widths if (column_widths && !column_widths.empty?)
35
-
36
- rows = table.to_a
37
- data = table.header ? rows + [table.header] : rows
33
+ def extract_widths
34
+ data = table.data
38
35
  colcount = data.max { |row_a, row_b| row_a.size <=> row_b.size }.size
39
36
 
40
- table.column_widths = find_maximas colcount, data
41
- self
37
+ self.class.find_maximas(colcount, data)
42
38
  end
43
39
 
44
40
  private
@@ -51,25 +47,28 @@ module TTY
51
47
  # the table's header and rows
52
48
  #
53
49
  # @api private
54
- def find_maximas(colcount, data)
50
+ def self.find_maximas(colcount, data)
55
51
  maximas = []
56
52
  start = 0
57
53
 
58
- start.upto(colcount - 1) do |index|
59
- maximas << find_maximum(data, index)
54
+ start.upto(colcount - 1) do |col_index|
55
+ maximas << find_maximum(data, col_index)
60
56
  end
61
57
  maximas
62
58
  end
63
59
 
64
- # Find a maximum column width.
60
+ # Find a maximum column width. The calculation takes into account
61
+ # wether the content is escaped or not.
65
62
  #
66
63
  # @param [Array] data
64
+ # the table data
67
65
  #
68
66
  # @param [Integer] index
67
+ # the column index
69
68
  #
70
69
  # @api private
71
- def find_maximum(data, index)
72
- data.map { |row| row[index] ? (row[index].to_s.size) : 0 }.max
70
+ def self.find_maximum(data, index)
71
+ data.map { |row| (value=row.call(index)) ? value.length : 0 }.max
73
72
  end
74
73
 
75
74
  end # ColumnSet
@@ -69,20 +69,40 @@ module TTY
69
69
  @height
70
70
  end
71
71
 
72
- def height
73
- lines.size
74
- end
75
-
76
- # Return number of lines this value spans
72
+ # Return number of lines this value spans. A distinction is being made
73
+ # between escaped and non-escaped strings.
74
+ #
75
+ # @return [Array[String]]
77
76
  #
77
+ # @api public
78
78
  def lines
79
- value.to_s.split(/\n/)
79
+ escaped = value.to_s.scan(/(\\n|\\t|\\r)/)
80
+ escaped.empty? ? value.to_s.split(/\n/) : [value.to_s]
80
81
  end
81
82
 
82
- def longest_line
83
+ # If the string contains unescaped new lines then the longest token
84
+ # deterimines the actual field length.
85
+ #
86
+ # @return [Integer]
87
+ #
88
+ # @api public
89
+ def length
83
90
  lines.max_by(&:length).size
84
91
  end
85
92
 
93
+ # Extract the number of lines this value spans
94
+ #
95
+ # @return [Integer]
96
+ #
97
+ # @api public
98
+ def height
99
+ lines.size
100
+ end
101
+
102
+ def chars
103
+ value.chars
104
+ end
105
+
86
106
  # Render value inside this field box
87
107
  #
88
108
  # @api public
@@ -28,6 +28,7 @@ module TTY
28
28
  #
29
29
  # @api private
30
30
  attr_reader :attributes
31
+ alias :fields :attributes
31
32
 
32
33
  # Initialize a Header
33
34
  #
@@ -46,13 +47,6 @@ module TTY
46
47
  Field.new(options)
47
48
  end
48
49
 
49
- # Filter header names including styling background,
50
- # text color and capitalization
51
- #
52
- #
53
- def filter
54
- end
55
-
56
50
  # Lookup a column in the header given a name
57
51
  #
58
52
  # @api public
@@ -66,7 +60,13 @@ module TTY
66
60
  end
67
61
  end
68
62
  end
69
- alias :call :[]
63
+
64
+ # Lookup attribute without evaluation
65
+ #
66
+ # @api public
67
+ def call(attribute)
68
+ @attributes[attribute]
69
+ end
70
70
 
71
71
  # Set value at index
72
72
  #
@@ -86,11 +86,20 @@ module TTY
86
86
  end
87
87
  alias :length :size
88
88
 
89
+ # Find maximum header height
90
+ #
91
+ # @return [Integer]
92
+ #
93
+ # @api public
94
+ def height
95
+ attributes.map { |field| field.height }.max
96
+ end
97
+
89
98
  # Convert the Header into an Array
90
99
  #
91
100
  # @api public
92
101
  def to_ary
93
- attributes.map { |attr| attr.value if attr.value }
102
+ attributes.map { |attr| attr.value if attr }
94
103
  end
95
104
 
96
105
  # Check if this header is equivalent to another header
@@ -7,6 +7,13 @@ module TTY
7
7
  # A class which responsiblity is to align table rows and header.
8
8
  class AlignmentSet < Vector
9
9
 
10
+ attr_reader :widths
11
+
12
+ def initialize(aligns, widths=nil)
13
+ @elements = convert_to_array(aligns)
14
+ @widths = widths
15
+ end
16
+
10
17
  # Lookup an alignment by index
11
18
  #
12
19
  # @param [Integer]
@@ -34,44 +41,32 @@ module TTY
34
41
  # @param [Hash] options
35
42
  # the table options
36
43
  #
37
- # @return [Array[String]]
44
+ # @return [TTY::Table::Field]
38
45
  #
39
46
  # @api public
40
- def call(row, options={})
41
- align_row(row, options)
42
- end
43
-
44
- # Align the supplied rows with the correct alignment.
45
- #
46
- # @param [Array] rows
47
- #
48
- # @return [Array[Array]]
49
- # the aligned rows
50
- #
51
- # @api private
52
- def align_rows(rows, options={})
53
- rows.map { |row| align_row(row, options) }
47
+ def call(field, row, col)
48
+ align_field(field, col)
54
49
  end
55
50
 
56
51
  private
57
52
 
58
53
  # Align each field in a row
59
54
  #
60
- # @param [Object] row
55
+ # @param [TTY::Table::Field] field
56
+ # the table field
57
+ #
58
+ # @param [Integer] col
59
+ # the table column index
61
60
  #
62
61
  # @param [Hash] options
63
62
  #
64
- # @return [Array[String]]
63
+ # @return [TTY::Table::Field]
65
64
  #
66
65
  # @api private
67
- def align_row(row, options={})
68
- index = 0
69
- row.map! do |field|
70
- column_width = options[:column_widths][index]
71
- alignment = Alignment.new(field.align || self[index])
72
- index += 1
73
- alignment.format(field, column_width)
74
- end
66
+ def align_field(field, col)
67
+ column_width = widths[col]
68
+ alignment = Alignment.new(field.align || self[col])
69
+ field.value = alignment.format(field, column_width)
75
70
  end
76
71
 
77
72
  end # AlignmentSet
@@ -0,0 +1,30 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ module TTY
4
+ class Table
5
+ module Operation
6
+
7
+ # A class responsible for escaping special chars in a table field
8
+ class Escape
9
+
10
+ # Escape special characters in a table field
11
+ #
12
+ # @param [TTY::Table::Field] field
13
+ #
14
+ # @param [Integer] row
15
+ # the field row index
16
+ #
17
+ # @param [Integer] col
18
+ # the field column index
19
+ #
20
+ # @api public
21
+ def call(field, row, col)
22
+ field.value = field.value.gsub(/(\t|\r|\n)/) do |val|
23
+ val.dump.gsub('"', '')
24
+ end
25
+ end
26
+
27
+ end # Escape
28
+ end # Operation
29
+ end # Table
30
+ end # TTY
@@ -0,0 +1,36 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ module TTY
4
+ class Table
5
+ module Operation
6
+
7
+ # A class responsible for transforming table field
8
+ class Filter
9
+
10
+ # Initialize a Filter
11
+ #
12
+ # @api public
13
+ def initialize(filter)
14
+ @filter = filter
15
+ end
16
+
17
+ # Apply filer to the provided table field
18
+ #
19
+ # @param [TTY::Table::Field] field
20
+ #
21
+ # @param [Integer] row
22
+ # the field row index
23
+ #
24
+ # @param [Integer] col
25
+ # the field column index
26
+ #
27
+ # @api public
28
+ def call(field, row, col)
29
+ field.value = @filter.call(field.value, row, col)
30
+ end
31
+
32
+ end # Filter
33
+
34
+ end # Operation
35
+ end # Table
36
+ end # TTY
@@ -7,21 +7,32 @@ module TTY
7
7
  # A class responsible for shortening text.
8
8
  class Truncation
9
9
 
10
- # Apply truncation to a row
10
+ attr_reader :widths
11
+
12
+ # Initialize a Truncation
13
+ #
14
+ # @api public
15
+ def initialize(widths)
16
+ @widths = widths
17
+ end
18
+
19
+ # Apply truncation to a field
20
+ #
21
+ # @param [TTY::Table::Field] field
22
+ # the table field
23
+ #
24
+ # @param [Integer] row
25
+ # the field row index
11
26
  #
12
- # @param [Array] row
13
- # the table row
27
+ # @param [Integer] col
28
+ # the field column index
14
29
  #
15
- # @return [Array[String]]
30
+ # @return [TTY::Table::Field]
16
31
  #
17
32
  # @api public
18
- def call(row, options={})
19
- index = 0
20
- row.map! do |field|
21
- width = options.fetch(:column_widths, {})[index] || field.width
22
- index += 1
23
- field.value = truncate(field.value, width)
24
- end
33
+ def call(field, row, col)
34
+ width = widths[col] || field.width
35
+ field.value = truncate(field.value, width)
25
36
  end
26
37
 
27
38
  # Shorten given string with traling character.
@@ -7,21 +7,32 @@ module TTY
7
7
  # A class responsible for wrapping text.
8
8
  class Wrapped
9
9
 
10
- # Apply truncation to a row
10
+ attr_reader :widths
11
+
12
+ # Initialize a Wrapped
13
+ #
14
+ # @api public
15
+ def initialize(widths)
16
+ @widths = widths
17
+ end
18
+
19
+ # Apply wrapping to a field
20
+ #
21
+ # @param [TTY::Table::Field] field
22
+ # the table field
23
+ #
24
+ # @param [Integer] row
25
+ # the field row index
11
26
  #
12
- # @param [Array] row
13
- # the table row
27
+ # @param [Integer] col
28
+ # the field column index
14
29
  #
15
30
  # @return [Array[String]]
16
31
  #
17
32
  # @api public
18
- def call(row, options={})
19
- index = 0
20
- row.map! do |field|
21
- width = options.fetch(:column_widths, {})[index] || field.width
22
- index += 1
23
- field.value = wrap(field.value, width)
24
- end
33
+ def call(field, row, col)
34
+ width = widths[col] || field.width
35
+ field.value = wrap(field.value, width)
25
36
  end
26
37
 
27
38
  # Wrap a long string according to the width.
@@ -49,19 +49,21 @@ module TTY
49
49
 
50
50
  # Apply operations to a table row
51
51
  #
52
- # @param [Symbol] type
53
- # the operation type
54
- # @param [#to_ary, Row] row
55
- # the row to apply operation to
52
+ # @param [Array[Symbol]] types
53
+ # the operation types
56
54
  # @param [Hash] options
57
55
  # the options for the row
58
56
  #
59
- # @return [Hash]
57
+ # @return [TTY::Table]
60
58
  #
61
59
  # @api public
62
- def run_operations(type, row, options={})
63
- options.merge!(:column_widths => table.column_widths)
64
- operations[type].each { |op| op.call(row, options) }
60
+ def run_operations(*args)
61
+ types = args
62
+ table.each_with_index do |val, row, col|
63
+ types.each do |type|
64
+ operations[type].each { |op| op.call(val, row, col) }
65
+ end
66
+ end
65
67
  end
66
68
 
67
69
  end # Operations
@@ -14,6 +14,6 @@ module TTY
14
14
 
15
15
  end # Horizontal
16
16
 
17
- end # Orientation
17
+ end # Orientation
18
18
  end # Table
19
19
  end # TTY
@@ -2,11 +2,11 @@
2
2
 
3
3
  module TTY
4
4
  class Table
5
- module Renderer
5
+ class Renderer
6
6
  class ASCII < Basic
7
7
 
8
- def render(table)
9
- super table, TTY::Table::Border::ASCII
8
+ def initialize(table, options={})
9
+ super(table, options.merge(:border_class => TTY::Table::Border::ASCII))
10
10
  end
11
11
 
12
12
  end # ASCII