everyday-cli-utils 0.2.1 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 87f14c900b87ccd8bcea65306bf14b7c75b39dc7
4
- data.tar.gz: dcf56c676139dcea0d31e0cfbdbf5ba11460aec8
3
+ metadata.gz: b519a76138a2e3d8d4906235acf55c0579a7f11f
4
+ data.tar.gz: c2d4e843d1be0a4c19c4b2b53b2e2b2da305724c
5
5
  SHA512:
6
- metadata.gz: 53da86e58af40d68695f27ea1e4849657913b119808cb70b281c22c13b0b83c6961f7a781b6d0cd9ac57e78979b9f3180bde1c4b9facaf5c57dc6d61ce5a09a6
7
- data.tar.gz: 83160f8e76371c1070f66949121b7a72480a067eab220042530adad49fc6b0584e6ffafc837afd203759a250a60e4ee7e836b6358c4549039560be41914703bb
6
+ metadata.gz: ca5221853db3b28969056198aaae0a3ba235b561c813f023e17a61a6311f63ebd04ba2327722ef8b66aaea06bbedcf8816b5c7c008395317dbab2b593c44101a
7
+ data.tar.gz: 76b6953166fc4afdd406905d56978f5a7776da41a71bd87e796eef676aeb583e992d72364be3495c3170668fe0ed72d8fabd4e7ac7f6a0180087d53fd3efab57
data/README.md CHANGED
@@ -8,6 +8,9 @@
8
8
 
9
9
  A set of CLI and general utilities.
10
10
 
11
+ ## Issue Tracking
12
+ Please use <https://everydayprogramminggenius.atlassian.net/browse/ECU> for issue tracking.
13
+
11
14
  ## Installation
12
15
 
13
16
  Add this line to your application's Gemfile:
@@ -24,7 +27,296 @@ Or install it yourself as:
24
27
 
25
28
  ## Usage
26
29
 
27
- TODO: Write usage instructions here
30
+ Because there are several different utilities in this gem, I have included a convenience method for including more than one in a single line
31
+
32
+ ```ruby
33
+ require 'everyday-cli-utils'
34
+ include EverydayCliUtils
35
+ import :format, :option
36
+ ```
37
+
38
+ You can also use `EverydayCliUtils::import :format, :option` if you don't want to include the module.
39
+
40
+ The possible values to pass to `import` are:
41
+
42
+ * `:ask`
43
+ * `:format`
44
+ * `:format_safe`
45
+ * `:histogram`
46
+ * `:histogram_safe`
47
+ * `:kmeans`
48
+ * `:kmeans_safe`
49
+ * `:maputil`
50
+ * `:maputil_safe`
51
+ * `:mycurses`
52
+ * `:option`
53
+
54
+ Some of the utilities normally modify built-in classes, like `String` and `Enumerable`. For utilities that do this, I have included a "safe" version that does not modify the built-in classes.
55
+
56
+ Here are the utilities:
57
+
58
+ ###EverydayCliUtils::Ask
59
+ Encapsulates the methods for prompting the user to select from a set of options.
60
+
61
+ ####Ask::ask(question, options, &block)
62
+ Prompts the user to select from a set of options. It calls `block` with the option selected. It is designed to take an array of symbols for the `options` parameter and will return the symbol selected rather than the index selected.
63
+
64
+ ######Parameters
65
+ * `question`: The question to show at the beginning of the prompt
66
+ * `options`: The array of options. These are automatically numbered from `1` to `options.count`. It is intended to be an array of symbols, but that is not required.
67
+ * `&block`: The block to call with the result of the prompting. It takes a single parameter which is the option selected (the value, not the index).
68
+
69
+ ####Ask::hash\_to\_options(hash, extra = [])
70
+ Take the keys of a hash and return them as an array and optionally include some extra options at the end of the array.
71
+
72
+ ######Parameters
73
+ * `hash`: The hash that uses the desired options as keys
74
+ * `extra` [optional]: The options to add on to the end of the array of options
75
+
76
+ ###EverydayCliUtils::Format
77
+
78
+ Encapsulates the methods for formatting command-line output.
79
+
80
+ ####Colors:
81
+ * `:black`
82
+ * `:red`
83
+ * `:green`
84
+ * `:yellow`
85
+ * `:blue`
86
+ * `:purple`
87
+ * `:cyan`
88
+ * `:white`
89
+ * `:none`
90
+
91
+ ####Format::colorize(text, fgcolor = nil, bgcolor = nil)
92
+ Apply colors to the text using ANSI escape sequences
93
+
94
+ ######Parameters
95
+ * `text`: The text to format
96
+ * `fgcolor` [optional]: The foreground color to use for the text (you probably shouldn't leave this out)
97
+ * `bgcolor` [optional]: The background color to use for the text
98
+
99
+ ####Format::bold(text, fgcolor = nil, bgcolor = nil)
100
+ Bold the text and optionally apply colors to it
101
+
102
+ ######Parameters
103
+ * `text`: The text to format
104
+ * `fgcolor` [optional]: The foreground color to use for the text
105
+ * `bgcolor` [optional]: The background color to use for the text
106
+
107
+ ####Format::underline(text, fgcolor = nil, bgcolor = nil)
108
+ Underline the text and optionally apply colors to it
109
+
110
+ ######Parameters
111
+ * `text`: The text to format
112
+ * `fgcolor` [optional]: The foreground color to use for the text
113
+ * `bgcolor` [optional]: The background color to use for the text
114
+
115
+ ####Format::boldunderline(text, fgcolor = nil, bgcolor = nil)
116
+ Bold and underline the text and optionally apply colors to it
117
+
118
+ ######Parameters
119
+ * `text`: The text to format
120
+ * `fgcolor` [optional]: The foreground color to use for the text
121
+ * `bgcolor` [optional]: The background color to use for the text
122
+
123
+ ####Modification to String class:
124
+ NOTE importing `:format_safe` will prevent these changes
125
+
126
+ `EverydayCliUtils::Format` modifies the `method_missing` and `respond_to?` methods of the `String` class. This is to add convenience methods to String that allow formatting by using a special method naming style. The regex is
127
+
128
+
129
+ ```ruby
130
+ colors = 'black|red|green|yellow|blue|purple|cyan|white|none'
131
+ /format(_bold)?(_underline)?(?:_fg_(#{colors}))?(?:_bg_(#{colors}))?/
132
+ ```
133
+
134
+ Here is an example:
135
+
136
+
137
+ ```ruby
138
+ 'hi'.format_bold_underline_fg_yellow_bg_green
139
+ ```
140
+
141
+ This will return a string that uses ANSI escape sequences to make the word 'hi' bold and underlined, with a foreground color of yellow and a background color of green. You can use any color and make any format supported by the `EverydayCliUtils::Format` module. All 4 parts of the method (not counting the required `format` start) are optional, so you can do something like `'hi'.format_underline_bg_white`, but you have to keep the same order, so you can't do `'hi'.format_underline_bold_bg_white_fg_black`.
142
+
143
+ ###EverydayCliUtils::Histogram
144
+
145
+ Create a text-based histogram. This is an extension to the `Enumerable` module, unless you import `:histogram_safe`, in which case you can use the static methods in `EverydayCliUtils::Histogram`, with an added first parameter of the collection.
146
+
147
+ ####Enumerable.histogram(ks = nil, width = 100, height = 50)
148
+ Create a histogram on the `Enumerable` data
149
+
150
+ ######Parameters
151
+ * `ks` [optional]: The array of averages (probably obtained from `kmeans` or `nmeans`). If provided, an extra row will be added to the bottom that will display the averages as vertical bars at the correct positions along the axis.
152
+ * `width` [optional]: The width (in characters) of the histogram.
153
+ * `height` [optional]: The height (in lines) of the histogram. This does not include the row added by the `ks` parameter.
154
+
155
+ ###EverydayCliUtils::Kmeans
156
+
157
+ Extends the `Enumerable` module with k-means and n-means functionality, unless you import `:kmeans_safe`, in which case you can use the static methods in `EverydayCliUtils::Kmeans` with an added first parameter of the collection.
158
+
159
+ ####Enumerable.outliers(sensitivity = 0.5, k = nil)
160
+ Returns an array of the outliers in the `Enumerable` data.
161
+
162
+ ######Parameters
163
+ * `sensitivity` [optional]: The sensitivity level to use when determining if a piece of data is an outlier. It is compared with the probability of that location on the normal curve multiplied by the number of data pieces in the cluster
164
+ * `k` [optional]: The number of averages to use. If provided, it will run k-means on the data to get the averages it uses. If omitted, it will use n-means on the data.
165
+
166
+ ####Enumerable.nmeans(max_k = 10, threshold = 0.05)
167
+ Run n-means (k-means with minimum optimal k) on the `Enumerable` data.
168
+
169
+ ######Parameters
170
+ * `max_k` [optional]: The maximum k value to try.
171
+ * `threshold` [optional]: The threshold used to determine if there is not enough benefit to increasing k by 1.
172
+
173
+ ####Enumerable.kmeans(k)
174
+ Run k-means on the `Enumerable` data.
175
+
176
+ ######Parameters
177
+ * `k`: The number of averages for the k-means algorithm
178
+
179
+ ####Enumerable.get_clusters(means)
180
+ Gets the clusters in the `Enumerable` data based on which mean each data point is closest to.
181
+
182
+ ######Parameters
183
+ * `means`: The means that the clusters are based on.
184
+
185
+ ###EverydayCliUtils::MapUtil
186
+
187
+ Extends the `Enumerable` module with some utility methods, unless you import `:maputil_safe`, in which case you can use the static methods in `EverydayCliUtils::MapUtil` with an added first parameter of the collection.
188
+
189
+ ####Enumerable.removefalse
190
+ Return the data without the values that are false.
191
+
192
+ ####Enumerable.filtermap(&block)
193
+ Return the mapped data with the false values removed.
194
+
195
+ ######Parameters
196
+ * `&block`: The block to use for the mapping. Returning `false` will cause the element to be removed.
197
+
198
+ ####Enumerable.sum
199
+ Return the sum of the data.
200
+
201
+ ####Enumerable.prod
202
+ Return the product of the data.
203
+
204
+ ####Enumerable.average
205
+ Return the average of the data.
206
+
207
+ ####Enumerable.std_dev
208
+ Return the standard deviation of the data.
209
+
210
+ ####Enumerable.summap(&block)
211
+ Return the sum of the mapped data.
212
+
213
+ ######Parameters
214
+ * `&block`: The block to use for the mapping.
215
+
216
+ ####Enumerable.productmap(&block)
217
+ Return the product of the mapped data.
218
+
219
+ ######Parameters
220
+ * `&block`: The block to use for the mapping.
221
+
222
+ ####Enumerable.chompall
223
+ Return the data with `chomp` called on all the elements.
224
+
225
+ ####Enumerable.join(join_str)
226
+ Return the data joined into a single string with `join_str` in between the elements.
227
+
228
+ ######Parameters
229
+ * `join_str`: The string to use for joining the elements together.
230
+
231
+ ####Hash.expand
232
+ Takes a shorthand hash (like `{ [:a, :b, :c, :d] => '1-4', e: '5' }`) and turns it into a full hash (like `{ a: '1-4', b: '1-4', c: '1-4', d: '1-4', :e => '5' }`)
233
+
234
+ ###EverydayCliUtils::MyCurses
235
+
236
+ Encapsulates the code for dealing with the curses library.
237
+
238
+ ###Fields:
239
+ ####MyCurses.headers
240
+ An array storing the header lines that will be printed out with `MyCurses.myprints`.
241
+
242
+ ####MyCurses.bodies
243
+ An array storing the body lines that will be printed out with `MyCurses.myprints`.
244
+
245
+ ####MyCurses.footers
246
+ An array storing the footer lines that will be printed out with `MyCurses.myprints`.
247
+
248
+ ###Methods:
249
+
250
+ ####MyCurses.new(use\_curses, linesh, linesf)
251
+ Initializes the class and sets the basic options.
252
+
253
+ ######Parameters
254
+ * `use_curses`: `true` to use curses, `false` to use `puts`
255
+ * `linesh`: the number of header lines
256
+ * `linesf`: the number of footer lines
257
+
258
+ ####MyCurses.clear
259
+ Clear the `headers`, `bodies`, and `footers` arrays
260
+
261
+ ####MyCurses.myprints
262
+ Print out all of the lines stored in the `headers`, `bodies`, and `footers` arrays. If `use_curses` is `true`, it will use curses and allow for scrolling. Otherwise, it will just print out all of the lines with `puts`
263
+
264
+ ####MyCurses.read\_ch
265
+ Update the character from the body pad.
266
+
267
+ ####MyCurses.clear\_ch
268
+ Clear out any newline, ENTER, UP, or DOWN characters from the queue.
269
+
270
+ ####MyCurses.scroll\_iteration
271
+ Update the display (including doing any scrolling) and read the next character.
272
+
273
+ ####MyCurses.header\_live\_append(str)
274
+ Append `str` to the header pad immediately and update it. Does not modify the `headers` array.
275
+
276
+ ######Parameters
277
+ * `str`: the string to append
278
+
279
+ ####MyCurses.body\_live\_append(str)
280
+ Append `str` to the body pad immediately and update it. Does not modify the `bodies` array.
281
+
282
+ ######Parameters
283
+ * `str`: the string to append
284
+
285
+ ####MyCurses.footer\_live\_append(str)
286
+ Append `str` to the footer pad immediately and update it. Does not modify the `footers` array.
287
+
288
+ ######Parameters
289
+ * `str`: the string to append
290
+
291
+ ####MyCurses.dispose
292
+ Close out the curses screen if curses was used.
293
+
294
+ ###EverydayCliUtils::Option
295
+
296
+ Some utility methods for the `OptionParser` class.
297
+
298
+ ####Option::add\_option(options, opts, names, opt_name, settings = {})
299
+ Add a boolean option to the `OptionParser`.
300
+
301
+ ######Parameters
302
+ * `options`: the hash of options
303
+ * `opts`: the `OptionParser` object
304
+ * `names`: the names of the options as an array (including leading hyphens)
305
+ * `opt_name`: the name of the option (usually a symbol)
306
+ * `settings`: additional optional options
307
+ * `toggle: true|false`: true to make it toggle the value in the options hash, false or omitted to just set it to true
308
+
309
+ ####Option::add\_option\_with\_param(options, opts, names, opt_name, settings = {})
310
+ Add a parameterized option to the `OptionParser`. It will set the specified option to the entered value if the option appears in the command. At least one of the names needs to have the parameter specified. You can pass over a block to have run after the value is set when parsing options.
311
+
312
+ ######Parameters
313
+ * `options`: the hash of options
314
+ * `opts`: the `OptionParser` object
315
+ * `names`: the names of the options as an array (including leading hyphens; at least one element needs to have the parameter specified)
316
+ * `opt_name`: the name of the option (usually a symbol)
317
+ * `settings`: additional optional options
318
+ * `type: <data type>`: specify a type (such as `Integer` or `Float`) for the option parser to try to parse the parameter to (default is `String` (no parsing))
319
+ * `append: true|false`: true to append the parameter to a list (for parameterized options that can occur multiple times), false or omitted to just set it to the parameter
28
320
 
29
321
  ## Contributing
30
322
 
@@ -1,7 +1,20 @@
1
1
  require_relative 'everyday-cli-utils/version'
2
2
 
3
3
  module EverydayCliUtils
4
- AVAILABLE_MODULES = [:ask, :format, :format_safe, :histogram, :histogram_safe, :kmeans, :kmeans_safe, :maputil, :maputil_safe, :mycurses, :option]
4
+ AVAILABLE_MODULES = [:ask, :format, :format_safe, :histogram, :histogram_safe, :kmeans, :kmeans_safe, :maputil, :maputil_safe, :mycurses, :option]
5
+ MODULE_TO_RELATIVE = {
6
+ ask: 'everyday-cli-utils/ask',
7
+ format: 'everyday-cli-utils/format',
8
+ format_safe: 'everyday-cli-utils/safe/format',
9
+ histogram: 'everyday-cli-utils/histogram',
10
+ histogram_safe: 'everyday-cli-utils/safe/histogram',
11
+ kmeans: 'everyday-cli-utils/kmeans',
12
+ kmeans_safe: 'everyday-cli-utils/safe/kmeans',
13
+ maputil: 'everyday-cli-utils/maputil',
14
+ maputil_safe: 'everyday-cli-utils/safe/maputil',
15
+ mycurses: 'everyday-cli-utils/mycurses',
16
+ option: 'everyday-cli-utils/option'
17
+ }
5
18
 
6
19
  def import(*names)
7
20
  EverydayCliUtils.import(*names)
@@ -9,31 +22,10 @@ module EverydayCliUtils
9
22
 
10
23
  def self.import(*names)
11
24
  names.each { |name|
12
- case (name)
13
- when :ask
14
- require_relative 'everyday-cli-utils/ask'
15
- when :format
16
- require_relative 'everyday-cli-utils/format'
17
- when :format_safe
18
- require_relative 'everyday-cli-utils/safe/format'
19
- when :histogram
20
- require_relative 'everyday-cli-utils/histogram'
21
- when :histogram_safe
22
- require_relative 'everyday-cli-utils/safe/histogram'
23
- when :kmeans
24
- require_relative 'everyday-cli-utils/kmeans'
25
- when :kmeans_safe
26
- require_relative 'everyday-cli-utils/safe/kmeans'
27
- when :maputil
28
- require_relative 'everyday-cli-utils/maputil'
29
- when :maputil_safe
30
- require_relative 'everyday-cli-utils/safe/maputil'
31
- when :mycurses
32
- require_relative 'everyday-cli-utils/mycurses'
33
- when :option
34
- require_relative 'everyday-cli-utils/option'
35
- else
36
- raise "#{name.to_s} not found!"
25
+ if MODULE_TO_RELATIVE.has_key?(name)
26
+ require_relative MODULE_TO_RELATIVE[name]
27
+ else
28
+ raise "#{name.to_s} not found!"
37
29
  end
38
30
  }
39
31
  end
@@ -44,4 +44,10 @@ module Enumerable
44
44
  def join(join_str)
45
45
  EverydayCliUtils::MapUtil.join(self, join_str)
46
46
  end
47
+ end
48
+
49
+ class Hash
50
+ def expand
51
+ EverydayCliUtils::MapUtil.expand(self)
52
+ end
47
53
  end
@@ -46,5 +46,17 @@ module EverydayCliUtils
46
46
  def self.join(collection, join_str)
47
47
  collection.map(&:to_s).reduce { |a, b| a << join_str << b }
48
48
  end
49
+
50
+ def self.expand(hash)
51
+ rval = {}
52
+ hash.each { |v|
53
+ if v[0].is_a? Array
54
+ v[0].each { |v2| rval[v2] = v[1] }
55
+ else
56
+ rval[v[0]] = v[1]
57
+ end
58
+ }
59
+ rval
60
+ end
49
61
  end
50
62
  end
@@ -1,3 +1,3 @@
1
1
  module EverydayCliUtils
2
- VERSION = '0.2.1'
2
+ VERSION = '0.3.0'
3
3
  end
@@ -1,5 +1,6 @@
1
1
  require_relative '../../lib/everyday-cli-utils'
2
- EverydayCliUtils::import :format
2
+ include EverydayCliUtils
3
+ import :format
3
4
 
4
5
  def extract_format(text)
5
6
  (text.scan(/#{"\e"}\[(.+?)m([^#{"\e"}]+?)#{"\e"}\[0m|([^#{"\e"}]+)/))[0][0]
@@ -1,5 +1,6 @@
1
1
  require_relative '../../lib/everyday-cli-utils'
2
- EverydayCliUtils.import :kmeans
2
+ include EverydayCliUtils
3
+ import :kmeans
3
4
 
4
5
  describe EverydayCliUtils::Kmeans do
5
6
  it 'finds the right clusters in simple data' do
@@ -1,5 +1,6 @@
1
1
  require_relative '../../lib/everyday-cli-utils'
2
- EverydayCliUtils.import :maputil
2
+ include EverydayCliUtils
3
+ import :maputil
3
4
 
4
5
  describe 'maputil' do
5
6
  it 'provides a shortcut for removing false values from a list' do
@@ -60,4 +61,11 @@ describe 'maputil' do
60
61
  joined = list.join('-')
61
62
  joined.should eq 'a-b-c-d-e-f'
62
63
  end
64
+
65
+ it 'provides a shortcut for making hashes with multiple keys that have the same value' do
66
+ hash = { [:a, :b, :c, :d] => '1-4', :e => '5' }
67
+ expanded = hash.expand
68
+ expected = { a: '1-4', b: '1-4', c: '1-4', d: '1-4', :e => '5' }
69
+ expanded.should eq expected
70
+ end
63
71
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: everyday-cli-utils
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Eric Henderson