howzit 2.0.9 → 2.0.12
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +1 -1
- data/CHANGELOG.md +25 -0
- data/fish/completions/howzit.fish +34 -2
- data/lib/howzit/buildnote.rb +156 -30
- data/lib/howzit/colors.rb +3 -0
- data/lib/howzit/console_logger.rb +1 -0
- data/lib/howzit/hash.rb +25 -4
- data/lib/howzit/prompt.rb +37 -2
- data/lib/howzit/stringutils.rb +130 -3
- data/lib/howzit/task.rb +10 -6
- data/lib/howzit/topic.rb +59 -8
- data/lib/howzit/util.rb +25 -0
- data/lib/howzit/version.rb +1 -1
- data/lib/howzit.rb +11 -0
- data/spec/task_spec.rb +6 -1
- metadata +1 -4
- data/lib/howzit/buildnotes.rb +0 -1252
- data/spec/buildnotes.md.bak +0 -22
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 700c444e11477c62c6de0f06b81b3029b21f3363f507c5a6cab927f2365d2be5
|
4
|
+
data.tar.gz: be862c2c31427abae2428a024009aea0f73885a5dc9652c5d2b5f308c181ca3b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz: '
|
6
|
+
metadata.gz: d07c309680eef72f5edb3b41d40354aa9cefa1b6efebd1c0dfbaa59f7cbfc95c6211433f081b6f21afa069cd5ae30f79dc42f1a4a08c96680b533b16519ca25b
|
7
|
+
data.tar.gz: '08ca9d51ec3793c1750d70f500bde1e68c1f327cd41d0b92839c317d6a421f96cbb8ef2f03204ab6cfe1ddb1d83a497084aa9590233d6ceb860921fdb473267e'
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,28 @@
|
|
1
|
+
### 2.0.12
|
2
|
+
|
3
|
+
2022-08-05 11:27
|
4
|
+
|
5
|
+
#### IMPROVED
|
6
|
+
|
7
|
+
- Show how many tasks will be included when requesting confirmation for an include? directive
|
8
|
+
|
9
|
+
### 2.0.11
|
10
|
+
|
11
|
+
2022-08-05 11:21
|
12
|
+
|
13
|
+
#### IMPROVED
|
14
|
+
|
15
|
+
- Update fish completions with all current command line options
|
16
|
+
|
17
|
+
### 2.0.10
|
18
|
+
|
19
|
+
2022-08-05 08:17
|
20
|
+
|
21
|
+
#### IMPROVED
|
22
|
+
|
23
|
+
- Provide more helpful feedback if no content is found in build note
|
24
|
+
- Confirm whether the user wants to create a new note when one isn't found
|
25
|
+
|
1
26
|
### 2.0.9
|
2
27
|
|
3
28
|
2022-08-05 07:29
|
@@ -1,3 +1,35 @@
|
|
1
1
|
complete -xc howzit -a "(howzit -L)"
|
2
|
-
complete -
|
3
|
-
|
2
|
+
complete -c howzit -l default -d "Answer all prompts with default response"
|
3
|
+
complete -c howzit -x -s m -l matching -a "partial exact fuzzy beginswith" -d "Topics matching type"
|
4
|
+
complete -c howzit -x -l multiple -a "first best all choose" -d "Multiple result handling"
|
5
|
+
complete -c howzit -s u -l no-upstream -d "Don't traverse up parent directories for additional build notes"
|
6
|
+
complete -c howzit -s u -l upstream -d "Traverse up parent directories for additional build notes"
|
7
|
+
complete -c howzit -s L -l list-completions -d "List topics for completion"
|
8
|
+
complete -c howzit -s l -l list -d "List available topics"
|
9
|
+
complete -c howzit -s R -l list-runnable -d "List topics containing @ directives (verbose)"
|
10
|
+
complete -c howzit -s T -l task-list -d "List topics containing @ directives (completion-compatible)"
|
11
|
+
complete -c howzit -l templates -d "List available templates"
|
12
|
+
complete -c howzit -l title-only -d "Output title only"
|
13
|
+
complete -c howzit -s c -l create -d "Create a skeleton build note in the current working directory"
|
14
|
+
complete -c howzit -f -l config-get -d "Display the configuration settings or setting for a specific key"
|
15
|
+
complete -c howzit -f -l config-set -d "Set a config value (must be a valid key)"
|
16
|
+
complete -c howzit -l edit-config -d "Edit configuration file using editor (subl)"
|
17
|
+
complete -c howzit -s e -l edit -d "Edit buildnotes file in current working directory using editor (subl)"
|
18
|
+
complete -c howzit -x -l grep -d "Display sections matching a search pattern"
|
19
|
+
complete -c howzit -s r -l run -a "(howzit -T)" -d "Execute @run, @open, and/or @copy commands for given topic"
|
20
|
+
complete -c howzit -s s -l select -d "Select topic from menu"
|
21
|
+
complete -c howzit -l color -d "Colorize output (default on)"
|
22
|
+
complete -c howzit -l no-color -d "Don't colorize output (default on)"
|
23
|
+
complete -c howzit -x -l header-format -d "Formatting style for topic titles (border, block)"
|
24
|
+
complete -c howzit -l md-highlight -d "Highlight Markdown syntax (default on), requires mdless or mdcat"
|
25
|
+
complete -c howzit -l no-md-highlight -d "Don't highlight Markdown syntax (default on), requires mdless or mdcat"
|
26
|
+
complete -c howzit -l pager -d "Paginate output (default on)"
|
27
|
+
complete -c howzit -l no-pager -d "Don't paginate output (default on)"
|
28
|
+
complete -c howzit -l show-code -d "Display the content of fenced run blocks"
|
29
|
+
complete -c howzit -s t -l title -d "Output title with build notes"
|
30
|
+
complete -c howzit -x -s w -l wrap -d "Wrap to specified width (default 80, 0 to disable)"
|
31
|
+
complete -c howzit -s d -l debug -d "Show debug messages (and all messages)"
|
32
|
+
complete -c howzit -s q -l quiet -d "Silence info message"
|
33
|
+
complete -c howzit -l verbose -d "Show all messages"
|
34
|
+
complete -c howzit -s h -l help -d "Display this screen"
|
35
|
+
complete -c howzit -s v -l version -d "Display version number"
|
data/lib/howzit/buildnote.rb
CHANGED
@@ -7,10 +7,27 @@ module Howzit
|
|
7
7
|
|
8
8
|
attr_reader :metadata, :title
|
9
9
|
|
10
|
+
##
|
11
|
+
## Initialize a build note
|
12
|
+
##
|
13
|
+
## @param file [String] The path to the build note file
|
14
|
+
## @param args [Array] additional args
|
15
|
+
##
|
10
16
|
def initialize(file: nil, args: [])
|
11
17
|
@topics = []
|
12
|
-
|
13
|
-
|
18
|
+
if note_file.nil?
|
19
|
+
res = Prompt.yn('No build notes file found, create one?', default: true)
|
20
|
+
|
21
|
+
create_note if res
|
22
|
+
Process.exit 0
|
23
|
+
end
|
24
|
+
content = Util.read_file(note_file)
|
25
|
+
if content.nil? || content.empty?
|
26
|
+
Howzit.console.error("{br}No content found in build note (#{note_file}){x}".c)
|
27
|
+
Process.exit 1
|
28
|
+
else
|
29
|
+
@metadata = content.split(/^#/)[0].strip.get_metadata
|
30
|
+
end
|
14
31
|
|
15
32
|
read_help(file)
|
16
33
|
end
|
@@ -19,14 +36,25 @@ module Howzit
|
|
19
36
|
puts "#<Howzit::BuildNote @topics=[#{@topics.count}]>"
|
20
37
|
end
|
21
38
|
|
39
|
+
##
|
40
|
+
## Public method to begin processing the build note based on command line options
|
41
|
+
##
|
22
42
|
def run
|
23
43
|
process
|
24
44
|
end
|
25
45
|
|
46
|
+
##
|
47
|
+
## Public method to open build note in editor
|
48
|
+
##
|
26
49
|
def edit
|
27
50
|
edit_note
|
28
51
|
end
|
29
52
|
|
53
|
+
##
|
54
|
+
## Find a topic based on a fuzzy match
|
55
|
+
##
|
56
|
+
## @param term [String] The search term
|
57
|
+
##
|
30
58
|
def find_topic(term)
|
31
59
|
@topics.filter do |topic|
|
32
60
|
rx = term.to_rx
|
@@ -34,11 +62,19 @@ module Howzit
|
|
34
62
|
end
|
35
63
|
end
|
36
64
|
|
65
|
+
##
|
66
|
+
## Call grep on all topics, filtering out those that don't match
|
67
|
+
##
|
68
|
+
## @param term [String] The search pattern
|
69
|
+
##
|
37
70
|
def grep(term)
|
38
71
|
@topics.filter { |topic| topic.grep(term) }
|
39
72
|
end
|
40
73
|
|
41
74
|
# Output a list of topic titles
|
75
|
+
#
|
76
|
+
# @return [String] formatted list of topics in build note
|
77
|
+
#
|
42
78
|
def list
|
43
79
|
output = []
|
44
80
|
output.push("{bg}Topics:{x}\n".c)
|
@@ -48,14 +84,32 @@ module Howzit
|
|
48
84
|
output.join("\n")
|
49
85
|
end
|
50
86
|
|
87
|
+
|
88
|
+
##
|
89
|
+
## Return an array of topic titles
|
90
|
+
##
|
91
|
+
## @return [Array] array of topic titles
|
92
|
+
##
|
51
93
|
def list_topics
|
52
94
|
@topics.map { |topic| topic.title }
|
53
95
|
end
|
54
96
|
|
97
|
+
##
|
98
|
+
## Return a list of topic titles suitable for shell completion
|
99
|
+
##
|
100
|
+
## @return [String] newline-separated list of topic titles
|
101
|
+
##
|
55
102
|
def list_completions
|
56
103
|
list_topics.join("\n")
|
57
104
|
end
|
58
105
|
|
106
|
+
##
|
107
|
+
## Return a list of topics containing @directives,
|
108
|
+
## suitable for shell completion
|
109
|
+
##
|
110
|
+
## @return [String] newline-separated list of topic
|
111
|
+
## titles
|
112
|
+
##
|
59
113
|
def list_runnable_completions
|
60
114
|
output = []
|
61
115
|
@topics.each do |topic|
|
@@ -64,6 +118,12 @@ module Howzit
|
|
64
118
|
output.join("\n")
|
65
119
|
end
|
66
120
|
|
121
|
+
##
|
122
|
+
## Return a formatted list of topics containing
|
123
|
+
## directives suitable for console output
|
124
|
+
##
|
125
|
+
## @return [String] formatted list
|
126
|
+
##
|
67
127
|
def list_runnable
|
68
128
|
output = []
|
69
129
|
output.push(%({bg}"Runnable" Topics:{x}\n).c)
|
@@ -82,6 +142,11 @@ module Howzit
|
|
82
142
|
output.join("\n")
|
83
143
|
end
|
84
144
|
|
145
|
+
##
|
146
|
+
## Read the help file contents
|
147
|
+
##
|
148
|
+
## @param file [String] The filepath
|
149
|
+
##
|
85
150
|
def read_file(file)
|
86
151
|
read_help_file(file)
|
87
152
|
end
|
@@ -210,28 +275,24 @@ module Howzit
|
|
210
275
|
buildnotes.reverse
|
211
276
|
end
|
212
277
|
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
278
|
+
##
|
279
|
+
## Glob current directory for valid build note filenames
|
280
|
+
## (must start with "build" or "howzit" and have
|
281
|
+
## extension of "txt", "md", or "markdown")
|
282
|
+
##
|
283
|
+
## @return [String] file path
|
284
|
+
##
|
221
285
|
def glob_note
|
222
|
-
|
223
|
-
# Check for a build note file in the current folder. Filename must start
|
224
|
-
# with "build" and have an extension of txt, md, or markdown.
|
225
|
-
|
226
|
-
Dir.glob('*.{txt,md,markdown}').each do |f|
|
227
|
-
if build_note?(f)
|
228
|
-
filename = f
|
229
|
-
break
|
230
|
-
end
|
231
|
-
end
|
232
|
-
filename
|
286
|
+
Dir.glob('*.{txt,md,markdown}').select(&:build_note?)[0]
|
233
287
|
end
|
234
288
|
|
289
|
+
##
|
290
|
+
## Search for a valid build note, checking current
|
291
|
+
## directory, git top level directory, and parent
|
292
|
+
## directories
|
293
|
+
##
|
294
|
+
## @return [String] filepath
|
295
|
+
##
|
235
296
|
def find_note_file
|
236
297
|
filename = glob_note
|
237
298
|
|
@@ -253,6 +314,11 @@ module Howzit
|
|
253
314
|
File.expand_path(filename)
|
254
315
|
end
|
255
316
|
|
317
|
+
##
|
318
|
+
## Search upstream directories for build notes
|
319
|
+
##
|
320
|
+
## @return [Array] array of build note paths
|
321
|
+
##
|
256
322
|
def read_upstream
|
257
323
|
buildnotes = glob_upstream
|
258
324
|
|
@@ -263,6 +329,13 @@ module Howzit
|
|
263
329
|
topics_dict
|
264
330
|
end
|
265
331
|
|
332
|
+
##
|
333
|
+
## Test to ensure that any `required` metadata in a
|
334
|
+
## template is fulfilled by the build note
|
335
|
+
##
|
336
|
+
## @param template [String] The template to read
|
337
|
+
## from
|
338
|
+
##
|
266
339
|
def ensure_requirements(template)
|
267
340
|
t_leader = Util.read_file(template).split(/^#/)[0].strip
|
268
341
|
if t_leader.length > 0
|
@@ -271,8 +344,8 @@ module Howzit
|
|
271
344
|
required = t_meta['required'].strip.split(/\s*,\s*/)
|
272
345
|
required.each do |req|
|
273
346
|
unless @metadata.keys.include?(req.downcase)
|
274
|
-
Howzit.console.error %({
|
275
|
-
Howzit.console.error %({
|
347
|
+
Howzit.console.error %({bRw}ERROR:{xbr} Missing required metadata key from template '{bw}#{File.basename(template, '.md')}{xr}'{x}).c
|
348
|
+
Howzit.console.error %({br}Please define {by}#{req.downcase}{xr} in build notes{x}).c
|
276
349
|
Process.exit 1
|
277
350
|
end
|
278
351
|
end
|
@@ -280,6 +353,11 @@ module Howzit
|
|
280
353
|
end
|
281
354
|
end
|
282
355
|
|
356
|
+
##
|
357
|
+
## Read a list of topics from an included template
|
358
|
+
##
|
359
|
+
## @param content [String] The template contents
|
360
|
+
##
|
283
361
|
def get_template_topics(content)
|
284
362
|
leader = content.split(/^#/)[0].strip
|
285
363
|
|
@@ -327,10 +405,16 @@ module Howzit
|
|
327
405
|
template_topics
|
328
406
|
end
|
329
407
|
|
330
|
-
|
331
|
-
|
408
|
+
##
|
409
|
+
## Import the contents of a filename as new topics
|
410
|
+
##
|
411
|
+
## @param mtch [MatchData] the filename match from
|
412
|
+
## the include directive
|
413
|
+
##
|
414
|
+
def include_file(mtch)
|
415
|
+
file = File.expand_path(mtch[1])
|
332
416
|
|
333
|
-
return
|
417
|
+
return mtch[0] unless File.exist?(file)
|
334
418
|
|
335
419
|
content = Util.read_file(file)
|
336
420
|
home = ENV['HOME']
|
@@ -345,6 +429,11 @@ module Howzit
|
|
345
429
|
end
|
346
430
|
end
|
347
431
|
|
432
|
+
##
|
433
|
+
## Get the title of the build note (top level header)
|
434
|
+
##
|
435
|
+
## @param truncate [Integer] Truncate to width
|
436
|
+
##
|
348
437
|
def note_title(truncate = 0)
|
349
438
|
help = Util.read_file(note_file)
|
350
439
|
title = help.match(/(?:^(\S.*?)(?=\n==)|^# ?(.*?)$)/)
|
@@ -357,7 +446,13 @@ module Howzit
|
|
357
446
|
title && truncate.positive? ? title.trunc(truncate) : title
|
358
447
|
end
|
359
448
|
|
360
|
-
# Read in the build notes file and output a hash of
|
449
|
+
# Read in the build notes file and output a hash of
|
450
|
+
# "Title" => contents
|
451
|
+
#
|
452
|
+
# @param path [String] The build note path
|
453
|
+
#
|
454
|
+
# @return [Array] array of Topics
|
455
|
+
#
|
361
456
|
def read_help_file(path = nil)
|
362
457
|
topics = []
|
363
458
|
|
@@ -365,6 +460,11 @@ module Howzit
|
|
365
460
|
|
366
461
|
help = Util.read_file(filename)
|
367
462
|
|
463
|
+
if help.nil? || help.empty?
|
464
|
+
Howzit.console.error("{br}No content found in #{filename}{x}".c)
|
465
|
+
Process.exit 1
|
466
|
+
end
|
467
|
+
|
368
468
|
@title = note_title
|
369
469
|
|
370
470
|
help.gsub!(/@include\((.*?)\)/) do
|
@@ -403,6 +503,11 @@ module Howzit
|
|
403
503
|
topics
|
404
504
|
end
|
405
505
|
|
506
|
+
##
|
507
|
+
## Read build note and include upstream topics
|
508
|
+
##
|
509
|
+
## @param path [String] The build note path
|
510
|
+
##
|
406
511
|
def read_help(path = nil)
|
407
512
|
@topics = read_help_file(path)
|
408
513
|
return unless path.nil? && Howzit.options[:include_upstream]
|
@@ -412,8 +517,17 @@ module Howzit
|
|
412
517
|
upstream_topics.each do |topic|
|
413
518
|
@topics.push(topic) unless find_topic(title.sub(/^.+:/, '')).count.positive?
|
414
519
|
end
|
520
|
+
|
521
|
+
if note_file && @topics.empty?
|
522
|
+
Howzit.console.error("{br}Note file found but no topics detected in #{note_file}{x}".c)
|
523
|
+
Process.exit 1
|
524
|
+
end
|
525
|
+
|
415
526
|
end
|
416
527
|
|
528
|
+
##
|
529
|
+
## Open build note in editor
|
530
|
+
##
|
417
531
|
def edit_note
|
418
532
|
editor = Howzit.options.fetch(:editor, ENV['EDITOR'])
|
419
533
|
|
@@ -431,7 +545,16 @@ module Howzit
|
|
431
545
|
end
|
432
546
|
end
|
433
547
|
|
434
|
-
|
548
|
+
##
|
549
|
+
## Run or print a topic
|
550
|
+
##
|
551
|
+
## @param topic [Topic] The topic
|
552
|
+
## @param run [Boolean] execute directives if
|
553
|
+
## true
|
554
|
+
## @param single [Boolean] is being output as a
|
555
|
+
## single topic
|
556
|
+
##
|
557
|
+
def process_topic(topic, run, single: false)
|
435
558
|
new_topic = topic.dup
|
436
559
|
|
437
560
|
# Handle variable replacement
|
@@ -445,6 +568,9 @@ module Howzit
|
|
445
568
|
output.nil? ? '' : output.join("\n")
|
446
569
|
end
|
447
570
|
|
571
|
+
##
|
572
|
+
## Search and process the build note
|
573
|
+
##
|
448
574
|
def process
|
449
575
|
output = []
|
450
576
|
|
@@ -537,10 +663,10 @@ module Howzit
|
|
537
663
|
|
538
664
|
if !topic_matches.empty?
|
539
665
|
# If we found a match
|
540
|
-
topic_matches.each { |topic_match| output.push(process_topic(topic_match, Howzit.options[:run], true)) }
|
666
|
+
topic_matches.each { |topic_match| output.push(process_topic(topic_match, Howzit.options[:run], single: true)) }
|
541
667
|
else
|
542
668
|
# If there's no argument or no match found, output all
|
543
|
-
topics.each { |k| output.push(process_topic(k, false, false)) }
|
669
|
+
topics.each { |k| output.push(process_topic(k, false, single: false)) }
|
544
670
|
end
|
545
671
|
Howzit.options[:paginate] = false if Howzit.options[:run]
|
546
672
|
Util.show(output.join("\n").strip, Howzit.options)
|
data/lib/howzit/colors.rb
CHANGED
@@ -4,7 +4,9 @@
|
|
4
4
|
module Howzit
|
5
5
|
# Terminal output color functions.
|
6
6
|
module Color
|
7
|
+
# Regexp to match excape sequences
|
7
8
|
ESCAPE_REGEX = /(?<=\[)(?:(?:(?:[349]|10)[0-9]|[0-9])?;?)+(?=m)/.freeze
|
9
|
+
|
8
10
|
# All available color names. Available as methods and string extensions.
|
9
11
|
#
|
10
12
|
# @example Use a color as a method. Color reset will be added to end of string.
|
@@ -79,6 +81,7 @@ module Howzit
|
|
79
81
|
[:default, '0;39']
|
80
82
|
].map(&:freeze).freeze
|
81
83
|
|
84
|
+
# Array of attribute keys only
|
82
85
|
ATTRIBUTE_NAMES = ATTRIBUTES.transpose.first
|
83
86
|
|
84
87
|
# Returns true if Howzit::Color supports the +feature+.
|
data/lib/howzit/hash.rb
CHANGED
@@ -5,7 +5,7 @@ class ::Hash
|
|
5
5
|
##
|
6
6
|
## Freeze all values in a hash
|
7
7
|
##
|
8
|
-
## @return Hash with all values frozen
|
8
|
+
## @return [Hash] Hash with all values frozen
|
9
9
|
##
|
10
10
|
def deep_freeze
|
11
11
|
chilled = {}
|
@@ -16,10 +16,18 @@ class ::Hash
|
|
16
16
|
chilled.freeze
|
17
17
|
end
|
18
18
|
|
19
|
+
##
|
20
|
+
## Deep freeze a hash in place (destructive)
|
21
|
+
##
|
19
22
|
def deep_freeze!
|
20
23
|
replace deep_thaw.deep_freeze
|
21
24
|
end
|
22
25
|
|
26
|
+
##
|
27
|
+
## Unfreeze nested hash values
|
28
|
+
##
|
29
|
+
## @return [Hash] Hash with all values unfrozen
|
30
|
+
##
|
23
31
|
def deep_thaw
|
24
32
|
chilled = {}
|
25
33
|
each do |k, v|
|
@@ -29,27 +37,40 @@ class ::Hash
|
|
29
37
|
chilled.dup
|
30
38
|
end
|
31
39
|
|
40
|
+
##
|
41
|
+
## Unfreeze nested hash values in place (destructive)
|
42
|
+
##
|
32
43
|
def deep_thaw!
|
33
44
|
replace deep_thaw
|
34
45
|
end
|
35
46
|
|
36
47
|
# Turn all keys into string
|
37
48
|
#
|
38
|
-
#
|
49
|
+
# @return [Hash] hash with all keys as strings
|
50
|
+
#
|
39
51
|
def stringify_keys
|
40
52
|
each_with_object({}) { |(k, v), hsh| hsh[k.to_s] = v.is_a?(Hash) ? v.stringify_keys : v }
|
41
53
|
end
|
42
54
|
|
55
|
+
##
|
56
|
+
## Turn all keys into strings in place (destructive)
|
57
|
+
##
|
43
58
|
def stringify_keys!
|
44
|
-
|
59
|
+
replace stringify_keys
|
45
60
|
end
|
46
61
|
|
47
62
|
# Turn all keys into symbols
|
63
|
+
#
|
64
|
+
# @return [Hash] hash with all keys as symbols
|
65
|
+
#
|
48
66
|
def symbolize_keys
|
49
67
|
each_with_object({}) { |(k, v), hsh| hsh[k.to_sym] = v.is_a?(Hash) ? v.symbolize_keys : v }
|
50
68
|
end
|
51
69
|
|
70
|
+
##
|
71
|
+
## Turn all keys into symbols in place (destructive)
|
72
|
+
##
|
52
73
|
def symbolize_keys!
|
53
|
-
|
74
|
+
replace symbolize_keys
|
54
75
|
end
|
55
76
|
end
|
data/lib/howzit/prompt.rb
CHANGED
@@ -4,10 +4,22 @@ module Howzit
|
|
4
4
|
# Command line prompt utils
|
5
5
|
module Prompt
|
6
6
|
class << self
|
7
|
-
|
7
|
+
|
8
|
+
##
|
9
|
+
## Display and read a Yes/No prompt
|
10
|
+
##
|
11
|
+
## @param prompt [String] The prompt string
|
12
|
+
## @param default [Boolean] default value if
|
13
|
+
## return is pressed or prompt is
|
14
|
+
## skipped
|
15
|
+
##
|
16
|
+
## @return [Boolean] result
|
17
|
+
##
|
18
|
+
def yn(prompt, default: true)
|
8
19
|
return default unless $stdout.isatty
|
9
20
|
|
10
21
|
return default if Howzit.options[:default]
|
22
|
+
|
11
23
|
tty_state = `stty -g`
|
12
24
|
system 'stty raw -echo cbreak isig'
|
13
25
|
yn = color_single_options(default ? %w[Y n] : %w[y N])
|
@@ -20,6 +32,14 @@ module Howzit
|
|
20
32
|
res.empty? ? default : res =~ /y/i
|
21
33
|
end
|
22
34
|
|
35
|
+
##
|
36
|
+
## Helper function to colorize the Y/N prompt
|
37
|
+
##
|
38
|
+
## @param choices [Array] The choices with
|
39
|
+
## default capitalized
|
40
|
+
##
|
41
|
+
## @return [String] colorized string
|
42
|
+
##
|
23
43
|
def color_single_options(choices = %w[y n])
|
24
44
|
out = []
|
25
45
|
choices.each do |choice|
|
@@ -33,6 +53,12 @@ module Howzit
|
|
33
53
|
Color.template("{xg}[#{out.join('/')}{xg}]{x}")
|
34
54
|
end
|
35
55
|
|
56
|
+
##
|
57
|
+
## Create a numbered list of options. Outputs directly
|
58
|
+
## to console, returns nothing
|
59
|
+
##
|
60
|
+
## @param matches [Array] The list items
|
61
|
+
##
|
36
62
|
def options_list(matches)
|
37
63
|
counter = 1
|
38
64
|
puts
|
@@ -43,6 +69,15 @@ module Howzit
|
|
43
69
|
puts
|
44
70
|
end
|
45
71
|
|
72
|
+
##
|
73
|
+
## Choose from a list of items. If fzf is available,
|
74
|
+
## uses that, otherwise generates its own list of
|
75
|
+
## options and accepts a numeric response
|
76
|
+
##
|
77
|
+
## @param matches [Array] The options list
|
78
|
+
##
|
79
|
+
## @return [Array] the selected results
|
80
|
+
##
|
46
81
|
def choose(matches)
|
47
82
|
if Util.command_exist?('fzf')
|
48
83
|
settings = [
|
@@ -80,7 +115,7 @@ module Howzit
|
|
80
115
|
end
|
81
116
|
line = line == '' ? 1 : line.to_i
|
82
117
|
|
83
|
-
return matches[line - 1] if line.positive? && line <= matches.length
|
118
|
+
return [matches[line - 1]] if line.positive? && line <= matches.length
|
84
119
|
|
85
120
|
puts 'Out of range'
|
86
121
|
options_list(matches)
|