cli_miami 0.0.9 → 1.0.1.pre

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 47e57b45bdc22855bb5fae82dcc3dd12c54a7122
4
- data.tar.gz: d13decde950c513d8bb42ffe54f6fc987c55927b
3
+ metadata.gz: 4027d96f33ad46d4e0859f84b1c9399ce569a8d3
4
+ data.tar.gz: b1442d5a721d9cedfd612ac86d73057617b2b808
5
5
  SHA512:
6
- metadata.gz: c06ffeeaa5f1afdf1614ae4d0ad6fd7a99226f70471a27ad93d61d6189eb56e8cc99b8c6213e1cf3da450102714a858ae6dbbd09c12b5786ee66c7e2f97c08a8
7
- data.tar.gz: 89e5be978ec19120b0eb269c18eea67159cfcad43c16177e10c1705e116669f76a5be73e153c76dd30195e966191db5a06da4f859dd5844a2b678a153829fd37
6
+ metadata.gz: 1f7b627d647f53c1f8cfd48cc3adbc5a02dbecdbf61a3581eeb3b24879d3b60cbecdee265b2461c6f08f7576082c2f9c23b1e8a032413a891fee5dc5f4e5fbeb
7
+ data.tar.gz: 2be499f83f714ac02761f01baa93e5fe0f2a133f78022700bd665490ca72044183504d59dfacd13534e3e46a23fed18076b90b54e2785bb11d8e78be4e89ef21
data/README.md CHANGED
@@ -1,6 +1,10 @@
1
- [![Gem Version](https://badge.fury.io/rb/cli_miami.svg)](http://badge.fury.io/rb/cli_miami)
2
- [![Build Status](https://travis-ci.org/brewster1134/CLI-Miami.svg)](https://travis-ci.org/brewster1134/CLI-Miami)
3
- [![Coverage Status](https://coveralls.io/repos/brewster1134/CLI-Miami/badge.png)](https://coveralls.io/r/brewster1134/CLI-Miami)
1
+ [![gem version](https://badge.fury.io/rb/CLI-Miami.svg)](https://rubygems.org/gems/CLI-Miami)
2
+ [![dependencies](https://gemnasium.com/brewster1134/CLI-Miami.svg)](https://gemnasium.com/brewster1134/CLI-Miami)
3
+ [![docs](http://inch-ci.org/github/brewster1134/CLI-Miami.svg?branch=master)](http://inch-ci.org/github/brewster1134/CLI-Miami)
4
+ [![build](https://travis-ci.org/brewster1134/CLI-Miami.svg?branch=master)](https://travis-ci.org/brewster1134/CLI-Miami)
5
+ [![coverage](https://coveralls.io/repos/brewster1134/CLI-Miami/badge.svg?branch=master)](https://coveralls.io/r/brewster1134/CLI-Miami?branch=master)
6
+ [![code climate](https://codeclimate.com/github/brewster1134/CLI-Miami/badges/gpa.svg)](https://codeclimate.com/github/brewster1134/CLI-Miami)
7
+ [![omniref](https://www.omniref.com/github/brewster1134/CLI-Miami.png)](https://www.omniref.com/github/brewster1134/CLI-Miami)
4
8
 
5
9
  # CLI Miami
6
10
  A feature rich alternative for `gets` and `puts` for your cli interface
@@ -85,3 +89,5 @@ yuyi -m https://raw.githubusercontent.com/brewster1134/CLI-Miami/master/yuyi_men
85
89
  bundle install
86
90
  bundle exec guard
87
91
  ```
92
+
93
+ [![WTFPL](http://www.wtfpl.net/wp-content/uploads/2012/12/wtfpl-badge-4.png)](http://www.wtfpl.net)
data/i18n/en.yml ADDED
@@ -0,0 +1,34 @@
1
+ en:
2
+ cli_miami:
3
+ # CliMiami core library strings
4
+ core:
5
+ empty: '[EMPTY]'
6
+ enter_end_value: 'Enter end value'
7
+ enter_start_value: 'Enter starting value'
8
+ enter_value_for: 'Enter a value for %{key}'
9
+ no_description: No description provided
10
+
11
+ errors:
12
+ # generic error type messages
13
+ convert: "`%{value}` cannot be converted to `%{type}`. Allowed values are: `%{allowed_values}` (%{description})"
14
+ length: "`%{value}` has a length of %{value_length}, but must be between %{min} and %{max} . Allowed values are: `%{allowed_values}` (%{description})"
15
+ regexp: "`%{value}` does not match the required format. Allowed values are: `%{allowed_values}` (%{description})"
16
+ type: "Unknown type %{type}"
17
+
18
+ # specific value type messages
19
+ # these messages will take precedence over the general messages above
20
+ array:
21
+ length: "Your array (%{value}) has %{value_length} items, but needs between %{allowed_values} (%{description})"
22
+ boolean:
23
+ file:
24
+ validate: "`%{value}` is not a valid path. Allowed values are: `%{allowed_values}` (%{description})"
25
+ fixnum:
26
+ length: "`%{value}` must be between %{min} and %{max} . Allowed values are: `%{allowed_values}` (%{description})"
27
+ float:
28
+ length: "`%{value}` must be between %{min} and %{max} . Allowed values are: `%{allowed_values}` (%{description})"
29
+ hash:
30
+ length: "Your object (%{value}) has %{value_length} items, but needs between %{allowed_values} (%{description})"
31
+ keys: "The object has `%{value}` set, but is missing `%{keys}`. Allowed values are: `%{allowed_values}` (%{description})"
32
+ range:
33
+ string:
34
+ symbol:
data/lib/cli_miami/ask.rb CHANGED
@@ -1,54 +1,194 @@
1
1
  #
2
- # class CliMiami::Ask
2
+ # class CliMiami::A
3
3
  #
4
-
5
- require 'readline'
6
-
7
4
  class CliMiami::A
8
- @@prompt = '>>> '
5
+ attr_reader :value
9
6
 
7
+ # A.sk API method
8
+ #
10
9
  # See documentation for CliMiami::S.ay
11
- # The same options are accepted
10
+ # The same options are accepted, with the addition of
11
+ # :readline - uses Readline instead of standard `gets`
12
+ # :type - symbol specifying what type of data is requested from the user
13
+ # :validate - hash of validation options
12
14
  #
13
15
  def self.sk question, options = {}, &block
14
- # set default options
15
- @options = {
16
- :readline => false
17
- }
18
-
19
- # merge preset options
20
- if options.is_a? Symbol
21
- @options.merge! CliMiami.presets[options]
22
- elsif preset = options.delete(:preset)
23
- @options.merge! CliMiami.presets[preset]
24
- end
16
+ new question, options, &block
17
+ end
25
18
 
26
- # merge remaining options
27
- if options.is_a? Hash
28
- @options.merge! options
29
- end
19
+ private
30
20
 
31
- CliMiami::S.ay question, @options
21
+ def initialize question, options
22
+ options = CliMiami.get_options options
32
23
 
33
- output = if @options[:readline]
34
- Readline.readline(@@prompt).chomp('/')
35
- else
36
- CliMiami::S.ay @@prompt, :newline => false
37
- $stdin.gets
38
- end.rstrip
24
+ # add description to question
25
+ question << ' (' << options[:description] << ')'
26
+
27
+ # display question
28
+ CliMiami::S.ay question, options
29
+
30
+ # request given type to user
31
+ @value = request_type options
39
32
 
40
33
  # return response if no block is passed
34
+ # rubocop:disable Style/GuardClause
41
35
  if block_given?
42
- yield output
36
+ yield @value
43
37
  else
44
- return output
38
+ return @value
45
39
  end
40
+ # rubocop:enable Style/GuardClause
46
41
  end
47
42
 
48
- private
43
+ # determine the expecting type, and request input form user
44
+ #
45
+ def request_type options
46
+ send("request_#{options[:type]}", options)
47
+ rescue
48
+ CliMiami::S.ay I18n.t('cli_miami.errors.type', options)
49
+ end
50
+
51
+ # for most types, a simple validation check is all that is needed
52
+ # if validation fails, we request the user to try again
53
+ #
54
+ # rubocop:disable Metrics/MethodLength, Metrics/PerceivedComplexity
55
+ def request_until_valid options, allow_empty_string = false
56
+ response = nil
57
+
58
+ while response.nil?
59
+ # get user input based on given file type
60
+ response = if options[:type] == :file
61
+ Readline.readline.chomp '/'
62
+ else
63
+ $stdin.gets.chomp
64
+ end
65
+
66
+ # for multiple entry type objects, we allow the user to justs press enter to finish adding entries
67
+ break if allow_empty_string && response == ''
68
+
69
+ # otherwise validate the user's input
70
+ validation = CliMiami::Validation.new response, options
71
+ if validation.valid?
72
+ response = validation.value
73
+ else
74
+ response = nil
75
+ CliMiami::S.ay validation.error, :cli_miami_fail
76
+ end
77
+ end
78
+
79
+ response
80
+ end
81
+ # rubocop:enable Metrics/MethodLength, Metrics/PerceivedComplexity
82
+ alias_method :request_boolean, :request_until_valid
83
+ alias_method :request_file, :request_until_valid
84
+ alias_method :request_float, :request_until_valid
85
+ alias_method :request_fixnum, :request_until_valid
86
+ alias_method :request_string, :request_until_valid
87
+ alias_method :request_symbol, :request_until_valid
88
+
89
+ # rubocop:disable Metrics/MethodLength
90
+ def request_array options
91
+ array = []
92
+ value_options = CliMiami.get_options(options[:value_options] || {})
93
+
94
+ # build the array by prompting the user
95
+ # until the array length is an acceptable length, keep prompting user for values
96
+ while array.length < options[:max]
97
+ response = request_until_valid value_options, true
98
+
99
+ if response.empty?
100
+ break if CliMiami::Validation.new(array, options).valid?
101
+ redo
102
+ else
103
+ array << response
104
+ end
49
105
 
50
- def self.prompt; @@prompt; end
51
- def self.prompt= prompt
52
- @@prompt = prompt
106
+ # update user
107
+ CliMiami::S.ay array.to_sentence, :cli_miami_success
108
+ end
109
+
110
+ array
111
+ end
112
+
113
+ # rubocop:disable Metrics/AbcSize, Metrics/BlockNesting, Metrics/PerceivedComplexity
114
+ def request_hash options
115
+ hash = {}
116
+ options[:keys] ||= []
117
+ value_options = CliMiami.get_options(options[:value_options] || {})
118
+ required_keys_set = false
119
+
120
+ # build the hash by prompting the user
121
+ # until the hash length of keys is an acceptable length, keep prompting user for values
122
+ while hash.keys.length < options[:max]
123
+ # if keys options is set, prompt for those values first
124
+ if required_keys_set == false
125
+ options[:keys].each do |key|
126
+ hash[key.to_sym] = request_until_valid value_options
127
+
128
+ # update user
129
+ CliMiami::S.ay hash.to_s, :cli_miami_success
130
+ end
131
+
132
+ # set boolean so we know all required keys are set
133
+ required_keys_set = true
134
+
135
+ # end this loop to re-check the while condition to make sure the max wasn't reached from required keys
136
+ # e.g. setting { max: 2, keys: [:foo, :bar] }
137
+ # this prevents users from entering user-defined keys since the max will already be met
138
+ next
139
+
140
+ # then start prompting for keys and values
141
+ else
142
+ # request key
143
+ user_key = request_until_valid value_options.merge(type: :symbol), true
144
+
145
+ if user_key.empty?
146
+ break if CliMiami::Validation.new(hash, options).valid?
147
+ redo
148
+ else
149
+ # request value
150
+ CliMiami::S.ay I18n.t('cli_miami.core.enter_value_for', key: user_key), :cli_miami_success
151
+ hash[user_key] = request_until_valid value_options, true
152
+ end
153
+ end
154
+
155
+ CliMiami::S.ay hash.to_s, :cli_miami_success
156
+ end
157
+
158
+ hash
159
+ end
160
+ # rubocop:enable Metrics/AbcSize, Metrics/BlockNesting, Metrics/PerceivedComplexity
161
+
162
+ # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
163
+ def request_range options
164
+ start_value = nil
165
+ end_value = nil
166
+ range_value_options = CliMiami.get_options type: :float
167
+
168
+ # get start value
169
+ until (Float(start_value) rescue nil)
170
+ CliMiami::S.ay I18n.t('cli_miami.core.enter_start_value'), preset: :cli_miami_success, newline: false
171
+ start_value = request_until_valid range_value_options
172
+ end
173
+
174
+ # get end value
175
+ until (Float(end_value) rescue nil)
176
+ CliMiami::S.ay I18n.t('cli_miami.core.enter_end_value'), preset: :cli_miami_success, newline: false
177
+ end_value = request_until_valid range_value_options
178
+ end
179
+
180
+ # swap values if entered in reverse
181
+ start_value, end_value = end_value, start_value if start_value > end_value
182
+
183
+ # build range object
184
+ range = Range.new start_value, end_value
185
+
186
+ # if range is invalid, start over and request it again
187
+ if CliMiami::Validation.new(range, options).valid?
188
+ range
189
+ else
190
+ request_range options
191
+ end
53
192
  end
193
+ # rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
54
194
  end
@@ -0,0 +1,84 @@
1
+ #
2
+ # 3rd party libraries & configuration
3
+ #
4
+ require 'active_support/core_ext/hash/conversions'
5
+ require 'active_support/core_ext/hash/keys'
6
+ require 'active_support/core_ext/string/inflections'
7
+ require 'i18n'
8
+ require 'readline'
9
+
10
+ # core object overrides
11
+ #
12
+ class Hash
13
+ def to_s
14
+ map do |k, v|
15
+ "#{k}: #{v}"
16
+ end.to_sentence
17
+ end
18
+ end
19
+
20
+ # i18n
21
+ #
22
+ # load yml locales included in the cli miami gem
23
+ # [PATH TO GEMS]/cli_miami/i18n/en.yml
24
+ I18n.load_path += Dir["#{File.dirname(__FILE__)}/../i18n/*.yml"]
25
+ # load locale in current directory named `i18n.yml`
26
+ # ./i18n.yml
27
+ I18n.load_path += Dir['./i18n.yml']
28
+ # load locales in the folder `i18n` in the current directory
29
+ # ./i18n/en.yml
30
+ I18n.load_path += Dir['./i18n/*.yml']
31
+
32
+ # readline
33
+ #
34
+ Readline.completion_append_character = '/'
35
+
36
+ # creates Boolean type that true/false inherit
37
+ # this allows true/false to respond to a single Boolean class to check for
38
+ #
39
+ # rubocop:disable Style/Documentation
40
+ module Boolean; end
41
+ class TrueClass; include Boolean; end
42
+ class FalseClass; include Boolean; end
43
+ # rubocop:enable Style/Documentation
44
+
45
+ # global configuration and setup
46
+ #
47
+ module CliMiami::Core
48
+ BOOLEAN_TRUE_VALUES = %w(true t yes y).freeze
49
+ BOOLEAN_FALSE_VALUES = %w(false f no n).freeze
50
+
51
+ # keys: type values allowed through the API
52
+ # values: type used to validate internally in the Validation class
53
+ TYPE_MAP = {
54
+ array: :array,
55
+ boolean: :boolean,
56
+ dir: :file,
57
+ directory: :file,
58
+ file: :file,
59
+ fixnum: :fixnum,
60
+ float: :float,
61
+ folder: :file,
62
+ hash: :hash,
63
+ integer: :fixnum,
64
+ list: :array,
65
+ number: :fixnum,
66
+ object: :hash,
67
+ path: :file,
68
+ range: :range,
69
+ string: :string,
70
+ symbol: :symbol
71
+ }.freeze
72
+
73
+ # default presets
74
+ # rubocop:disable Style/ClassVars
75
+ @@presets = {
76
+ cli_miami_fail: {
77
+ color: :red
78
+ },
79
+ cli_miami_success: {
80
+ color: :green
81
+ }
82
+ }
83
+ # rubocop:enable Style/ClassVars
84
+ end
@@ -0,0 +1,108 @@
1
+ #
2
+ # Build custom i18n error messages
3
+ #
4
+ class CliMiami::Error
5
+ attr_reader :message
6
+
7
+ private
8
+
9
+ def initialize value, options, *error_keys
10
+ options[:value] = convert_type_to_string value
11
+ options[:allowed_values] = allowed_values options
12
+
13
+ @message = i18n_lookup_keys(options, *error_keys) || 'Unknown Error'
14
+ end
15
+
16
+ # convert value from it's type, to a user friendly string
17
+ # with core ruby objects, we create a `.to_string` method instead of changes the default `.to_s` method
18
+ #
19
+ # rubocop:disable Metrics/MethodLength, Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
20
+ def convert_type_to_string value
21
+ case value
22
+
23
+ when Array
24
+ value.map do |e|
25
+ if e.nil? || e == ''
26
+ I18n.t 'cli_miami.core.empty'
27
+ else
28
+ convert_type_to_string e
29
+ end
30
+ end.to_sentence
31
+
32
+ when Hash
33
+ value.map do |k, v|
34
+ v = if v.nil? || v == ''
35
+ I18n.t 'cli_miami.core.empty'
36
+ else
37
+ convert_type_to_string v
38
+ end
39
+
40
+ "#{k}: #{v}"
41
+ end.to_sentence
42
+
43
+ when Range
44
+ "#{value.min}-#{value.max}"
45
+
46
+ when File
47
+ File.expand_path value
48
+
49
+ else
50
+ value.to_s
51
+
52
+ end
53
+ end
54
+ # rubocop:enable Metrics/MethodLength, Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
55
+
56
+ # get allowed values based on validation details
57
+ #
58
+ # rubocop:disable Metrics/MethodLength
59
+ def allowed_values options
60
+ case options[:type]
61
+ when :array, :hash
62
+ if options[:value_options]
63
+ allowed_values options[:value_options]
64
+ else
65
+ "#{options[:min]}-#{options[:max]}"
66
+ end
67
+
68
+ when :boolean
69
+ all_boolean_values = CliMiami::BOOLEAN_TRUE_VALUES + CliMiami::BOOLEAN_FALSE_VALUES
70
+ all_boolean_values.to_sentence
71
+
72
+ when :fixnum, :float, :range, :string, :symbol
73
+ "#{options[:min]}-#{options[:max]}"
74
+
75
+ when :regexp
76
+ options[:regexp].inspect
77
+
78
+ else
79
+ '?'
80
+ end
81
+ end
82
+ # rubocop:enable Metrics/MethodLength
83
+
84
+ # build an i18n dot notation string to use for lookup in the language yaml
85
+ #
86
+ # rubocop:disable Style/ClosingParenthesisIndentation
87
+ def i18n_lookup_keys options, *error_keys
88
+ # check for type specific error first, then look for generic errors
89
+ i18n_lookup(options,
90
+ 'cli_miami',
91
+ 'errors',
92
+ options[:type].to_s,
93
+ *error_keys
94
+ ) || i18n_lookup(options,
95
+ 'cli_miami',
96
+ 'errors',
97
+ *error_keys
98
+ )
99
+ end
100
+ # rubocop:enable Style/ClosingParenthesisIndentation
101
+
102
+ # use i18n dot notation keys to lookup string
103
+ #
104
+ def i18n_lookup options, *keys
105
+ i18n_string = keys.flatten.compact.each(&:to_s).join('.')
106
+ I18n.t i18n_string, options if I18n.exists? i18n_string
107
+ end
108
+ end
data/lib/cli_miami/say.rb CHANGED
@@ -1,13 +1,15 @@
1
- #
2
- # class CliMiami::Say
3
- #
4
1
  require 'term/ansicolor'
5
2
 
3
+ # Reopen String class for ANSI color support
6
4
  class String
7
5
  include Term::ANSIColor
8
6
  end
9
7
 
8
+ #
9
+ # class CliMiami::S.ay
10
+ #
10
11
  class CliMiami::S
12
+ # S.ay API method
11
13
  #
12
14
  # @param options [Symbol or Hash] options can be preset symbol, or a hash of options.
13
15
  #
@@ -18,7 +20,7 @@ class CliMiami::S
18
20
  # color: => [symbol] See README for ansi color codes
19
21
  # bgcolor: => [symbol] See README for ansi color codes
20
22
  # style: => [symbol] See README for ansi style codes
21
- # justify: => [center|ljust|rjust] The type of justification to use
23
+ # justify: => [center|left|right] The type of justification to use
22
24
  # padding: => [integer] The maximum string size to justify text in
23
25
  # indent: => [integer] The number of characters to indent
24
26
  # newline: => [boolean] True if you want a newline after the output
@@ -27,75 +29,83 @@ class CliMiami::S
27
29
  # @return
28
30
  #
29
31
  def self.ay text = '', options = {}
30
- # backup text and convert it to a string
31
- original_text = text = text.to_s
32
-
33
32
  # set default options
34
- @options = {
35
- :style => [],
36
- :newline => true
37
- }
33
+ options = CliMiami.get_options options
34
+ new text, options
35
+ end
38
36
 
39
- # merge preset options
40
- if options.is_a? Symbol
41
- @options.merge! CliMiami.presets[options]
42
- elsif preset = options.delete(:preset)
43
- @options.merge! CliMiami.presets[preset]
44
- end
37
+ private
45
38
 
46
- # merge remaining options
47
- if options.is_a? Hash
48
- @options.merge! options
49
- end
39
+ def initialize text, options
40
+ @text = text
41
+ @options = options
50
42
 
51
- # convert single style into an array for processing
52
- if !@options[:style].is_a? Array
53
- @options[:style] = [@options[:style]]
54
- end
43
+ # formatter methods
44
+ modify_justification!
45
+ modify_text_color!
46
+ modify_background_color!
47
+ modify_styles!
48
+ modify_indentation!
49
+ modify_overwrite!
55
50
 
56
- # Justify/Padding options
57
- if @options[:justify] && @options[:padding]
58
- text = text.send @options[:justify], @options[:padding]
59
- end
51
+ # render formatted text to user
52
+ print_output
53
+ end
54
+
55
+ # Justify/Padding options
56
+ # must convert option to support String class method
57
+ def modify_justification!
58
+ justify =
59
+ case @options[:justify]
60
+ when :center then :center
61
+ when :right then :rjust
62
+ else :ljust
63
+ end
64
+
65
+ @text = @text.send justify, @options[:padding]
66
+ end
60
67
 
61
- # Set foreground color
68
+ # Set foreground color
69
+ def modify_text_color!
62
70
  if @options[:color]
63
71
  # if bright style is passed, use the bright color variation
64
- text = if @options[:style].delete :bright
65
- text.send("bright_#{@options[:color]}")
72
+ @text = if @options[:style].delete :bright
73
+ @text.send "bright_#{@options[:color]}"
66
74
  else
67
- text.send(@options[:color])
75
+ @text.send @options[:color]
68
76
  end
69
77
  end
78
+ end
70
79
 
71
- # Set background color
72
- if @options[:bgcolor]
73
- text = text.send("on_#{@options[:bgcolor]}")
74
- end
80
+ # Set background color
81
+ def modify_background_color!
82
+ @text = @text.send("on_#{@options[:bgcolor]}") if @options[:bgcolor]
83
+ end
75
84
 
76
- # Apply all styles
85
+ # Apply all styles
86
+ def modify_styles!
77
87
  @options[:style].each do |style|
78
- text = text.send(style)
88
+ @text = @text.send(style)
79
89
  end
90
+ end
80
91
 
81
- # Indent
82
- if @options[:indent]
83
- text = (' ' * @options[:indent]) + text
84
- end
92
+ # Indent
93
+ def modify_indentation!
94
+ @text = (' ' * @options[:indent]) + @text if @options[:indent]
95
+ end
85
96
 
86
- # Flag text to be overwritten by next text written
87
- if @options[:overwrite]
88
- text = "#{text}\r"
89
- end
97
+ # Flag text to be overwritten by next text written
98
+ def modify_overwrite!
99
+ @text = "#{@text}\r" if @options[:overwrite]
100
+ end
90
101
 
102
+ # finally render the formatted text to the screen
103
+ def print_output
91
104
  # Determine if a newline should be used
92
105
  if !@options[:newline] || @options[:overwrite]
93
- $stdout.print text
106
+ $stdout.print @text + ' '
94
107
  else
95
- $stdout.puts text
108
+ $stdout.puts @text
96
109
  end
97
-
98
- # return original text
99
- return original_text
100
110
  end
101
111
  end