tty 0.0.9 → 0.0.10

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 (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