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 +4 -4
- data/README.md +9 -3
- data/i18n/en.yml +34 -0
- data/lib/cli_miami/ask.rb +174 -34
- data/lib/cli_miami/core.rb +84 -0
- data/lib/cli_miami/error.rb +108 -0
- data/lib/cli_miami/say.rb +62 -52
- data/lib/cli_miami/validation.rb +189 -0
- data/lib/cli_miami.rb +1 -1
- data/lib/namespaced.rb +71 -21
- data/spec/fixtures/i18n.yml +36 -0
- data/spec/lib/cli_miami/ask_spec.rb +134 -0
- data/spec/lib/cli_miami/error_spec.rb +75 -0
- data/spec/lib/cli_miami/say_spec.rb +87 -0
- data/spec/lib/cli_miami/validation_spec.rb +52 -0
- data/spec/lib/cli_miami_spec.rb +81 -0
- data/spec/spec_helper.rb +83 -0
- metadata +122 -28
- data/.gitignore +0 -2
- data/.rspec +0 -3
- data/.travis.yml +0 -6
- data/Gemfile +0 -11
- data/Gemfile.lock +0 -100
- data/Guardfile +0 -5
- data/yuyi_menu +0 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4027d96f33ad46d4e0859f84b1c9399ce569a8d3
|
4
|
+
data.tar.gz: b1442d5a721d9cedfd612ac86d73057617b2b808
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1f7b627d647f53c1f8cfd48cc3adbc5a02dbecdbf61a3581eeb3b24879d3b60cbecdee265b2461c6f08f7576082c2f9c23b1e8a032413a891fee5dc5f4e5fbeb
|
7
|
+
data.tar.gz: 2be499f83f714ac02761f01baa93e5fe0f2a133f78022700bd665490ca72044183504d59dfacd13534e3e46a23fed18076b90b54e2785bb11d8e78be4e89ef21
|
data/README.md
CHANGED
@@ -1,6 +1,10 @@
|
|
1
|
-
[](https://rubygems.org/gems/CLI-Miami)
|
2
|
+
[](https://gemnasium.com/brewster1134/CLI-Miami)
|
3
|
+
[](http://inch-ci.org/github/brewster1134/CLI-Miami)
|
4
|
+
[](https://travis-ci.org/brewster1134/CLI-Miami)
|
5
|
+
[](https://coveralls.io/r/brewster1134/CLI-Miami?branch=master)
|
6
|
+
[](https://codeclimate.com/github/brewster1134/CLI-Miami)
|
7
|
+
[](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
|
+
[](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::
|
2
|
+
# class CliMiami::A
|
3
3
|
#
|
4
|
-
|
5
|
-
require 'readline'
|
6
|
-
|
7
4
|
class CliMiami::A
|
8
|
-
|
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
|
-
|
15
|
-
|
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
|
-
|
27
|
-
if options.is_a? Hash
|
28
|
-
@options.merge! options
|
29
|
-
end
|
19
|
+
private
|
30
20
|
|
31
|
-
|
21
|
+
def initialize question, options
|
22
|
+
options = CliMiami.get_options options
|
32
23
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
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
|
36
|
+
yield @value
|
43
37
|
else
|
44
|
-
return
|
38
|
+
return @value
|
45
39
|
end
|
40
|
+
# rubocop:enable Style/GuardClause
|
46
41
|
end
|
47
42
|
|
48
|
-
|
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
|
-
|
51
|
-
|
52
|
-
|
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|
|
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
|
-
|
35
|
-
|
36
|
-
|
37
|
-
}
|
33
|
+
options = CliMiami.get_options options
|
34
|
+
new text, options
|
35
|
+
end
|
38
36
|
|
39
|
-
|
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
|
-
|
47
|
-
|
48
|
-
|
49
|
-
end
|
39
|
+
def initialize text, options
|
40
|
+
@text = text
|
41
|
+
@options = options
|
50
42
|
|
51
|
-
#
|
52
|
-
|
53
|
-
|
54
|
-
|
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
|
-
#
|
57
|
-
|
58
|
-
|
59
|
-
|
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
|
-
|
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
|
72
|
+
@text = if @options[:style].delete :bright
|
73
|
+
@text.send "bright_#{@options[:color]}"
|
66
74
|
else
|
67
|
-
text.send
|
75
|
+
@text.send @options[:color]
|
68
76
|
end
|
69
77
|
end
|
78
|
+
end
|
70
79
|
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
80
|
+
# Set background color
|
81
|
+
def modify_background_color!
|
82
|
+
@text = @text.send("on_#{@options[:bgcolor]}") if @options[:bgcolor]
|
83
|
+
end
|
75
84
|
|
76
|
-
|
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
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
92
|
+
# Indent
|
93
|
+
def modify_indentation!
|
94
|
+
@text = (' ' * @options[:indent]) + @text if @options[:indent]
|
95
|
+
end
|
85
96
|
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
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
|