howzit 2.1.18 → 2.1.21

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.
@@ -57,7 +57,7 @@ module Howzit
57
57
  ## @param template [String] The template title
58
58
  ##
59
59
  def edit_template(template)
60
- file = template.sub(/(\.md)?$/i, ".md")
60
+ file = template.sub(/(\.md)?$/i, '.md')
61
61
  file = File.join(Howzit.config.template_folder, file)
62
62
  edit_template_file(file)
63
63
  end
@@ -70,9 +70,39 @@ module Howzit
70
70
  def find_topic(term = nil)
71
71
  return @topics if term.nil?
72
72
 
73
+ rx = term.to_rx
74
+
73
75
  @topics.filter do |topic|
74
- rx = term.to_rx
75
- topic.title.downcase.sub(/ *\(.*?\) *$/, "") =~ rx
76
+ title = topic.title.downcase.sub(/ *\(.*?\) *$/, '')
77
+ match = title =~ rx
78
+
79
+ if !match && term =~ /[,:]/
80
+ normalized = title.gsub(/\s*([,:])\s*/, '\1')
81
+ match = normalized =~ rx
82
+ end
83
+
84
+ match
85
+ end
86
+ end
87
+
88
+ ##
89
+ ## Find a topic with an exact whole-word match
90
+ ##
91
+ ## @param term [String] The search term
92
+ ##
93
+ ## @return [Array] Array of topics that exactly match the term
94
+ ##
95
+ def find_topic_exact(term = nil)
96
+ return [] if term.nil?
97
+
98
+ @topics.filter do |topic|
99
+ title = topic.title.downcase.sub(/ *\(.*?\) *$/, '').strip
100
+ # Split both the title and search term into words
101
+ title_words = title.split
102
+ search_words = term.split
103
+
104
+ # Check if all search words match the title words exactly (case-insensitive)
105
+ search_words.map(&:downcase) == title_words.map(&:downcase)
76
106
  end
77
107
  end
78
108
 
@@ -84,7 +114,7 @@ module Howzit
84
114
  title = "#{title} project notes"
85
115
  url = "[#{title}](file://#{note_file})"
86
116
  Util.os_copy(url)
87
- Howzit.console.info("Link copied to clipboard.")
117
+ Howzit.console.info('Link copied to clipboard.')
88
118
  end
89
119
 
90
120
  ##
@@ -117,9 +147,7 @@ module Howzit
117
147
  def list_topics
118
148
  @topics.map do |topic|
119
149
  title = topic.title
120
- unless topic.named_args.empty?
121
- title += "(#{topic.named_args.keys.join(", ")})"
122
- end
150
+ title += "(#{topic.named_args.keys.join(', ')})" unless topic.named_args.empty?
123
151
  title
124
152
  end
125
153
  end
@@ -143,13 +171,11 @@ module Howzit
143
171
  def list_runnable_completions
144
172
  output = []
145
173
  @topics.each do |topic|
146
- if topic.tasks.count.positive?
147
- title = topic.title
148
- unless topic.named_args.empty?
149
- title += "(#{topic.named_args.keys.join(", ")})"
150
- end
151
- output.push(title)
152
- end
174
+ next unless topic.tasks.count.positive?
175
+
176
+ title = topic.title
177
+ title += "(#{topic.named_args.keys.join(', ')})" unless topic.named_args.empty?
178
+ output.push(title)
153
179
  end
154
180
  output.join("\n")
155
181
  end
@@ -172,9 +198,7 @@ module Howzit
172
198
  next if s_out.empty?
173
199
 
174
200
  title = topic.title
175
- unless topic.named_args.empty?
176
- title += " {dy}({xy}#{topic.named_args.keys.join(", ")}{dy}){x}"
177
- end
201
+ title += " {dy}({xy}#{topic.named_args.keys.join(', ')}{dy}){x}" unless topic.named_args.empty?
178
202
 
179
203
  output.push("- {g}#{title}{x}".c)
180
204
  output.push(s_out.join("\n"))
@@ -199,7 +223,7 @@ module Howzit
199
223
  ## @param prompt [Boolean] confirm file creation?
200
224
  ##
201
225
  def create_template_file(file, prompt: false)
202
- trap("SIGINT") do
226
+ trap('SIGINT') do
203
227
  Howzit.console.info "\nCancelled"
204
228
  exit!
205
229
  end
@@ -211,7 +235,7 @@ module Howzit
211
235
  Process.exit 0 unless res
212
236
  end
213
237
 
214
- title = File.basename(file, ".md")
238
+ title = File.basename(file, '.md')
215
239
 
216
240
  note = <<~EOBUILDNOTES
217
241
  # #{title}
@@ -223,12 +247,12 @@ module Howzit
223
247
  if File.exist?(file) && !default
224
248
  file = "{by}#{file}".c
225
249
  unless Prompt.yn("Are you sure you want to overwrite #{file}", default: false)
226
- Howzit.console.info("Cancelled")
250
+ Howzit.console.info('Cancelled')
227
251
  Process.exit 0
228
252
  end
229
253
  end
230
254
 
231
- File.open(file, "w") do |f|
255
+ File.open(file, 'w') do |f|
232
256
  f.puts note
233
257
  Howzit.console.info("{by}Template {bw}#{title}{by} written to {bw}#{file}{x}".c)
234
258
  end
@@ -243,7 +267,7 @@ module Howzit
243
267
 
244
268
  # Create a buildnotes skeleton
245
269
  def create_note(prompt: false)
246
- trap("SIGINT") do
270
+ trap('SIGINT') do
247
271
  Howzit.console.info "\nCancelled"
248
272
  exit!
249
273
  end
@@ -251,7 +275,7 @@ module Howzit
251
275
  default = !$stdout.isatty || Howzit.options[:default]
252
276
 
253
277
  if prompt && !default
254
- res = Prompt.yn("No build notes file found, create one?", default: true)
278
+ res = Prompt.yn('No build notes file found, create one?', default: true)
255
279
  Process.exit 0 unless res
256
280
  end
257
281
 
@@ -274,14 +298,14 @@ module Howzit
274
298
  input = $stdin.gets.chomp
275
299
  title = input unless input.empty?
276
300
  end
277
- summary = ""
301
+ summary = ''
278
302
  unless default
279
- printf "{bw}Project summary: {x}".c
303
+ printf '{bw}Project summary: {x}'.c
280
304
  input = $stdin.gets.chomp
281
305
  summary = input unless input.empty?
282
306
  end
283
307
 
284
- fname = "buildnotes.md"
308
+ fname = 'buildnotes.md'
285
309
  unless default
286
310
  printf "{bw}Build notes filename (must begin with 'howzit' or 'build')\n{xg}[#{fname}]{bw}: {x}".c
287
311
  input = $stdin.gets.chomp
@@ -316,12 +340,12 @@ module Howzit
316
340
  if File.exist?(fname) && !default
317
341
  file = "{by}#{fname}".c
318
342
  unless Prompt.yn("Are you absolutely sure you want to overwrite #{file}", default: false)
319
- Howzit.console.info("Canceled")
343
+ Howzit.console.info('Canceled')
320
344
  Process.exit 0
321
345
  end
322
346
  end
323
347
 
324
- File.open(fname, "w") do |f|
348
+ File.open(fname, 'w') do |f|
325
349
  f.puts note
326
350
  Howzit.console.info("{by}Build notes for {bw}#{title}{by} written to {bw}#{fname}{x}".c)
327
351
  end
@@ -345,6 +369,70 @@ module Howzit
345
369
 
346
370
  private
347
371
 
372
+ def topic_search_terms_from_cli
373
+ args = Howzit.cli_args || []
374
+ raw = args.join(' ').strip
375
+ return [] if raw.empty?
376
+
377
+ smart_split_topics(raw).map { |term| term.strip.downcase }.reject(&:empty?)
378
+ end
379
+
380
+ def smart_split_topics(raw)
381
+ segments, separators = segments_and_separators_for(raw)
382
+ return segments if separators.empty?
383
+
384
+ combined = []
385
+ current = segments.shift || ''
386
+
387
+ separators.each_with_index do |separator, idx|
388
+ next_segment = segments[idx] || ''
389
+ if keep_separator_with_current?(current, separator, next_segment)
390
+ current = "#{current}#{separator}#{next_segment}"
391
+ else
392
+ combined << current
393
+ current = next_segment
394
+ end
395
+ end
396
+
397
+ combined << current
398
+ combined
399
+ end
400
+
401
+ def segments_and_separators_for(raw)
402
+ segments = []
403
+ separators = []
404
+ current = String.new
405
+
406
+ raw.each_char do |char|
407
+ if char =~ /[,:]/
408
+ segments << current
409
+ separators << char
410
+ current = String.new
411
+ else
412
+ current << char
413
+ end
414
+ end
415
+
416
+ segments << current
417
+ [segments, separators]
418
+ end
419
+
420
+ def keep_separator_with_current?(current, separator, next_segment)
421
+ candidate = "#{current}#{separator}#{next_segment}"
422
+ normalized_candidate = normalize_separator_string(candidate)
423
+ return false if normalized_candidate.empty?
424
+
425
+ @topics.any? do |topic|
426
+ normalize_separator_string(topic.title).start_with?(normalized_candidate)
427
+ end
428
+ end
429
+
430
+ def normalize_separator_string(string)
431
+ return '' if string.nil?
432
+
433
+ string.downcase.gsub(/\s+/, ' ').strip.gsub(/\s*([,:])\s*/, '\1')
434
+ end
435
+
348
436
  ##
349
437
  ## Import the contents of a filename as new topics
350
438
  ##
@@ -357,15 +445,15 @@ module Howzit
357
445
  return mtch[0] unless File.exist?(file)
358
446
 
359
447
  content = Util.read_file(file)
360
- home = ENV["HOME"]
361
- short_path = File.dirname(file.sub(/^#{home}/, "~"))
448
+ home = ENV['HOME']
449
+ short_path = File.dirname(file.sub(/^#{home}/, '~'))
362
450
  prefix = "#{short_path}/#{File.basename(file)}:"
363
451
  parts = content.split(/^##+/)
364
452
  parts.shift
365
453
  if parts.empty?
366
454
  content
367
455
  else
368
- "## #{parts.join("## ")}".gsub(/^(##+ *)(?=\S)/, "\\1#{prefix}")
456
+ "## #{parts.join('## ')}".gsub(/^(##+ *)(?=\S)/, "\\1#{prefix}")
369
457
  end
370
458
  end
371
459
 
@@ -382,15 +470,15 @@ module Howzit
382
470
 
383
471
  t_meta = t_leader.metadata
384
472
 
385
- return unless t_meta.key?("required")
473
+ return unless t_meta.key?('required')
386
474
 
387
- required = t_meta["required"].strip.split(/\s*,\s*/)
475
+ required = t_meta['required'].strip.split(/\s*,\s*/)
388
476
  required.each do |req|
389
477
  next if @metadata.keys.include?(req.downcase)
390
478
 
391
479
  Howzit.console.error %({bRw}ERROR:{xbr} Missing required metadata key from template '{bw}#{File.basename(
392
- template, ".md"
393
- )}{xr}'{x}).c
480
+ template, '.md'
481
+ )}{xr}'{x}).c
394
482
  Howzit.console.error %({br}Please define {by}#{req.downcase}{xr} in build notes{x}).c
395
483
  Process.exit 1
396
484
  end
@@ -408,8 +496,8 @@ module Howzit
408
496
  subtopics = nil
409
497
 
410
498
  if template =~ /\[(.*?)\]$/
411
- subtopics = Regexp.last_match[1].split(/\s*\|\s*/).map { |t| t.gsub(/\*/, ".*?") }
412
- template.sub!(/\[.*?\]$/, "").strip
499
+ subtopics = Regexp.last_match[1].split(/\s*\|\s*/).map { |t| t.gsub(/\*/, '.*?') }
500
+ template.sub!(/\[.*?\]$/, '').strip
413
501
  end
414
502
 
415
503
  [template, subtopics]
@@ -429,7 +517,7 @@ module Howzit
429
517
  templates.each do |template|
430
518
  template, subtopics = detect_subtopics(template)
431
519
 
432
- file = template.sub(/(\.md)?$/i, ".md")
520
+ file = template.sub(/(\.md)?$/i, '.md')
433
521
  file = File.join(Howzit.config.template_folder, file)
434
522
 
435
523
  next unless File.exist?(file)
@@ -493,7 +581,7 @@ module Howzit
493
581
  buildnotes = []
494
582
  filename = nil
495
583
 
496
- while dir != "/" && (dir =~ %r{[A-Z]:/}).nil?
584
+ while dir != '/' && (dir =~ %r{[A-Z]:/}).nil?
497
585
  Dir.chdir(dir)
498
586
  filename = glob_note
499
587
  unless filename.nil?
@@ -516,7 +604,7 @@ module Howzit
516
604
  ## @return [String] file path
517
605
  ##
518
606
  def glob_note
519
- Dir.glob("*.{txt,md,markdown}").select(&:build_note?).sort[0]
607
+ Dir.glob('*.{txt,md,markdown}').select(&:build_note?).sort[0]
520
608
  end
521
609
 
522
610
  ##
@@ -529,9 +617,9 @@ module Howzit
529
617
  def find_note_file
530
618
  filename = glob_note
531
619
 
532
- if filename.nil? && "git".available?
620
+ if filename.nil? && 'git'.available?
533
621
  proj_dir = `git rev-parse --show-toplevel 2>/dev/null`.strip
534
- unless proj_dir == ""
622
+ unless proj_dir == ''
535
623
  Dir.chdir(proj_dir)
536
624
  filename = glob_note
537
625
  end
@@ -575,8 +663,8 @@ module Howzit
575
663
 
576
664
  data = leader.metadata
577
665
 
578
- if data.key?("template")
579
- templates = data["template"].strip.split(/\s*,\s*/)
666
+ if data.key?('template')
667
+ templates = data['template'].strip.split(/\s*,\s*/)
580
668
 
581
669
  template_topics.concat(gather_templates(templates))
582
670
  end
@@ -618,13 +706,13 @@ module Howzit
618
706
 
619
707
  lines = sect.split(/\n/)
620
708
  title = lines.slice!(0).strip
621
- prefix = ""
709
+ prefix = ''
622
710
  if path && path != note_file
623
711
  if path =~ /#{Howzit.config.template_folder}/
624
- short_path = File.basename(path, ".md")
712
+ short_path = File.basename(path, '.md')
625
713
  else
626
- home = ENV["HOME"]
627
- short_path = File.dirname(path.sub(/^#{home}/, "~"))
714
+ home = ENV['HOME']
715
+ short_path = File.dirname(path.sub(/^#{home}/, '~'))
628
716
  prefix = "_from #{short_path}_\n\n"
629
717
  end
630
718
  title = "#{short_path}:#{title}"
@@ -636,7 +724,7 @@ module Howzit
636
724
  end
637
725
 
638
726
  template_topics.each do |topic|
639
- topics.push(topic) unless find_topic(topic.title.sub(/^.+:/, "")).count.positive?
727
+ topics.push(topic) unless find_topic(topic.title.sub(/^.+:/, '')).count.positive?
640
728
  end
641
729
 
642
730
  topics
@@ -655,7 +743,7 @@ module Howzit
655
743
  upstream_topics = read_upstream
656
744
 
657
745
  upstream_topics.each do |topic|
658
- @topics.push(topic) unless find_topic(topic.title.sub(/^.+:/, "")).count.positive?
746
+ @topics.push(topic) unless find_topic(topic.title.sub(/^.+:/, '')).count.positive?
659
747
  end
660
748
  Howzit.has_read_upstream = true
661
749
  end
@@ -670,11 +758,11 @@ module Howzit
670
758
  ## Open build note in editor
671
759
  ##
672
760
  def edit_note
673
- editor = Howzit.options.fetch(:editor, ENV["EDITOR"])
761
+ editor = Howzit.options.fetch(:editor, ENV['EDITOR'])
674
762
 
675
763
  editor = Howzit.config.update_editor if editor.nil?
676
764
 
677
- raise "No editor defined" if editor.nil?
765
+ raise 'No editor defined' if editor.nil?
678
766
 
679
767
  raise "Invalid editor (#{editor})" unless Util.valid_command?(editor)
680
768
 
@@ -688,7 +776,7 @@ module Howzit
688
776
  ## @param template [String] The template name
689
777
  ##
690
778
  def create_template(template)
691
- file = template.sub(/(\.md)?$/i, ".md")
779
+ file = template.sub(/(\.md)?$/i, '.md')
692
780
  file = File.join(Howzit.config.template_folder, file)
693
781
  create_template_file(file, prompt: false)
694
782
  end
@@ -697,11 +785,11 @@ module Howzit
697
785
  ## Open template in editor
698
786
  ##
699
787
  def edit_template_file(file)
700
- editor = Howzit.options.fetch(:editor, ENV["EDITOR"])
788
+ editor = Howzit.options.fetch(:editor, ENV['EDITOR'])
701
789
 
702
790
  editor = Howzit.config.update_editor if editor.nil?
703
791
 
704
- raise "No editor defined" if editor.nil?
792
+ raise 'No editor defined' if editor.nil?
705
793
 
706
794
  raise "Invalid editor (#{editor})" unless Util.valid_command?(editor)
707
795
 
@@ -722,12 +810,12 @@ module Howzit
722
810
  new_topic = topic.is_a?(String) ? find_topic(topic)[0] : topic.dup
723
811
 
724
812
  output = if run
725
- new_topic.run
726
- else
727
- new_topic.print_out({ single: single })
728
- end
813
+ new_topic.run
814
+ else
815
+ new_topic.print_out({ single: single })
816
+ end
729
817
 
730
- output.nil? ? "" : output.join("\n\n")
818
+ output.nil? ? '' : output.join("\n\n")
731
819
  end
732
820
 
733
821
  ##
@@ -735,6 +823,10 @@ module Howzit
735
823
  ##
736
824
  def process
737
825
  output = []
826
+ if Howzit.options[:run]
827
+ Howzit.run_log = []
828
+ Howzit.multi_topic_run = false
829
+ end
738
830
 
739
831
  unless note_file
740
832
  Process.exit 0 if Howzit.options[:list_runnable_titles] || Howzit.options[:list_topic_titles]
@@ -748,7 +840,7 @@ module Howzit
748
840
  Process.exit(0)
749
841
  elsif Howzit.options[:output_title] && !Howzit.options[:run]
750
842
  if @title && !@title.empty?
751
- header = @title.format_header({ hr: "\u{2550}", color: "{bwK}" })
843
+ header = @title.format_header({ hr: "\u{2550}", color: '{bwK}' })
752
844
  output.push("#{header}\n")
753
845
  end
754
846
  end
@@ -774,62 +866,139 @@ module Howzit
774
866
  Process.exit(0)
775
867
  end
776
868
 
777
- topic_matches = []
778
-
869
+ # Handle grep and choose modes (batch all results)
779
870
  if Howzit.options[:grep]
871
+ topic_matches = []
780
872
  matches = grep(Howzit.options[:grep])
781
873
  case Howzit.options[:multiple_matches]
782
874
  when :all
783
875
  topic_matches.concat(matches.sort_by(&:title))
784
876
  else
785
- topic_matches.concat(Prompt.choose(matches.map(&:title), height: :max))
877
+ topic_matches.concat(Prompt.choose(matches.map(&:title), height: :max, query: Howzit.options[:grep]))
786
878
  end
879
+ process_topic_matches(topic_matches, output)
787
880
  elsif Howzit.options[:choose]
881
+ topic_matches = []
788
882
  titles = Prompt.choose(list_topics, height: :max)
789
883
  titles.each { |title| topic_matches.push(find_topic(title)[0]) }
790
- # If there are arguments use those to search for a matching topic
884
+ process_topic_matches(topic_matches, output)
791
885
  elsif !Howzit.cli_args.empty?
792
- search = Howzit.cli_args.join(" ").strip.downcase.split(/ *, */).map(&:strip)
886
+ # Collect all topic matches first (showing menus as needed)
887
+ search = topic_search_terms_from_cli
888
+ topic_matches = collect_topic_matches(search, output)
889
+ process_topic_matches(topic_matches, output)
890
+ else
891
+ # No arguments - show all topics
892
+ if Howzit.options[:run]
893
+ Howzit.run_log = []
894
+ Howzit.multi_topic_run = topics.length > 1
895
+ end
896
+ topics.each { |k| output.push(process_topic(k, false, single: false)) }
897
+ finalize_output(output)
898
+ end
899
+ end
793
900
 
794
- search.each do |s|
795
- matches = find_topic(s)
901
+ ##
902
+ ## Collect all topic matches from search terms, showing menus as needed
903
+ ## but not displaying/running until all selections are made
904
+ ##
905
+ ## @param search_terms [Array] Array of search term strings
906
+ ## @param output [Array] Output array for error messages
907
+ ##
908
+ ## @return [Array] Array of all matched topics
909
+ ##
910
+ def collect_topic_matches(search_terms, output)
911
+ all_matches = []
796
912
 
797
- if matches.empty?
798
- output.push(%({bR}ERROR:{xr} No topic match found for {bw}#{s}{x}\n).c)
799
- else
800
- case Howzit.options[:multiple_matches]
801
- when :first
802
- topic_matches.push(matches[0])
803
- when :best
804
- topic_matches.push(matches.sort_by { |a| [a.title.comp_distance(s), a.title.length] })
805
- when :all
806
- topic_matches.concat(matches)
807
- else
808
- titles = matches.map(&:title)
809
- res = Prompt.choose(titles)
810
- old_matching = Howzit.options[:matching]
811
- Howzit.options[:matching] = "exact"
812
- res.each { |title| topic_matches.concat(find_topic(title)) }
813
- Howzit.options[:matching] = old_matching
814
- end
815
- end
816
- end
913
+ search_terms.each do |s|
914
+ # First check for exact whole-word matches
915
+ exact_matches = find_topic_exact(s)
916
+
917
+ topic_matches = if !exact_matches.empty?
918
+ exact_matches
919
+ else
920
+ resolve_fuzzy_matches(s, output)
921
+ end
817
922
 
818
- if topic_matches.empty? && !Howzit.options[:show_all_on_error]
819
- Util.show(output.join("\n"), { color: true, highlight: false, paginate: false, wrap: 0 })
820
- Process.exit 1
923
+ if topic_matches.empty?
924
+ output.push(%({bR}ERROR:{xr} No topic match found for {bw}#{s}{x}\n).c)
925
+ else
926
+ all_matches.concat(topic_matches)
821
927
  end
822
928
  end
823
929
 
930
+ all_matches
931
+ end
932
+
933
+ ##
934
+ ## Resolve fuzzy matches for a search term
935
+ ##
936
+ ## @param search_term [String] The search term
937
+ ## @param output [Array] Output array for errors
938
+ ##
939
+ ## @return [Array] Array of matched topics
940
+ ##
941
+ def resolve_fuzzy_matches(search_term, output)
942
+ matches = find_topic(search_term)
943
+
944
+ return [] if matches.empty?
945
+
946
+ case Howzit.options[:multiple_matches]
947
+ when :first
948
+ [matches[0]]
949
+ when :best
950
+ [matches.sort_by { |a| [a.title.comp_distance(search_term), a.title.length] }.first]
951
+ when :all
952
+ matches
953
+ else
954
+ titles = matches.map(&:title)
955
+ res = Prompt.choose(titles, query: search_term)
956
+ old_matching = Howzit.options[:matching]
957
+ Howzit.options[:matching] = 'exact'
958
+ selected = res.flat_map { |title| find_topic(title) }
959
+ Howzit.options[:matching] = old_matching
960
+ selected
961
+ end
962
+ end
963
+
964
+ ##
965
+ ## Process collected topic matches and display output
966
+ ##
967
+ ## @param topic_matches [Array] Array of matched topics
968
+ ## @param output [Array] Output array
969
+ ##
970
+ def process_topic_matches(topic_matches, output)
971
+ if topic_matches.empty? && !Howzit.options[:show_all_on_error]
972
+ Util.show(output.join("\n"), { color: true, highlight: false, paginate: false, wrap: 0 })
973
+ Process.exit 1
974
+ end
975
+
976
+ if Howzit.options[:run]
977
+ Howzit.run_log = []
978
+ Howzit.multi_topic_run = topic_matches.length > 1
979
+ end
980
+
824
981
  if !topic_matches.empty?
825
- # If we found a match
826
982
  topic_matches.map! { |topic| topic.is_a?(String) ? find_topic(topic)[0] : topic }
827
983
  topic_matches.each { |topic_match| output.push(process_topic(topic_match, Howzit.options[:run], single: true)) }
828
984
  else
829
- # If there's no argument or no match found, output all
830
985
  topics.each { |k| output.push(process_topic(k, false, single: false)) }
831
986
  end
832
- Howzit.options[:paginate] = false if Howzit.options[:run]
987
+
988
+ finalize_output(output)
989
+ end
990
+
991
+ ##
992
+ ## Finalize and display output with run summary if applicable
993
+ ##
994
+ ## @param output [Array] Output array
995
+ ##
996
+ def finalize_output(output)
997
+ if Howzit.options[:run]
998
+ Howzit.options[:paginate] = false
999
+ summary = Howzit::RunReport.format
1000
+ output.push(summary) unless summary.empty?
1001
+ end
833
1002
  Util.show(output.join("\n").strip, Howzit.options)
834
1003
  end
835
1004
  end