kosi 0.0.1 → 0.0.2
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/.coveralls.yml +1 -1
- data/.rspec +2 -2
- data/.rubocop.yml +11 -11
- data/.travis.yml +8 -8
- data/Gemfile +12 -12
- data/README.md +2 -1
- data/Rakefile +8 -8
- data/kosi.gemspec +28 -28
- data/lib/kosi.rb +13 -13
- data/lib/kosi/align.rb +33 -33
- data/lib/kosi/char_option.rb +17 -17
- data/lib/kosi/connector_char.rb +26 -26
- data/lib/kosi/header.rb +18 -18
- data/lib/kosi/horizontal_border_char.rb +26 -26
- data/lib/kosi/options.rb +15 -15
- data/lib/kosi/separate_each_row.rb +15 -15
- data/lib/kosi/validators.rb +3 -3
- data/lib/kosi/validators/each_array_length_validator.rb +21 -21
- data/lib/kosi/validators/row_type_validator.rb +19 -19
- data/lib/kosi/version.rb +4 -4
- data/lib/kosi/vertical_border_char.rb +26 -26
- data/lib/table.rb +149 -138
- data/spec/kosi/align_spec.rb +77 -77
- data/spec/kosi/connector_char_spec.rb +59 -59
- data/spec/kosi/header_spec.rb +93 -93
- data/spec/kosi/horizontal_border_char_spec.rb +59 -59
- data/spec/kosi/separate_each_row_spec.rb +55 -55
- data/spec/kosi/validators/each_array_length_validator_spec.rb +56 -56
- data/spec/kosi/validators/row_type_validator_spec.rb +51 -51
- data/spec/kosi/vertical_border_char_spec.rb +59 -59
- data/spec/spec_helper.rb +16 -16
- data/spec/table_spec.rb +145 -134
- metadata +2 -3
- data/README.html +0 -273
data/lib/kosi/options.rb
CHANGED
@@ -1,15 +1,15 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
# TableFormat for Terminal(Use Japanese Charactors)
|
4
|
-
module Kosi
|
5
|
-
# Options
|
6
|
-
module OptionKeys
|
7
|
-
ALIGN = :align
|
8
|
-
HEADER = :header
|
9
|
-
HAS_HEADER = :has_header
|
10
|
-
CONNECTOR_CHAR = :connector_char
|
11
|
-
HORIZONTAL_BORDER_CHAR = :horizontal_border_char
|
12
|
-
VERTICAL_BORDER_CHAR = :vertical_border_char
|
13
|
-
SEPARATE_EACH_ROW = :separate_each_row
|
14
|
-
end
|
15
|
-
end
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
# TableFormat for Terminal(Use Japanese Charactors)
|
4
|
+
module Kosi
|
5
|
+
# Options
|
6
|
+
module OptionKeys
|
7
|
+
ALIGN = :align
|
8
|
+
HEADER = :header
|
9
|
+
HAS_HEADER = :has_header
|
10
|
+
CONNECTOR_CHAR = :connector_char
|
11
|
+
HORIZONTAL_BORDER_CHAR = :horizontal_border_char
|
12
|
+
VERTICAL_BORDER_CHAR = :vertical_border_char
|
13
|
+
SEPARATE_EACH_ROW = :separate_each_row
|
14
|
+
end
|
15
|
+
end
|
@@ -1,15 +1,15 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
require 'kosi/options'
|
3
|
-
|
4
|
-
# TableFormat for Terminal(Use Japanese Charactors)
|
5
|
-
module Kosi
|
6
|
-
# SeparateEachRow
|
7
|
-
class SeparateEachRow
|
8
|
-
attr_reader :value
|
9
|
-
DEFAULT = false
|
10
|
-
|
11
|
-
def initialize(options)
|
12
|
-
@value = options[OptionKeys::SEPARATE_EACH_ROW] || DEFAULT
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'kosi/options'
|
3
|
+
|
4
|
+
# TableFormat for Terminal(Use Japanese Charactors)
|
5
|
+
module Kosi
|
6
|
+
# SeparateEachRow
|
7
|
+
class SeparateEachRow
|
8
|
+
attr_reader :value
|
9
|
+
DEFAULT = false
|
10
|
+
|
11
|
+
def initialize(options)
|
12
|
+
@value = options[OptionKeys::SEPARATE_EACH_ROW] || DEFAULT
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
data/lib/kosi/validators.rb
CHANGED
@@ -1,3 +1,3 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
require 'kosi/validators/each_array_length_validator'
|
3
|
-
require 'kosi/validators/row_type_validator'
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'kosi/validators/each_array_length_validator'
|
3
|
+
require 'kosi/validators/row_type_validator'
|
@@ -1,21 +1,21 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
# Kosi
|
4
|
-
module Kosi
|
5
|
-
# Validators
|
6
|
-
module Validators
|
7
|
-
# EachArrayLength Validator
|
8
|
-
# if row class is not Array, fail ArgumentError.
|
9
|
-
class EachArrayLength
|
10
|
-
INVALID_ARRAY_LENGTH_MESSAGE = \
|
11
|
-
'invalid array length.each array must be same length'
|
12
|
-
def self.validate(row)
|
13
|
-
row_sizes = row.map(&:size)
|
14
|
-
return if row_sizes.uniq.size == 0
|
15
|
-
unless row_sizes.uniq.size == 1
|
16
|
-
fail ArgumentError, INVALID_ARRAY_LENGTH_MESSAGE
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
# Kosi
|
4
|
+
module Kosi
|
5
|
+
# Validators
|
6
|
+
module Validators
|
7
|
+
# EachArrayLength Validator
|
8
|
+
# if row class is not Array, fail ArgumentError.
|
9
|
+
class EachArrayLength
|
10
|
+
INVALID_ARRAY_LENGTH_MESSAGE = \
|
11
|
+
'invalid array length.each array must be same length'
|
12
|
+
def self.validate(row)
|
13
|
+
row_sizes = row.map(&:size)
|
14
|
+
return if row_sizes.uniq.size == 0
|
15
|
+
unless row_sizes.uniq.size == 1
|
16
|
+
fail ArgumentError, INVALID_ARRAY_LENGTH_MESSAGE
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -1,19 +1,19 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
# Kosi
|
4
|
-
module Kosi
|
5
|
-
# Validators
|
6
|
-
module Validators
|
7
|
-
# RowType Validator
|
8
|
-
# if row class is not Array, fail ArgumentError.
|
9
|
-
class RowType
|
10
|
-
INVALID_ROW_MESSAGE = 'invalid row class %s. row class must be Array.'
|
11
|
-
def self.validate(row)
|
12
|
-
unless row.is_a?(Array)
|
13
|
-
message = format(INVALID_ROW_MESSAGE, row.class)
|
14
|
-
fail ArgumentError, message
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
# Kosi
|
4
|
+
module Kosi
|
5
|
+
# Validators
|
6
|
+
module Validators
|
7
|
+
# RowType Validator
|
8
|
+
# if row class is not Array, fail ArgumentError.
|
9
|
+
class RowType
|
10
|
+
INVALID_ROW_MESSAGE = 'invalid row class %s. row class must be Array.'
|
11
|
+
def self.validate(row)
|
12
|
+
unless row.is_a?(Array)
|
13
|
+
message = format(INVALID_ROW_MESSAGE, row.class)
|
14
|
+
fail ArgumentError, message
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/lib/kosi/version.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# TableFormat for Terminal(Use Japanese Charactors)
|
2
|
-
module Kosi
|
3
|
-
VERSION = '0.0.
|
4
|
-
end
|
1
|
+
# TableFormat for Terminal(Use Japanese Charactors)
|
2
|
+
module Kosi
|
3
|
+
VERSION = '0.0.2'
|
4
|
+
end
|
@@ -1,26 +1,26 @@
|
|
1
|
-
require 'kosi/options'
|
2
|
-
require 'kosi/char_option'
|
3
|
-
|
4
|
-
# TableFormat for Terminal(Use Japanese Charactors)
|
5
|
-
module Kosi
|
6
|
-
# VerticalBorderChar
|
7
|
-
class VerticalBorderChar < CharOption
|
8
|
-
DEFAULT = '|'
|
9
|
-
INVALID_CHAR_MSG = \
|
10
|
-
'vertical_border_char must be 1 length(%d) char %s'
|
11
|
-
|
12
|
-
def default
|
13
|
-
DEFAULT
|
14
|
-
end
|
15
|
-
|
16
|
-
def key
|
17
|
-
OptionKeys::VERTICAL_BORDER_CHAR
|
18
|
-
end
|
19
|
-
|
20
|
-
private
|
21
|
-
|
22
|
-
def invalid_char_msg
|
23
|
-
INVALID_CHAR_MSG
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
1
|
+
require 'kosi/options'
|
2
|
+
require 'kosi/char_option'
|
3
|
+
|
4
|
+
# TableFormat for Terminal(Use Japanese Charactors)
|
5
|
+
module Kosi
|
6
|
+
# VerticalBorderChar
|
7
|
+
class VerticalBorderChar < CharOption
|
8
|
+
DEFAULT = '|'
|
9
|
+
INVALID_CHAR_MSG = \
|
10
|
+
'vertical_border_char must be 1 length(%d) char %s'
|
11
|
+
|
12
|
+
def default
|
13
|
+
DEFAULT
|
14
|
+
end
|
15
|
+
|
16
|
+
def key
|
17
|
+
OptionKeys::VERTICAL_BORDER_CHAR
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def invalid_char_msg
|
23
|
+
INVALID_CHAR_MSG
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
data/lib/table.rb
CHANGED
@@ -1,138 +1,149 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
require 'kosi'
|
3
|
-
require 'kosi/validators'
|
4
|
-
|
5
|
-
# TableFormat for Terminal(Use Japanese Charactors)
|
6
|
-
module Kosi
|
7
|
-
# Table
|
8
|
-
class Table
|
9
|
-
attr_reader :align, :header, :connector_char, :horizontal_border_char,
|
10
|
-
:vertical_border_char, :separate_each_row
|
11
|
-
|
12
|
-
def initialize(options = {})
|
13
|
-
@align = Kosi::Align.new(options)
|
14
|
-
@header = Kosi::Header.new(options)
|
15
|
-
@connector_char = Kosi::ConnectorChar.new(options)
|
16
|
-
@horizontal_border_char = Kosi::HorizontalBorderChar.new(options)
|
17
|
-
@vertical_border_char = Kosi::VerticalBorderChar.new(options)
|
18
|
-
@separate_each_row = Kosi::SeparateEachRow.new(options)
|
19
|
-
end
|
20
|
-
|
21
|
-
def render(rows)
|
22
|
-
check_rows_type(rows)
|
23
|
-
check_each_array_length(rows)
|
24
|
-
header = read_header
|
25
|
-
|
26
|
-
|
27
|
-
table_format_rows
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
tmp_rows
|
44
|
-
tmp_rows
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
max_lengths[i]
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
a
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
results
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
results <<
|
92
|
-
results
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
results <<
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
ret
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
@header.
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'kosi'
|
3
|
+
require 'kosi/validators'
|
4
|
+
|
5
|
+
# TableFormat for Terminal(Use Japanese Charactors)
|
6
|
+
module Kosi
|
7
|
+
# Table
|
8
|
+
class Table
|
9
|
+
attr_reader :align, :header, :connector_char, :horizontal_border_char,
|
10
|
+
:vertical_border_char, :separate_each_row
|
11
|
+
|
12
|
+
def initialize(options = {})
|
13
|
+
@align = Kosi::Align.new(options)
|
14
|
+
@header = Kosi::Header.new(options)
|
15
|
+
@connector_char = Kosi::ConnectorChar.new(options)
|
16
|
+
@horizontal_border_char = Kosi::HorizontalBorderChar.new(options)
|
17
|
+
@vertical_border_char = Kosi::VerticalBorderChar.new(options)
|
18
|
+
@separate_each_row = Kosi::SeparateEachRow.new(options)
|
19
|
+
end
|
20
|
+
|
21
|
+
def render(rows)
|
22
|
+
check_rows_type(rows)
|
23
|
+
check_each_array_length(rows)
|
24
|
+
header = read_header
|
25
|
+
escaped_rows = escape_ansi_escape_sequence(rows)
|
26
|
+
max_lengths = get_max_lengths(escaped_rows, header)
|
27
|
+
table_format_rows = get_table_format_rows(rows, max_lengths, header)
|
28
|
+
table_format_rows.join("\n") + "\n"
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def check_rows_type(rows)
|
34
|
+
Validators::RowType.validate(rows)
|
35
|
+
rows.each { |row|Validators::RowType.validate(row) }
|
36
|
+
end
|
37
|
+
|
38
|
+
def check_each_array_length(rows)
|
39
|
+
Validators::EachArrayLength.validate(rows)
|
40
|
+
end
|
41
|
+
|
42
|
+
def get_max_lengths(rows, header)
|
43
|
+
tmp_rows = rows.dup
|
44
|
+
tmp_rows << header unless @header.empty?
|
45
|
+
tmp_rows.reduce([]) do |max_lengths, row|
|
46
|
+
row.each_with_index do |e, i|
|
47
|
+
s = ascii1_other2_size(String(e))
|
48
|
+
next unless greater?(s, max_lengths[i])
|
49
|
+
max_lengths[i] = s
|
50
|
+
end
|
51
|
+
max_lengths
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def greater?(one, other)
|
56
|
+
return true if other.nil?
|
57
|
+
one > other
|
58
|
+
end
|
59
|
+
|
60
|
+
def ascii1_other2_size(column)
|
61
|
+
column.split('').reduce(0) do |a, e|
|
62
|
+
a += half?(e) ? 1 : 2
|
63
|
+
a
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def half?(char)
|
68
|
+
case char.ord
|
69
|
+
when 1..127, 65_377..65_439
|
70
|
+
true
|
71
|
+
else
|
72
|
+
false
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def get_table_format_rows(rows, max_lengths, header)
|
77
|
+
top_bottom_line = top_bottom(max_lengths)
|
78
|
+
results = [top_bottom_line]
|
79
|
+
append_header(results, header, max_lengths, top_bottom_line)
|
80
|
+
rows.each do |col|
|
81
|
+
results += formated_row(col, max_lengths, top_bottom_line)
|
82
|
+
end
|
83
|
+
results << top_bottom_line unless @separate_each_row.value
|
84
|
+
results
|
85
|
+
end
|
86
|
+
|
87
|
+
def formated_row(col, max_lengths, top_bottom_line)
|
88
|
+
results = []
|
89
|
+
row_results = get_columns(col, max_lengths)
|
90
|
+
virtical = @vertical_border_char.value
|
91
|
+
results << "#{virtical}#{row_results.join(virtical)}#{virtical}"
|
92
|
+
results << top_bottom_line if @separate_each_row.value
|
93
|
+
results
|
94
|
+
end
|
95
|
+
|
96
|
+
def append_header(results, header, max_lengths, top_bottom_line)
|
97
|
+
unless @header.empty?
|
98
|
+
results << formated_header(header, max_lengths)
|
99
|
+
results << top_bottom_line
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def top_bottom(max_lengths)
|
104
|
+
results = max_lengths.reduce([]) do |ret, column_size|
|
105
|
+
ret << @horizontal_border_char.value * column_size
|
106
|
+
ret
|
107
|
+
end
|
108
|
+
con = @connector_char.value
|
109
|
+
"#{con}#{results.join(con)}#{con}"
|
110
|
+
end
|
111
|
+
|
112
|
+
def read_header
|
113
|
+
return nil if @header.empty?
|
114
|
+
@header.value
|
115
|
+
end
|
116
|
+
|
117
|
+
def escape_ansi_escape_sequence(rows)
|
118
|
+
rows.reduce([]) do |r, e|
|
119
|
+
r << e.map do |f|f.to_s.gsub(/\x1b(\[|\(|\))[;?0-9]*[0-9A-Za-z]/, '')
|
120
|
+
.gsub(/\x1b(\[|\(|\))[;?0-9]*[0-9A-Za-z]/, '')
|
121
|
+
.gsub(/(\x03|\x1a)/, '')
|
122
|
+
end
|
123
|
+
r
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
def formated_header(header, max_lengths)
|
128
|
+
header_results = []
|
129
|
+
header.size.times do |i|
|
130
|
+
column = String(header[i])
|
131
|
+
diff = ascii1_other2_size(column) - column.size
|
132
|
+
header_results << @align.apply(column, max_lengths[i], diff)
|
133
|
+
end
|
134
|
+
virtical = @vertical_border_char.value
|
135
|
+
header_line = header_results.join(virtical)
|
136
|
+
"#{virtical}#{header_line}#{virtical}"
|
137
|
+
end
|
138
|
+
|
139
|
+
def get_columns(columns, max_lengths)
|
140
|
+
column_results = []
|
141
|
+
columns.size.times do |i|
|
142
|
+
column = String(columns[i])
|
143
|
+
diff = ascii1_other2_size(column) - column.size
|
144
|
+
column_results << @align.apply(column, max_lengths[i], diff)
|
145
|
+
end
|
146
|
+
column_results
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|