command_kit 0.3.0 → 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 -6
- data/.rubocop.yml +13 -0
- data/ChangeLog.md +18 -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/bug_report.rb +105 -0
- data/lib/command_kit/colors.rb +4 -4
- data/lib/command_kit/edit.rb +54 -0
- data/lib/command_kit/env.rb +1 -1
- data/lib/command_kit/options/option.rb +5 -1
- data/lib/command_kit/options/option_value.rb +2 -2
- data/lib/command_kit/options/parser.rb +1 -1
- 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 +1 -1
- 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/stdio.rb +5 -1
- data/lib/command_kit/version.rb +1 -1
- data/spec/bug_report_spec.rb +266 -0
- data/spec/colors_spec.rb +6 -0
- data/spec/command_name_spec.rb +1 -1
- data/spec/edit_spec.rb +72 -0
- data/spec/options/option_spec.rb +12 -2
- 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/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
- metadata +33 -7
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'command_kit/printing/indent'
|
2
|
+
|
3
|
+
module CommandKit
|
4
|
+
module Printing
|
5
|
+
#
|
6
|
+
# Supports printing aligned key/value fields.
|
7
|
+
#
|
8
|
+
# @since 0.4.0
|
9
|
+
#
|
10
|
+
module Fields
|
11
|
+
include Indent
|
12
|
+
|
13
|
+
#
|
14
|
+
# Prints a Hash as left-justified `:` separated fields.
|
15
|
+
#
|
16
|
+
# @param [Hash, Array<(Object, Object)>] fields
|
17
|
+
# The fields to print.
|
18
|
+
#
|
19
|
+
# @example
|
20
|
+
# print_fields('Name' => 'foo', 'Version' => '0.1.0')
|
21
|
+
# # Name: foo
|
22
|
+
# # Version: 0.1.0
|
23
|
+
#
|
24
|
+
# @api public
|
25
|
+
#
|
26
|
+
def print_fields(fields)
|
27
|
+
max_length = 0
|
28
|
+
|
29
|
+
fields = fields.map { |name,value|
|
30
|
+
name = name.to_s
|
31
|
+
value = value.to_s
|
32
|
+
max_length = name.length if name.length > max_length
|
33
|
+
|
34
|
+
[name, value]
|
35
|
+
}
|
36
|
+
|
37
|
+
fields.each do |name,value|
|
38
|
+
first_line, *rest = value.to_s.lines(chomp: true)
|
39
|
+
|
40
|
+
# print the first line with the header
|
41
|
+
header = "#{name}:".ljust(max_length + 1)
|
42
|
+
puts "#{header} #{first_line}"
|
43
|
+
|
44
|
+
# indent and print the rest of the lines
|
45
|
+
indent(max_length + 2) do
|
46
|
+
rest.each do |line|
|
47
|
+
puts line
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
return nil
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'command_kit/printing/indent'
|
4
|
+
|
5
|
+
module CommandKit
|
6
|
+
module Printing
|
7
|
+
#
|
8
|
+
# Methods for printing lists.
|
9
|
+
#
|
10
|
+
# ## Examples
|
11
|
+
#
|
12
|
+
# include Printing::Lists
|
13
|
+
#
|
14
|
+
# def main
|
15
|
+
# print_list %w[foo bar baz]
|
16
|
+
# # * foo
|
17
|
+
# # * bar
|
18
|
+
# # * baz
|
19
|
+
#
|
20
|
+
# list = ['item 1', 'item 2', ['sub-item 1', 'sub-item 2']]
|
21
|
+
# print_list(list)
|
22
|
+
# # * item 1
|
23
|
+
# # * item 2
|
24
|
+
# # * sub-item 1
|
25
|
+
# # * sub-item 2
|
26
|
+
#
|
27
|
+
# print_list %w[foo bar baz], bullet: '-'
|
28
|
+
# # - foo
|
29
|
+
# # - bar
|
30
|
+
# # - baz
|
31
|
+
# end
|
32
|
+
#
|
33
|
+
# @since 0.4.0
|
34
|
+
#
|
35
|
+
module Lists
|
36
|
+
include Indent
|
37
|
+
|
38
|
+
#
|
39
|
+
# Prints a bulleted list of items.
|
40
|
+
#
|
41
|
+
# @param [Array<#to_s, Array>] list
|
42
|
+
# The list of items to print.
|
43
|
+
#
|
44
|
+
# @param [String] bullet
|
45
|
+
# The bullet character to use for line item.
|
46
|
+
#
|
47
|
+
# @example
|
48
|
+
# print_list %w[foo bar baz]
|
49
|
+
# # * foo
|
50
|
+
# # * bar
|
51
|
+
# # * baz
|
52
|
+
#
|
53
|
+
# @example print a nested list:
|
54
|
+
# list = ['item 1', 'item 2', ['sub-item 1', 'sub-item 2']]
|
55
|
+
# print_list(list)
|
56
|
+
# # * item 1
|
57
|
+
# # * item 2
|
58
|
+
# # * sub-item 1
|
59
|
+
# # * sub-item 2
|
60
|
+
#
|
61
|
+
# @example with a custom bullet character:
|
62
|
+
# print_list %w[foo bar baz], bullet: '-'
|
63
|
+
# # - foo
|
64
|
+
# # - bar
|
65
|
+
# # - baz
|
66
|
+
#
|
67
|
+
# @since 0.4.0
|
68
|
+
#
|
69
|
+
def print_list(list, bullet: '*')
|
70
|
+
list.each do |item|
|
71
|
+
case item
|
72
|
+
when Array
|
73
|
+
indent { print_list(item, bullet: bullet) }
|
74
|
+
else
|
75
|
+
first_line, *rest = item.to_s.lines(chomp: true)
|
76
|
+
|
77
|
+
# print the bullet only on the first list
|
78
|
+
puts "#{bullet} #{first_line}"
|
79
|
+
|
80
|
+
# indent the remaining lines
|
81
|
+
indent(bullet.length + 1) do
|
82
|
+
rest.each do |line|
|
83
|
+
puts line
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -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
|