ruby-zoom 3.3.5 → 3.4.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.
- checksums.yaml +4 -4
- data/bin/z +17 -16
- data/bin/zc +17 -16
- data/bin/zf +17 -16
- data/bin/zg +17 -16
- data/bin/zl +17 -16
- data/bin/zr +17 -16
- data/lib/zoom.rb +28 -30
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4b0167d84e86358ed277f8967bdb634e3038b4f3
|
4
|
+
data.tar.gz: 20c8158ecff707794d5711caeea8f305b930f46d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d16ae4eca8e12c6ce49a31e9a6f054e53bc9126f30b0e71640b0f7587ffebf1c4586a1bfc759dc14ec4bcf7282a45607235dcee0a89e185047743af1ba308f45
|
7
|
+
data.tar.gz: 8b1e9e636145a1c4ab3823a6b7772e948171ed890e592e67b1834e6bfce7dad03d460d3371cf5eea4c551a1d31910711bbdb02ad194fe2dd3db6d2e154bd4b47
|
data/bin/z
CHANGED
@@ -200,18 +200,19 @@ end
|
|
200
200
|
|
201
201
|
options = parse(ARGV)
|
202
202
|
|
203
|
+
zoom = Zoom.new
|
203
204
|
begin
|
204
205
|
case options["action"]
|
205
206
|
when "add"
|
206
|
-
|
207
|
+
zoom.interactive_add_profile(options["use"])
|
207
208
|
when "cache"
|
208
|
-
|
209
|
+
zoom.shortcut_cache
|
209
210
|
when "delete"
|
210
|
-
|
211
|
+
zoom.delete_profile(options["use"])
|
211
212
|
when "edit"
|
212
|
-
|
213
|
+
zoom.interactive_edit_profile(options["use"])
|
213
214
|
when "editor"
|
214
|
-
|
215
|
+
zoom.configure_editor(options["use"])
|
215
216
|
when "examples"
|
216
217
|
puts [
|
217
218
|
"EXAMPLES:",
|
@@ -238,31 +239,31 @@ begin
|
|
238
239
|
" $ z --go 10,20,30-40"
|
239
240
|
].join("\n")
|
240
241
|
when "go"
|
241
|
-
|
242
|
+
zoom.loop_through_results(options["use"])
|
242
243
|
when "list_profiles"
|
243
|
-
|
244
|
+
zoom.list_profiles
|
244
245
|
when "list_profile_names"
|
245
|
-
|
246
|
+
zoom.list_profile_names
|
246
247
|
when "list_tags"
|
247
|
-
|
248
|
+
zoom.list_tags
|
248
249
|
when "pager"
|
249
|
-
|
250
|
+
zoom.pager
|
250
251
|
when "repeat"
|
251
|
-
|
252
|
+
zoom.repeat
|
252
253
|
when "rc"
|
253
|
-
|
254
|
+
zoom.default
|
254
255
|
when "rename"
|
255
|
-
|
256
|
+
zoom.rename_profile(
|
256
257
|
options["rename"],
|
257
258
|
options["use"]
|
258
259
|
)
|
259
260
|
when "switch"
|
260
|
-
|
261
|
+
zoom.switch_profile(options["use"])
|
261
262
|
when "which"
|
262
|
-
|
263
|
+
zoom.show_current
|
263
264
|
else
|
264
265
|
# Search and save results
|
265
|
-
|
266
|
+
zoom.exec_profile(
|
266
267
|
options["use"],
|
267
268
|
options["subargs"],
|
268
269
|
options["pattern"]
|
data/bin/zc
CHANGED
@@ -200,18 +200,19 @@ end
|
|
200
200
|
|
201
201
|
options = parse(ARGV)
|
202
202
|
|
203
|
+
zoom = Zoom.new
|
203
204
|
begin
|
204
205
|
case options["action"]
|
205
206
|
when "add"
|
206
|
-
|
207
|
+
zoom.interactive_add_profile(options["use"])
|
207
208
|
when "cache"
|
208
|
-
|
209
|
+
zoom.shortcut_cache
|
209
210
|
when "delete"
|
210
|
-
|
211
|
+
zoom.delete_profile(options["use"])
|
211
212
|
when "edit"
|
212
|
-
|
213
|
+
zoom.interactive_edit_profile(options["use"])
|
213
214
|
when "editor"
|
214
|
-
|
215
|
+
zoom.configure_editor(options["use"])
|
215
216
|
when "examples"
|
216
217
|
puts [
|
217
218
|
"EXAMPLES:",
|
@@ -238,31 +239,31 @@ begin
|
|
238
239
|
" $ z --go 10,20,30-40"
|
239
240
|
].join("\n")
|
240
241
|
when "go"
|
241
|
-
|
242
|
+
zoom.loop_through_results(options["use"])
|
242
243
|
when "list_profiles"
|
243
|
-
|
244
|
+
zoom.list_profiles
|
244
245
|
when "list_profile_names"
|
245
|
-
|
246
|
+
zoom.list_profile_names
|
246
247
|
when "list_tags"
|
247
|
-
|
248
|
+
zoom.list_tags
|
248
249
|
when "pager"
|
249
|
-
|
250
|
+
zoom.pager
|
250
251
|
when "repeat"
|
251
|
-
|
252
|
+
zoom.repeat
|
252
253
|
when "rc"
|
253
|
-
|
254
|
+
zoom.default
|
254
255
|
when "rename"
|
255
|
-
|
256
|
+
zoom.rename_profile(
|
256
257
|
options["rename"],
|
257
258
|
options["use"]
|
258
259
|
)
|
259
260
|
when "switch"
|
260
|
-
|
261
|
+
zoom.switch_profile(options["use"])
|
261
262
|
when "which"
|
262
|
-
|
263
|
+
zoom.show_current
|
263
264
|
else
|
264
265
|
# Search and save results
|
265
|
-
|
266
|
+
zoom.exec_profile(
|
266
267
|
options["use"],
|
267
268
|
options["subargs"],
|
268
269
|
options["pattern"]
|
data/bin/zf
CHANGED
@@ -200,18 +200,19 @@ end
|
|
200
200
|
|
201
201
|
options = parse(ARGV)
|
202
202
|
|
203
|
+
zoom = Zoom.new
|
203
204
|
begin
|
204
205
|
case options["action"]
|
205
206
|
when "add"
|
206
|
-
|
207
|
+
zoom.interactive_add_profile(options["use"])
|
207
208
|
when "cache"
|
208
|
-
|
209
|
+
zoom.shortcut_cache
|
209
210
|
when "delete"
|
210
|
-
|
211
|
+
zoom.delete_profile(options["use"])
|
211
212
|
when "edit"
|
212
|
-
|
213
|
+
zoom.interactive_edit_profile(options["use"])
|
213
214
|
when "editor"
|
214
|
-
|
215
|
+
zoom.configure_editor(options["use"])
|
215
216
|
when "examples"
|
216
217
|
puts [
|
217
218
|
"EXAMPLES:",
|
@@ -238,31 +239,31 @@ begin
|
|
238
239
|
" $ z --go 10,20,30-40"
|
239
240
|
].join("\n")
|
240
241
|
when "go"
|
241
|
-
|
242
|
+
zoom.loop_through_results(options["use"])
|
242
243
|
when "list_profiles"
|
243
|
-
|
244
|
+
zoom.list_profiles
|
244
245
|
when "list_profile_names"
|
245
|
-
|
246
|
+
zoom.list_profile_names
|
246
247
|
when "list_tags"
|
247
|
-
|
248
|
+
zoom.list_tags
|
248
249
|
when "pager"
|
249
|
-
|
250
|
+
zoom.pager
|
250
251
|
when "repeat"
|
251
|
-
|
252
|
+
zoom.repeat
|
252
253
|
when "rc"
|
253
|
-
|
254
|
+
zoom.default
|
254
255
|
when "rename"
|
255
|
-
|
256
|
+
zoom.rename_profile(
|
256
257
|
options["rename"],
|
257
258
|
options["use"]
|
258
259
|
)
|
259
260
|
when "switch"
|
260
|
-
|
261
|
+
zoom.switch_profile(options["use"])
|
261
262
|
when "which"
|
262
|
-
|
263
|
+
zoom.show_current
|
263
264
|
else
|
264
265
|
# Search and save results
|
265
|
-
|
266
|
+
zoom.exec_profile(
|
266
267
|
options["use"],
|
267
268
|
options["subargs"],
|
268
269
|
options["pattern"]
|
data/bin/zg
CHANGED
@@ -200,18 +200,19 @@ end
|
|
200
200
|
|
201
201
|
options = parse(ARGV)
|
202
202
|
|
203
|
+
zoom = Zoom.new
|
203
204
|
begin
|
204
205
|
case options["action"]
|
205
206
|
when "add"
|
206
|
-
|
207
|
+
zoom.interactive_add_profile(options["use"])
|
207
208
|
when "cache"
|
208
|
-
|
209
|
+
zoom.shortcut_cache
|
209
210
|
when "delete"
|
210
|
-
|
211
|
+
zoom.delete_profile(options["use"])
|
211
212
|
when "edit"
|
212
|
-
|
213
|
+
zoom.interactive_edit_profile(options["use"])
|
213
214
|
when "editor"
|
214
|
-
|
215
|
+
zoom.configure_editor(options["use"])
|
215
216
|
when "examples"
|
216
217
|
puts [
|
217
218
|
"EXAMPLES:",
|
@@ -238,31 +239,31 @@ begin
|
|
238
239
|
" $ z --go 10,20,30-40"
|
239
240
|
].join("\n")
|
240
241
|
when "go"
|
241
|
-
|
242
|
+
zoom.loop_through_results(options["use"])
|
242
243
|
when "list_profiles"
|
243
|
-
|
244
|
+
zoom.list_profiles
|
244
245
|
when "list_profile_names"
|
245
|
-
|
246
|
+
zoom.list_profile_names
|
246
247
|
when "list_tags"
|
247
|
-
|
248
|
+
zoom.list_tags
|
248
249
|
when "pager"
|
249
|
-
|
250
|
+
zoom.pager
|
250
251
|
when "repeat"
|
251
|
-
|
252
|
+
zoom.repeat
|
252
253
|
when "rc"
|
253
|
-
|
254
|
+
zoom.default
|
254
255
|
when "rename"
|
255
|
-
|
256
|
+
zoom.rename_profile(
|
256
257
|
options["rename"],
|
257
258
|
options["use"]
|
258
259
|
)
|
259
260
|
when "switch"
|
260
|
-
|
261
|
+
zoom.switch_profile(options["use"])
|
261
262
|
when "which"
|
262
|
-
|
263
|
+
zoom.show_current
|
263
264
|
else
|
264
265
|
# Search and save results
|
265
|
-
|
266
|
+
zoom.exec_profile(
|
266
267
|
options["use"],
|
267
268
|
options["subargs"],
|
268
269
|
options["pattern"]
|
data/bin/zl
CHANGED
@@ -200,18 +200,19 @@ end
|
|
200
200
|
|
201
201
|
options = parse(ARGV)
|
202
202
|
|
203
|
+
zoom = Zoom.new
|
203
204
|
begin
|
204
205
|
case options["action"]
|
205
206
|
when "add"
|
206
|
-
|
207
|
+
zoom.interactive_add_profile(options["use"])
|
207
208
|
when "cache"
|
208
|
-
|
209
|
+
zoom.shortcut_cache
|
209
210
|
when "delete"
|
210
|
-
|
211
|
+
zoom.delete_profile(options["use"])
|
211
212
|
when "edit"
|
212
|
-
|
213
|
+
zoom.interactive_edit_profile(options["use"])
|
213
214
|
when "editor"
|
214
|
-
|
215
|
+
zoom.configure_editor(options["use"])
|
215
216
|
when "examples"
|
216
217
|
puts [
|
217
218
|
"EXAMPLES:",
|
@@ -238,31 +239,31 @@ begin
|
|
238
239
|
" $ z --go 10,20,30-40"
|
239
240
|
].join("\n")
|
240
241
|
when "go"
|
241
|
-
|
242
|
+
zoom.loop_through_results(options["use"])
|
242
243
|
when "list_profiles"
|
243
|
-
|
244
|
+
zoom.list_profiles
|
244
245
|
when "list_profile_names"
|
245
|
-
|
246
|
+
zoom.list_profile_names
|
246
247
|
when "list_tags"
|
247
|
-
|
248
|
+
zoom.list_tags
|
248
249
|
when "pager"
|
249
|
-
|
250
|
+
zoom.pager
|
250
251
|
when "repeat"
|
251
|
-
|
252
|
+
zoom.repeat
|
252
253
|
when "rc"
|
253
|
-
|
254
|
+
zoom.default
|
254
255
|
when "rename"
|
255
|
-
|
256
|
+
zoom.rename_profile(
|
256
257
|
options["rename"],
|
257
258
|
options["use"]
|
258
259
|
)
|
259
260
|
when "switch"
|
260
|
-
|
261
|
+
zoom.switch_profile(options["use"])
|
261
262
|
when "which"
|
262
|
-
|
263
|
+
zoom.show_current
|
263
264
|
else
|
264
265
|
# Search and save results
|
265
|
-
|
266
|
+
zoom.exec_profile(
|
266
267
|
options["use"],
|
267
268
|
options["subargs"],
|
268
269
|
options["pattern"]
|
data/bin/zr
CHANGED
@@ -200,18 +200,19 @@ end
|
|
200
200
|
|
201
201
|
options = parse(ARGV)
|
202
202
|
|
203
|
+
zoom = Zoom.new
|
203
204
|
begin
|
204
205
|
case options["action"]
|
205
206
|
when "add"
|
206
|
-
|
207
|
+
zoom.interactive_add_profile(options["use"])
|
207
208
|
when "cache"
|
208
|
-
|
209
|
+
zoom.shortcut_cache
|
209
210
|
when "delete"
|
210
|
-
|
211
|
+
zoom.delete_profile(options["use"])
|
211
212
|
when "edit"
|
212
|
-
|
213
|
+
zoom.interactive_edit_profile(options["use"])
|
213
214
|
when "editor"
|
214
|
-
|
215
|
+
zoom.configure_editor(options["use"])
|
215
216
|
when "examples"
|
216
217
|
puts [
|
217
218
|
"EXAMPLES:",
|
@@ -238,31 +239,31 @@ begin
|
|
238
239
|
" $ z --go 10,20,30-40"
|
239
240
|
].join("\n")
|
240
241
|
when "go"
|
241
|
-
|
242
|
+
zoom.loop_through_results(options["use"])
|
242
243
|
when "list_profiles"
|
243
|
-
|
244
|
+
zoom.list_profiles
|
244
245
|
when "list_profile_names"
|
245
|
-
|
246
|
+
zoom.list_profile_names
|
246
247
|
when "list_tags"
|
247
|
-
|
248
|
+
zoom.list_tags
|
248
249
|
when "pager"
|
249
|
-
|
250
|
+
zoom.pager
|
250
251
|
when "repeat"
|
251
|
-
|
252
|
+
zoom.repeat
|
252
253
|
when "rc"
|
253
|
-
|
254
|
+
zoom.default
|
254
255
|
when "rename"
|
255
|
-
|
256
|
+
zoom.rename_profile(
|
256
257
|
options["rename"],
|
257
258
|
options["use"]
|
258
259
|
)
|
259
260
|
when "switch"
|
260
|
-
|
261
|
+
zoom.switch_profile(options["use"])
|
261
262
|
when "which"
|
262
|
-
|
263
|
+
zoom.show_current
|
263
264
|
else
|
264
265
|
# Search and save results
|
265
|
-
|
266
|
+
zoom.exec_profile(
|
266
267
|
options["use"],
|
267
268
|
options["subargs"],
|
268
269
|
options["pattern"]
|
data/lib/zoom.rb
CHANGED
@@ -1,17 +1,9 @@
|
|
1
1
|
require "io/wait"
|
2
2
|
require "json"
|
3
3
|
require "pathname"
|
4
|
-
require "singleton"
|
5
4
|
require "string"
|
6
5
|
|
7
6
|
class Zoom
|
8
|
-
include Singleton
|
9
|
-
|
10
|
-
@@cache_file = Pathname.new("~/.zoom_cache").expand_path
|
11
|
-
@@info_file = Pathname.new("~/.zoominfo").expand_path
|
12
|
-
@@rc_file = Pathname.new("~/.zoomrc").expand_path
|
13
|
-
@@shortcut_file = Pathname.new("~/.zoom_shortcuts").expand_path
|
14
|
-
|
15
7
|
def add_profile(
|
16
8
|
name,
|
17
9
|
clas,
|
@@ -42,7 +34,7 @@ class Zoom
|
|
42
34
|
end
|
43
35
|
|
44
36
|
def clear_cache
|
45
|
-
|
37
|
+
@cache_file.delete if (@cache_file.exist?)
|
46
38
|
end
|
47
39
|
|
48
40
|
def configure_editor(editor)
|
@@ -55,24 +47,24 @@ class Zoom
|
|
55
47
|
write_zoomrc
|
56
48
|
end
|
57
49
|
|
58
|
-
def
|
50
|
+
def default
|
59
51
|
default_zoominfo
|
60
52
|
default_zoomrc
|
61
53
|
end
|
62
54
|
|
63
|
-
def
|
55
|
+
def default_zoominfo
|
64
56
|
info = Hash.new
|
65
57
|
info["profile"] = "default"
|
66
58
|
|
67
59
|
# Reset last command to be empty
|
68
60
|
info["last_command"] = Hash.new
|
69
61
|
|
70
|
-
File.open(
|
62
|
+
File.open(@info_file, "w") do |file|
|
71
63
|
file.write(JSON.pretty_generate(info))
|
72
64
|
end
|
73
65
|
end
|
74
66
|
|
75
|
-
def
|
67
|
+
def default_zoomrc
|
76
68
|
rc = Hash.new
|
77
69
|
profiles = Hash.new
|
78
70
|
|
@@ -133,7 +125,7 @@ class Zoom
|
|
133
125
|
# Default editor (use $EDITOR)
|
134
126
|
rc["editor"] = ""
|
135
127
|
|
136
|
-
File.open(
|
128
|
+
File.open(@rc_file, "w") do |file|
|
137
129
|
file.write(JSON.pretty_generate(rc))
|
138
130
|
end
|
139
131
|
end
|
@@ -209,7 +201,7 @@ class Zoom
|
|
209
201
|
|
210
202
|
def get_location_of_result(result)
|
211
203
|
count = 0
|
212
|
-
File.open(
|
204
|
+
File.open(@shortcut_file) do |file|
|
213
205
|
file.each do |line|
|
214
206
|
count += 1
|
215
207
|
if (count == result)
|
@@ -230,6 +222,11 @@ class Zoom
|
|
230
222
|
private :get_new_value
|
231
223
|
|
232
224
|
def initialize
|
225
|
+
@cache_file = Pathname.new("~/.zoom_cache").expand_path
|
226
|
+
@info_file = Pathname.new("~/.zoominfo").expand_path
|
227
|
+
@rc_file = Pathname.new("~/.zoomrc").expand_path
|
228
|
+
@shortcut_file = Pathname.new("~/.zoom_shortcuts").expand_path
|
229
|
+
|
233
230
|
# Load custom profiles
|
234
231
|
custom_profs = Pathname.new("~/.zoom_profiles.rb").expand_path
|
235
232
|
require_relative custom_profs if (custom_profs.exist?)
|
@@ -243,6 +240,7 @@ class Zoom
|
|
243
240
|
@editor = "vim" if (@editor.nil? || @editor.empty?)
|
244
241
|
@editor = ScoobyDoo.where_are_you(@editor)
|
245
242
|
@editor = ScoobyDoo.where_are_you("vi") if (@editor.nil?)
|
243
|
+
|
246
244
|
end
|
247
245
|
|
248
246
|
def interactive_add_profile(name)
|
@@ -359,13 +357,13 @@ class Zoom
|
|
359
357
|
end
|
360
358
|
|
361
359
|
def list_tags
|
362
|
-
return if (
|
360
|
+
return if (!@cache_file.exist?)
|
363
361
|
|
364
362
|
# Open shortcut file for writing
|
365
|
-
shct = File.open(
|
363
|
+
shct = File.open(@shortcut_file, "r")
|
366
364
|
|
367
365
|
# Read in cache
|
368
|
-
File.open(
|
366
|
+
File.open(@cache_file) do |cache|
|
369
367
|
count = 1
|
370
368
|
|
371
369
|
cache.each do |line|
|
@@ -442,7 +440,7 @@ class Zoom
|
|
442
440
|
private :open_editor_to_result
|
443
441
|
|
444
442
|
def pager
|
445
|
-
File.open(
|
443
|
+
File.open(@cache_file, "w") do |f|
|
446
444
|
f.write("ZOOM_EXE_DIR=#{Dir.pwd}\n")
|
447
445
|
begin
|
448
446
|
$stdin.each_line do |line|
|
@@ -477,20 +475,20 @@ class Zoom
|
|
477
475
|
private :parse_tags
|
478
476
|
|
479
477
|
def read_zoominfo
|
480
|
-
if (
|
481
|
-
|
478
|
+
if (!@info_file.exist? && !@info_file.symlink?)
|
479
|
+
default_zoominfo
|
482
480
|
end
|
483
481
|
|
484
|
-
@info = JSON.parse(File.read(
|
482
|
+
@info = JSON.parse(File.read(@info_file))
|
485
483
|
end
|
486
484
|
private :read_zoominfo
|
487
485
|
|
488
486
|
def read_zoomrc
|
489
|
-
if (
|
490
|
-
|
487
|
+
if (!@rc_file.exist? && !@rc_file.symlink?)
|
488
|
+
default_zoomrc
|
491
489
|
end
|
492
490
|
|
493
|
-
@rc = JSON.parse(File.read(
|
491
|
+
@rc = JSON.parse(File.read(@rc_file))
|
494
492
|
@profiles = Hash.new
|
495
493
|
@rc["profiles"].each do |name, prof|
|
496
494
|
@profiles[name] = Zoom::Profile.from_json(prof)
|
@@ -540,7 +538,7 @@ class Zoom
|
|
540
538
|
private :remove_colors
|
541
539
|
|
542
540
|
def shortcut_cache(profile = nil)
|
543
|
-
return if (
|
541
|
+
return if (!@cache_file.exist?)
|
544
542
|
return if (@info["last_command"].empty?)
|
545
543
|
|
546
544
|
if (profile.nil?)
|
@@ -548,10 +546,10 @@ class Zoom
|
|
548
546
|
end
|
549
547
|
|
550
548
|
# Open shortcut file for writing
|
551
|
-
shct = File.open(
|
549
|
+
shct = File.open(@shortcut_file, "w")
|
552
550
|
|
553
551
|
# Read in cache
|
554
|
-
File.open(
|
552
|
+
File.open(@cache_file) do |cache|
|
555
553
|
start_dir = ""
|
556
554
|
file = nil
|
557
555
|
filename = ""
|
@@ -618,7 +616,7 @@ class Zoom
|
|
618
616
|
end
|
619
617
|
|
620
618
|
def write_zoominfo
|
621
|
-
File.open(
|
619
|
+
File.open(@info_file, "w") do |file|
|
622
620
|
file.write(JSON.pretty_generate(@info))
|
623
621
|
end
|
624
622
|
end
|
@@ -626,7 +624,7 @@ class Zoom
|
|
626
624
|
|
627
625
|
def write_zoomrc
|
628
626
|
@rc["profiles"] = @profiles
|
629
|
-
File.open(
|
627
|
+
File.open(@rc_file, "w") do |file|
|
630
628
|
file.write(JSON.pretty_generate(@rc))
|
631
629
|
end
|
632
630
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ruby-zoom
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.
|
4
|
+
version: 3.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Miles Whittaker
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2016-02-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: minitest
|