command_kit 0.2.2 → 0.4.0
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.
- checksums.yaml +4 -4
- data/.github/workflows/ruby.yml +4 -5
- data/.rubocop.yml +14 -1
- data/ChangeLog.md +82 -0
- data/Gemfile +2 -0
- data/LICENSE.txt +1 -1
- data/README.md +18 -9
- data/command_kit.gemspec +0 -1
- data/examples/printing/tables.rb +141 -0
- data/gemspec.yml +3 -3
- data/lib/command_kit/arguments/argument.rb +2 -2
- data/lib/command_kit/arguments.rb +27 -2
- data/lib/command_kit/bug_report.rb +105 -0
- data/lib/command_kit/colors.rb +488 -15
- data/lib/command_kit/command.rb +1 -2
- data/lib/command_kit/edit.rb +54 -0
- data/lib/command_kit/env.rb +1 -1
- data/lib/command_kit/file_utils.rb +46 -0
- data/lib/command_kit/options/option.rb +45 -22
- data/lib/command_kit/options/option_value.rb +2 -2
- data/lib/command_kit/options/parser.rb +1 -4
- data/lib/command_kit/options/quiet.rb +1 -1
- data/lib/command_kit/options/verbose.rb +2 -2
- data/lib/command_kit/options/version.rb +10 -0
- data/lib/command_kit/options.rb +89 -14
- data/lib/command_kit/os.rb +1 -1
- data/lib/command_kit/printing/fields.rb +56 -0
- data/lib/command_kit/printing/indent.rb +1 -1
- data/lib/command_kit/printing/lists.rb +91 -0
- data/lib/command_kit/printing/tables/border_style.rb +169 -0
- data/lib/command_kit/printing/tables/cell_builder.rb +93 -0
- data/lib/command_kit/printing/tables/row_builder.rb +111 -0
- data/lib/command_kit/printing/tables/style.rb +198 -0
- data/lib/command_kit/printing/tables/table_builder.rb +145 -0
- data/lib/command_kit/printing/tables/table_formatter.rb +254 -0
- data/lib/command_kit/printing/tables.rb +208 -0
- data/lib/command_kit/program_name.rb +9 -0
- data/lib/command_kit/stdio.rb +5 -1
- data/lib/command_kit/version.rb +1 -1
- data/spec/arguments_spec.rb +33 -0
- data/spec/bug_report_spec.rb +266 -0
- data/spec/colors_spec.rb +232 -195
- data/spec/command_name_spec.rb +1 -1
- data/spec/command_spec.rb +2 -2
- data/spec/edit_spec.rb +72 -0
- data/spec/file_utils_spec.rb +59 -0
- data/spec/fixtures/template.erb +5 -0
- data/spec/options/option_spec.rb +48 -2
- data/spec/options/parser_spec.rb +0 -10
- data/spec/options/quiet_spec.rb +51 -0
- data/spec/options/verbose_spec.rb +51 -0
- data/spec/options/version_spec.rb +146 -0
- data/spec/options_spec.rb +46 -0
- data/spec/pager_spec.rb +1 -1
- data/spec/printing/fields_spec.rb +167 -0
- data/spec/printing/lists_spec.rb +99 -0
- data/spec/printing/tables/border_style.rb +43 -0
- data/spec/printing/tables/cell_builer_spec.rb +135 -0
- data/spec/printing/tables/row_builder_spec.rb +165 -0
- data/spec/printing/tables/style_spec.rb +377 -0
- data/spec/printing/tables/table_builder_spec.rb +252 -0
- data/spec/printing/tables/table_formatter_spec.rb +1180 -0
- data/spec/printing/tables_spec.rb +1069 -0
- data/spec/program_name_spec.rb +8 -0
- metadata +36 -7
@@ -0,0 +1,169 @@
|
|
1
|
+
module CommandKit
|
2
|
+
module Printing
|
3
|
+
module Tables
|
4
|
+
#
|
5
|
+
# Represents the table's border style.
|
6
|
+
#
|
7
|
+
# @api private
|
8
|
+
#
|
9
|
+
class BorderStyle
|
10
|
+
|
11
|
+
# The top-left-corner border character.
|
12
|
+
#
|
13
|
+
# @return [String]
|
14
|
+
attr_reader :top_left_corner
|
15
|
+
|
16
|
+
# The top-border character.
|
17
|
+
#
|
18
|
+
# @return [String]
|
19
|
+
attr_reader :top_border
|
20
|
+
|
21
|
+
# The top-joined-border character.
|
22
|
+
#
|
23
|
+
# @return [String]
|
24
|
+
attr_reader :top_joined_border
|
25
|
+
|
26
|
+
# The top-right-corner border character.
|
27
|
+
#
|
28
|
+
# @return [String]
|
29
|
+
attr_reader :top_right_corner
|
30
|
+
|
31
|
+
# The left-hand-side border character.
|
32
|
+
#
|
33
|
+
# @return [String]
|
34
|
+
attr_reader :left_border
|
35
|
+
|
36
|
+
# The left-hand-side-joined-border character.
|
37
|
+
#
|
38
|
+
# @return [String]
|
39
|
+
attr_reader :left_joined_border
|
40
|
+
|
41
|
+
# The horizontal-separator character.
|
42
|
+
#
|
43
|
+
# @return [String]
|
44
|
+
attr_reader :horizontal_separator
|
45
|
+
|
46
|
+
# The vertical-separator character.
|
47
|
+
#
|
48
|
+
# @return [String]
|
49
|
+
attr_reader :vertical_separator
|
50
|
+
|
51
|
+
# The inner-joined border character.
|
52
|
+
#
|
53
|
+
# @return [String]
|
54
|
+
attr_reader :inner_joined_border
|
55
|
+
|
56
|
+
# The right-hand-side border character.
|
57
|
+
#
|
58
|
+
# @return [String]
|
59
|
+
attr_reader :right_border
|
60
|
+
|
61
|
+
# The right-hand-side joined border character.
|
62
|
+
#
|
63
|
+
# @return [String]
|
64
|
+
attr_reader :right_joined_border
|
65
|
+
|
66
|
+
# The bottom border character.
|
67
|
+
#
|
68
|
+
# @return [String]
|
69
|
+
attr_reader :bottom_border
|
70
|
+
|
71
|
+
# The bottom-left-corner border character.
|
72
|
+
#
|
73
|
+
# @return [String]
|
74
|
+
attr_reader :bottom_left_corner
|
75
|
+
|
76
|
+
# The bottom-joined border character.
|
77
|
+
#
|
78
|
+
# @return [String]
|
79
|
+
attr_reader :bottom_joined_border
|
80
|
+
|
81
|
+
# The bottom-right-corner border character.
|
82
|
+
#
|
83
|
+
# @return [String]
|
84
|
+
attr_reader :bottom_right_corner
|
85
|
+
|
86
|
+
#
|
87
|
+
# Initializes the border style.
|
88
|
+
#
|
89
|
+
# @param [String] top_left_corner
|
90
|
+
# The top-left-corner border character.
|
91
|
+
#
|
92
|
+
# @param [String] top_border
|
93
|
+
# The top-border character.
|
94
|
+
#
|
95
|
+
# @param [String] top_joined_border
|
96
|
+
# The top-joined-border character.
|
97
|
+
#
|
98
|
+
# @param [String] top_right_corner
|
99
|
+
# The top-right-corner border character.
|
100
|
+
#
|
101
|
+
# @param [String] left_border
|
102
|
+
# The left-hand-side border character.
|
103
|
+
#
|
104
|
+
# @param [String] left_joined_border
|
105
|
+
# The left-hand-side-joined-border character.
|
106
|
+
#
|
107
|
+
# @param [String] horizontal_separator
|
108
|
+
# The horizontal-separator character.
|
109
|
+
#
|
110
|
+
# @param [String] vertical_separator
|
111
|
+
# The vertical-separator character.
|
112
|
+
#
|
113
|
+
# @param [String] inner_joined_border
|
114
|
+
# The inner-joined border character.
|
115
|
+
#
|
116
|
+
# @param [String] right_border
|
117
|
+
# The right-hand-side border character.
|
118
|
+
#
|
119
|
+
# @param [String] right_joined_border
|
120
|
+
# The right-hand-side joined border character.
|
121
|
+
#
|
122
|
+
# @param [String] bottom_border
|
123
|
+
# The bottom border character.
|
124
|
+
#
|
125
|
+
# @param [String] bottom_left_corner
|
126
|
+
# The bottom-left-corner border character.
|
127
|
+
#
|
128
|
+
# @param [String] bottom_joined_border
|
129
|
+
# The bottom-joined border character.
|
130
|
+
#
|
131
|
+
# @param [String] bottom_right_corner
|
132
|
+
# The bottom-right-corner border character.
|
133
|
+
#
|
134
|
+
def initialize(top_left_corner: ' ',
|
135
|
+
top_border: ' ',
|
136
|
+
top_joined_border: ' ',
|
137
|
+
top_right_corner: ' ',
|
138
|
+
left_border: ' ',
|
139
|
+
left_joined_border: ' ',
|
140
|
+
horizontal_separator: ' ',
|
141
|
+
vertical_separator: ' ',
|
142
|
+
inner_joined_border: ' ',
|
143
|
+
right_border: ' ',
|
144
|
+
right_joined_border: ' ',
|
145
|
+
bottom_border: ' ',
|
146
|
+
bottom_left_corner: ' ',
|
147
|
+
bottom_joined_border: ' ',
|
148
|
+
bottom_right_corner: ' ')
|
149
|
+
@top_left_corner = top_left_corner
|
150
|
+
@top_border = top_border
|
151
|
+
@top_joined_border = top_joined_border
|
152
|
+
@top_right_corner = top_right_corner
|
153
|
+
@left_border = left_border
|
154
|
+
@left_joined_border = left_joined_border
|
155
|
+
@horizontal_separator = horizontal_separator
|
156
|
+
@vertical_separator = vertical_separator
|
157
|
+
@inner_joined_border = inner_joined_border
|
158
|
+
@right_border = right_border
|
159
|
+
@right_joined_border = right_joined_border
|
160
|
+
@bottom_border = bottom_border
|
161
|
+
@bottom_left_corner = bottom_left_corner
|
162
|
+
@bottom_joined_border = bottom_joined_border
|
163
|
+
@bottom_right_corner = bottom_right_corner
|
164
|
+
end
|
165
|
+
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module CommandKit
|
4
|
+
module Printing
|
5
|
+
module Tables
|
6
|
+
#
|
7
|
+
# Build's a cell and calculates it's dimensions.
|
8
|
+
#
|
9
|
+
# @api private
|
10
|
+
#
|
11
|
+
class CellBuilder
|
12
|
+
|
13
|
+
# The lines within the cell.
|
14
|
+
#
|
15
|
+
# @return [Array<String>]
|
16
|
+
attr_reader :lines
|
17
|
+
|
18
|
+
# The height (in lines) of the cell.
|
19
|
+
#
|
20
|
+
# @return [Integer]
|
21
|
+
attr_reader :height
|
22
|
+
|
23
|
+
# The with (in characters) of the cell.
|
24
|
+
#
|
25
|
+
# @return [Integer]
|
26
|
+
attr_reader :width
|
27
|
+
|
28
|
+
#
|
29
|
+
# Initializes the cell.
|
30
|
+
#
|
31
|
+
# @param [#to_s] value
|
32
|
+
# The value for the cell.
|
33
|
+
#
|
34
|
+
def initialize(value=nil)
|
35
|
+
@lines = []
|
36
|
+
@height = 0
|
37
|
+
@width = 0
|
38
|
+
|
39
|
+
if value
|
40
|
+
value.to_s.each_line(chomp: true) do |line|
|
41
|
+
self << line
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
#
|
47
|
+
# Calculates the width of a string, sans any ASNI escape sequences.
|
48
|
+
#
|
49
|
+
# @param [String] string
|
50
|
+
# The string to calculate the width of.
|
51
|
+
#
|
52
|
+
# @return [Integer]
|
53
|
+
# The display width of the string.
|
54
|
+
#
|
55
|
+
def self.line_width(string)
|
56
|
+
string.gsub(/\e\[\d+m/,'').length
|
57
|
+
end
|
58
|
+
|
59
|
+
#
|
60
|
+
# Adds a line to the cell.
|
61
|
+
#
|
62
|
+
# @param [String] line
|
63
|
+
# A line to add to the cell.
|
64
|
+
#
|
65
|
+
# @return [self]
|
66
|
+
#
|
67
|
+
def <<(line)
|
68
|
+
line_width = self.class.line_width(line)
|
69
|
+
|
70
|
+
@height += 1
|
71
|
+
@width = line_width if line_width > @width
|
72
|
+
|
73
|
+
@lines << line
|
74
|
+
return self
|
75
|
+
end
|
76
|
+
|
77
|
+
#
|
78
|
+
# Fetches a line from the cell.
|
79
|
+
#
|
80
|
+
# @param [Integer] line_index
|
81
|
+
# The line index to fetch.
|
82
|
+
#
|
83
|
+
# @return [String]
|
84
|
+
# The line at the line index or an empty String if the cell is empty.
|
85
|
+
#
|
86
|
+
def [](line_index)
|
87
|
+
@lines.fetch(line_index,'')
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
require 'command_kit/printing/tables/cell_builder'
|
2
|
+
|
3
|
+
module CommandKit
|
4
|
+
module Printing
|
5
|
+
module Tables
|
6
|
+
#
|
7
|
+
# Builds a table row and calculates it's dimensions.
|
8
|
+
#
|
9
|
+
# @api private
|
10
|
+
#
|
11
|
+
class RowBuilder
|
12
|
+
|
13
|
+
include Enumerable
|
14
|
+
|
15
|
+
# The cells within the row.
|
16
|
+
#
|
17
|
+
# @return [Array<CellBuilder>]
|
18
|
+
attr_reader :cells
|
19
|
+
|
20
|
+
# The height (in lines) for the row.
|
21
|
+
#
|
22
|
+
# @return [Integer]
|
23
|
+
attr_reader :height
|
24
|
+
|
25
|
+
# The width (in characters) for the row.
|
26
|
+
#
|
27
|
+
# @return [Integer]
|
28
|
+
attr_reader :width
|
29
|
+
|
30
|
+
# The number of columns in the row.
|
31
|
+
#
|
32
|
+
# @return [Integer]
|
33
|
+
attr_reader :columns
|
34
|
+
|
35
|
+
#
|
36
|
+
# Initializes the row.
|
37
|
+
#
|
38
|
+
# @param [Array, nil] cells
|
39
|
+
# The cells for the row.
|
40
|
+
#
|
41
|
+
def initialize(cells=nil)
|
42
|
+
@cells = []
|
43
|
+
|
44
|
+
@height = 0
|
45
|
+
@width = 0
|
46
|
+
|
47
|
+
@columns = 0
|
48
|
+
|
49
|
+
if cells
|
50
|
+
cells.each { |value| self << value }
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
# An empty cell.
|
55
|
+
EMPTY_CELL = CellBuilder.new
|
56
|
+
|
57
|
+
#
|
58
|
+
# Appends a value to the row.
|
59
|
+
#
|
60
|
+
# @param [#to_s] value
|
61
|
+
# The cell value to add to the row.
|
62
|
+
#
|
63
|
+
# @return [self]
|
64
|
+
#
|
65
|
+
def <<(value)
|
66
|
+
new_cell = if value then CellBuilder.new(value)
|
67
|
+
else EMPTY_CELL
|
68
|
+
end
|
69
|
+
|
70
|
+
@height = new_cell.height if new_cell.height > @height
|
71
|
+
@width += new_cell.width
|
72
|
+
@columns += 1
|
73
|
+
|
74
|
+
@cells << new_cell
|
75
|
+
return self
|
76
|
+
end
|
77
|
+
|
78
|
+
#
|
79
|
+
# Fetches a cell from the row.
|
80
|
+
#
|
81
|
+
# @param [Integer] column_index
|
82
|
+
# The column index.
|
83
|
+
#
|
84
|
+
# @return [CellBuilder]
|
85
|
+
# The cell at the given column index or an empty cell if the row
|
86
|
+
# does not have a cell at the given column index.
|
87
|
+
#
|
88
|
+
def [](column_index)
|
89
|
+
@cells.fetch(column_index,EMPTY_CELL)
|
90
|
+
end
|
91
|
+
|
92
|
+
#
|
93
|
+
# Enumerates over each cell in the row.
|
94
|
+
#
|
95
|
+
# @yield [cell]
|
96
|
+
# The given block will be passed each cell within the row.
|
97
|
+
#
|
98
|
+
# @yieldparam [CellBuilder] cell
|
99
|
+
# A cell within the row.
|
100
|
+
#
|
101
|
+
# @return [Enumerator]
|
102
|
+
# If no block is given, an Enumerator will be returned.
|
103
|
+
#
|
104
|
+
def each(&block)
|
105
|
+
@cells.each(&block)
|
106
|
+
end
|
107
|
+
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
@@ -0,0 +1,198 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'command_kit/printing/tables/border_style'
|
4
|
+
|
5
|
+
module CommandKit
|
6
|
+
module Printing
|
7
|
+
module Tables
|
8
|
+
#
|
9
|
+
# Contains the table's style configuration.
|
10
|
+
#
|
11
|
+
# @api private
|
12
|
+
#
|
13
|
+
class Style
|
14
|
+
|
15
|
+
# Built-in border styles.
|
16
|
+
BORDER_STYLES = {
|
17
|
+
ascii: BorderStyle.new(
|
18
|
+
top_left_corner: '+',
|
19
|
+
top_border: '-',
|
20
|
+
top_joined_border: '+',
|
21
|
+
top_right_corner: '+',
|
22
|
+
left_border: '|',
|
23
|
+
left_joined_border: '+',
|
24
|
+
horizontal_separator: '-',
|
25
|
+
vertical_separator: '|',
|
26
|
+
inner_joined_border: '+',
|
27
|
+
right_border: '|',
|
28
|
+
right_joined_border: '+',
|
29
|
+
bottom_border: '-',
|
30
|
+
bottom_left_corner: '+',
|
31
|
+
bottom_joined_border: '+',
|
32
|
+
bottom_right_corner: '+'
|
33
|
+
),
|
34
|
+
|
35
|
+
line: BorderStyle.new(
|
36
|
+
top_left_corner: '┌',
|
37
|
+
top_border: '─',
|
38
|
+
top_joined_border: '┬',
|
39
|
+
top_right_corner: '┐',
|
40
|
+
left_border: '│',
|
41
|
+
left_joined_border: '├',
|
42
|
+
horizontal_separator: '─',
|
43
|
+
vertical_separator: '│',
|
44
|
+
inner_joined_border: '┼',
|
45
|
+
right_border: '│',
|
46
|
+
right_joined_border: '┤',
|
47
|
+
bottom_border: '─',
|
48
|
+
bottom_left_corner: '└',
|
49
|
+
bottom_joined_border: '┴',
|
50
|
+
bottom_right_corner: '┘'
|
51
|
+
),
|
52
|
+
|
53
|
+
double_line: BorderStyle.new(
|
54
|
+
top_left_corner: '╔',
|
55
|
+
top_border: '═',
|
56
|
+
top_joined_border: '╦',
|
57
|
+
top_right_corner: '╗',
|
58
|
+
left_border: '║',
|
59
|
+
left_joined_border: '╠',
|
60
|
+
horizontal_separator: '═',
|
61
|
+
vertical_separator: '║',
|
62
|
+
inner_joined_border: '╬',
|
63
|
+
right_border: '║',
|
64
|
+
right_joined_border: '╣',
|
65
|
+
bottom_border: '═',
|
66
|
+
bottom_left_corner: '╚',
|
67
|
+
bottom_joined_border: '╩',
|
68
|
+
bottom_right_corner: '╝'
|
69
|
+
)
|
70
|
+
}
|
71
|
+
|
72
|
+
# The border style.
|
73
|
+
#
|
74
|
+
# @return [BorderStyle]
|
75
|
+
attr_reader :border
|
76
|
+
|
77
|
+
# The padding to use for cells.
|
78
|
+
#
|
79
|
+
# @return [Integer]
|
80
|
+
attr_reader :padding
|
81
|
+
|
82
|
+
# The justification to use for cells.
|
83
|
+
#
|
84
|
+
# @return [:left, :right, :center]
|
85
|
+
attr_reader :justify
|
86
|
+
|
87
|
+
# The justification to use for header cells.
|
88
|
+
#
|
89
|
+
# @return [:left, :right, :center]
|
90
|
+
attr_reader :justify_header
|
91
|
+
|
92
|
+
# Specifies whether to separate rows with a border row.
|
93
|
+
#
|
94
|
+
# @return [Boolean]
|
95
|
+
attr_reader :separate_rows
|
96
|
+
|
97
|
+
#
|
98
|
+
# Initializes the style.
|
99
|
+
#
|
100
|
+
# @param [:line, :double_line, nil, Hash{Symbol => String}, :ascii] border
|
101
|
+
# The border style or a custom Hash of border characters.
|
102
|
+
#
|
103
|
+
# @option border [String] :top_left_corner (' ')
|
104
|
+
# The top-left-corner border character.
|
105
|
+
#
|
106
|
+
# @option border [String] :top_border (' ')
|
107
|
+
# The top-border character.
|
108
|
+
#
|
109
|
+
# @option border [String] :top_joined_border (' ')
|
110
|
+
# The top-joined-border character.
|
111
|
+
#
|
112
|
+
# @option border [String] :top_right_corner (' ')
|
113
|
+
# The top-right-corner border character.
|
114
|
+
#
|
115
|
+
# @option border [String] :left_border (' ')
|
116
|
+
# The left-hand-side border character.
|
117
|
+
#
|
118
|
+
# @option border [String] :left_joined_border (' ')
|
119
|
+
# The left-hand-side-joined-border character.
|
120
|
+
#
|
121
|
+
# @option border [String] :horizontal_separator (' ')
|
122
|
+
# The horizontal-separator character.
|
123
|
+
#
|
124
|
+
# @option border [String] :vertical_separator (' ')
|
125
|
+
# The vertical-separator character.
|
126
|
+
#
|
127
|
+
# @option border [String] :inner_joined_border (' ')
|
128
|
+
# The inner-joined border character.
|
129
|
+
#
|
130
|
+
# @option border [String] :right_border (' ')
|
131
|
+
# The right-hand-side border character.
|
132
|
+
#
|
133
|
+
# @option border [String] :right_joined_border (' ')
|
134
|
+
# The right-hand-side joined border character.
|
135
|
+
#
|
136
|
+
# @option border [String] :bottom_border (' ')
|
137
|
+
# The bottom border character.
|
138
|
+
#
|
139
|
+
# @option border [String] :bottom_left_corner (' ')
|
140
|
+
# The bottom-left-corner border character.
|
141
|
+
#
|
142
|
+
# @option border [String] :bottom_joined_border (' ')
|
143
|
+
# The bottom-joined border character.
|
144
|
+
#
|
145
|
+
# @option border [String] :bottom_right_corner (' ')
|
146
|
+
# The bottom-right-corner border character.
|
147
|
+
#
|
148
|
+
# @param [Integer] padding
|
149
|
+
# The number of characters to pad table cell values with.
|
150
|
+
#
|
151
|
+
# @param [:left, :right, :center] justify
|
152
|
+
# Specifies how to justify the table cell values.
|
153
|
+
#
|
154
|
+
# @param [:left, :right, :center] justify_header
|
155
|
+
# Specifies how to justify the table header cell values.
|
156
|
+
#
|
157
|
+
# @param [Boolean] separate_rows
|
158
|
+
# Specifies whether to add separator rows in between the rows.
|
159
|
+
#
|
160
|
+
def initialize(border: nil,
|
161
|
+
padding: 1,
|
162
|
+
justify: :left,
|
163
|
+
justify_header: :center,
|
164
|
+
separate_rows: false)
|
165
|
+
@border = case border
|
166
|
+
when Hash
|
167
|
+
BorderStyle.new(**border)
|
168
|
+
when Symbol
|
169
|
+
BORDER_STYLES.fetch(border) do
|
170
|
+
raise(ArgumentError,"unknown border style (#{border.inspect}) must be either #{BORDER_STYLES.keys.map(&:inspect).join(', ')}")
|
171
|
+
end
|
172
|
+
when nil then nil
|
173
|
+
else
|
174
|
+
raise(ArgumentError,"invalid border value (#{border.inspect}) must be either #{BORDER_STYLES.keys.map(&:inspect).join(', ')}, Hash, or nil")
|
175
|
+
end
|
176
|
+
|
177
|
+
@padding = padding
|
178
|
+
|
179
|
+
@justify = justify
|
180
|
+
@justify_header = justify_header
|
181
|
+
|
182
|
+
@separate_rows = separate_rows
|
183
|
+
end
|
184
|
+
|
185
|
+
#
|
186
|
+
# Determines if the rows should be separated.
|
187
|
+
#
|
188
|
+
# @return [Boolean]
|
189
|
+
# Specifies whether each row should be separated with a separator row.
|
190
|
+
#
|
191
|
+
def separate_rows?
|
192
|
+
@separate_rows
|
193
|
+
end
|
194
|
+
|
195
|
+
end
|
196
|
+
end
|
197
|
+
end
|
198
|
+
end
|
@@ -0,0 +1,145 @@
|
|
1
|
+
require 'command_kit/printing/tables/row_builder'
|
2
|
+
|
3
|
+
module CommandKit
|
4
|
+
module Printing
|
5
|
+
module Tables
|
6
|
+
#
|
7
|
+
# Builds a table and calculates it's dimensions.
|
8
|
+
#
|
9
|
+
# @api private
|
10
|
+
#
|
11
|
+
class TableBuilder
|
12
|
+
|
13
|
+
include Enumerable
|
14
|
+
|
15
|
+
# The rows within the table.
|
16
|
+
#
|
17
|
+
# @return [Array<RowBuilder>]
|
18
|
+
attr_reader :rows
|
19
|
+
|
20
|
+
# Indicates whether the table has a header row.
|
21
|
+
#
|
22
|
+
# @return [Boolean]
|
23
|
+
attr_reader :header
|
24
|
+
|
25
|
+
# The height (in lines) of the table.
|
26
|
+
#
|
27
|
+
# @return [Integer]
|
28
|
+
attr_reader :height
|
29
|
+
|
30
|
+
# The width (in characters) of the table.
|
31
|
+
#
|
32
|
+
# @return [Integer]
|
33
|
+
attr_reader :width
|
34
|
+
|
35
|
+
# The maximum number of rows in the table.
|
36
|
+
#
|
37
|
+
# @return [Integer]
|
38
|
+
attr_reader :max_rows
|
39
|
+
|
40
|
+
# The maximum number of columns in the table.
|
41
|
+
#
|
42
|
+
# @return [Integer]
|
43
|
+
attr_reader :max_columns
|
44
|
+
|
45
|
+
# The widths of the columns in the table.
|
46
|
+
#
|
47
|
+
# @return [Array<Integer>]
|
48
|
+
attr_reader :column_widths
|
49
|
+
|
50
|
+
#
|
51
|
+
# Initializes the table.
|
52
|
+
#
|
53
|
+
# @param [Array<Array>] rows
|
54
|
+
# The rows for the table.
|
55
|
+
#
|
56
|
+
# @param [Array] header
|
57
|
+
# The header row.
|
58
|
+
#
|
59
|
+
def initialize(rows=[], header: nil)
|
60
|
+
@rows = []
|
61
|
+
@height = 0
|
62
|
+
@width = 0
|
63
|
+
@column_widths = []
|
64
|
+
|
65
|
+
@max_rows = 0
|
66
|
+
@max_columns = 0
|
67
|
+
|
68
|
+
@header = !header.nil?
|
69
|
+
|
70
|
+
self << header if header
|
71
|
+
rows.each { |row| self << row }
|
72
|
+
end
|
73
|
+
|
74
|
+
#
|
75
|
+
# Determines whether the table has a header row.
|
76
|
+
#
|
77
|
+
# @return [Boolean]
|
78
|
+
# Indicates whether the first row of the table is a header row.
|
79
|
+
#
|
80
|
+
def header?
|
81
|
+
@header
|
82
|
+
end
|
83
|
+
|
84
|
+
#
|
85
|
+
# Appends a row to the table.
|
86
|
+
#
|
87
|
+
# @param [Array] row
|
88
|
+
# The row to append.
|
89
|
+
#
|
90
|
+
# @return [self]
|
91
|
+
#
|
92
|
+
def <<(row)
|
93
|
+
new_row = RowBuilder.new(row)
|
94
|
+
|
95
|
+
new_row.each_with_index do |cell,index|
|
96
|
+
column_width = @column_widths[index] || 0
|
97
|
+
|
98
|
+
if cell.width > column_width
|
99
|
+
@column_widths[index] = cell.width
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
@height += new_row.height
|
104
|
+
@width = new_row.width if new_row.width > @width
|
105
|
+
|
106
|
+
@max_rows += 1
|
107
|
+
@max_columns = new_row.columns if new_row.columns > @max_columns
|
108
|
+
|
109
|
+
@rows << new_row
|
110
|
+
return self
|
111
|
+
end
|
112
|
+
|
113
|
+
#
|
114
|
+
# Fetches a row from the table.
|
115
|
+
#
|
116
|
+
# @param [Integer] row_index
|
117
|
+
# The row index to fetch the row at.
|
118
|
+
#
|
119
|
+
# @return [RowBuilder, nil]
|
120
|
+
# The row or `nil` if no row exists at the given row index.
|
121
|
+
#
|
122
|
+
def [](row_index)
|
123
|
+
@rows[row_index]
|
124
|
+
end
|
125
|
+
|
126
|
+
#
|
127
|
+
# Enumerates over each row in the table.
|
128
|
+
#
|
129
|
+
# @yield [row]
|
130
|
+
# If a block is given, it will be passed each row within the table.
|
131
|
+
#
|
132
|
+
# @yieldparam [RowBuilder] row
|
133
|
+
# A row within the table.
|
134
|
+
#
|
135
|
+
# @return [Enumerator]
|
136
|
+
# If no block is given, an Enumerator will be returned.
|
137
|
+
#
|
138
|
+
def each(&block)
|
139
|
+
@rows.each(&block)
|
140
|
+
end
|
141
|
+
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|