hoodie 0.5.5 → 1.0.1
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/.gitignore +1 -0
- data/Gemfile +19 -0
- data/Rakefile +8 -23
- data/hoodie.gemspec +0 -23
- data/lib/hoodie.rb +40 -48
- data/lib/hoodie/configuration.rb +39 -2
- data/lib/hoodie/core_ext/blank.rb +6 -6
- data/lib/hoodie/core_ext/hash.rb +108 -13
- data/lib/hoodie/core_ext/string.rb +5 -3
- data/lib/hoodie/core_ext/try.rb +4 -3
- data/lib/hoodie/inflections.rb +18 -0
- data/lib/hoodie/inflections/defaults.rb +17 -0
- data/lib/hoodie/inflections/inflections.rb +17 -0
- data/lib/hoodie/inflections/rules_collection.rb +17 -0
- data/lib/hoodie/logging.rb +22 -4
- data/lib/hoodie/stash.rb +83 -80
- data/lib/hoodie/stash/disk_store.rb +142 -118
- data/lib/hoodie/stash/mem_store.rb +10 -9
- data/lib/hoodie/stash/memoizable.rb +46 -0
- data/lib/hoodie/utils.rb +13 -183
- data/lib/hoodie/utils/ansi.rb +199 -0
- data/lib/hoodie/utils/crypto.rb +288 -0
- data/lib/hoodie/utils/equalizer.rb +146 -0
- data/lib/hoodie/utils/file_helper.rb +225 -0
- data/lib/hoodie/utils/konstruktor.rb +77 -0
- data/lib/hoodie/utils/machine.rb +83 -0
- data/lib/hoodie/utils/os.rb +56 -0
- data/lib/hoodie/utils/retry.rb +235 -0
- data/lib/hoodie/utils/timeout.rb +54 -0
- data/lib/hoodie/utils/url_helper.rb +104 -0
- data/lib/hoodie/version.rb +4 -4
- metadata +13 -234
- data/lib/hoodie/identity_map.rb +0 -96
- data/lib/hoodie/memoizable.rb +0 -43
- data/lib/hoodie/obfuscate.rb +0 -121
- data/lib/hoodie/observable.rb +0 -309
- data/lib/hoodie/os.rb +0 -43
- data/lib/hoodie/proxy.rb +0 -68
- data/lib/hoodie/rash.rb +0 -125
- data/lib/hoodie/timers.rb +0 -355
@@ -1,8 +1,8 @@
|
|
1
1
|
# encoding: UTF-8
|
2
2
|
#
|
3
|
-
# Author:
|
4
|
-
#
|
5
|
-
# Copyright (C) 2014-2015 Stefano Harding
|
3
|
+
# Author: Stefano Harding <riddopic@gmail.com>
|
4
|
+
# License: Apache License, Version 2.0
|
5
|
+
# Copyright: (C) 2014-2015 Stefano Harding
|
6
6
|
#
|
7
7
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
8
8
|
# you may not use this file except in compliance with the License.
|
@@ -17,13 +17,14 @@
|
|
17
17
|
# limitations under the License.
|
18
18
|
#
|
19
19
|
|
20
|
-
module
|
20
|
+
module Hoodie
|
21
21
|
# Basic cache object stash store (uses a Hash)
|
22
|
-
|
22
|
+
#
|
23
|
+
class MemStash
|
23
24
|
include Enumerable
|
24
25
|
|
25
|
-
#
|
26
|
-
#
|
26
|
+
# @!attribute [r] :store
|
27
|
+
# @return [Stash::MemStash] location of Stash::DiskStore store.
|
27
28
|
attr_reader :store
|
28
29
|
|
29
30
|
# Initializes a new store object.
|
@@ -124,7 +125,7 @@ module MemStash
|
|
124
125
|
#
|
125
126
|
# @param key [Symbol, String] a string or symbol representing the key
|
126
127
|
#
|
127
|
-
# @return [
|
128
|
+
# @return [Boolean]
|
128
129
|
#
|
129
130
|
def include?(key)
|
130
131
|
@store.include? key
|
@@ -135,7 +136,7 @@ module MemStash
|
|
135
136
|
#
|
136
137
|
# @param value [String] a string representing the value
|
137
138
|
#
|
138
|
-
# @return [
|
139
|
+
# @return [Boolean]
|
139
140
|
#
|
140
141
|
def value?(value)
|
141
142
|
@store.value? value
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
#
|
3
|
+
# Author: Stefano Harding <riddopic@gmail.com>
|
4
|
+
# License: Apache License, Version 2.0
|
5
|
+
# Copyright: (C) 2014-2015 Stefano Harding
|
6
|
+
#
|
7
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
8
|
+
# you may not use this file except in compliance with the License.
|
9
|
+
# You may obtain a copy of the License at
|
10
|
+
#
|
11
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
12
|
+
#
|
13
|
+
# Unless required by applicable law or agreed to in writing, software
|
14
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
15
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
16
|
+
# See the License for the specific language governing permissions and
|
17
|
+
# limitations under the License.
|
18
|
+
#
|
19
|
+
|
20
|
+
require 'hoodie/stash' unless defined?(Stash)
|
21
|
+
|
22
|
+
module Hoodie
|
23
|
+
# Memoization is an optimization that saves the return value of a
|
24
|
+
# method so it doesn't need to be re-computed every time that method
|
25
|
+
# is called.
|
26
|
+
#
|
27
|
+
module Memoizable
|
28
|
+
# Create a new memoized method. To use, extend class with Memoizable,
|
29
|
+
# then, in initialize, call memoize
|
30
|
+
#
|
31
|
+
# @return [undefined]
|
32
|
+
#
|
33
|
+
def memoize(methods, cache = nil)
|
34
|
+
cache ||= Hoodie::Stash.new
|
35
|
+
methods.each do |name|
|
36
|
+
uncached_name = "#{name}_uncached".to_sym
|
37
|
+
singleton_class.class_eval do
|
38
|
+
alias_method uncached_name, name
|
39
|
+
define_method(name) do |*a, &b|
|
40
|
+
cache.cache(name) { send uncached_name, *a, &b }
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
data/lib/hoodie/utils.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
# encoding: UTF-8
|
2
2
|
#
|
3
|
-
# Author:
|
4
|
-
#
|
5
|
-
# Copyright (C) 2014-2015 Stefano Harding
|
3
|
+
# Author: Stefano Harding <riddopic@gmail.com>
|
4
|
+
# License: Apache License, Version 2.0
|
5
|
+
# Copyright: (C) 2014-2015 Stefano Harding
|
6
6
|
#
|
7
7
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
8
8
|
# you may not use this file except in compliance with the License.
|
@@ -17,183 +17,13 @@
|
|
17
17
|
# limitations under the License.
|
18
18
|
#
|
19
19
|
|
20
|
-
require '
|
21
|
-
require '
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
private_class_method :included
|
31
|
-
|
32
|
-
module ClassMethods
|
33
|
-
def callable(call_her)
|
34
|
-
call_her.respond_to?(:call) ? call_her : lambda { call_her }
|
35
|
-
end
|
36
|
-
|
37
|
-
def camelize(underscored_word)
|
38
|
-
underscored_word.to_s.gsub(/(?:^|_)(.)/) { $1.upcase }
|
39
|
-
end
|
40
|
-
|
41
|
-
def classify(table_name)
|
42
|
-
camelize singularize(table_name.to_s.sub(/.*\./, ''))
|
43
|
-
end
|
44
|
-
|
45
|
-
def class_name
|
46
|
-
demodulize(self.class)
|
47
|
-
end
|
48
|
-
|
49
|
-
def caller_name(position = 0)
|
50
|
-
caller[position][/`.*'/][1..-2]
|
51
|
-
end
|
52
|
-
|
53
|
-
def demodulize(class_name_in_module)
|
54
|
-
class_name_in_module.to_s.sub(/^.*::/, '')
|
55
|
-
end
|
56
|
-
|
57
|
-
def pluralize(word)
|
58
|
-
word.to_s.sub(/([^s])$/, '\1s')
|
59
|
-
end
|
60
|
-
|
61
|
-
def singularize(word)
|
62
|
-
word.to_s.sub(/s$/, '').sub(/ie$/, 'y')
|
63
|
-
end
|
64
|
-
|
65
|
-
def underscore(camel_cased_word)
|
66
|
-
word = camel_cased_word.to_s.dup
|
67
|
-
word.gsub!(/::/, '/')
|
68
|
-
word.gsub!(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
|
69
|
-
word.gsub!(/([a-z\d])([A-Z])/, '\1_\2')
|
70
|
-
word.tr! '-', '_'
|
71
|
-
word.downcase!
|
72
|
-
word
|
73
|
-
end
|
74
|
-
|
75
|
-
# Return the date and time in "HTTP-date" format as defined by RFC 7231.
|
76
|
-
#
|
77
|
-
# @return [Date,Time] in "HTTP-date" format
|
78
|
-
def utc_httpdate
|
79
|
-
Time.now.utc.httpdate
|
80
|
-
end
|
81
|
-
|
82
|
-
def request_id
|
83
|
-
SecureRandom.uuid
|
84
|
-
end
|
85
|
-
|
86
|
-
def twenty_four_hours_ago
|
87
|
-
Time.now - ( 60 * 60 * 24)
|
88
|
-
end
|
89
|
-
|
90
|
-
def verify_options(accepted, actual) # @private
|
91
|
-
return unless debug || $DEBUG
|
92
|
-
unless (act=Set[*actual.keys]).subset?(acc=Set[*accepted])
|
93
|
-
raise Croesus::Errors::UnknownOption,
|
94
|
-
"\nDetected unknown option(s): #{(act - acc).to_a.inspect}\n" <<
|
95
|
-
"Accepted options are: #{accepted.inspect}"
|
96
|
-
end
|
97
|
-
yield if block_given?
|
98
|
-
end
|
99
|
-
|
100
|
-
# Returns the columns and lines of the current tty.
|
101
|
-
#
|
102
|
-
# @return [Integer]
|
103
|
-
# number of columns and lines of tty, returns [0, 0] if no tty present.
|
104
|
-
#
|
105
|
-
# @api public
|
106
|
-
def terminal_dimensions
|
107
|
-
[0, 0] unless STDOUT.tty?
|
108
|
-
[80, 40] if OS.windows?
|
109
|
-
|
110
|
-
if ENV['COLUMNS'] && ENV['LINES']
|
111
|
-
[ENV['COLUMNS'].to_i, ENV['LINES'].to_i]
|
112
|
-
elsif ENV['TERM'] && command_in_path?('tput')
|
113
|
-
[`tput cols`.to_i, `tput lines`.to_i]
|
114
|
-
elsif command_in_path?('stty')
|
115
|
-
`stty size`.scan(/\d+/).map {|s| s.to_i }
|
116
|
-
else
|
117
|
-
[0, 0]
|
118
|
-
end
|
119
|
-
rescue
|
120
|
-
[0, 0]
|
121
|
-
end
|
122
|
-
|
123
|
-
# Checks in PATH returns true if the command is found
|
124
|
-
def command_in_path?(command)
|
125
|
-
found = ENV['PATH'].split(File::PATH_SEPARATOR).map do |p|
|
126
|
-
File.exist?(File.join(p, command))
|
127
|
-
end
|
128
|
-
found.include?(true)
|
129
|
-
end
|
130
|
-
|
131
|
-
# Runs a code block, and retries it when an exception occurs. Should the
|
132
|
-
# number of retries be reached without success, the last exception will be
|
133
|
-
# raised.
|
134
|
-
#
|
135
|
-
# @param opts [Hash{Symbol => Value}]
|
136
|
-
# @option opts [Fixnum] :tries
|
137
|
-
# number of attempts to retry before raising the last exception
|
138
|
-
# @option opts [Fixnum] :sleep
|
139
|
-
# number of seconds to wait between retries, use lambda to exponentially
|
140
|
-
# increasing delay between retries
|
141
|
-
# @option opts [Array(Exception)] :on
|
142
|
-
# the type of exception(s) to catch and retry on
|
143
|
-
# @option opts [Regex] :matching
|
144
|
-
# match based on the exception message
|
145
|
-
# @option opts [Block] :ensure
|
146
|
-
# ensure a block of code is executed, regardless of whether an exception
|
147
|
-
# is raised
|
148
|
-
#
|
149
|
-
# @return [Block]
|
150
|
-
#
|
151
|
-
def retrier(opts = {}, &block)
|
152
|
-
defaults = {
|
153
|
-
tries: 2,
|
154
|
-
sleep: 1,
|
155
|
-
on: StandardError,
|
156
|
-
matching: /.*/,
|
157
|
-
:ensure => Proc.new {}
|
158
|
-
}
|
159
|
-
|
160
|
-
check_for_invalid_options(opts, defaults)
|
161
|
-
defaults.merge!(opts)
|
162
|
-
|
163
|
-
return if defaults[:tries] == 0
|
164
|
-
|
165
|
-
on_exception, tries = [defaults[:on]].flatten, defaults[:tries]
|
166
|
-
retries = 0
|
167
|
-
retry_exception = nil
|
168
|
-
|
169
|
-
begin
|
170
|
-
yield retries, retry_exception
|
171
|
-
rescue *on_exception => exception
|
172
|
-
raise unless exception.message =~ defaults[:matching]
|
173
|
-
raise if retries+1 >= defaults[:tries]
|
174
|
-
|
175
|
-
# Interrupt Exception could be raised while sleeping
|
176
|
-
begin
|
177
|
-
sleep defaults[:sleep].respond_to?(:call) ?
|
178
|
-
defaults[:sleep].call(retries) : defaults[:sleep]
|
179
|
-
rescue *on_exception
|
180
|
-
end
|
181
|
-
|
182
|
-
retries += 1
|
183
|
-
retry_exception = exception
|
184
|
-
retry
|
185
|
-
ensure
|
186
|
-
defaults[:ensure].call(retries)
|
187
|
-
end
|
188
|
-
end
|
189
|
-
|
190
|
-
private # P R O P R I E T À P R I V A T A Vietato L'accesso
|
191
|
-
|
192
|
-
def check_for_invalid_options(custom_options, defaults)
|
193
|
-
invalid_options = defaults.merge(custom_options).keys - defaults.keys
|
194
|
-
raise ArgumentError.new('[Retrier] Invalid options: ' \
|
195
|
-
"#{invalid_options.join(", ")}") unless invalid_options.empty?
|
196
|
-
end
|
197
|
-
end
|
198
|
-
end
|
199
|
-
end
|
20
|
+
require 'hoodie/utils/ansi'
|
21
|
+
require 'hoodie/utils/crypto'
|
22
|
+
require 'hoodie/utils/equalizer'
|
23
|
+
require 'hoodie/utils/file_helper'
|
24
|
+
require 'hoodie/utils/konstruktor'
|
25
|
+
require 'hoodie/utils/machine'
|
26
|
+
require 'hoodie/utils/os'
|
27
|
+
require 'hoodie/utils/retry'
|
28
|
+
require 'hoodie/utils/timeout'
|
29
|
+
require 'hoodie/utils/url_helper'
|
@@ -0,0 +1,199 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
#
|
3
|
+
# Author: Stefano Harding <riddopic@gmail.com>
|
4
|
+
# License: Apache License, Version 2.0
|
5
|
+
# Copyright: (C) 2014-2015 Stefano Harding
|
6
|
+
#
|
7
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
8
|
+
# you may not use this file except in compliance with the License.
|
9
|
+
# You may obtain a copy of the License at
|
10
|
+
#
|
11
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
12
|
+
#
|
13
|
+
# Unless required by applicable law or agreed to in writing, software
|
14
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
15
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
16
|
+
# See the License for the specific language governing permissions and
|
17
|
+
# limitations under the License.
|
18
|
+
#
|
19
|
+
|
20
|
+
module Hoodie
|
21
|
+
|
22
|
+
# ANSI Mixin Module
|
23
|
+
#
|
24
|
+
# Standard use is to mix this module into String.
|
25
|
+
#
|
26
|
+
# @example Mix this module into String to enable easy ANSI coloring methods
|
27
|
+
# like:
|
28
|
+
# "bold red".red.bold
|
29
|
+
#
|
30
|
+
# @example Or
|
31
|
+
# "green".green
|
32
|
+
#
|
33
|
+
module ANSI
|
34
|
+
extend self
|
35
|
+
|
36
|
+
# Defines our ANSI color codes
|
37
|
+
ANSI_COLORS = {
|
38
|
+
black: 30,
|
39
|
+
red: 31,
|
40
|
+
green: 32,
|
41
|
+
yellow: 33,
|
42
|
+
blue: 34,
|
43
|
+
magenta: 35,
|
44
|
+
cyan: 36,
|
45
|
+
white: 37
|
46
|
+
}
|
47
|
+
|
48
|
+
# @!method black(string=nil, &block)
|
49
|
+
# Sets the foreground color to black for the supplied string.
|
50
|
+
# @param [String] string The string to operate on.
|
51
|
+
# @yieldreturn [String] The string to operate on.
|
52
|
+
# @return [String] The colored string.
|
53
|
+
#
|
54
|
+
# @!method red(string=nil, &block)
|
55
|
+
# Sets the foreground color to red for the supplied string.
|
56
|
+
# @param [String] string The string to operate on.
|
57
|
+
# @yieldreturn [String] The string to operate on.
|
58
|
+
# @return [String] The colored string.
|
59
|
+
#
|
60
|
+
# @!method green(string=nil, &block)
|
61
|
+
# Sets the foreground color to green for the supplied string.
|
62
|
+
# @param [String] string The string to operate on.
|
63
|
+
# @yieldreturn [String] The string to operate on.
|
64
|
+
# @return [String] The colored string.
|
65
|
+
#
|
66
|
+
# @!method yellow(string=nil, &block)
|
67
|
+
# Sets the foreground color to yellow for the supplied string.
|
68
|
+
# @param [String] string The string to operate on.
|
69
|
+
# @yieldreturn [String] The string to operate on.
|
70
|
+
# @return [String] The colored string.
|
71
|
+
#
|
72
|
+
# @!method blue(string=nil, &block)
|
73
|
+
# Sets the foreground color to blue for the supplied string.
|
74
|
+
# @param [String] string The string to operate on.
|
75
|
+
# @yieldreturn [String] The string to operate on.
|
76
|
+
# @return [String] The colored string.
|
77
|
+
#
|
78
|
+
# @!method magenta(string=nil, &block)
|
79
|
+
# Sets the foreground color to magenta for the supplied string.
|
80
|
+
# @param [String] string The string to operate on.
|
81
|
+
# @yieldreturn [String] The string to operate on.
|
82
|
+
# @return [String] The colored string.
|
83
|
+
#
|
84
|
+
# @!method cyan(string=nil, &block)
|
85
|
+
# Sets the foreground color to cyan for the supplied string.
|
86
|
+
# @param [String] string The string to operate on.
|
87
|
+
# @yieldreturn [String] The string to operate on.
|
88
|
+
# @return [String] The colored string.
|
89
|
+
#
|
90
|
+
# @!method white(string=nil, &block)
|
91
|
+
# Sets the foreground color to white for the supplied string.
|
92
|
+
# @param [String] string The string to operate on.
|
93
|
+
# @yieldreturn [String] The string to operate on.
|
94
|
+
# @return [String] The colored string.
|
95
|
+
|
96
|
+
# Defines our ANSI attribute codes
|
97
|
+
ANSI_ATTRIBUTES = {
|
98
|
+
normal: 0,
|
99
|
+
bold: 1
|
100
|
+
}
|
101
|
+
|
102
|
+
# @!method normal(string=nil, &block)
|
103
|
+
# Sets the foreground color to normal for the supplied string.
|
104
|
+
# @param [String] string The string to operate on.
|
105
|
+
# @yieldreturn [String] The string to operate on.
|
106
|
+
# @return [String] The colored string.
|
107
|
+
#
|
108
|
+
# @!method bold(string=nil, &block)
|
109
|
+
# Sets the foreground color to bold for the supplied string.
|
110
|
+
# @param [String] string The string to operate on.
|
111
|
+
# @yieldreturn [String] The string to operate on.
|
112
|
+
# @return [String] The colored string.
|
113
|
+
|
114
|
+
# Defines a RegEx for stripping ANSI codes from strings
|
115
|
+
ANSI_REGEX = /\e\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]/
|
116
|
+
|
117
|
+
# Dynamicly constructs ANSI methods for the color methods based on the ANSI
|
118
|
+
# code hash passed in.
|
119
|
+
#
|
120
|
+
# @param [Hash] hash
|
121
|
+
# A hash where the keys represent the method names and the values are the
|
122
|
+
# ANSI codes.
|
123
|
+
#
|
124
|
+
# @return [Boolean]
|
125
|
+
# True if successful.
|
126
|
+
#
|
127
|
+
def build_ansi_methods(hash)
|
128
|
+
hash.each do |key, value|
|
129
|
+
|
130
|
+
define_method(key) do |string=nil, &block|
|
131
|
+
result = Array.new
|
132
|
+
|
133
|
+
result << %(\e[#{value}m)
|
134
|
+
if block_given?
|
135
|
+
result << block.call
|
136
|
+
elsif string.respond_to?(:to_str)
|
137
|
+
result << string.to_str
|
138
|
+
elsif respond_to?(:to_str)
|
139
|
+
result << to_str
|
140
|
+
else
|
141
|
+
return result
|
142
|
+
end
|
143
|
+
result << %(\e[0m)
|
144
|
+
|
145
|
+
result.join
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
true
|
150
|
+
end
|
151
|
+
|
152
|
+
# Removes ANSI code sequences from a string.
|
153
|
+
#
|
154
|
+
# @param [String] string
|
155
|
+
# The string to operate on.
|
156
|
+
#
|
157
|
+
# @yieldreturn [String]
|
158
|
+
# The string to operate on.
|
159
|
+
#
|
160
|
+
# @return [String]
|
161
|
+
# The supplied string stripped of ANSI codes.
|
162
|
+
#
|
163
|
+
def uncolor(string = nil, &block)
|
164
|
+
if block_given?
|
165
|
+
block.call.to_str.gsub(ANSI_REGEX, '')
|
166
|
+
elsif string.respond_to?(:to_str)
|
167
|
+
string.to_str.gsub(ANSI_REGEX, '')
|
168
|
+
elsif respond_to?(:to_str)
|
169
|
+
to_str.gsub(ANSI_REGEX, '')
|
170
|
+
else
|
171
|
+
''
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
def reset(string = nil, &block)
|
176
|
+
result = Array.new
|
177
|
+
|
178
|
+
result << %(\e[2J)
|
179
|
+
if block_given?
|
180
|
+
result << block.call
|
181
|
+
elsif string.respond_to?(:to_str)
|
182
|
+
result << string.to_str
|
183
|
+
elsif respond_to?(:to_str)
|
184
|
+
result << to_str
|
185
|
+
else
|
186
|
+
return result
|
187
|
+
end
|
188
|
+
|
189
|
+
result.join
|
190
|
+
end
|
191
|
+
|
192
|
+
def goto(x=0, y=0)
|
193
|
+
%(\e[#{x};#{y}H)
|
194
|
+
end
|
195
|
+
|
196
|
+
build_ansi_methods(ANSI_COLORS)
|
197
|
+
build_ansi_methods(ANSI_ATTRIBUTES)
|
198
|
+
end
|
199
|
+
end
|