howzit 2.0.15 → 2.0.16

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bb673909d87ac094a2111c1f6fa364fb54183059267e009886562c89a81310d7
4
- data.tar.gz: ec766bf5d2f3b3454a289f429e28c12f19545a79dfe6f10d29f0afb04abdc9b2
3
+ metadata.gz: df621f3d6e973282799aa664b3042f22f641754d979cf711848146b04c89cd92
4
+ data.tar.gz: 134041be4b4eaecc4cb31793dbe57dfdefed601b56ef8d1b17b399615831c0ad
5
5
  SHA512:
6
- metadata.gz: b5f2e3624bad256848b1c2d8a4bc95dcbbee5d8cf0e2c63efa79b139ca3a330ce773edb2e68375ea72158de0ce69ffaedd7673f36cbee5cd937c255ccaa3e5fe
7
- data.tar.gz: f024cd0ffb6b41ab6184cf36ef65e644e90f5ab7e5c57b8a2c9cc1be404802f992f708464a3a2ab984122fddb4880ec704cda85dd371aeee735b417e15d942c2
6
+ metadata.gz: c896a32bef2ea983ef78082e685ac0f89e93a2e48b751c9dc5a3f744eb2687cf3005ffdcd5ea09284a3710ea56cc001746193855a195986290f9a98242598317
7
+ data.tar.gz: 05ccc75166128a3e2aefa7f143cd6076bef60dba024bb7c508aabc5865334f2e95bafaedeb151850704c6ac6fcc888101560f74e75b4b4cfc1afabe8ddaacaae
data/CHANGELOG.md CHANGED
@@ -1,3 +1,15 @@
1
+ ### 2.0.16
2
+
3
+ 2022-08-07 06:05
4
+
5
+ #### NEW
6
+
7
+ - --edit-template NAME will open a template in your editor, offering to create it if missing
8
+
9
+ #### FIXED
10
+
11
+ - If --show-code is given (or :show_all_code: is set to true), show content of @directives instead of title
12
+
1
13
  ### 2.0.15
2
14
 
3
15
  2022-08-05 17:16
data/bin/howzit CHANGED
@@ -94,6 +94,11 @@ OptionParser.new do |opts|
94
94
  Process.exit 0
95
95
  end
96
96
 
97
+ opts.on('--edit-template NAME', 'Create or edit a template') do |template|
98
+ Howzit.buildnote.edit_template(template)
99
+ Process.exit 0
100
+ end
101
+
97
102
  opts.on('--config-get [KEY]', 'Display the configuration settings or setting for a specific key') do |k|
98
103
  if k.nil?
99
104
  Howzit::Config::DEFAULTS.sort_by { |key, _| key }.each do |key, _|
@@ -11,23 +11,15 @@ module Howzit
11
11
  ## Initialize a build note
12
12
  ##
13
13
  ## @param file [String] The path to the build note file
14
- ## @param args [Array] additional args
15
14
  ##
16
- def initialize(file: nil, args: [])
15
+ def initialize(file: nil)
17
16
  @topics = []
18
- if note_file.nil?
19
- res = Prompt.yn('No build notes file found, create one?', default: true)
17
+ create_note(prompt: true) if note_file.nil?
20
18
 
21
- create_note if res
22
- Process.exit 0
23
- end
24
19
  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
20
+ raise "{br}No content found in build note (#{note_file}){x}".c if content.nil? || content.empty?
21
+
22
+ @metadata = content.split(/^#/)[0].strip.get_metadata
31
23
 
32
24
  read_help(file)
33
25
  end
@@ -55,6 +47,17 @@ module Howzit
55
47
  edit_note
56
48
  end
57
49
 
50
+ ##
51
+ ## Public method to open a template in the editor
52
+ ##
53
+ ## @param template [String] The template title
54
+ ##
55
+ def edit_template(template)
56
+ file = template.sub(/(\.md)?$/i, '.md')
57
+ file = File.join(Howzit.config.template_folder, file)
58
+ edit_template_file(file)
59
+ end
60
+
58
61
  ##
59
62
  ## Find a topic based on a fuzzy match
60
63
  ##
@@ -62,6 +65,7 @@ module Howzit
62
65
  ##
63
66
  def find_topic(term = nil)
64
67
  return @topics if term.nil?
68
+
65
69
  @topics.filter do |topic|
66
70
  rx = term.to_rx
67
71
  topic.title.downcase =~ rx
@@ -137,15 +141,14 @@ module Howzit
137
141
  find_topic(Howzit.options[:for_topic]).each do |topic|
138
142
  s_out = []
139
143
 
140
- topic.tasks.each do |task|
141
- s_out.push(task.to_list)
142
- end
144
+ topic.tasks.each { |task| s_out.push(task.to_list) }
143
145
 
144
- unless s_out.empty?
145
- output.push("- {bw}#{topic.title}{x}".c)
146
- output.push(s_out.join("\n"))
147
- end
146
+ next if s_out.empty?
147
+
148
+ output.push("- {bw}#{topic.title}{x}".c)
149
+ output.push(s_out.join("\n"))
148
150
  end
151
+
149
152
  output.join("\n")
150
153
  end
151
154
 
@@ -158,22 +161,75 @@ module Howzit
158
161
  read_help_file(file)
159
162
  end
160
163
 
164
+ ##
165
+ ## Create a template file
166
+ ##
167
+ ## @param file [String] file path
168
+ ## @param prompt [Boolean] confirm file creation?
169
+ ##
170
+ def create_template_file(file, prompt: false)
171
+ trap('SIGINT') do
172
+ Howzit.console.info "\nCancelled"
173
+ exit!
174
+ end
175
+
176
+ default = !$stdout.isatty || Howzit.options[:default]
177
+
178
+ if prompt && !default && !File.exist?(file)
179
+ res = Prompt.yn("{bg}Template {bw}#{File.basename(file)}{bg} not found, create it?{x}".c, default: true)
180
+ Process.exit 0 unless res
181
+ end
182
+
183
+ title = File.basename(file, '.md')
184
+
185
+ note = <<~EOBUILDNOTES
186
+ # #{title}
187
+
188
+ ## Template Topic
189
+
190
+ EOBUILDNOTES
191
+
192
+ if File.exist?(file) && !default
193
+ file = "{by}#{file}".c
194
+ unless Prompt.yn("Are you sure you want to overwrite #{file}", default: false)
195
+ puts 'Cancelled'
196
+ Process.exit 0
197
+ end
198
+ end
199
+
200
+ File.open(file, 'w') do |f|
201
+ f.puts note
202
+ puts "{by}Template {bw}#{title}{by} written to {bw}#{file}{x}".c
203
+ end
204
+
205
+ if File.exist?(file) && !default && Prompt.yn("{bg}Do you want to open {bw}#{file} {bg}for editing?{x}".c,
206
+ default: false)
207
+ edit_template_file(file)
208
+ end
209
+
210
+ Process.exit 0
211
+ end
212
+
161
213
  # Create a buildnotes skeleton
162
- def create_note
214
+ def create_note(prompt: false)
163
215
  trap('SIGINT') do
164
216
  Howzit.console.info "\nCancelled"
165
217
  exit!
166
218
  end
219
+
167
220
  default = !$stdout.isatty || Howzit.options[:default]
221
+
222
+ if prompt && !default
223
+ res = Prompt.yn('No build notes file found, create one?', default: true)
224
+ Process.exit 0 unless res
225
+ end
226
+
168
227
  # First make sure there isn't already a buildnotes file
169
228
  if note_file
170
229
  fname = "{by}#{note_file}{bw}".c
171
230
  unless default
172
231
  res = Prompt.yn("#{fname} exists and appears to be a build note, continue anyway?", default: false)
173
- unless res
174
- puts 'Canceled'
175
- Process.exit 0
176
- end
232
+ Process.exit 0 unless res
177
233
  end
178
234
  end
179
235
 
@@ -228,9 +284,7 @@ module Howzit
228
284
 
229
285
  if File.exist?(fname) && !default
230
286
  file = "{by}#{fname}".c
231
- res = Prompt.yn("Are you absolutely sure you want to overwrite #{file}", default: false)
232
-
233
- unless res
287
+ unless Prompt.yn("Are you absolutely sure you want to overwrite #{file}", default: false)
234
288
  puts 'Canceled'
235
289
  Process.exit 0
236
290
  end
@@ -238,13 +292,12 @@ module Howzit
238
292
 
239
293
  File.open(fname, 'w') do |f|
240
294
  f.puts note
241
- puts "{by}Build notes for #{title} written to #{fname}".c
295
+ puts "{by}Build notes for {bw}#{title}{by} written to {bw}#{fname}{x}".c
242
296
  end
243
297
 
244
- if File.exist?(fname) && !default
245
- res = Prompt.yn("{bg}Do you want to open {bw}#{file} {bg}for editing?{x}".c, default: false)
246
-
247
- edit_note if res
298
+ if File.exist?(fname) && !default && Prompt.yn("{bg}Do you want to open {bw}#{fname} {bg}for editing?{x}".c,
299
+ default: false)
300
+ edit_note
248
301
  end
249
302
 
250
303
  Process.exit 0
@@ -261,6 +314,139 @@ module Howzit
261
314
 
262
315
  private
263
316
 
317
+ ##
318
+ ## Import the contents of a filename as new topics
319
+ ##
320
+ ## @param mtch [MatchData] the filename match from
321
+ ## the include directive
322
+ ##
323
+ def include_file(mtch)
324
+ file = File.expand_path(mtch[1])
325
+
326
+ return mtch[0] unless File.exist?(file)
327
+
328
+ content = Util.read_file(file)
329
+ home = ENV['HOME']
330
+ short_path = File.dirname(file.sub(/^#{home}/, '~'))
331
+ prefix = "#{short_path}/#{File.basename(file)}:"
332
+ parts = content.split(/^##+/)
333
+ parts.shift
334
+ if parts.empty?
335
+ content
336
+ else
337
+ "## #{parts.join('## ')}".gsub(/^(##+ *)(?=\S)/, "\\1#{prefix}")
338
+ end
339
+ end
340
+
341
+ ##
342
+ ## Test to ensure that any `required` metadata in a
343
+ ## template is fulfilled by the build note
344
+ ##
345
+ ## @param template [String] The template to read
346
+ ## from
347
+ ##
348
+ def ensure_requirements(template)
349
+ t_leader = Util.read_file(template).split(/^#/)[0].strip
350
+ if t_leader.length > 0
351
+ t_meta = t_leader.get_metadata
352
+ if t_meta.key?('required')
353
+ required = t_meta['required'].strip.split(/\s*,\s*/)
354
+ required.each do |req|
355
+ unless @metadata.keys.include?(req.downcase)
356
+ Howzit.console.error %({bRw}ERROR:{xbr} Missing required metadata key from template '{bw}#{File.basename(template, '.md')}{xr}'{x}).c
357
+ Howzit.console.error %({br}Please define {by}#{req.downcase}{xr} in build notes{x}).c
358
+ Process.exit 1
359
+ end
360
+ end
361
+ end
362
+ end
363
+ end
364
+
365
+ ##
366
+ ## Test a template string for bracketed subtopics
367
+ ##
368
+ ## @param template [String] The template name
369
+ ##
370
+ ## @return [Array] [[String] updated template name, [Array]
371
+ ## subtopic titles]
372
+ ##
373
+ def detect_subtopics(template)
374
+ subtopics = nil
375
+
376
+ if template =~ /\[(.*?)\]$/
377
+ subtopics = Regexp.last_match[1].split(/\s*\|\s*/).map { |t| t.gsub(/\*/, '.*?')}
378
+ template.sub!(/\[.*?\]$/, '').strip
379
+ end
380
+
381
+ [template, subtopics]
382
+ end
383
+
384
+ ##
385
+ ## Enumerate templates and read their associated files
386
+ ## into topics
387
+ ##
388
+ ## @param templates [Array] The templates to read
389
+ ##
390
+ ## @return [Array] template topics
391
+ ##
392
+ def gather_templates(templates)
393
+ template_topics = []
394
+
395
+ templates.each do |template|
396
+ template, subtopics = detect_subtopics(template)
397
+
398
+ file = template.sub(/(\.md)?$/i, '.md')
399
+ file = File.join(Howzit.config.template_folder, file)
400
+
401
+ next unless File.exist?(file)
402
+
403
+ ensure_requirements(file)
404
+
405
+ template_topics.concat(read_template(template, file, subtopics))
406
+ end
407
+
408
+ template_topics
409
+ end
410
+
411
+ ##
412
+ ## Filter topics based on subtopic titles
413
+ ##
414
+ ## @param note [BuildNote] The note
415
+ ## @param subtopics [Array] The subtopics to
416
+ ## extract
417
+ ##
418
+ ## @return [Array] extracted subtopics
419
+ ##
420
+ def extract_subtopics(note, subtopics)
421
+ template_topics = []
422
+
423
+ subtopics.each do |subtopic|
424
+ note.topics.each { |topic| template_topics.push(topic) if topic.title =~ /^(.*?:)?#{subtopic}$/i }
425
+ end
426
+
427
+ template_topics
428
+ end
429
+
430
+ ##
431
+ ## Read a template file
432
+ ##
433
+ ## @param template [String] The template title
434
+ ## @param file [String] The file path
435
+ ## @param subtopics [Array] The subtopics to
436
+ ## extract, nil to return all
437
+ ##
438
+ ## @return [Array] extracted topics
439
+ ##
440
+ def read_template(template, file, subtopics = nil)
441
+ note = BuildNote.new(file: file)
442
+
443
+ template_topics = subtopics.nil? ? note.topics : extract_subtopics(note, subtopics)
444
+ template_topics.map do |topic|
445
+ topic.parent = template
446
+ topic
447
+ end
448
+ end
449
+
264
450
  ##
265
451
  ## Traverse up directory tree looking for build notes
266
452
  ##
@@ -341,30 +527,6 @@ module Howzit
341
527
  topics_dict
342
528
  end
343
529
 
344
- ##
345
- ## Test to ensure that any `required` metadata in a
346
- ## template is fulfilled by the build note
347
- ##
348
- ## @param template [String] The template to read
349
- ## from
350
- ##
351
- def ensure_requirements(template)
352
- t_leader = Util.read_file(template).split(/^#/)[0].strip
353
- if t_leader.length > 0
354
- t_meta = t_leader.get_metadata
355
- if t_meta.key?('required')
356
- required = t_meta['required'].strip.split(/\s*,\s*/)
357
- required.each do |req|
358
- unless @metadata.keys.include?(req.downcase)
359
- Howzit.console.error %({bRw}ERROR:{xbr} Missing required metadata key from template '{bw}#{File.basename(template, '.md')}{xr}'{x}).c
360
- Howzit.console.error %({br}Please define {by}#{req.downcase}{xr} in build notes{x}).c
361
- Process.exit 1
362
- end
363
- end
364
- end
365
- end
366
- end
367
-
368
530
  ##
369
531
  ## Read a list of topics from an included template
370
532
  ##
@@ -375,87 +537,17 @@ module Howzit
375
537
 
376
538
  template_topics = []
377
539
 
378
- if leader.length > 0
379
- data = leader.get_metadata
380
-
381
- if data.key?('template')
382
- templates = data['template'].strip.split(/\s*,\s*/)
383
- templates.each do |t|
384
- tasks = nil
385
- if t =~ /\[(.*?)\]$/
386
- tasks = Regexp.last_match[1].split(/\s*,\s*/).map {|t| t.gsub(/\*/, '.*?')}
387
- t = t.sub(/\[.*?\]$/, '').strip
388
- end
389
-
390
- t_file = t.sub(/(\.md)?$/, '.md')
391
- template = File.join(Howzit.config.template_folder, t_file)
392
- if File.exist?(template)
393
- ensure_requirements(template)
394
-
395
- t_topics = BuildNote.new(file: template)
396
- if tasks
397
- tasks.each do |task|
398
- t_topics.topics.each do |topic|
399
- if topic.title =~ /^(.*?:)?#{task}$/i
400
- topic.parent = t
401
- template_topics.push(topic)
402
- end
403
- end
404
- end
405
- else
406
- t_topics.topics.map! do |topic|
407
- topic.parent = t
408
- topic
409
- end
410
-
411
- template_topics.concat(t_topics.topics)
412
- end
413
- end
414
- end
415
- end
416
- end
417
- template_topics
418
- end
540
+ return template_topics if leader.empty?
419
541
 
420
- ##
421
- ## Import the contents of a filename as new topics
422
- ##
423
- ## @param mtch [MatchData] the filename match from
424
- ## the include directive
425
- ##
426
- def include_file(mtch)
427
- file = File.expand_path(mtch[1])
542
+ data = leader.get_metadata
428
543
 
429
- return mtch[0] unless File.exist?(file)
544
+ if data.key?('template')
545
+ templates = data['template'].strip.split(/\s*,\s*/)
430
546
 
431
- content = Util.read_file(file)
432
- home = ENV['HOME']
433
- short_path = File.dirname(file.sub(/^#{home}/, '~'))
434
- prefix = "#{short_path}/#{File.basename(file)}:"
435
- parts = content.split(/^##+/)
436
- parts.shift
437
- if parts.empty?
438
- content
439
- else
440
- "## #{parts.join('## ')}".gsub(/^(##+ *)(?=\S)/, "\\1#{prefix}")
547
+ template_topics.concat(gather_templates(templates))
441
548
  end
442
- end
443
-
444
- ##
445
- ## Get the title of the build note (top level header)
446
- ##
447
- ## @param truncate [Integer] Truncate to width
448
- ##
449
- def note_title(truncate = 0)
450
- help = Util.read_file(note_file)
451
- title = help.match(/(?:^(\S.*?)(?=\n==)|^# ?(.*?)$)/)
452
- title = if title
453
- title[1].nil? ? title[2] : title[1]
454
- else
455
- note_file.sub(/(\.\w+)?$/, '')
456
- end
457
549
 
458
- title && truncate.positive? ? title.trunc(truncate) : title
550
+ template_topics
459
551
  end
460
552
 
461
553
  # Read in the build notes file and output a hash of
@@ -477,7 +569,7 @@ module Howzit
477
569
  Process.exit 1
478
570
  end
479
571
 
480
- @title = note_title
572
+ @title = help.note_title(filename)
481
573
 
482
574
  help.gsub!(/@include\((.*?)\)/) do
483
575
  include_file(Regexp.last_match)
@@ -547,14 +639,33 @@ module Howzit
547
639
 
548
640
  raise "Invalid editor (#{editor})" unless Util.valid_command?(editor)
549
641
 
550
- if note_file.nil?
551
- res = Prompt.yn('No build notes file found, create one?', default: true)
642
+ create_note(prompt: true) if note_file.nil?
643
+ `#{editor} "#{note_file}"`
644
+ end
552
645
 
553
- create_note if res
554
- edit_note
555
- else
556
- `#{editor} "#{note_file}"`
557
- end
646
+ ##
647
+ ## Public method to create a new template
648
+ ##
649
+ ## @param template [String] The template name
650
+ ##
651
+ def create_template(template)
652
+ file = template.sub(/(\.md)?$/i, '.md')
653
+ file = File.join(Howzit.config.template_folder, file)
654
+ create_template_file(file, prompt: false)
655
+ end
656
+
657
+ ##
658
+ ## Open template in editor
659
+ ##
660
+ def edit_template_file(file)
661
+ editor = Howzit.options.fetch(:editor, ENV['EDITOR'])
662
+
663
+ raise 'No editor defined' if editor.nil?
664
+
665
+ raise "Invalid editor (#{editor})" unless Util.valid_command?(editor)
666
+
667
+ create_template_file(file, prompt: true) unless File.exist?(file)
668
+ `#{editor} "#{file}"`
558
669
  end
559
670
 
560
671
  ##
@@ -589,17 +700,11 @@ module Howzit
589
700
  unless note_file
590
701
  Process.exit 0 if Howzit.options[:list_runnable_titles] || Howzit.options[:list_topic_titles]
591
702
 
592
- # clear the buffer
593
- ARGV.length.times do
594
- ARGV.shift
595
- end
596
- res = yn("No build notes file found, create one?", false)
597
- create_note if res
598
- Process.exit 1
703
+ create_note(prompt: true)
599
704
  end
600
705
 
601
706
  if Howzit.options[:title_only]
602
- out = note_title(20)
707
+ out = Util.read_file(note_file).note_title(note_file, 20)
603
708
  $stdout.print(out.strip)
604
709
  Process.exit(0)
605
710
  elsif Howzit.options[:output_title] && !Howzit.options[:run]
data/lib/howzit/prompt.rb CHANGED
@@ -75,16 +75,24 @@ module Howzit
75
75
  ## options and accepts a numeric response
76
76
  ##
77
77
  ## @param matches [Array] The options list
78
+ ## @param height [Symbol] height of fzf menu
79
+ ## (:auto adjusts height to
80
+ ## number of options, anything
81
+ ## else gets max height for
82
+ ## terminal)
78
83
  ##
79
84
  ## @return [Array] the selected results
80
85
  ##
81
86
  def choose(matches, height: :auto)
82
- height = if height == :auto
83
- matches.count + 3
84
- else
85
- TTY::Screen.rows
86
- end
87
+ return [] if !$stdout.isatty || matches.count.zero?
88
+
87
89
  if Util.command_exist?('fzf')
90
+ height = if height == :auto
91
+ matches.count + 3
92
+ else
93
+ TTY::Screen.rows
94
+ end
95
+
88
96
  settings = [
89
97
  '-0',
90
98
  '-1',
@@ -102,6 +110,8 @@ module Howzit
102
110
  return res.split(/\n/)
103
111
  end
104
112
 
113
+ return matches if matches.count == 1
114
+
105
115
  res = matches[0..9]
106
116
  stty_save = `stty -g`.chomp
107
117
 
@@ -126,7 +136,7 @@ module Howzit
126
136
  puts 'Out of range'
127
137
  options_list(matches)
128
138
  end
129
- rescue Interrupt
139
+ ensure
130
140
  system('stty', stty_save)
131
141
  exit
132
142
  end
@@ -16,6 +16,22 @@ module Howzit
16
16
  true
17
17
  end
18
18
 
19
+ ##
20
+ ## Get the title of the build note (top level header)
21
+ ##
22
+ ## @param truncate [Integer] Truncate to width
23
+ ##
24
+ def note_title(file, truncate = 0)
25
+ title = match(/(?:^(\S.*?)(?=\n==)|^# ?(.*?)$)/)
26
+ title = if title
27
+ title[1].nil? ? title[2] : title[1]
28
+ else
29
+ file.sub(/(\.\w+)?$/, '')
30
+ end
31
+
32
+ title && truncate.positive? ? title.trunc(truncate) : title
33
+ end
34
+
19
35
  ##
20
36
  ## Replace slash escaped characters in a string with a
21
37
  ## zero-width space that will prevent a shell from
@@ -275,9 +291,9 @@ module Howzit
275
291
  data = {}
276
292
  meta.each do |k, v|
277
293
  case k
278
- when /^templ\w+$/
294
+ when /^te?m?pl(ate)?s?$/
279
295
  data['template'] = v
280
- when /^req\w+$/
296
+ when /^req\w*$/
281
297
  data['required'] = v
282
298
  else
283
299
  data[k] = v
data/lib/howzit/task.rb CHANGED
@@ -8,11 +8,21 @@ module Howzit
8
8
  ##
9
9
  ## Initialize a Task object
10
10
  ##
11
- def initialize(params, optional: false, default: true)
12
- @type = params[:type]
13
- @title = params[:title]
14
- @action = params[:action].render_arguments
15
- @parent = params[:parent] || nil
11
+ ## @param attributes [Hash] the task attributes
12
+ ## @param optional [Boolean] Task requires
13
+ ## confirmation
14
+ ## @param default [Boolean] Default response
15
+ ## for confirmation dialog
16
+ ##
17
+ ## @option attributes :type [Symbol] task type (:block, :run, :include, :copy)
18
+ ## @option attributes :title [String] task title
19
+ ## @option attributes :action [String] task action
20
+ ## @option attributes :parent [String] title of nested (included) topic origin
21
+ def initialize(attributes, optional: false, default: true)
22
+ @type = attributes[:type] || :run
23
+ @title = attributes[:title] || nil
24
+ @action = attributes[:action].render_arguments || nil
25
+ @parent = attributes[:parent] || nil
16
26
  @optional = optional
17
27
  @default = default
18
28
  end
@@ -56,7 +66,7 @@ module Howzit
56
66
  ##
57
67
  ## Execute an include task
58
68
  ##
59
- ## @return [Integer] number of tasks executed
69
+ ## @return [Array] [[Array] output, [Integer] number of tasks executed]
60
70
  ##
61
71
  def run_include
62
72
  output = []
data/lib/howzit/topic.rb CHANGED
@@ -137,6 +137,7 @@ module Howzit
137
137
  cmd = m[:cmd]
138
138
  obj = m[:action]
139
139
  title = m[:title].empty? ? obj : m[:title].strip
140
+ title = Howzit.options[:show_all_code] ? obj : title
140
141
  optional = m[:optional] =~ /[?!]+/ ? true : false
141
142
  default = m[:optional] =~ /!/ ? false : true
142
143
  option = if optional
@@ -222,7 +223,7 @@ module Howzit
222
223
  default = c[:optional] =~ /!/ ? false : true
223
224
  obj = c[:action]
224
225
  title = c[:title].nil? ? obj : c[:title].strip
225
-
226
+ title = Howzit.options[:show_all_code] ? obj : title
226
227
  case cmd
227
228
  when /include/i
228
229
  # matches = Howzit.buildnote.find_topic(obj)
data/lib/howzit/util.rb CHANGED
@@ -116,6 +116,11 @@ module Howzit
116
116
 
117
117
  # Paginate the output
118
118
  def page(text)
119
+ unless $stdout.isatty
120
+ puts text
121
+ return
122
+ end
123
+
119
124
  read_io, write_io = IO.pipe
120
125
 
121
126
  input = $stdin
@@ -3,5 +3,5 @@
3
3
  # Primary module for this gem.
4
4
  module Howzit
5
5
  # Current Howzit version.
6
- VERSION = '2.0.15'
6
+ VERSION = '2.0.16'
7
7
  end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Howzit::Prompt do
6
+ subject(:prompt) { Howzit::Prompt }
7
+
8
+ describe '.yn' do
9
+ it 'returns default response' do
10
+ Howzit.options[:default] = true
11
+ expect(prompt.yn('Test prompt', default: true)).to be_truthy
12
+ expect(prompt.yn('Test prompt', default: false)).not_to be_truthy
13
+ end
14
+ end
15
+
16
+ describe '.color_single_options' do
17
+ it 'returns uncolored string' do
18
+ Howzit::Color.coloring = false
19
+ expect(prompt.color_single_options(%w[y n])).to eq "[y/n]"
20
+ end
21
+ end
22
+
23
+ describe '.options_list' do
24
+ it 'creates a formatted list of options' do
25
+ options = %w[one two three four five].each_with_object([]) do |x, arr|
26
+ arr << "Option item #{x}"
27
+ end
28
+ expect { prompt.options_list(options) }.to output(/ 2 \) Option item two/).to_stdout
29
+ end
30
+ end
31
+
32
+ describe '.choose' do
33
+ it 'returns a single match' do
34
+ expect(prompt.choose(['option 1']).count).to eq 1
35
+ end
36
+ end
37
+ end
data/spec/spec_helper.rb CHANGED
@@ -1,13 +1,11 @@
1
- # require 'simplecov'
1
+ # frozen_string_literal: true
2
2
 
3
- # SimpleCov.start
4
-
5
- # if ENV['CI'] == 'true'
6
- # require 'codecov'
7
- # SimpleCov.formatter = SimpleCov::Formatter::Codecov
8
- # else
9
- # SimpleCov.formatter = SimpleCov::Formatter::HTMLFormatter
10
- # end
3
+ unless ENV['CI'] == 'true'
4
+ # SimpleCov::Formatter::Codecov # For CI
5
+ require 'simplecov'
6
+ SimpleCov.formatter = SimpleCov::Formatter::HTMLFormatter
7
+ SimpleCov.start
8
+ end
11
9
 
12
10
  require 'howzit'
13
11
  require 'cli-test'
data/spec/task_spec.rb CHANGED
@@ -6,8 +6,7 @@ describe Howzit::Task do
6
6
  subject(:task) do
7
7
  Howzit::Task.new({ type: :run,
8
8
  title: 'List Directory',
9
- action: 'ls',
10
- parent: nil })
9
+ action: 'ls &> /dev/null' })
11
10
  end
12
11
 
13
12
  describe ".new" do
data/spec/topic_spec.rb CHANGED
@@ -7,14 +7,14 @@ describe Howzit::Topic do
7
7
  content = 'Test Content'
8
8
  subject(:topic) { Howzit::Topic.new(title, content) }
9
9
 
10
- describe ".new" do
11
- it "makes a new topic instance" do
10
+ describe '.new' do
11
+ it 'makes a new topic instance' do
12
12
  expect(topic).to be_a Howzit::Topic
13
13
  end
14
- it "has the correct title" do
14
+ it 'has the correct title' do
15
15
  expect(topic.title).to eq title
16
16
  end
17
- it "has the correct content" do
17
+ it 'has the correct content' do
18
18
  expect(topic.content).to eq content
19
19
  end
20
20
  end
@@ -23,34 +23,49 @@ end
23
23
  describe Howzit::Topic do
24
24
  subject(:topic) { @hz.find_topic('Topic Balogna')[0] }
25
25
 
26
- describe ".title" do
27
- it "has the correct title" do
28
- expect(topic.title).to match /Topic Balogna/
26
+ describe '.title' do
27
+ it 'has the correct title' do
28
+ expect(topic.title).to match(/Topic Balogna/)
29
29
  end
30
30
  end
31
31
 
32
- describe ".tasks" do
33
- it "has 2 tasks" do
32
+ describe '.tasks' do
33
+ it 'has 2 tasks' do
34
34
  expect(topic.tasks.count).to eq 2
35
35
  end
36
36
  end
37
37
 
38
- describe ".prereqs" do
39
- it "has prereq" do
38
+ describe '.prereqs' do
39
+ it 'has prereq' do
40
40
  expect(topic.prereqs.count).to eq 1
41
41
  end
42
- it "has postreq" do
42
+ end
43
+
44
+ describe '.postreqs' do
45
+ it 'has postreq' do
43
46
  expect(topic.postreqs.count).to eq 1
44
47
  end
45
48
  end
46
49
 
47
- describe ".run" do
50
+ describe '.grep' do
51
+ it 'returns true for matching pattern in content' do
52
+ expect(topic.grep('prereq.*?ite')).to be_truthy
53
+ end
54
+ it 'returns true for matching pattern in title' do
55
+ expect(topic.grep('bal.*?na')).to be_truthy
56
+ end
57
+ it 'fails on bad pattern' do
58
+ expect(topic.grep('xxx+')).to_not be_truthy
59
+ end
60
+ end
61
+
62
+ describe '.run' do
48
63
  Howzit.options[:default] = true
49
- it "shows prereq and postreq" do
64
+ it 'shows prereq and postreq' do
50
65
  expect { topic.run }.to output(/prerequisite/).to_stdout
51
66
  expect { topic.run }.to output(/postrequisite/).to_stdout
52
67
  end
53
- it "Copies to clipboard" do
68
+ it 'Copies to clipboard' do
54
69
  expect {
55
70
  ENV['RUBYOPT'] = '-W1'
56
71
  Howzit.options[:log_level] = 0
@@ -58,4 +73,19 @@ describe Howzit::Topic do
58
73
  }.to output(/Copied/).to_stderr
59
74
  end
60
75
  end
76
+
77
+ describe '.print_out' do
78
+ Howzit.options[:header_format] = :block
79
+ Howzit.options[:color] = false
80
+ it 'prints the topic title' do
81
+ expect(topic.print_out({single: true, header: true}).join("\n").uncolor).to match(/▌Topic Balogna/)
82
+ end
83
+ it 'prints a task title' do
84
+ expect(topic.print_out({single: true, header: true}).join("\n").uncolor).to match(/▶ Null Output/)
85
+ end
86
+ it 'prints task action with --show-code' do
87
+ Howzit.options[:show_all_code] = true
88
+ expect(topic.print_out({single: true, header: true}).join("\n").uncolor).to match(/▶ ls -1/)
89
+ end
90
+ end
61
91
  end
data/spec/util_spec.rb ADDED
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Howzit::Util do
6
+ subject(:util) { Howzit::Util }
7
+
8
+ describe '.read_file' do
9
+ it 'reads file to a string' do
10
+ buildnote = util.read_file('builda.md')
11
+ expect(buildnote).not_to be_empty
12
+ expect(buildnote).to be_a String
13
+ end
14
+ end
15
+
16
+ describe '.valid_command?' do
17
+ it 'finds a command' do
18
+ expect(util.command_exist?('ls')).to be_truthy
19
+ end
20
+ it 'validates a command' do
21
+ expect(util.valid_command?('ls -1')).to be_truthy
22
+ end
23
+ end
24
+
25
+ describe '.which_highlighter' do
26
+ it 'finds mdless' do
27
+ Howzit.options[:highlighter] = 'mdless'
28
+ expect(util.which_highlighter).to eq 'mdless'
29
+ end
30
+ end
31
+
32
+ describe '.which_pager' do
33
+ it 'finds the more utility' do
34
+ Howzit.options[:pager] = 'more'
35
+ expect(util.which_pager).to eq 'more'
36
+ Howzit.options[:pager] = 'auto'
37
+ expect(util.which_pager).to_not eq 'more'
38
+ end
39
+ end
40
+
41
+ describe '.show' do
42
+ it 'prints output' do
43
+ buildnote = util.read_file('builda.md')
44
+ expect { util.show(buildnote) }.to output(/Balogna/).to_stdout
45
+ end
46
+
47
+ it 'pages output' do
48
+ buildnote = util.read_file('builda.md')
49
+ expect { util.page(buildnote) }.to output(/Balogna/).to_stdout
50
+ end
51
+ end
52
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: howzit
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.15
4
+ version: 2.0.16
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brett Terpstra
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-08-05 00:00:00.000000000 Z
11
+ date: 2022-08-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -331,10 +331,12 @@ files:
331
331
  - spec/.rubocop.yml
332
332
  - spec/buildnote_spec.rb
333
333
  - spec/cli_spec.rb
334
+ - spec/prompt_spec.rb
334
335
  - spec/ruby_gem_spec.rb
335
336
  - spec/spec_helper.rb
336
337
  - spec/task_spec.rb
337
338
  - spec/topic_spec.rb
339
+ - spec/util_spec.rb
338
340
  - update_readmes.rb
339
341
  homepage: https://github.com/ttscoff/howzit
340
342
  licenses:
@@ -364,7 +366,9 @@ test_files:
364
366
  - spec/.rubocop.yml
365
367
  - spec/buildnote_spec.rb
366
368
  - spec/cli_spec.rb
369
+ - spec/prompt_spec.rb
367
370
  - spec/ruby_gem_spec.rb
368
371
  - spec/spec_helper.rb
369
372
  - spec/task_spec.rb
370
373
  - spec/topic_spec.rb
374
+ - spec/util_spec.rb