cliqr 1.2.0 → 2.0.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.
Files changed (82) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +95 -0
  3. data/README.md +9 -71
  4. data/examples/numbers +1 -2
  5. data/examples/vagrant +0 -3
  6. data/lib/cliqr.rb +52 -11
  7. data/lib/cliqr/argument_validation/argument_type_validator.rb +2 -2
  8. data/lib/cliqr/argument_validation/validator.rb +3 -3
  9. data/lib/cliqr/{cli → command}/argument_operator.rb +2 -2
  10. data/lib/cliqr/{cli → command}/argument_operator_context.rb +1 -1
  11. data/lib/cliqr/{cli/command.rb → command/base_command.rb} +2 -2
  12. data/lib/cliqr/command/color.rb +174 -0
  13. data/lib/cliqr/{cli → command}/command_context.rb +68 -20
  14. data/lib/cliqr/command/shell_banner_builder.rb +17 -0
  15. data/lib/cliqr/command/shell_command.rb +125 -0
  16. data/lib/cliqr/command/shell_prompt_builder.rb +26 -0
  17. data/lib/cliqr/config/action.rb +226 -0
  18. data/lib/cliqr/config/base.rb +84 -0
  19. data/lib/cliqr/config/command.rb +137 -0
  20. data/lib/cliqr/config/dsl.rb +81 -0
  21. data/lib/cliqr/config/event.rb +43 -0
  22. data/lib/cliqr/config/event_based.rb +78 -0
  23. data/lib/cliqr/config/named.rb +55 -0
  24. data/lib/cliqr/config/option.rb +95 -0
  25. data/lib/cliqr/config/option_based.rb +130 -0
  26. data/lib/cliqr/config/shell.rb +87 -0
  27. data/lib/cliqr/config/validation/validation_set.rb +66 -0
  28. data/lib/cliqr/config/validation/validator_factory.rb +403 -0
  29. data/lib/cliqr/config/validation/verifiable.rb +91 -0
  30. data/lib/cliqr/error.rb +20 -4
  31. data/lib/cliqr/events/event.rb +56 -0
  32. data/lib/cliqr/events/event_context.rb +31 -0
  33. data/lib/cliqr/events/handler.rb +32 -0
  34. data/lib/cliqr/events/invoker.rb +70 -0
  35. data/lib/cliqr/{cli → executor}/command_runner_factory.rb +3 -3
  36. data/lib/cliqr/{cli → executor}/router.rb +4 -4
  37. data/lib/cliqr/{cli/executor.rb → executor/runner.rb} +25 -10
  38. data/lib/cliqr/interface.rb +98 -0
  39. data/lib/cliqr/parser/token_factory.rb +1 -1
  40. data/lib/cliqr/usage/command_usage_context.rb +94 -0
  41. data/lib/cliqr/usage/option_usage_context.rb +86 -0
  42. data/lib/cliqr/usage/templates/partial/action_list.erb +10 -0
  43. data/lib/cliqr/usage/templates/partial/command_name.erb +3 -0
  44. data/lib/cliqr/usage/templates/partial/option_list.erb +18 -0
  45. data/lib/cliqr/usage/templates/partial/usage_info.erb +5 -0
  46. data/lib/cliqr/usage/templates/usage/cli.erb +4 -0
  47. data/lib/cliqr/usage/templates/usage/shell.erb +2 -0
  48. data/lib/cliqr/usage/usage_builder.rb +59 -0
  49. data/lib/cliqr/util.rb +81 -34
  50. data/lib/cliqr/version.rb +1 -1
  51. data/spec/config/action_config_validator_spec.rb +127 -5
  52. data/spec/config/config_finalize_spec.rb +3 -3
  53. data/spec/config/config_validator_spec.rb +120 -17
  54. data/spec/config/option_config_validator_spec.rb +1 -1
  55. data/spec/dsl/interface_spec.rb +2 -2
  56. data/spec/dsl/usage_spec.rb +461 -465
  57. data/spec/executor/action_executor_spec.rb +1 -1
  58. data/spec/executor/color_executor_spec.rb +125 -0
  59. data/spec/executor/command_runner_spec.rb +6 -8
  60. data/spec/executor/event_executor_spec.rb +365 -0
  61. data/spec/executor/executor_spec.rb +49 -11
  62. data/spec/executor/help_executor_spec.rb +107 -103
  63. data/spec/fixtures/action_reader_command.rb +1 -1
  64. data/spec/fixtures/test_arg_printer_event_handler.rb +9 -0
  65. data/spec/fixtures/test_color_shell_prompt.rb +13 -0
  66. data/spec/fixtures/test_empty_event_handler.rb +5 -0
  67. data/spec/fixtures/test_invoker_event_handler.rb +9 -0
  68. data/spec/fixtures/test_shell_banner.rb +8 -0
  69. data/spec/fixtures/test_shell_prompt.rb +13 -0
  70. data/spec/shell/shell_executor_spec.rb +700 -0
  71. data/spec/validation/validation_spec.rb +2 -2
  72. metadata +65 -27
  73. data/lib/cliqr/cli/config.rb +0 -554
  74. data/lib/cliqr/cli/interface.rb +0 -107
  75. data/lib/cliqr/cli/shell_command.rb +0 -69
  76. data/lib/cliqr/cli/usage_builder.rb +0 -185
  77. data/lib/cliqr/config_validation/validation_set.rb +0 -48
  78. data/lib/cliqr/config_validation/validator_factory.rb +0 -319
  79. data/lib/cliqr/config_validation/verifiable.rb +0 -89
  80. data/lib/cliqr/dsl.rb +0 -59
  81. data/spec/executor/shell_executor_spec.rb +0 -233
  82. data/templates/usage.erb +0 -39
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9250bde8a2cd431432f1d68618d748b5e6ea378f
4
- data.tar.gz: 1d2f297559d079b1b1592c5863f3b2ccb4782037
3
+ metadata.gz: 5305e3f607fd5cbf6d6c55840630671129ec96bf
4
+ data.tar.gz: 21995e4b7b23b3c3d29011eb9b42a614ca54d38a
5
5
  SHA512:
6
- metadata.gz: aff0bc4667372517b12b61a84c4c4236179ec1aa37157be2676a71861daf6c639182cb11f06a698eb6b76cb1796f0c1b5c8142a4fde63f50b3d2f39ce9cec180
7
- data.tar.gz: 5eee04fc1abd977ae5ff3156b02c4d694b33b30b9ec793dff92edd2d2c5f70605e15316aa67c18e8b1bd3cf04f9d88b304f7e4c8be9ab35bce1564288da8fb12
6
+ metadata.gz: b2e59b44f6b5656afbd8e75039fbf0cd46fff0421b1923fb8b3cf04f2972ad96359dbbef31f205190476123f80b5b686b3270db6f603329f6ab2194be6771e08
7
+ data.tar.gz: 3b0b7571dcbf6d460e4b61fbbfee83923e2c784c450311a00060ecd828ec17ba2a70820d4f8302ac9dbd27b2ba2189f2e713a96ba78fcc8bf66b98140ebf52b2
@@ -91,6 +91,101 @@ item in this nested table for further details.
91
91
 
92
92
  <!-- markdown-toc end -->
93
93
 
94
+ 2.0.0 / 2015-07-09
95
+ ==================
96
+
97
+ Another big release!
98
+
99
+ ## Features
100
+
101
+ ### Event handling
102
+
103
+ Added ability to invoke arbitiary events and define handlers to handle certain kind of events.
104
+
105
+ Here is an example:
106
+ ``` ruby
107
+ Cliqr.interface do
108
+ name 'my-command'
109
+ on :bar do |event, ch, num|
110
+ puts 'invoked event in base'
111
+ puts "option = #{opt}"
112
+ puts "ch = #{ch}; num = #{num}"
113
+ end
114
+
115
+ action :my_action do
116
+ on :bar do |event, ch, num|
117
+ puts 'invoked event in action'
118
+ puts "option = #{opt}"
119
+ puts "ch = #{ch}; num = #{num}"
120
+ end
121
+
122
+ handler do
123
+ invoke :bar, 'a', 10
124
+ end
125
+
126
+ option :opt
127
+ end
128
+ end
129
+ ```
130
+ Upon execution:
131
+ ``` bash
132
+ $ my-command my_action --opt qwerty
133
+ invoked event in action
134
+ option = qwerty
135
+ ch = a; num = 10
136
+ invoked event in base
137
+ option = qwerty
138
+ ch = a; num = 10
139
+ ```
140
+
141
+ Events can be chained as above example shows.
142
+
143
+ #### Default events for shell
144
+
145
+ When a shell starts a `shell_start` event is invoked. Upon exit, a `shell_exit` event is invoked.
146
+
147
+ ### Colors
148
+
149
+ Enabled colors in command handlers and usage output. Just call a function with the name of the color you want. Colors can also be disabled.
150
+
151
+ ### Customizable banner and prompt for shell
152
+
153
+ The shell action now allows you to configure the banner displayed in the beginning and define a method to build the prompt.
154
+
155
+ ## Backward incompatible changes
156
+
157
+ The shell action can only be used in the base command config.
158
+
159
+ ## Improvements
160
+
161
+ ### Partial templated
162
+
163
+ Templates are reused to build help doc by incorporation of partial erb templating.
164
+
165
+ ### Improve default prompt
166
+
167
+ Count is shown in the default prompt.
168
+
169
+ ### Screen capture in README
170
+
171
+ A screen capture of the example is added to readme now.
172
+
173
+ ## Minor changes
174
+
175
+ ### Shorten the quickstart example
176
+
177
+ ### Re-organize code and move specs around
178
+
179
+ ### Multi OS testing suprted added to CI
180
+
181
+ CI now runs all specs for Linux and OSX
182
+
183
+ ## Bugfixes
184
+
185
+ ### Fix examples to follow new breaking shell config change
186
+
187
+ ### Do not put allow arguments in shell config
188
+
94
189
  1.2.0 / 2015-06-18
95
190
  ==================
96
191
 
data/README.md CHANGED
@@ -45,7 +45,7 @@ how to use `cliqr`.
45
45
  ## Quickstart
46
46
 
47
47
  To get things started quickly here is an example of a basic `cliqr`
48
- based CLI application (lets call this script `numbers`):
48
+ based CLI application (lets call this script `greet`):
49
49
 
50
50
  ``` ruby
51
51
  #!/usr/bin/env ruby
@@ -53,90 +53,28 @@ based CLI application (lets call this script `numbers`):
53
53
  require 'cliqr'
54
54
 
55
55
  cli = Cliqr.interface do
56
- name 'numbers'
57
- description 'A simplistic example for quickly getting started with cliqr.'
56
+ name 'greet'
57
+ description 'A "hello world" app to demonstrate cliqr.'
58
58
  version '0.0.1' # optional; adds a version action to our simple command
59
59
 
60
60
  # main command handler
61
61
  handler do
62
- puts "Hi #{name}" if name?
63
- puts 'Nothing to do here. Please try the sort action.'
62
+ puts "Hi #{name}" if name? # name is command's option defined below
63
+ puts "Please tell me your name" unless name?
64
64
  end
65
65
 
66
66
  option :name do
67
67
  description 'Your name.'
68
- operator do
69
- value.split(' ').first # only get the first name
70
- end
71
- end
72
-
73
- action :sort do
74
- description 'Sort a set of random numbers'
75
- shell :disable
76
-
77
- handler do
78
- fail StandardError, 'count should be a non-zero positive number' unless count > 0
79
- result = [].tap { |numbers| count.times { numbers << rand(9999) } }.sort
80
- result = result.reverse if order? && order == :descending
81
- puts result
82
- end
83
-
84
- option :count do
85
- short 'c' # optional, but usually a good idea to have it
86
- description 'Count of something.'
87
- type :numeric # restricts values for this option to numbers
88
- end
89
-
90
- option :order do
91
- short 'o'
92
- description 'Order of sort.'
93
-
94
- # This is how you can make sure that the input is valid.
95
- operator do
96
- fail StandardError, "Unknown order #{value}" unless [:ascending, :descending].include?(value.to_sym)
97
- value.to_sym
98
- end
99
- end
100
68
  end
101
69
  end
102
70
 
103
71
  cli.execute(ARGV)
104
72
  ```
105
73
 
106
- Now you can execute this script:
107
-
108
- ``` bash
109
- $ ./numbers
110
- Nothing to do here. Please try the sort action.
111
- $ ./numbers --name "Anshul Verma"
112
- Hi Anshul
113
- Nothing to do here. Please try the sort action.
114
- $ ./numbers sort -c 5
115
- 4519
116
- 5612
117
- 6038
118
- 6872
119
- 8259
120
- $ ./numbers sort -c 5 --order descending
121
- 8742
122
- 7995
123
- 6593
124
- 2730
125
- 806
126
- ```
127
-
128
- A shell command is auto generated for you by `cliqr`. Here is how it works:
129
-
130
- ``` bash
131
- $ ./numbers shell
132
- Starting shell for command "numbers"
133
- numbers > sort -c 5
134
- 1259
135
- 2031
136
- 4864
137
- 8355
138
- 9824
139
- ```
74
+ Here is a screen capture of this script in action:
75
+ ![greet script demo]
76
+ (https://raw.githubusercontent.com/anshulverma/cliqr/master/screenshots/greet.gif
77
+ "Binary tree example")
140
78
 
141
79
  ## Installation
142
80
 
@@ -24,7 +24,6 @@ cli = Cliqr.interface do
24
24
 
25
25
  action :sort do
26
26
  description 'Sort a set of random numbers'
27
- shell :disable
28
27
 
29
28
  handler do
30
29
  fail StandardError, 'count should be a non-zero positive number' unless count > 0
@@ -41,7 +40,7 @@ cli = Cliqr.interface do
41
40
 
42
41
  option :order do
43
42
  short 'o'
44
- description 'Order of sort.'
43
+ description 'Order of sort (either :ascending or :descending).'
45
44
 
46
45
  # This is how you can make sure that the input is valid.
47
46
  operator do
@@ -23,10 +23,8 @@ EOS
23
23
 
24
24
  action :box do
25
25
  description 'manages boxes: installation, removal, etc.'
26
- shell :disable
27
26
 
28
27
  action :add do
29
- shell :disable
30
28
  handler do
31
29
  puts 'This command was not invoked properly. The help for this command is available below.'
32
30
  forward 'vagrant box add help'
@@ -57,7 +55,6 @@ EOS
57
55
 
58
56
  action :up do
59
57
  description 'starts and provisions the vagrant environment'
60
- shell :disable
61
58
  arguments :disable
62
59
  handler do
63
60
  puts 'A Vagrant environment or target machine is required to run this command. ' \
@@ -1,11 +1,10 @@
1
1
  # encoding: utf-8
2
2
 
3
+ require 'cliqr/interface'
3
4
  require 'cliqr/version'
4
5
  require 'cliqr/error'
5
-
6
- require 'cliqr/cli/config'
7
- require 'cliqr/cli/interface'
8
- require 'cliqr/cli/command'
6
+ require 'cliqr/config/command'
7
+ require 'cliqr/command/shell_prompt_builder'
9
8
 
10
9
  # Top level namespace for the Cliqr gem
11
10
  #
@@ -23,13 +22,13 @@ module Cliqr
23
22
  # option
24
23
  # end
25
24
  #
26
- # @return [Cliqr::CLI::Interface]
25
+ # @return [Cliqr::Interface]
27
26
  #
28
27
  # @api public
29
28
  def interface(&block)
30
- config = CLI::Config.build(&block)
29
+ config = Cliqr::Config::Command.build(&block)
31
30
  config.setup_defaults
32
- CLI::Interface.build(config)
31
+ Cliqr::Interface.build(config)
33
32
  end
34
33
 
35
34
  # All cliqr commands should extend from this. Here is an example:
@@ -41,12 +40,12 @@ module Cliqr
41
40
  # end
42
41
  # end
43
42
  #
44
- # @return [Cliqr::CLI::Command]
43
+ # @return [Cliqr::Command::BaseCommand]
45
44
  def command
46
- CLI::Command
45
+ Command::BaseCommand
47
46
  end
48
47
 
49
- # A argument operator must extend from [Cliqr::CLI::ArgumentOperator]
48
+ # A argument operator must extend from [Cliqr::Command::ArgumentOperator]
50
49
  #
51
50
  # @example
52
51
  # class MyOperator < Cliqr.operator
@@ -57,7 +56,49 @@ module Cliqr
57
56
  #
58
57
  # @return [Cliar::CLI::ArgumentOperator]
59
58
  def operator
60
- CLI::ArgumentOperator
59
+ Command::ArgumentOperator
60
+ end
61
+
62
+ # A custom shell prompt builder must extend from this
63
+ #
64
+ # @example
65
+ # class MyCustomPrompt < Cliqr.shell_prompt
66
+ # def build(context)
67
+ # # build a prompt string
68
+ # end
69
+ # end
70
+ #
71
+ # @return [Cliqr::Command::ShellPromptBuilder]
72
+ def shell_prompt
73
+ Command::ShellPromptBuilder
74
+ end
75
+
76
+ # A custom shell banner builder must extend from this
77
+ #
78
+ # @example
79
+ # class MyCustomBanner < Cliqr.shell_banner
80
+ # def build(context)
81
+ # # build a banner string
82
+ # end
83
+ # end
84
+ #
85
+ # @return [Cliqr::Command::ShellBannerBuilder]
86
+ def shell_banner
87
+ Command::ShellBannerBuilder
88
+ end
89
+
90
+ # A custom event handler must extend from this
91
+ #
92
+ # @example
93
+ # class MyEventHandler < Cliqr.event_handler
94
+ # def handle(context, event)
95
+ # # handle event
96
+ # end
97
+ # end
98
+ #
99
+ # @return [Cliqr::Events::Handler]
100
+ def event_handler
101
+ Events::Handler
61
102
  end
62
103
  end
63
104
  end
@@ -17,9 +17,9 @@ module Cliqr
17
17
  # Check if a type of a argument matches a required type
18
18
  def type_of?(argument, required_type)
19
19
  case required_type
20
- when CLI::NUMERIC_ARGUMENT_TYPE
20
+ when Config::NUMERIC_ARGUMENT_TYPE
21
21
  Integer(argument)
22
- when CLI::BOOLEAN_ARGUMENT_TYPE
22
+ when Config::BOOLEAN_ARGUMENT_TYPE
23
23
  fail ArgumentError unless argument.class == TrueClass || argument.class == FalseClass
24
24
  end
25
25
  true
@@ -25,9 +25,9 @@ module Cliqr
25
25
  # @return [Cliqr::Parser::ParsedInput] Validated parsed input
26
26
  def validate(args, config)
27
27
  errors = ValidationErrors.new
28
- config.options.each do |option|
29
- validate_argument(args.option(option.name), option, errors) \
30
- if args.options.key?(option.name.to_s)
28
+ config.options.each do |(name, option)|
29
+ validate_argument(args.option(name), option, errors) \
30
+ if args.options.key?(name.to_s)
31
31
  end
32
32
  fail(Cliqr::Error::IllegalArgumentError, "illegal argument error - #{errors}") \
33
33
  unless errors.empty?
@@ -1,7 +1,7 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  module Cliqr
4
- module CLI
4
+ module Command
5
5
  # Operates on the value of a argument after it has been validated
6
6
  #
7
7
  # @api private
@@ -14,7 +14,7 @@ module Cliqr
14
14
  # @return [Cliqr::CLI::ArgumentOperator]
15
15
  def self.for_type(type)
16
16
  case type
17
- when CLI::NUMERIC_ARGUMENT_TYPE
17
+ when Config::NUMERIC_ARGUMENT_TYPE
18
18
  NumericArgumentOperator.new
19
19
  else
20
20
  DEFAULT_ARGUMENT_OPERATOR
@@ -1,7 +1,7 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  module Cliqr
4
- module CLI
4
+ module Command
5
5
  # Context in which a anonymous argument operator runs
6
6
  #
7
7
  # @api private
@@ -1,11 +1,11 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  module Cliqr
4
- module CLI
4
+ module Command
5
5
  # Base class for all commands to extend from
6
6
  #
7
7
  # @api private
8
- class Command
8
+ class BaseCommand
9
9
  # Execute the command
10
10
  #
11
11
  # @return [Integer] Exit status of the command execution
@@ -0,0 +1,174 @@
1
+ # encoding: utf-8
2
+
3
+ module Cliqr
4
+ module Command
5
+ # Colors that can be used in a command to colorize strings
6
+ #
7
+ # @api private
8
+ module Color
9
+ # Create a new color instance
10
+ #
11
+ # @return [Cliqr::Command::Color]
12
+ def initialize(config = nil)
13
+ # check and disable colors if needed
14
+ check_color_setting(config) unless config.nil?
15
+ end
16
+
17
+ # Colorize a string with black color
18
+ #
19
+ # @return [String]
20
+ def black(str)
21
+ colorize(str, 30)
22
+ end
23
+
24
+ # Colorize a string with red color
25
+ #
26
+ # @return [String]
27
+ def red(str)
28
+ colorize(str, 31)
29
+ end
30
+
31
+ # Colorize a string with green color
32
+ #
33
+ # @return [String]
34
+ def green(str)
35
+ colorize(str, 32)
36
+ end
37
+
38
+ # Colorize a string with yellow color
39
+ #
40
+ # @return [String]
41
+ def yellow(str)
42
+ colorize(str, 33)
43
+ end
44
+
45
+ # Colorize a string with blue color
46
+ #
47
+ # @return [String]
48
+ def blue(str)
49
+ colorize(str, 34)
50
+ end
51
+
52
+ # Colorize a string with magenta color
53
+ #
54
+ # @return [String]
55
+ def magenta(str)
56
+ colorize(str, 35)
57
+ end
58
+
59
+ # Colorize a string with cyan color
60
+ #
61
+ # @return [String]
62
+ def cyan(str)
63
+ colorize(str, 36)
64
+ end
65
+
66
+ # Colorize a string with gray color
67
+ #
68
+ # @return [String]
69
+ def gray(str)
70
+ colorize(str, 37)
71
+ end
72
+
73
+ # Colorize a the background in black
74
+ #
75
+ # @return [String]
76
+ def bg_black(str)
77
+ colorize(str, 40)
78
+ end
79
+
80
+ # Colorize a the background in red
81
+ #
82
+ # @return [String]
83
+ def bg_red(str)
84
+ colorize(str, 41)
85
+ end
86
+
87
+ # Colorize a the background in green
88
+ #
89
+ # @return [String]
90
+ def bg_green(str)
91
+ colorize(str, 42)
92
+ end
93
+
94
+ # Colorize a the background in yellow
95
+ #
96
+ # @return [String]
97
+ def bg_yellow(str)
98
+ colorize(str, 43)
99
+ end
100
+
101
+ # Colorize a the background in blue
102
+ #
103
+ # @return [String]
104
+ def bg_blue(str)
105
+ colorize(str, 44)
106
+ end
107
+
108
+ # Colorize a the background in magenta
109
+ #
110
+ # @return [String]
111
+ def bg_magenta(str)
112
+ colorize(str, 45)
113
+ end
114
+
115
+ # Colorize a the background in cyan
116
+ #
117
+ # @return [String]
118
+ def bg_cyan(str)
119
+ colorize(str, 46)
120
+ end
121
+
122
+ # Colorize a the background in gray
123
+ #
124
+ # @return [String]
125
+ def bg_gray(str)
126
+ colorize(str, 47)
127
+ end
128
+
129
+ # Returns the bold representation
130
+ #
131
+ # @return [String]
132
+ def bold(str)
133
+ colorize(str, 1, 22)
134
+ end
135
+
136
+ # Reverses the color of a string and its background
137
+ #
138
+ # @return [String]
139
+ def reverse_color(str)
140
+ colorize(str, 7, 27)
141
+ end
142
+
143
+ # Disable colors
144
+ #
145
+ # @return [Cliqr::Command::Color]
146
+ def disable_color
147
+ instance_eval do
148
+ def colorize(str, *_args)
149
+ str
150
+ end
151
+ end
152
+ end
153
+
154
+ protected
155
+
156
+ # Check if color is disabled
157
+ #
158
+ # @return [Cliqr::Command::CommandContext]
159
+ def check_color_setting(config)
160
+ return self if config.root.color?
161
+ disable_color
162
+ end
163
+
164
+ private
165
+
166
+ # Wrap a string in a specific color code
167
+ #
168
+ # @return [String]
169
+ def colorize(str, color_code, end_tag = 0)
170
+ "\033[#{color_code}m#{str}\033[#{end_tag}m"
171
+ end
172
+ end
173
+ end
174
+ end