command_line_reporter 2.1 → 3.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.
- data/README.md +29 -7
- data/examples/nested.rb +2 -2
- data/examples/progress.rb +10 -8
- data/examples/quiet.rb +1 -1
- data/examples/simple.rb +2 -1
- data/examples/table.rb +38 -16
- data/lib/column.rb +52 -35
- data/lib/command_line_reporter.rb +39 -25
- data/lib/nested_formatter.rb +20 -5
- data/lib/progress_formatter.rb +17 -2
- data/lib/row.rb +64 -46
- data/lib/table.rb +42 -28
- data/lib/version.rb +1 -1
- data/spec/column_spec.rb +342 -49
- data/spec/command_line_reporter_spec.rb +104 -3
- data/spec/nested_formatter_spec.rb +44 -3
- data/spec/progress_formatter_spec.rb +26 -0
- data/spec/row_spec.rb +47 -10
- data/spec/table_spec.rb +73 -19
- metadata +14 -3
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
## Command Line Reporter
|
2
2
|
|
3
|
-
This gem provides a DSL that makes it easy to write reports of various types in ruby. It
|
3
|
+
This gem provides a DSL that makes it easy to write reports of various types in ruby. It eliminates
|
4
4
|
the need to litter your source with *puts* statements instead providing a more readable, expressive
|
5
5
|
interface to your application. Some of the best features include:
|
6
6
|
|
@@ -9,12 +9,15 @@ interface to your application. Some of the best features include:
|
|
9
9
|
* Easily created headers and footers for your report
|
10
10
|
* Output suppression that makes it easy for your script to support a _quiet_ flag
|
11
11
|
|
12
|
+
The latest release also supports colors allowing you to distinguish data in new ways including bold
|
13
|
+
if your terminal supports it.
|
14
|
+
|
12
15
|
### Installation
|
13
16
|
|
14
|
-
It is up on rubygems.org so add it to your bundle
|
17
|
+
It is up on rubygems.org so add it to your bundle in the Gemfile
|
15
18
|
|
16
19
|
```bash
|
17
|
-
gem 'command_line_reporter', '>=
|
20
|
+
gem 'command_line_reporter', '>=3.0'
|
18
21
|
```
|
19
22
|
|
20
23
|
or do it the old fashioned way:
|
@@ -55,6 +58,8 @@ There are several methods the mixin provides that do not depend on the formatter
|
|
55
58
|
Either true|false. _Default: false_
|
56
59
|
* _:rule_ - true|false indicates whether to include a horizontal rule below|above the
|
57
60
|
header|footer. _Default: false_
|
61
|
+
* _:color_ - The color to use for the terminal output i.e. 'red' or 'blue' or 'green'
|
62
|
+
* _:bold_ - true|false to boldface the font
|
58
63
|
* _report(hash) {block}_
|
59
64
|
* The first argument is a hash that defines the options for the method. See the details in the
|
60
65
|
formatter section for allowed values.
|
@@ -69,34 +74,51 @@ There are several methods the mixin provides that do not depend on the formatter
|
|
69
74
|
* _horizontal_rule(hash)_
|
70
75
|
* _:char_ - The character used to build the rule. _Default: '-'_
|
71
76
|
* _:width_ - The width in characters of the rule. _Default: 100_
|
77
|
+
* _:color_ - The color to use for the terminal output i.e. 'red' or 'blue' or 'green'
|
78
|
+
* _:bold_ - true|false to boldface the font
|
72
79
|
* _vertical_spacing(int)_
|
73
80
|
* Number of blank lines to output. _Default: 1_
|
74
81
|
* _datetime(hash)_
|
75
82
|
* _:align_ - 'left'|'center'|'right' alignment of the timestamp. _Default: 'left'_
|
76
83
|
* _:width_ - The width of the string in characters. _Default: 100_
|
77
84
|
* _:format_ - Any allowed format from #strftime#. _Default: %Y-%m-%d %H:%I:%S%p_
|
85
|
+
* _:color_ - The color to use for the terminal output i.e. 'red' or 'blue' or 'green'
|
86
|
+
* _:bold_ - true|false to boldface the font
|
78
87
|
* _aligned(string, hash)_
|
79
88
|
* _text_ - String to display
|
80
89
|
* _:align_ - 'left'|'right'|'center' align the string text. _Default: 'left'_
|
81
90
|
* _:width_ - The width in characters of the string text. _Default: 100_
|
91
|
+
* _:color_ - The color to use for the terminal output i.e. 'red' or 'blue' or 'green'
|
92
|
+
* _:bold_ - true|false to boldface the font
|
82
93
|
* _table(hash) {block}_
|
83
94
|
* The first argument is a hash that defines properties of the table.
|
84
95
|
* _:border_ - true|false indicates whether to include borders around the table cells
|
85
96
|
* The second argument is a block which includes calls the to the _row_ method
|
86
97
|
* _row {block}_
|
87
|
-
*
|
98
|
+
* _:header_ - Set to true to indicate if this is a header row in the table.
|
99
|
+
* _:color_ - The color to use for the terminal output i.e. 'red' or 'blue' or 'green'
|
100
|
+
* _:bold_ - true|false to boldface the font
|
88
101
|
* _column(string, hash)_
|
89
102
|
* _text_ - String to display in the table cell
|
90
103
|
* _options_ - The options to define the column
|
91
104
|
* :width - defines the width of the column
|
92
105
|
* :padding - The number of spaces to put on both the left and right of the text.
|
93
106
|
* :align - Allowed values are left|right|center
|
107
|
+
* :color - The color to use for the terminal output i.e. 'red' or 'blue' or 'green'
|
108
|
+
* :bold - true|false to boldface the font
|
94
109
|
|
95
110
|
### To Do
|
96
111
|
|
97
|
-
*
|
98
|
-
*
|
99
|
-
|
112
|
+
* Refactor the table structure to use a formatter that produces the current ascii output
|
113
|
+
* After the formatter is added to a table then create one for html output
|
114
|
+
* Add the ability for a column to span across others in a table
|
115
|
+
|
116
|
+
### Contributors
|
117
|
+
|
118
|
+
* Thanks to [Mike Gunderloy](https://github.com/ffmike) for suggesting the need for suppressing
|
119
|
+
output and putting together a fantastic pull request and discussion
|
120
|
+
* Thanks to [Jason Rogers](https://github.com/jacaetevha) and [Peter
|
121
|
+
Suschlik](https://github.com/splattael) for their contributions as well on items I missed
|
100
122
|
|
101
123
|
### License
|
102
124
|
|
data/examples/nested.rb
CHANGED
data/examples/progress.rb
CHANGED
@@ -16,12 +16,14 @@ class Example
|
|
16
16
|
10.times do
|
17
17
|
x += 1
|
18
18
|
sleep 0.1
|
19
|
-
formatter.progress
|
19
|
+
# formatter.progress
|
20
|
+
progress
|
20
21
|
|
21
22
|
10.times do
|
22
23
|
x += 1
|
23
24
|
sleep 0.1
|
24
|
-
formatter.progress
|
25
|
+
# formatter.progress
|
26
|
+
progress
|
25
27
|
end
|
26
28
|
end
|
27
29
|
end
|
@@ -32,24 +34,24 @@ class Example
|
|
32
34
|
10.times do
|
33
35
|
y += 1
|
34
36
|
sleep 0.1
|
35
|
-
|
37
|
+
progress("#{y*10}%")
|
36
38
|
end
|
37
39
|
end
|
38
40
|
|
39
41
|
report do
|
40
42
|
3.times do
|
41
|
-
|
43
|
+
progress("\\")
|
42
44
|
sleep 0.1
|
43
|
-
|
45
|
+
progress("/")
|
44
46
|
sleep 0.1
|
45
|
-
|
47
|
+
progress("-")
|
46
48
|
sleep 0.1
|
47
49
|
end
|
48
50
|
end
|
49
51
|
|
50
|
-
report do
|
52
|
+
report(:color => 'red') do
|
51
53
|
100.times do
|
52
|
-
|
54
|
+
progress(erase_chars + NYAN_CHARS)
|
53
55
|
sleep 0.1
|
54
56
|
end
|
55
57
|
end
|
data/examples/quiet.rb
CHANGED
data/examples/simple.rb
CHANGED
data/examples/table.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# recoil <co>mmand_<li>ne_<re>porter
|
1
2
|
require 'command_line_reporter'
|
2
3
|
|
3
4
|
class Example
|
@@ -7,40 +8,61 @@ class Example
|
|
7
8
|
header(:title => 'TABLE EXAMPLES - Borders, Wrapping, Alignment and Padding', :align => 'center', :width => 70)
|
8
9
|
|
9
10
|
2.times do |j|
|
10
|
-
header
|
11
|
+
header :title => "Table #{j}", :align => 'center', :width => 65
|
11
12
|
|
12
|
-
table
|
13
|
+
table :border => j % 2 == 0 do
|
13
14
|
3.times do
|
14
15
|
row do
|
15
16
|
i = 0
|
16
17
|
3.times do
|
17
18
|
i += 10
|
18
|
-
column
|
19
|
+
column 'x' * (0 + rand(50)), :align => %w[left right center][rand(3)], :width => i, :padding => rand(5)
|
19
20
|
end
|
20
21
|
end
|
21
22
|
end
|
22
23
|
end
|
23
24
|
|
24
|
-
vertical_spacing
|
25
|
+
vertical_spacing 2
|
25
26
|
end
|
26
27
|
|
27
|
-
header
|
28
|
+
header :title => 'An example of a table with a header row. The color and border properties are not inherited'
|
28
29
|
|
29
|
-
table
|
30
|
-
row do
|
31
|
-
column
|
32
|
-
column
|
33
|
-
column
|
30
|
+
table :border => true do
|
31
|
+
row :header => true, :color => 'red' do
|
32
|
+
column 'MY NAME IS REALLY LONG AND WILL WRAP AND HOPE', :width => 20, :align => 'center', :color => 'blue'
|
33
|
+
column 'ADDRESS', :width => 30, :padding => 5
|
34
|
+
column 'CITY', :width => 15
|
35
|
+
end
|
36
|
+
row :color => 'green', :bold => true do
|
37
|
+
column 'Ceaser'
|
38
|
+
column '1 Appian Way'
|
39
|
+
column 'Rome'
|
34
40
|
end
|
35
41
|
row do
|
36
|
-
column
|
37
|
-
column
|
38
|
-
column
|
42
|
+
column 'Richard Feynman'
|
43
|
+
column '1 Golden Gate'
|
44
|
+
column 'Quantum Field'
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
vertical_spacing 2
|
49
|
+
header :title => 'The same table with the properties inherited from the first row'
|
50
|
+
|
51
|
+
table :border => true do
|
52
|
+
row :color => 'red' do
|
53
|
+
column 'MY NAME IS REALLY LONG AND WILL WRAP AND HOPE', :width => 20, :align => 'center', :color => 'blue'
|
54
|
+
column 'ADDRESS', :width => 30, :padding => 5
|
55
|
+
column 'CITY', :width => 15
|
56
|
+
end
|
57
|
+
row :color => 'green', :bold => true do
|
58
|
+
column 'Ceaser'
|
59
|
+
column '1 Appian Way'
|
60
|
+
column 'Rome'
|
39
61
|
end
|
40
62
|
row do
|
41
|
-
column
|
42
|
-
column
|
43
|
-
column
|
63
|
+
column 'Richard Feynman'
|
64
|
+
column '1 Golden Gate'
|
65
|
+
column 'Quantum Field'
|
44
66
|
end
|
45
67
|
end
|
46
68
|
end
|
data/lib/column.rb
CHANGED
@@ -1,50 +1,67 @@
|
|
1
1
|
require 'options_validator'
|
2
|
+
require 'colored'
|
2
3
|
|
3
|
-
|
4
|
-
|
4
|
+
module CommandLineReporter
|
5
|
+
class Column
|
6
|
+
include OptionsValidator
|
5
7
|
|
6
|
-
|
7
|
-
|
8
|
+
VALID_OPTIONS = [:width, :padding, :align, :color, :bold, :underline, :reversed]
|
9
|
+
attr_accessor :text, :size, *VALID_OPTIONS
|
8
10
|
|
9
|
-
|
10
|
-
|
11
|
+
def initialize(text = nil, options = {})
|
12
|
+
self.validate_options(options, *VALID_OPTIONS)
|
11
13
|
|
12
|
-
|
14
|
+
self.text = text
|
13
15
|
|
14
|
-
|
15
|
-
|
16
|
-
|
16
|
+
self.width = options[:width] || 10
|
17
|
+
self.align = options[:align] || 'left'
|
18
|
+
self.padding = options[:padding] || 0
|
19
|
+
self.color = options[:color] || nil
|
20
|
+
self.bold = options[:bold] || false
|
21
|
+
self.underline = options[:underline] || false
|
22
|
+
self.reversed = options[:reversed] || false
|
17
23
|
|
18
|
-
|
19
|
-
|
24
|
+
raise ArgumentError unless self.width > 0
|
25
|
+
raise ArgumentError unless self.padding.to_s.match(/^\d+$/)
|
20
26
|
|
21
|
-
|
22
|
-
|
27
|
+
self.size = self.width - 2 * self.padding
|
28
|
+
end
|
23
29
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
30
|
+
def screen_rows
|
31
|
+
if self.text.nil? || self.text.empty?
|
32
|
+
[' ' * self.width]
|
33
|
+
else
|
34
|
+
self.text.scan(/.{1,#{self.size}}/m).map {|s| to_cell(s)}
|
35
|
+
end
|
29
36
|
end
|
30
|
-
end
|
31
37
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
38
|
+
private
|
39
|
+
|
40
|
+
def to_cell(str)
|
41
|
+
# NOTE: For making underline and reversed work Change so that based on the
|
42
|
+
# unformatted text it determines how much spacing to add left and right
|
43
|
+
# then colorize the cell text
|
44
|
+
cell = if str.empty?
|
45
|
+
' ' * self.size
|
46
|
+
else
|
47
|
+
case self.align
|
48
|
+
when 'left'
|
49
|
+
str.ljust(self.size)
|
50
|
+
when 'right'
|
51
|
+
str.rjust(self.size)
|
52
|
+
when 'center'
|
53
|
+
str.ljust((self.size - str.size)/2.0 + str.size).rjust(self.size)
|
54
|
+
end
|
45
55
|
end
|
46
|
-
end
|
47
56
|
|
48
|
-
|
57
|
+
padding_str = ' ' * self.padding
|
58
|
+
padding_str + colorize(cell) + padding_str
|
59
|
+
end
|
60
|
+
|
61
|
+
def colorize(str)
|
62
|
+
str = str.send(color) if self.color
|
63
|
+
str = str.send('bold') if self.bold
|
64
|
+
str
|
65
|
+
end
|
49
66
|
end
|
50
67
|
end
|
@@ -11,6 +11,7 @@ module CommandLineReporter
|
|
11
11
|
DEFAULTS = {
|
12
12
|
:width => 100,
|
13
13
|
:align => 'left',
|
14
|
+
:formatter => 'nested',
|
14
15
|
}
|
15
16
|
|
16
17
|
def suppress_output
|
@@ -36,21 +37,25 @@ module CommandLineReporter
|
|
36
37
|
end
|
37
38
|
|
38
39
|
def report(options = {}, &block)
|
39
|
-
self.formatter ||=
|
40
|
+
self.formatter ||= DEFAULTS[:formatter]
|
40
41
|
self.formatter.format(options, block)
|
41
42
|
end
|
42
43
|
|
44
|
+
def progress(override = nil)
|
45
|
+
self.formatter.progress(override)
|
46
|
+
end
|
47
|
+
|
43
48
|
def footer(options = {})
|
44
49
|
section(:footer, options)
|
45
50
|
end
|
46
51
|
|
47
52
|
def horizontal_rule(options = {})
|
48
|
-
validate_options(options, :char, :width)
|
53
|
+
validate_options(options, :char, :width, :color, :bold)
|
49
54
|
|
50
55
|
char = options[:char].is_a?(String) ? options[:char] : '-'
|
51
56
|
width = options[:width] || DEFAULTS[:width]
|
52
57
|
|
53
|
-
|
58
|
+
aligned(char * width, :width => width, :color => options[:color], :bold => options[:bold])
|
54
59
|
end
|
55
60
|
|
56
61
|
def vertical_spacing(lines = 1)
|
@@ -60,7 +65,7 @@ module CommandLineReporter
|
|
60
65
|
end
|
61
66
|
|
62
67
|
def datetime(options = {})
|
63
|
-
validate_options(options, :align, :width, :format)
|
68
|
+
validate_options(options, :align, :width, :format, :color, :bold)
|
64
69
|
|
65
70
|
format = options[:format] || '%Y-%m-%d - %l:%M:%S%p'
|
66
71
|
align = options[:align] || DEFAULTS[:align]
|
@@ -70,67 +75,76 @@ module CommandLineReporter
|
|
70
75
|
|
71
76
|
raise Exception if text.size > width
|
72
77
|
|
73
|
-
aligned(text,
|
78
|
+
aligned(text, :align => align, :width => width, :color => options[:color], :bold => options[:bold])
|
74
79
|
end
|
75
80
|
|
76
81
|
def aligned(text, options = {})
|
77
|
-
validate_options(options, :align, :width)
|
82
|
+
validate_options(options, :align, :width, :color, :bold)
|
78
83
|
|
79
84
|
align = options[:align] || DEFAULTS[:align]
|
80
85
|
width = options[:width] || DEFAULTS[:width]
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
86
|
+
color = options[:color]
|
87
|
+
bold = options[:bold] || false
|
88
|
+
|
89
|
+
line = case align
|
90
|
+
when 'left'
|
91
|
+
text
|
92
|
+
when 'right'
|
93
|
+
text.rjust(width)
|
94
|
+
when 'center'
|
95
|
+
text.rjust((width - text.size)/2 + text.size)
|
96
|
+
else
|
97
|
+
raise ArgumentError
|
98
|
+
end
|
99
|
+
|
100
|
+
line = line.send(color) if color
|
101
|
+
line = line.send('bold') if bold
|
102
|
+
|
103
|
+
puts line
|
92
104
|
end
|
93
105
|
|
94
106
|
def table(options = {})
|
95
|
-
@table = Table.new(options)
|
107
|
+
@table = CommandLineReporter::Table.new(options)
|
96
108
|
yield
|
97
109
|
@table.output
|
98
110
|
end
|
99
111
|
|
100
112
|
def row(options = {})
|
101
|
-
@row = Row.new
|
113
|
+
@row = CommandLineReporter::Row.new(options)
|
102
114
|
yield
|
103
115
|
@table.add(@row)
|
104
116
|
end
|
105
117
|
|
106
118
|
def column(text, options = {})
|
107
|
-
col = Column.new(text, options)
|
119
|
+
col = CommandLineReporter::Column.new(text, options)
|
108
120
|
@row.add(col)
|
109
121
|
end
|
110
122
|
|
111
123
|
private
|
112
124
|
|
113
125
|
def section(type, options)
|
114
|
-
validate_options(options, :title, :width, :align, :spacing, :timestamp, :rule)
|
126
|
+
validate_options(options, :title, :width, :align, :spacing, :timestamp, :rule, :color, :bold)
|
115
127
|
|
116
128
|
title = options[:title] || 'Report'
|
117
129
|
width = options[:width] || DEFAULTS[:width]
|
118
130
|
align = options[:align] || DEFAULTS[:align]
|
119
131
|
lines = options[:spacing] || 1
|
132
|
+
color = options[:color]
|
133
|
+
bold = options[:bold] || false
|
120
134
|
|
121
135
|
# This also ensures that width is a Fixnum
|
122
136
|
raise ArgumentError if title.size > width
|
123
137
|
|
124
138
|
if type == :footer
|
125
139
|
vertical_spacing(lines)
|
126
|
-
horizontal_rule(:char => options[:rule], :width => width) if options[:rule]
|
140
|
+
horizontal_rule(:char => options[:rule], :width => width, :color => color, :bold => bold) if options[:rule]
|
127
141
|
end
|
128
142
|
|
129
|
-
aligned(title,
|
130
|
-
datetime(:align => align, :width => width) if options[:timestamp]
|
143
|
+
aligned(title, :align => align, :width => width, :color => color, :bold => bold)
|
144
|
+
datetime(:align => align, :width => width, :color => color, :bold => bold) if options[:timestamp]
|
131
145
|
|
132
146
|
if type == :header
|
133
|
-
horizontal_rule(:char => options[:rule], :width => width) if options[:rule]
|
147
|
+
horizontal_rule(:char => options[:rule], :width => width, :color => color, :bold => bold) if options[:rule]
|
134
148
|
vertical_spacing(lines)
|
135
149
|
end
|
136
150
|
end
|
data/lib/nested_formatter.rb
CHANGED
@@ -1,13 +1,17 @@
|
|
1
1
|
require 'singleton'
|
2
|
+
require 'options_validator'
|
3
|
+
require 'colored'
|
2
4
|
|
3
5
|
module CommandLineReporter
|
4
6
|
class NestedFormatter
|
5
7
|
include Singleton
|
8
|
+
include OptionsValidator
|
6
9
|
|
7
|
-
|
10
|
+
VALID_OPTIONS = [:message, :type, :complete, :indent_size, :color, :bold]
|
11
|
+
attr_accessor :indent_size, :complete_string, :message_string, :color, :bold
|
8
12
|
|
9
13
|
def format(options, block)
|
10
|
-
|
14
|
+
self.validate_options(options, *VALID_OPTIONS)
|
11
15
|
|
12
16
|
indent_level :incr
|
13
17
|
|
@@ -17,15 +21,15 @@ module CommandLineReporter
|
|
17
21
|
complete_str = options[:complete] || self.complete_string
|
18
22
|
|
19
23
|
if options[:type] == 'inline'
|
20
|
-
|
24
|
+
colorize("#{message_str}...", true, options)
|
21
25
|
else
|
22
|
-
|
26
|
+
colorize(message_str, false, options)
|
23
27
|
complete_str = padding + complete_str
|
24
28
|
end
|
25
29
|
|
26
30
|
block.call
|
27
31
|
|
28
|
-
|
32
|
+
colorize(complete_str, false, options)
|
29
33
|
|
30
34
|
indent_level :decr
|
31
35
|
end
|
@@ -44,6 +48,17 @@ module CommandLineReporter
|
|
44
48
|
|
45
49
|
private
|
46
50
|
|
51
|
+
def colorize(str, inline, options)
|
52
|
+
str = str.send(options[:color]) if options[:color]
|
53
|
+
str = str.bold if options[:bold]
|
54
|
+
|
55
|
+
if inline
|
56
|
+
print str
|
57
|
+
else
|
58
|
+
puts str
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
47
62
|
def indent_level(value)
|
48
63
|
case value
|
49
64
|
when :incr
|
data/lib/progress_formatter.rb
CHANGED
@@ -1,19 +1,34 @@
|
|
1
1
|
require 'singleton'
|
2
|
+
require 'options_validator'
|
3
|
+
require 'colored'
|
2
4
|
|
3
5
|
module CommandLineReporter
|
4
6
|
class ProgressFormatter
|
5
7
|
include Singleton
|
8
|
+
include OptionsValidator
|
6
9
|
|
7
|
-
|
10
|
+
VALID_OPTIONS = [:indicator, :color, :bold]
|
11
|
+
attr_accessor *VALID_OPTIONS
|
8
12
|
|
9
13
|
def format(options, block)
|
14
|
+
self.validate_options(options, *VALID_OPTIONS)
|
15
|
+
|
10
16
|
self.indicator = options[:indicator] if options[:indicator]
|
17
|
+
self.color = options[:color]
|
18
|
+
self.bold = options[:bold] || false
|
19
|
+
|
11
20
|
block.call
|
21
|
+
|
12
22
|
puts
|
13
23
|
end
|
14
24
|
|
15
25
|
def progress(override = nil)
|
16
|
-
|
26
|
+
str = override || self.indicator
|
27
|
+
|
28
|
+
str = str.send(self.color) if self.color
|
29
|
+
str = str.send('bold') if self.bold
|
30
|
+
|
31
|
+
print str
|
17
32
|
end
|
18
33
|
|
19
34
|
def indicator
|