tabelinha 0.0.0 → 0.1.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/lib/table.rb +217 -0
- metadata +4 -4
- data/lib/tabelinha.rb +0 -7
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 86fbedf86c14565b197bb8b2755d8dac50b8318db5cb2a5ce73c96f0422991e9
|
|
4
|
+
data.tar.gz: 37f9eb12e0fb5ccb27ed17682d87e60ce3408a89d933b1cabea498d1db8ee39f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 0e2af67e046d2b6ec5fb9ce3f93ec62ffe6c563b6ae6da1e80cd2e5c427da3cb5d725f49a18c1fa86e4bd5286443b51bb61a1a2f7aba5d3e6521e406ad86308b
|
|
7
|
+
data.tar.gz: 0440eb7588135806ec8d057ee0f6b2a7a64bbd901a41823c599cf331cfb8836d2427c1fa29ada5d5c2538d233e9124c113292a4f026e307b460ae9f3cb1aacf4
|
data/lib/table.rb
ADDED
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
module Tabelinha
|
|
2
|
+
module_function
|
|
3
|
+
|
|
4
|
+
# Generates a formatted table with customizable options.
|
|
5
|
+
#
|
|
6
|
+
# @param rows [Array<Array<String>>] An array of rows, where each row is an array of cells to be displayed in the table.
|
|
7
|
+
# @param options [Hash] An optional hash of configuration options to customize the appearance of the table.
|
|
8
|
+
# @option options [Boolean] :space_linebroken (true) If true, adds extra space between rows with line breaks.
|
|
9
|
+
# @option options [Integer] :padding (1) The number of spaces padding each cell.
|
|
10
|
+
# @option options [Float] :max_width (Float::INFINITY) The maximum width of the table.
|
|
11
|
+
# @option options [Hash] :corners Hash containing characters for table corners.
|
|
12
|
+
# @option options [String] :top_right ('┌') Character for the top-right corner.
|
|
13
|
+
# @option options [String] :top_left ('┐') Character for the top-left corner.
|
|
14
|
+
# @option options [String] :bottom_right ('└') Character for the bottom-right corner.
|
|
15
|
+
# @option options [String] :bottom_left ('┘') Character for the bottom-left corner.
|
|
16
|
+
# @option options [Hash] :straight Hash containing characters for straight lines.
|
|
17
|
+
# @option options [String] :vertical ('│') Character for vertical lines.
|
|
18
|
+
# @option options [String] :horizontal ('─') Character for horizontal lines.
|
|
19
|
+
# @option options [Hash] :junctions Hash containing characters for junctions.
|
|
20
|
+
# @option options [String] :top ('┬') Character for the top junction.
|
|
21
|
+
# @option options [String] :middle ('┼') Character for the middle junction.
|
|
22
|
+
# @option options [String] :bottom ('┴') Character for the bottom junction.
|
|
23
|
+
#
|
|
24
|
+
# @example
|
|
25
|
+
# rows = [
|
|
26
|
+
# ['Header 1', 'Header 2', 'Header 3'],
|
|
27
|
+
# ['Value 1', 'Value 2', 'Value 3'],
|
|
28
|
+
# ['Another Value 1', 'Another Value 2', 'Another Value 3']
|
|
29
|
+
# ]
|
|
30
|
+
#
|
|
31
|
+
# options = {
|
|
32
|
+
# space_linebroken: true,
|
|
33
|
+
# padding: 1,
|
|
34
|
+
# max_width: 80,
|
|
35
|
+
# corners: { top_right: '┌', top_left: '┐', bottom_right: '└', bottom_left: '┘' },
|
|
36
|
+
# straight: { vertical: '│', horizontal: '─' },
|
|
37
|
+
# junctions: { top: '┬', middle: '┼', bottom: '┴' }
|
|
38
|
+
# }
|
|
39
|
+
#
|
|
40
|
+
# table(rows, options)
|
|
41
|
+
#
|
|
42
|
+
# This method generates a formatted table with the specified rows and options. It supports various formatting elements
|
|
43
|
+
# to provide flexibility in table appearance.
|
|
44
|
+
|
|
45
|
+
def table(rows, options = {})
|
|
46
|
+
# sets options
|
|
47
|
+
|
|
48
|
+
options = {
|
|
49
|
+
space_linebroken: true,
|
|
50
|
+
padding: 1,
|
|
51
|
+
max_width: Float::INFINITY,
|
|
52
|
+
corners: {
|
|
53
|
+
top_right: '┌',
|
|
54
|
+
top_left: '┐',
|
|
55
|
+
bottom_right: '└',
|
|
56
|
+
bottom_left: '┘'
|
|
57
|
+
},
|
|
58
|
+
straight: {
|
|
59
|
+
vertical: '│',
|
|
60
|
+
horizontal: '─'
|
|
61
|
+
},
|
|
62
|
+
junctions: {
|
|
63
|
+
top: '┬',
|
|
64
|
+
middle: '┼',
|
|
65
|
+
bottom: '┴'
|
|
66
|
+
}
|
|
67
|
+
}.merge(options)
|
|
68
|
+
|
|
69
|
+
padding_amount = options[:padding]
|
|
70
|
+
padding = ' ' * padding_amount
|
|
71
|
+
|
|
72
|
+
# split \n and normalize rows
|
|
73
|
+
|
|
74
|
+
newline_treated_rows = []
|
|
75
|
+
|
|
76
|
+
rows.each do |row|
|
|
77
|
+
max_size = 0
|
|
78
|
+
split_row = row.map do |cell|
|
|
79
|
+
split_cells = cell.split("\n")
|
|
80
|
+
max_size = split_cells.length if split_cells.length > max_size
|
|
81
|
+
split_cells
|
|
82
|
+
end.map do |split_cells|
|
|
83
|
+
split_cells += Array.new(max_size - split_cells.length, '')
|
|
84
|
+
end.transpose
|
|
85
|
+
|
|
86
|
+
newline_treated_rows += split_row
|
|
87
|
+
if options[:space_linebroken] && split_row.length > 1
|
|
88
|
+
newline_treated_rows << Array.new(split_row.first.length,
|
|
89
|
+
' ')
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
rows = newline_treated_rows
|
|
94
|
+
|
|
95
|
+
# set widths for each column to be printed, fitting terminal size
|
|
96
|
+
|
|
97
|
+
columns = rows.transpose
|
|
98
|
+
|
|
99
|
+
total_column_width = options[:max_width] - columns.length - 1
|
|
100
|
+
current_column_widths = columns.map { |column| column.map { |cell| cell.gsub(/\e\[([;\d]+)?m/, '').length }.max }
|
|
101
|
+
|
|
102
|
+
actual_column_widths = current_column_widths
|
|
103
|
+
if current_column_widths.sum > total_column_width
|
|
104
|
+
even_width_per_column = total_column_width / columns.length
|
|
105
|
+
even_width_per_column = 1 if even_width_per_column.zero?
|
|
106
|
+
|
|
107
|
+
width_for_linebroken = total_column_width - actual_column_widths.select { |n| n < even_width_per_column }.sum
|
|
108
|
+
|
|
109
|
+
actual_column_widths = current_column_widths.map do |width|
|
|
110
|
+
width > even_width_per_column ? even_width_per_column : width
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
# write the top of the table
|
|
115
|
+
|
|
116
|
+
table = ''
|
|
117
|
+
table << options.dig(:corners, :top_right)
|
|
118
|
+
table << actual_column_widths.map do |width|
|
|
119
|
+
str = ''
|
|
120
|
+
str << options.dig(:straight, :horizontal) * width
|
|
121
|
+
str << options.dig(:straight, :horizontal) * padding_amount * 2
|
|
122
|
+
end.join(options.dig(:junctions, :top))
|
|
123
|
+
|
|
124
|
+
table << options.dig(:corners, :top_left)
|
|
125
|
+
table << "\n"
|
|
126
|
+
|
|
127
|
+
# write the contents of the table(breaks lines if needed)
|
|
128
|
+
|
|
129
|
+
rows.each do |row|
|
|
130
|
+
stripped_columns = row.map.with_index do |cell, column_i|
|
|
131
|
+
width = actual_column_widths[column_i]
|
|
132
|
+
cell.chars.each { |a| }
|
|
133
|
+
no_ansi = cell.gsub(/\e\[([;\d]+)?m/, '')
|
|
134
|
+
|
|
135
|
+
divide_cell(cell, width)
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
height = stripped_columns.map(&:length).max
|
|
139
|
+
height += 1 if height > 1 && options[:space_linebroken]
|
|
140
|
+
new_columns = stripped_columns.map.with_index do |column, column_i|
|
|
141
|
+
width = actual_column_widths[column_i]
|
|
142
|
+
column.fill(' ' * width, column.length..(height - 1))
|
|
143
|
+
column
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
table << new_columns.transpose.map do |row|
|
|
147
|
+
str = ''
|
|
148
|
+
str << options.dig(:straight, :vertical) + padding
|
|
149
|
+
str << row.join(padding + options.dig(:straight, :vertical) + padding)
|
|
150
|
+
str << padding + options.dig(:straight, :vertical)
|
|
151
|
+
end.join("\n")
|
|
152
|
+
table << "\n"
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
# writes the bottom of the table
|
|
156
|
+
|
|
157
|
+
table << options.dig(:corners, :bottom_right)
|
|
158
|
+
table << actual_column_widths.map do |width|
|
|
159
|
+
str = ''
|
|
160
|
+
str << options.dig(:straight, :horizontal) * width
|
|
161
|
+
str << options.dig(:straight, :horizontal) * padding_amount * 2
|
|
162
|
+
end.join(options.dig(:junctions, :bottom))
|
|
163
|
+
table << options.dig(:corners, :bottom_left)
|
|
164
|
+
table << "\n"
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
private_class_method def divide_cell(cell, width)
|
|
168
|
+
buckets = []
|
|
169
|
+
current_bucket = { content: '', ansi_codes: [] }
|
|
170
|
+
current_ansi = { content: '', start_index: 0, end_index: -1 }
|
|
171
|
+
inside_ansi = false
|
|
172
|
+
|
|
173
|
+
cell.chars.each do |char|
|
|
174
|
+
if (char == "\e") || inside_ansi
|
|
175
|
+
current_ansi[:start_index] = current_bucket[:content].length
|
|
176
|
+
current_ansi[:content] << char
|
|
177
|
+
inside_ansi = char != 'm'
|
|
178
|
+
|
|
179
|
+
if !inside_ansi
|
|
180
|
+
current_bucket[:ansi_codes] << current_ansi
|
|
181
|
+
current_ansi = { content: '', start_index: 0, end_index: -1 }
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
next
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
current_bucket[:content] << char
|
|
188
|
+
next if current_bucket[:content].length < width
|
|
189
|
+
|
|
190
|
+
buckets << current_bucket
|
|
191
|
+
current_bucket = { content: '', ansi_codes: [] }
|
|
192
|
+
current_bucket[:ansi_codes] = buckets.last[:ansi_codes].select { |ac| ac[:end_index] == -1 }.map do |ac|
|
|
193
|
+
{ content: ac[:content], start_index: 0, end_index: -1 }
|
|
194
|
+
end
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
if !current_bucket[:content].empty?
|
|
198
|
+
current_bucket[:content] = current_bucket[:content].ljust(width)
|
|
199
|
+
buckets << current_bucket
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
ansi_code_end = "\e[m"
|
|
203
|
+
buckets.map do |bucket|
|
|
204
|
+
content_result = bucket[:content]
|
|
205
|
+
|
|
206
|
+
bucket[:ansi_codes].sort_by { |ac| ac[:end_index] == -1 ? Float::INFINITY : ac[:end_index] }.reverse.each do |ac|
|
|
207
|
+
content_result.insert(ac[:end_index], ansi_code_end)
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
bucket[:ansi_codes].sort_by { |ac| ac[:start_index] }.reverse.each do |ac|
|
|
211
|
+
content_result.insert(ac[:start_index], ac[:content])
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
content_result
|
|
215
|
+
end
|
|
216
|
+
end
|
|
217
|
+
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: tabelinha
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.1.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Hikari Luz
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2023-10-
|
|
11
|
+
date: 2023-10-09 00:00:00.000000000 Z
|
|
12
12
|
dependencies: []
|
|
13
13
|
description: This gem generates tables from a array of rows, allowing options and
|
|
14
14
|
tools ranging from what character the table is made of, to breaking lines if the
|
|
@@ -18,8 +18,8 @@ executables: []
|
|
|
18
18
|
extensions: []
|
|
19
19
|
extra_rdoc_files: []
|
|
20
20
|
files:
|
|
21
|
-
- lib/
|
|
22
|
-
homepage: https://
|
|
21
|
+
- lib/table.rb
|
|
22
|
+
homepage: https://github.com/Hikari-desuyoo/tabelinha
|
|
23
23
|
licenses:
|
|
24
24
|
- GPL-2.0
|
|
25
25
|
metadata: {}
|