cliutils 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.DS_Store +0 -0
- data/.gitignore +1 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +48 -0
- data/LICENSE.txt +22 -0
- data/README.md +288 -0
- data/README.rdoc +19 -0
- data/Rakefile +45 -0
- data/bin/cliutils +38 -0
- data/cliutils.gemspec +28 -0
- data/features/cli_manager.feature +13 -0
- data/features/step_definitions/cli_manager_steps.rb +1 -0
- data/features/support/env.rb +16 -0
- data/html/CLIUtils/Configuration.html +271 -0
- data/html/CLIUtils/Configurator.html +504 -0
- data/html/CLIUtils/LoggerDelegator.html +344 -0
- data/html/CLIUtils/Messenging.html +284 -0
- data/html/CLIUtils/Prefs.html +330 -0
- data/html/CLIUtils/PrettyIO.html +799 -0
- data/html/CLIUtils.html +112 -0
- data/html/Hash.html +453 -0
- data/html/Logger.html +183 -0
- data/html/Object.html +120 -0
- data/html/README_md.html +454 -0
- data/html/String.html +413 -0
- data/html/created.rid +13 -0
- data/html/fonts/Lato-Light.ttf +0 -0
- data/html/fonts/Lato-LightItalic.ttf +0 -0
- data/html/fonts/Lato-Regular.ttf +0 -0
- data/html/fonts/Lato-RegularItalic.ttf +0 -0
- data/html/fonts/SourceCodePro-Bold.ttf +0 -0
- data/html/fonts/SourceCodePro-Regular.ttf +0 -0
- data/html/fonts.css +167 -0
- data/html/images/add.png +0 -0
- data/html/images/arrow_up.png +0 -0
- data/html/images/brick.png +0 -0
- data/html/images/brick_link.png +0 -0
- data/html/images/bug.png +0 -0
- data/html/images/bullet_black.png +0 -0
- data/html/images/bullet_toggle_minus.png +0 -0
- data/html/images/bullet_toggle_plus.png +0 -0
- data/html/images/date.png +0 -0
- data/html/images/delete.png +0 -0
- data/html/images/find.png +0 -0
- data/html/images/loadingAnimation.gif +0 -0
- data/html/images/macFFBgHack.png +0 -0
- data/html/images/package.png +0 -0
- data/html/images/page_green.png +0 -0
- data/html/images/page_white_text.png +0 -0
- data/html/images/page_white_width.png +0 -0
- data/html/images/plugin.png +0 -0
- data/html/images/ruby.png +0 -0
- data/html/images/tag_blue.png +0 -0
- data/html/images/tag_green.png +0 -0
- data/html/images/transparent.png +0 -0
- data/html/images/wrench.png +0 -0
- data/html/images/wrench_orange.png +0 -0
- data/html/images/zoom.png +0 -0
- data/html/index.html +455 -0
- data/html/js/darkfish.js +140 -0
- data/html/js/jquery.js +18 -0
- data/html/js/navigation.js +142 -0
- data/html/js/search.js +109 -0
- data/html/js/search_index.js +1 -0
- data/html/js/searcher.js +228 -0
- data/html/rdoc.css +580 -0
- data/html/table_of_contents.html +399 -0
- data/lib/.DS_Store +0 -0
- data/lib/cliutils/configuration.rb +48 -0
- data/lib/cliutils/configurator.rb +119 -0
- data/lib/cliutils/ext/Hash+Extensions.rb +145 -0
- data/lib/cliutils/ext/Logger+Extensions.rb +27 -0
- data/lib/cliutils/ext/String+Extensions.rb +26 -0
- data/lib/cliutils/logger-delegator.rb +66 -0
- data/lib/cliutils/messenging.rb +51 -0
- data/lib/cliutils/prefs.rb +116 -0
- data/lib/cliutils/pretty-io.rb +255 -0
- data/lib/cliutils/version.rb +3 -0
- data/lib/cliutils.rb +15 -0
- data/res/readme-images/messenger-types-1.png +0 -0
- data/res/readme-images/messenger-warn.png +0 -0
- data/res/readme-images/multi-logger.png +0 -0
- data/res/readme-images/prettyio-color-chart.png +0 -0
- data/res/readme-images/prettyio-gnarly-text.png +0 -0
- data/res/readme-images/prettyio-red-text.png +0 -0
- data/res/readme-images/prompting.png +0 -0
- data/res/readme-images/wrapping.png +0 -0
- data/test/configurator_test.rb +50 -0
- data/test/hash_extensions_test.rb +50 -0
- data/test/logger_extensions_test.rb +16 -0
- data/test/messenging_test.rb +53 -0
- data/test/prefs_test.rb +29 -0
- data/test/string_extesions_test.rb +14 -0
- data/test/test_files/prefstest.yaml +33 -0
- metadata +199 -0
@@ -0,0 +1,145 @@
|
|
1
|
+
# ======================================================
|
2
|
+
# Hash Class
|
3
|
+
#
|
4
|
+
# Contains many convenient methods borrowed from Rails
|
5
|
+
# http://api.rubyonrails.org/classes/Hash.html
|
6
|
+
# ======================================================
|
7
|
+
class Hash
|
8
|
+
# ====================================================
|
9
|
+
# Methods
|
10
|
+
# ====================================================
|
11
|
+
# ----------------------------------------------------
|
12
|
+
# deep_merge! method
|
13
|
+
#
|
14
|
+
# Deep merges a hash into the current one.
|
15
|
+
# @param other_hash The hash to merge in
|
16
|
+
# @param &block
|
17
|
+
# @return Hash
|
18
|
+
# ----------------------------------------------------
|
19
|
+
def deep_merge!(other_hash, &block)
|
20
|
+
other_hash.each_pair do |k,v|
|
21
|
+
tv = self[k]
|
22
|
+
if tv.is_a?(Hash) && v.is_a?(Hash)
|
23
|
+
self[k] = tv.deep_merge(v, &block)
|
24
|
+
else
|
25
|
+
self[k] = block && tv ? block.call(k, tv, v) : v
|
26
|
+
end
|
27
|
+
end
|
28
|
+
self
|
29
|
+
end
|
30
|
+
|
31
|
+
# ----------------------------------------------------
|
32
|
+
# deep_stringify_keys method
|
33
|
+
#
|
34
|
+
# Recursively turns all Hash keys into strings and
|
35
|
+
# returns the new Hash.
|
36
|
+
# @return Hash
|
37
|
+
# ----------------------------------------------------
|
38
|
+
def deep_stringify_keys
|
39
|
+
deep_transform_keys{ |key| key.to_s }
|
40
|
+
end
|
41
|
+
|
42
|
+
# ----------------------------------------------------
|
43
|
+
# deep_symbolize_keys! method
|
44
|
+
#
|
45
|
+
# Same as deep_stringify_keys, but destructively
|
46
|
+
# alters the original Hash.
|
47
|
+
# @return Hash
|
48
|
+
# ----------------------------------------------------
|
49
|
+
def deep_stringify_keys!
|
50
|
+
deep_transform_keys!{ |key| key.to_s }
|
51
|
+
end
|
52
|
+
|
53
|
+
# ----------------------------------------------------
|
54
|
+
# deep_symbolize_keys method
|
55
|
+
#
|
56
|
+
# Recursively turns all Hash keys into symbols and
|
57
|
+
# returns the new Hash.
|
58
|
+
# @return Hash
|
59
|
+
# ----------------------------------------------------
|
60
|
+
def deep_symbolize_keys
|
61
|
+
deep_transform_keys{ |key| key.to_sym rescue key }
|
62
|
+
end
|
63
|
+
|
64
|
+
# ----------------------------------------------------
|
65
|
+
# deep_symbolize_keys! method
|
66
|
+
#
|
67
|
+
# Same as deep_symbolize_keys, but destructively
|
68
|
+
# alters the original Hash.
|
69
|
+
# @return Hash
|
70
|
+
# ----------------------------------------------------
|
71
|
+
def deep_symbolize_keys!
|
72
|
+
deep_transform_keys!{ |key| key.to_sym rescue key }
|
73
|
+
end
|
74
|
+
|
75
|
+
# ----------------------------------------------------
|
76
|
+
# deep_transform_keys method
|
77
|
+
#
|
78
|
+
# Generic method to perform recursive operations on a
|
79
|
+
# Hash.
|
80
|
+
# @return Hash
|
81
|
+
# ----------------------------------------------------
|
82
|
+
def deep_transform_keys(&block)
|
83
|
+
_deep_transform_keys_in_object(self, &block)
|
84
|
+
end
|
85
|
+
|
86
|
+
# ----------------------------------------------------
|
87
|
+
# deep_transform_keys! method
|
88
|
+
#
|
89
|
+
# Same as deep_transform_keys, but destructively
|
90
|
+
# alters the original Hash.
|
91
|
+
# @return Hash
|
92
|
+
# ----------------------------------------------------
|
93
|
+
def deep_transform_keys!(&block)
|
94
|
+
_deep_transform_keys_in_object!(self, &block)
|
95
|
+
end
|
96
|
+
|
97
|
+
private
|
98
|
+
|
99
|
+
# ----------------------------------------------------
|
100
|
+
# _deep_transform_keys_in_object method
|
101
|
+
#
|
102
|
+
# Modification to deep_transform_keys that allows for
|
103
|
+
# the existence of arrays.
|
104
|
+
# https://github.com/rails/rails/pull/9720/files?short_path=4be3c90
|
105
|
+
# @param object The object to examine
|
106
|
+
# @param &block A block to execute on the opject
|
107
|
+
# @return Object
|
108
|
+
# ----------------------------------------------------
|
109
|
+
def _deep_transform_keys_in_object(object, &block)
|
110
|
+
case object
|
111
|
+
when Hash
|
112
|
+
object.each_with_object({}) do |(key, value), result|
|
113
|
+
result[yield(key)] = _deep_transform_keys_in_object(value, &block)
|
114
|
+
end
|
115
|
+
when Array
|
116
|
+
object.map {|e| _deep_transform_keys_in_object(e, &block) }
|
117
|
+
else
|
118
|
+
object
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
# ----------------------------------------------------
|
123
|
+
# _deep_transform_keys_in_object! method
|
124
|
+
#
|
125
|
+
# Same as _deep_transform_keys_in_object, but
|
126
|
+
# destructively alters the original Object.
|
127
|
+
# @param object The object to examine
|
128
|
+
# @param &block A block to execute on the opject
|
129
|
+
# @return Object
|
130
|
+
# ----------------------------------------------------
|
131
|
+
def _deep_transform_keys_in_object!(object, &block)
|
132
|
+
case object
|
133
|
+
when Hash
|
134
|
+
object.keys.each do |key|
|
135
|
+
value = object.delete(key)
|
136
|
+
object[yield(key)] = _deep_transform_keys_in_object!(value, &block)
|
137
|
+
end
|
138
|
+
object
|
139
|
+
when Array
|
140
|
+
object.map! {|e| _deep_transform_keys_in_object!(e, &block)}
|
141
|
+
else
|
142
|
+
object
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'logger'
|
2
|
+
|
3
|
+
# ======================================================
|
4
|
+
# Logger Class
|
5
|
+
# ======================================================
|
6
|
+
class Logger
|
7
|
+
# ----------------------------------------------------
|
8
|
+
# custom_level method
|
9
|
+
#
|
10
|
+
# Creates a custom Logger level based on the passed
|
11
|
+
# tag.
|
12
|
+
# @param tag The Logger level to create
|
13
|
+
# @return Void
|
14
|
+
# ----------------------------------------------------
|
15
|
+
def self.custom_level(tag)
|
16
|
+
SEV_LABEL << tag
|
17
|
+
idx = SEV_LABEL.size - 1
|
18
|
+
|
19
|
+
define_method(tag.downcase.gsub(/\W+/, '_').to_sym) do |progname, &block|
|
20
|
+
add(idx, nil, progname, &block)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
custom_level('PROMPT')
|
25
|
+
custom_level('SECTION')
|
26
|
+
custom_level('SUCCESS')
|
27
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# ======================================================
|
2
|
+
# String Class
|
3
|
+
# ======================================================
|
4
|
+
class String
|
5
|
+
# ====================================================
|
6
|
+
# Color String Methods
|
7
|
+
# ====================================================
|
8
|
+
# ----------------------------------------------------
|
9
|
+
# colorize method
|
10
|
+
#
|
11
|
+
# Outputs a string in a formatted color.
|
12
|
+
# @param color_code The code to use
|
13
|
+
# @return Void
|
14
|
+
# ----------------------------------------------------
|
15
|
+
def colorize(color_code)
|
16
|
+
"\033[#{ color_code }m#{ self }\033[0m"
|
17
|
+
end
|
18
|
+
|
19
|
+
def blue; colorize(34) end
|
20
|
+
def cyan; colorize(36) end
|
21
|
+
def green; colorize(32) end
|
22
|
+
def purple; colorize(35) end
|
23
|
+
def red; colorize(31) end
|
24
|
+
def white; colorize(37) end
|
25
|
+
def yellow; colorize(33) end
|
26
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
module CLIUtils
|
2
|
+
# ======================================================
|
3
|
+
# LoggerDelegator Class
|
4
|
+
#
|
5
|
+
# Manages any configuration values and the flat YAML file
|
6
|
+
# into which they get stored.
|
7
|
+
# ======================================================
|
8
|
+
class LoggerDelegator
|
9
|
+
# ====================================================
|
10
|
+
# Attributes
|
11
|
+
# ====================================================
|
12
|
+
attr_reader :devices
|
13
|
+
|
14
|
+
# ====================================================
|
15
|
+
# Methods
|
16
|
+
# ====================================================
|
17
|
+
# ----------------------------------------------------
|
18
|
+
# initialize method
|
19
|
+
#
|
20
|
+
# Initializer
|
21
|
+
# @param *targets The endpoints to delegate to
|
22
|
+
# @return void
|
23
|
+
# ----------------------------------------------------
|
24
|
+
def initialize(*targets)
|
25
|
+
@targets = targets
|
26
|
+
LoggerDelegator.delegate
|
27
|
+
end
|
28
|
+
|
29
|
+
# ----------------------------------------------------
|
30
|
+
# attach method
|
31
|
+
#
|
32
|
+
# Attaches a new target to delegate to.
|
33
|
+
# @return void
|
34
|
+
# ----------------------------------------------------
|
35
|
+
def attach(target)
|
36
|
+
@targets << target
|
37
|
+
LoggerDelegator.delegate
|
38
|
+
end
|
39
|
+
|
40
|
+
# ----------------------------------------------------
|
41
|
+
# delegate_all method
|
42
|
+
#
|
43
|
+
# Creates delegator methods for all of the methods
|
44
|
+
# on IO.
|
45
|
+
# @return void
|
46
|
+
# ----------------------------------------------------
|
47
|
+
def self.delegate
|
48
|
+
%w(log debug info warn error section success).each do |m|
|
49
|
+
define_method(m) do |*args|
|
50
|
+
@targets.map { |t| t.send(m, *args) }
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
# ----------------------------------------------------
|
56
|
+
# detach method
|
57
|
+
#
|
58
|
+
# Detaches a delegation target.
|
59
|
+
# @return void
|
60
|
+
# ----------------------------------------------------
|
61
|
+
def detach(target)
|
62
|
+
@targets.delete(target)
|
63
|
+
LoggerDelegator.delegate
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module CLIUtils
|
2
|
+
# ======================================================
|
3
|
+
# CLIMessenger Module
|
4
|
+
# Outputs color-coordinated messages to a CLI
|
5
|
+
# ======================================================
|
6
|
+
module Messenging
|
7
|
+
include CLIUtils::PrettyIO
|
8
|
+
|
9
|
+
# ====================================================
|
10
|
+
# Methods
|
11
|
+
# ====================================================
|
12
|
+
# ----------------------------------------------------
|
13
|
+
# included method
|
14
|
+
#
|
15
|
+
# Hook called when this module gets mixed in; extends
|
16
|
+
# the includer with the methods defined here.
|
17
|
+
# @param k The includer
|
18
|
+
# @return Void
|
19
|
+
# ----------------------------------------------------
|
20
|
+
def self.included(k)
|
21
|
+
k.extend(self)
|
22
|
+
end
|
23
|
+
|
24
|
+
# ----------------------------------------------------
|
25
|
+
# default_instance method
|
26
|
+
#
|
27
|
+
# Returns a default instance of LoggerDelegator that
|
28
|
+
# delegates to STDOUT only.
|
29
|
+
# @return LoggerDelegator
|
30
|
+
# ----------------------------------------------------
|
31
|
+
def default_instance
|
32
|
+
stdout_logger = Logger.new(STDOUT)
|
33
|
+
stdout_logger.formatter = proc do |severity, datetime, progname, msg|
|
34
|
+
send(severity.downcase, msg)
|
35
|
+
end
|
36
|
+
|
37
|
+
LoggerDelegator.new(stdout_logger)
|
38
|
+
end
|
39
|
+
|
40
|
+
# ----------------------------------------------------
|
41
|
+
# messenger method
|
42
|
+
#
|
43
|
+
# Singleton method to return (or initialize, if needed)
|
44
|
+
# a LoggerDelegator.
|
45
|
+
# @return LoggerDelegator
|
46
|
+
# ----------------------------------------------------
|
47
|
+
def messenger
|
48
|
+
@messenger ||= default_instance
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
module CLIUtils
|
2
|
+
# ======================================================
|
3
|
+
# PrefManager Class
|
4
|
+
#
|
5
|
+
# Engine to derive preferences from a YAML file, deliver
|
6
|
+
# those to a user via a prompt, and collect the results.
|
7
|
+
# ======================================================
|
8
|
+
class Prefs
|
9
|
+
include PrettyIO
|
10
|
+
# ====================================================
|
11
|
+
# Attributes
|
12
|
+
# ====================================================
|
13
|
+
attr_reader :answers, :config_path, :prompts
|
14
|
+
|
15
|
+
# ====================================================
|
16
|
+
# Methods
|
17
|
+
# ====================================================
|
18
|
+
# ----------------------------------------------------
|
19
|
+
# initialize method
|
20
|
+
#
|
21
|
+
# Reads prompt data from YAML file.
|
22
|
+
# @return Void
|
23
|
+
# ----------------------------------------------------
|
24
|
+
def initialize(data)
|
25
|
+
@answers = []
|
26
|
+
@prompts = {}
|
27
|
+
|
28
|
+
case data
|
29
|
+
when String
|
30
|
+
if File.exists?(data)
|
31
|
+
@config_path = data
|
32
|
+
|
33
|
+
prompts = YAML::load_file(data)
|
34
|
+
@prompts.deep_merge!(prompts).deep_symbolize_keys!
|
35
|
+
else
|
36
|
+
fail "Invalid configuration file: #{ yaml_path }"
|
37
|
+
end
|
38
|
+
when Array
|
39
|
+
@config_path = nil
|
40
|
+
|
41
|
+
prompts = {:prompts => data}
|
42
|
+
@prompts.deep_merge!(prompts).deep_symbolize_keys!
|
43
|
+
else
|
44
|
+
fail 'Invalid configuration data'
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# ----------------------------------------------------
|
49
|
+
# ask method
|
50
|
+
#
|
51
|
+
# Runs through all of the prompt questions and collects
|
52
|
+
# answers from the user. Note that all questions w/o
|
53
|
+
# requirements are examined first; once those are
|
54
|
+
# complete, questions w/ requirements are examined.
|
55
|
+
# @return Void
|
56
|
+
# ----------------------------------------------------
|
57
|
+
def ask
|
58
|
+
@prompts[:prompts].reject { |p| p[:requirements] }.each do |p|
|
59
|
+
_deliver_prompt(p)
|
60
|
+
end
|
61
|
+
|
62
|
+
@prompts[:prompts].find_all { |p| p[:requirements] }.each do |p|
|
63
|
+
_deliver_prompt(p) if _requirements_fulfilled?(p)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
private
|
68
|
+
|
69
|
+
# ----------------------------------------------------
|
70
|
+
# _deliver_prompt method
|
71
|
+
#
|
72
|
+
# Utility method for prompting the user to answer the
|
73
|
+
# question (taking into account any options).
|
74
|
+
# @param p The prompt
|
75
|
+
# @return Void
|
76
|
+
# ----------------------------------------------------
|
77
|
+
def _deliver_prompt(p)
|
78
|
+
if p[:options].nil?
|
79
|
+
pref = prompt(p[:prompt], p[:default])
|
80
|
+
else
|
81
|
+
valid_option_chosen = false
|
82
|
+
until valid_option_chosen
|
83
|
+
pref = prompt(p[:prompt], p[:default])
|
84
|
+
if p[:options].include?(pref)
|
85
|
+
valid_option_chosen = true
|
86
|
+
else
|
87
|
+
error("Invalid option chosen: #{ pref }")
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
p[:answer] = pref
|
93
|
+
@answers << p
|
94
|
+
end
|
95
|
+
|
96
|
+
# ----------------------------------------------------
|
97
|
+
# _requirements_fulfilled? method
|
98
|
+
#
|
99
|
+
# Utility method for determining whether a prompt's
|
100
|
+
# requirements have already been fulfilled.
|
101
|
+
# @param p The prompt
|
102
|
+
# @return Void
|
103
|
+
# ----------------------------------------------------
|
104
|
+
def _requirements_fulfilled?(p)
|
105
|
+
ret = true
|
106
|
+
p[:requirements].each do |req|
|
107
|
+
a = @answers.detect do |answer|
|
108
|
+
answer[:key] == req[:key] &&
|
109
|
+
answer[:answer] == req[:value]
|
110
|
+
end
|
111
|
+
ret = false if a.nil?
|
112
|
+
end
|
113
|
+
ret
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
@@ -0,0 +1,255 @@
|
|
1
|
+
begin
|
2
|
+
require 'Win32/Console/ANSI' if (/cygwin|mswin|mingw|bccwin|wince|emx/ =~ RUBY_PLATFORM) != nil
|
3
|
+
rescue LoadError
|
4
|
+
raise 'You must run `gem install win32console` to use CLIMessage on Windows'
|
5
|
+
end
|
6
|
+
|
7
|
+
require 'readline'
|
8
|
+
|
9
|
+
module CLIUtils
|
10
|
+
# ======================================================
|
11
|
+
# CLIMessenger Module
|
12
|
+
# Outputs color-coordinated messages to a CLI
|
13
|
+
# ======================================================
|
14
|
+
module PrettyIO
|
15
|
+
@@wrap = true
|
16
|
+
@@wrap_char_limit = 40
|
17
|
+
|
18
|
+
# ====================================================
|
19
|
+
# Methods
|
20
|
+
# ====================================================
|
21
|
+
# ----------------------------------------------------
|
22
|
+
# included method
|
23
|
+
#
|
24
|
+
# Hook called when this module gets mixed in; extends
|
25
|
+
# the includer with the methods defined here.
|
26
|
+
# @param k The includer
|
27
|
+
# @return Void
|
28
|
+
# ----------------------------------------------------
|
29
|
+
def self.included(k)
|
30
|
+
k.extend(self)
|
31
|
+
end
|
32
|
+
|
33
|
+
# ----------------------------------------------------
|
34
|
+
# color_chart method
|
35
|
+
#
|
36
|
+
# Displays a chart of all the possible ANSI foreground
|
37
|
+
# and background color combinations.
|
38
|
+
# @return Void
|
39
|
+
# ----------------------------------------------------
|
40
|
+
def color_chart
|
41
|
+
[0, 1, 4, 5, 7].each do |attr|
|
42
|
+
puts '----------------------------------------------------------------'
|
43
|
+
puts "ESC[#{attr};Foreground;Background"
|
44
|
+
30.upto(37) do |fg|
|
45
|
+
40.upto(47) do |bg|
|
46
|
+
print "\033[#{attr};#{fg};#{bg}m #{fg};#{bg} "
|
47
|
+
end
|
48
|
+
puts "\033[0m"
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# ----------------------------------------------------
|
54
|
+
# debug method
|
55
|
+
#
|
56
|
+
# Empty method so that Messenging doesn't freak
|
57
|
+
# out when passed a debug message.
|
58
|
+
# @return Void
|
59
|
+
# ----------------------------------------------------
|
60
|
+
def debug(m); end
|
61
|
+
|
62
|
+
# ----------------------------------------------------
|
63
|
+
# error method
|
64
|
+
#
|
65
|
+
# Outputs a formatted-red error message.
|
66
|
+
# @param m The message to output
|
67
|
+
# @return Void
|
68
|
+
# ----------------------------------------------------
|
69
|
+
def error(m)
|
70
|
+
puts _word_wrap(m, '# ').red
|
71
|
+
end
|
72
|
+
|
73
|
+
# ----------------------------------------------------
|
74
|
+
# info method
|
75
|
+
#
|
76
|
+
# Outputs a formatted-blue informational message.
|
77
|
+
# @param m The message to output
|
78
|
+
# @return Void
|
79
|
+
# ----------------------------------------------------
|
80
|
+
def info(m)
|
81
|
+
puts _word_wrap(m, '# ').blue
|
82
|
+
end
|
83
|
+
|
84
|
+
# ----------------------------------------------------
|
85
|
+
# info_block method
|
86
|
+
#
|
87
|
+
# Wraps a block in an opening and closing info message.
|
88
|
+
# @param m1 The opening message to output
|
89
|
+
# @param m2 The closing message to output
|
90
|
+
# @param multiline Whether the message should be multiline
|
91
|
+
# @return Void
|
92
|
+
# ----------------------------------------------------
|
93
|
+
def info_block(m1, m2 = 'Done.', multiline = false)
|
94
|
+
if block_given?
|
95
|
+
if multiline
|
96
|
+
info(m1)
|
97
|
+
else
|
98
|
+
print _word_wrap(m1, '# ').blue
|
99
|
+
end
|
100
|
+
|
101
|
+
yield
|
102
|
+
|
103
|
+
if multiline
|
104
|
+
info(m2)
|
105
|
+
else
|
106
|
+
puts _word_wrap(m2, '# ').blue
|
107
|
+
end
|
108
|
+
else
|
109
|
+
fail 'Did not specify a valid block'
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
# ----------------------------------------------------
|
114
|
+
# log method
|
115
|
+
#
|
116
|
+
# Empty method so that Messenging doesn't freak
|
117
|
+
# out when passed a debug message.
|
118
|
+
# @return Void
|
119
|
+
# ----------------------------------------------------
|
120
|
+
def log(m); end
|
121
|
+
|
122
|
+
# ----------------------------------------------------
|
123
|
+
# prompt method
|
124
|
+
#
|
125
|
+
# Outputs a prompt, collects the user's response, and
|
126
|
+
# returns it.
|
127
|
+
# @param prompt The prompt to output
|
128
|
+
# @param default The default option
|
129
|
+
# @return String
|
130
|
+
# ----------------------------------------------------
|
131
|
+
def prompt(prompt, default = nil, start_dir = '')
|
132
|
+
Readline.completion_append_character = nil
|
133
|
+
Readline.completion_proc = lambda do |prefix|
|
134
|
+
files = Dir["#{start_dir}#{prefix}*"]
|
135
|
+
files.
|
136
|
+
map { |f| File.expand_path(f) }.
|
137
|
+
map { |f| File.directory?(f) ? f + "/" : f }
|
138
|
+
end
|
139
|
+
choice = Readline.readline("# #{ prompt }#{ default.nil? ? ':' : " [default: #{ default }]:" } ".cyan)
|
140
|
+
if choice.empty?
|
141
|
+
default
|
142
|
+
else
|
143
|
+
choice
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
# ----------------------------------------------------
|
148
|
+
# section method
|
149
|
+
#
|
150
|
+
# Outputs a formatted-purple section message.
|
151
|
+
# @param m The message to output
|
152
|
+
# @return Void
|
153
|
+
# ----------------------------------------------------
|
154
|
+
def section(m)
|
155
|
+
puts _word_wrap(m, '---> ').purple
|
156
|
+
end
|
157
|
+
|
158
|
+
# ----------------------------------------------------
|
159
|
+
# section_block method
|
160
|
+
#
|
161
|
+
# Wraps a block in an opening and closing section
|
162
|
+
# message.
|
163
|
+
# @param m1 The opening message to output
|
164
|
+
# @param m2 The closing message to output
|
165
|
+
# @param multiline A multiline message or not
|
166
|
+
# @return Void
|
167
|
+
# ----------------------------------------------------
|
168
|
+
def section_block(m, multiline = true)
|
169
|
+
if block_given?
|
170
|
+
if multiline
|
171
|
+
section(m)
|
172
|
+
else
|
173
|
+
print _word_wrap(m, '---> ').purple
|
174
|
+
end
|
175
|
+
|
176
|
+
yield
|
177
|
+
else
|
178
|
+
fail 'Did not specify a valid block'
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
# ----------------------------------------------------
|
183
|
+
# success method
|
184
|
+
#
|
185
|
+
# Outputs a formatted-green success message.
|
186
|
+
# @param m The message to output
|
187
|
+
# @return Void
|
188
|
+
# ----------------------------------------------------
|
189
|
+
def success(m)
|
190
|
+
puts _word_wrap(m, '# ').green
|
191
|
+
end
|
192
|
+
|
193
|
+
# ----------------------------------------------------
|
194
|
+
# warning method
|
195
|
+
#
|
196
|
+
# Outputs a formatted-yellow warning message.
|
197
|
+
# @param m The message to output
|
198
|
+
# @return Void
|
199
|
+
# ----------------------------------------------------
|
200
|
+
def warn(m)
|
201
|
+
puts _word_wrap(m, '# ').yellow
|
202
|
+
end
|
203
|
+
|
204
|
+
# ----------------------------------------------------
|
205
|
+
# wrap method
|
206
|
+
#
|
207
|
+
# Toggles wrapping on or off
|
208
|
+
# @return Integer
|
209
|
+
# ----------------------------------------------------
|
210
|
+
def self.wrap(on)
|
211
|
+
@@wrap = on
|
212
|
+
end
|
213
|
+
|
214
|
+
# ----------------------------------------------------
|
215
|
+
# wrap_limit method
|
216
|
+
#
|
217
|
+
# Returns the current character wrap amount
|
218
|
+
# @return Integer
|
219
|
+
# ----------------------------------------------------
|
220
|
+
def self.wrap_limit
|
221
|
+
@@wrap_char_limit
|
222
|
+
end
|
223
|
+
|
224
|
+
# ----------------------------------------------------
|
225
|
+
# wrap_at method
|
226
|
+
#
|
227
|
+
# Sets the number of characters at which to wrap
|
228
|
+
# @return Integer
|
229
|
+
# ----------------------------------------------------
|
230
|
+
def self.wrap_at(chars)
|
231
|
+
@@wrap_char_limit = chars
|
232
|
+
end
|
233
|
+
|
234
|
+
private
|
235
|
+
|
236
|
+
# ----------------------------------------------------
|
237
|
+
# _word_wrap method
|
238
|
+
#
|
239
|
+
# Outputs a wrapped string (where each line is limited
|
240
|
+
# to a certain number of characters).
|
241
|
+
# @param text The text to wrap
|
242
|
+
# @param prefix_str The prefix for each line
|
243
|
+
# @param line_width The number of characters per line
|
244
|
+
# @return String
|
245
|
+
# ----------------------------------------------------
|
246
|
+
def _word_wrap(text, prefix_str)
|
247
|
+
if @@wrap
|
248
|
+
return text if @@wrap_char_limit <= 0
|
249
|
+
text.gsub(/\n/, ' ').gsub(/(.{1,#{@@wrap_char_limit - prefix_str.length}})(\s+|$)/, "#{ prefix_str }\\1\n").strip
|
250
|
+
else
|
251
|
+
text
|
252
|
+
end
|
253
|
+
end
|
254
|
+
end
|
255
|
+
end
|
data/lib/cliutils.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'cliutils/ext/Hash+Extensions'
|
2
|
+
require 'cliutils/ext/Logger+Extensions'
|
3
|
+
require 'cliutils/ext/String+Extensions'
|
4
|
+
|
5
|
+
require 'cliutils/pretty-io'
|
6
|
+
require 'cliutils/configurator'
|
7
|
+
require 'cliutils/configuration'
|
8
|
+
require 'cliutils/logger-delegator'
|
9
|
+
require 'cliutils/messenging'
|
10
|
+
require 'cliutils/prefs'
|
11
|
+
require 'cliutils/version'
|
12
|
+
|
13
|
+
module CLIUtils
|
14
|
+
|
15
|
+
end
|