markdown_exec 1.3.0 → 1.3.2

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.
data/lib/markdown_exec.rb CHANGED
@@ -11,13 +11,18 @@ require 'shellwords'
11
11
  require 'tty-prompt'
12
12
  require 'yaml'
13
13
 
14
+ require_relative 'cli'
14
15
  require_relative 'colorize'
15
16
  require_relative 'env'
17
+ # require_relative 'environment_opt_parse'
18
+ require_relative 'object_present'
16
19
  require_relative 'shared'
17
20
  require_relative 'tap'
18
21
  require_relative 'markdown_exec/version'
19
22
 
23
+ include CLI
20
24
  include Tap
25
+
21
26
  tap_config envvar: MarkdownExec::TAP_DEBUG
22
27
 
23
28
  $stderr.sync = true
@@ -25,6 +30,8 @@ $stdout.sync = true
25
30
 
26
31
  BLOCK_SIZE = 1024
27
32
 
33
+ class FileMissingError < StandardError; end
34
+
28
35
  # hash with keys sorted by name
29
36
  #
30
37
  class Hash
@@ -33,26 +40,34 @@ class Hash
33
40
  end
34
41
  end
35
42
 
36
- # is the value a non-empty string or a binary?
43
+ # stdout manager
37
44
  #
38
- # :reek:ManualDispatch ### temp
39
- class Object
40
- def present?
41
- case self.class.to_s
42
- when 'FalseClass', 'TrueClass'
43
- true
44
- else
45
- self && (!respond_to?(:blank?) || !blank?)
46
- end
45
+ module FOUT
46
+ # standard output; not for debug
47
+ #
48
+ def fout(str)
49
+ puts str
47
50
  end
48
- end
49
51
 
50
- # is value empty?
51
- #
52
- class String
53
- BLANK_RE = /\A[[:space:]]*\z/.freeze
54
- def blank?
55
- empty? || BLANK_RE.match?(self)
52
+ def fout_list(str)
53
+ puts str
54
+ end
55
+
56
+ def fout_section(name, data)
57
+ puts "# #{name}"
58
+ puts data.to_yaml
59
+ end
60
+
61
+ def approved_fout?(level)
62
+ level <= @options[:display_level]
63
+ end
64
+
65
+ # display output at level or lower than filter (DISPLAY_LEVEL_DEFAULT)
66
+ #
67
+ def lout(str, level: DISPLAY_LEVEL_BASE)
68
+ return unless approved_fout? level
69
+
70
+ fout level == DISPLAY_LEVEL_BASE ? str : @options[:display_level_xbase_prefix] + str
56
71
  end
57
72
  end
58
73
 
@@ -64,6 +79,29 @@ module MarkdownExec
64
79
  # :reek:IrresponsibleModule
65
80
  class Error < StandardError; end
66
81
 
82
+ # cache lines in text file
83
+ #
84
+ class CFile
85
+ def initialize
86
+ @cache = {}
87
+ end
88
+
89
+ def readlines(filename)
90
+ if @cache[filename]
91
+ @cache[filename].each do |line|
92
+ yield line if block_given?
93
+ end
94
+ else
95
+ lines = []
96
+ File.readlines(filename).each do |line|
97
+ lines.push line
98
+ yield line if block_given?
99
+ end
100
+ @cache[filename] = lines
101
+ end
102
+ end
103
+ end # class CFile
104
+
67
105
  ## an imported markdown document
68
106
  #
69
107
  class MDoc
@@ -74,7 +112,7 @@ module MarkdownExec
74
112
  def collect_recursively_required_code(name)
75
113
  get_required_blocks(name)
76
114
  .map do |block|
77
- block.tap_inspect name: :block, format: :yaml
115
+ block.tap_yaml name: :block
78
116
  body = block[:body].join("\n")
79
117
 
80
118
  if block[:cann]
@@ -106,12 +144,12 @@ module MarkdownExec
106
144
  block[:body]
107
145
  end
108
146
  end.flatten(1)
109
- .tap_inspect format: :yaml
147
+ .tap_yaml
110
148
  end
111
149
 
112
150
  def get_block_by_name(name, default = {})
113
151
  name.tap_inspect name: :name
114
- @table.select { |block| block[:name] == name }.fetch(0, default).tap_inspect format: :yaml
152
+ @table.select { |block| block[:name] == name }.fetch(0, default).tap_yaml
115
153
  end
116
154
 
117
155
  def get_required_blocks(name)
@@ -125,19 +163,19 @@ module MarkdownExec
125
163
 
126
164
  # insert function blocks
127
165
  sel.map do |block|
128
- block.tap_inspect name: :block, format: :yaml
166
+ block.tap_yaml name: :block
129
167
  if (call = block[:call])
130
168
  [get_block_by_name("[#{call.match(/^\((\S+) |\)/)[1]}]").merge({ cann: call })]
131
169
  else
132
170
  []
133
171
  end + [block]
134
- end.flatten(1) # .tap_inspect format: :yaml
172
+ end.flatten(1) # .tap_yaml
135
173
  end
136
174
 
137
175
  # :reek:UtilityFunction
138
176
  def hide_menu_block_per_options(opts, block)
139
177
  (opts[:hide_blocks_by_name] &&
140
- block[:name].match(Regexp.new(opts[:block_name_excluded_match]))).tap_inspect
178
+ block[:name].match(Regexp.new(opts[:block_name_hidden_match]))).tap_inspect
141
179
  end
142
180
 
143
181
  def blocks_for_menu(opts)
@@ -161,7 +199,7 @@ module MarkdownExec
161
199
  .compact
162
200
  .flatten(1)
163
201
  end
164
- all.tap_inspect format: :yaml
202
+ all.tap_yaml
165
203
  end
166
204
  end # class MDoc
167
205
 
@@ -297,9 +335,12 @@ module MarkdownExec
297
335
  class MarkParse
298
336
  attr_reader :options
299
337
 
338
+ include FOUT
339
+
300
340
  def initialize(options = {})
301
341
  @options = options
302
- @prompt = TTY::Prompt.new(interrupt: :exit)
342
+ @prompt = TTY::Prompt.new(interrupt: :exit, symbols: { cross: ' ' })
343
+ # @prompt = TTY::Prompt.new(interrupt: :exit, symbols: { cross: options[:menu_divider_symbol] })
303
344
  @execute_aborted_at = nil
304
345
  @execute_completed_at = nil
305
346
  @execute_error = nil
@@ -309,6 +350,7 @@ module MarkdownExec
309
350
  @execute_script_filespec = nil
310
351
  @execute_started_at = nil
311
352
  @option_parser = nil
353
+ @cfile = CFile.new
312
354
  end
313
355
 
314
356
  ##
@@ -316,7 +358,7 @@ module MarkdownExec
316
358
 
317
359
  def base_options
318
360
  menu_iter do |item|
319
- # noisy item.tap_inspect name: :item, format: :yaml
361
+ # noisy item.tap_yaml name: :item
320
362
  next unless item[:opt_name].present?
321
363
 
322
364
  item_default = item[:default]
@@ -326,13 +368,13 @@ module MarkdownExec
326
368
  else
327
369
  env_str(item[:env_var], default: OptionValue.new(item_default).for_hash)
328
370
  end
329
- [item[:opt_name], item[:proc1] ? item[:proc1].call(value) : value]
371
+ [item[:opt_name], item[:proccode] ? item[:proccode].call(value) : value]
330
372
  end.compact.to_h.merge(
331
373
  {
332
374
  menu_exit_at_top: true,
333
375
  menu_with_exit: true
334
376
  }
335
- ).tap_inspect format: :yaml
377
+ ).tap_yaml
336
378
  end
337
379
 
338
380
  def default_options
@@ -341,10 +383,6 @@ module MarkdownExec
341
383
  exclude_expect_blocks: true,
342
384
  hide_blocks_by_name: true,
343
385
  output_saved_script_filename: false,
344
- prompt_approve_block: 'Process?',
345
- prompt_select_block: 'Choose a block:',
346
- prompt_select_md: 'Choose a file:',
347
- prompt_select_output: 'Choose a file:',
348
386
  saved_script_filename: nil, # calculated
349
387
  struct: true # allow get_block_summary()
350
388
  }
@@ -352,7 +390,7 @@ module MarkdownExec
352
390
 
353
391
  def approve_block(opts, mdoc)
354
392
  required_blocks = mdoc.collect_recursively_required_code(opts[:block_name])
355
- display_command(opts, required_blocks) if opts[:output_script] || opts[:user_must_approve]
393
+ display_required_code(opts, required_blocks) if opts[:output_script] || opts[:user_must_approve]
356
394
 
357
395
  allow = true
358
396
  if opts[:user_must_approve]
@@ -362,10 +400,10 @@ module MarkdownExec
362
400
  # menu.enum '.'
363
401
  # menu.filter true
364
402
 
365
- menu.choice 'Yes', 1
366
- menu.choice 'No', 2
367
- menu.choice 'Copy script to clipboard', 3
368
- menu.choice 'Save script', 4
403
+ menu.choice opts[:prompt_yes], 1
404
+ menu.choice opts[:prompt_no], 2
405
+ menu.choice opts[:prompt_script_to_clipboard], 3
406
+ menu.choice opts[:prompt_save_script], 4
369
407
  end).tap_inspect name: :sel
370
408
  allow = (sel == 1)
371
409
  if sel == 3
@@ -397,15 +435,22 @@ module MarkdownExec
397
435
  selected[:name]
398
436
  end
399
437
 
438
+ # def cc(str)
439
+ # puts " - - - #{Process.clock_gettime(Process::CLOCK_MONOTONIC)} - #{str}"
440
+ # end
441
+
400
442
  # :reek:DuplicateMethodCall
401
443
  # :reek:UncommunicativeVariableName { exclude: [ e ] }
402
444
  # :reek:LongYieldList
403
445
  def command_execute(opts, command)
446
+ # dd = lambda { |s| puts 'command_execute() ' + s }
447
+ #d 'execute command and yield outputs'
404
448
  @execute_files = Hash.new([])
405
449
  @execute_options = opts
406
450
  @execute_started_at = Time.now.utc
407
451
 
408
452
  Open3.popen3(@options[:shell], '-c', command) do |stdin, stdout, stderr, exec_thr|
453
+ #d 'command started'
409
454
  Thread.new do
410
455
  until (line = stdout.gets).nil?
411
456
  @execute_files[EF_STDOUT] = @execute_files[EF_STDOUT] + [line]
@@ -413,7 +458,7 @@ module MarkdownExec
413
458
  yield nil, line, nil, exec_thr if block_given?
414
459
  end
415
460
  rescue IOError
416
- # thread killed, do nothing
461
+ #d 'stdout IOError, thread killed, do nothing'
417
462
  end
418
463
 
419
464
  Thread.new do
@@ -423,7 +468,7 @@ module MarkdownExec
423
468
  yield nil, nil, line, exec_thr if block_given?
424
469
  end
425
470
  rescue IOError
426
- # thread killed, do nothing
471
+ #d 'stderr IOError, thread killed, do nothing'
427
472
  end
428
473
 
429
474
  in_thr = Thread.new do
@@ -432,22 +477,33 @@ module MarkdownExec
432
477
  @execute_files[EF_STDIN] = @execute_files[EF_STDIN] + [line]
433
478
  yield line, nil, nil, exec_thr if block_given?
434
479
  end
480
+ #d 'exec_thr now dead'
481
+ rescue StandardError
482
+ #d 'stdin error, thread killed, do nothing'
435
483
  end
436
484
 
485
+ #d 'join exec_thr'
437
486
  exec_thr.join
487
+
488
+ #d 'wait before closing stdin'
489
+ sleep 0.1
490
+
491
+ #d 'kill stdin thread'
438
492
  in_thr.kill
439
493
  # @return_code = exec_thr.value
494
+ #d 'command end'
440
495
  end
496
+ #d 'command completed'
441
497
  @execute_completed_at = Time.now.utc
442
498
  rescue Errno::ENOENT => e
443
- # error triggered by missing command in script
499
+ #d 'command error ENOENT triggered by missing command in script'
444
500
  @execute_aborted_at = Time.now.utc
445
501
  @execute_error_message = e.message
446
502
  @execute_error = e
447
503
  @execute_files[EF_STDERR] += [@execute_error_message]
448
504
  fout "Error ENOENT: #{e.inspect}"
449
505
  rescue SignalException => e
450
- # SIGTERM triggered by user or system
506
+ #d 'command SIGTERM triggered by user or system'
451
507
  @execute_aborted_at = Time.now.utc
452
508
  @execute_error_message = 'SIGTERM'
453
509
  @execute_error = e
@@ -458,15 +514,15 @@ module MarkdownExec
458
514
  def count_blocks_in_filename
459
515
  fenced_start_and_end_match = Regexp.new @options[:fenced_start_and_end_match]
460
516
  cnt = 0
461
- File.readlines(@options[:filename]).each do |line|
517
+ @cfile.readlines(@options[:filename]).each do |line|
462
518
  cnt += 1 if line.match(fenced_start_and_end_match)
463
519
  end
464
520
  cnt / 2
465
521
  end
466
522
 
467
523
  # :reek:DuplicateMethodCall
468
- def display_command(_opts, required_blocks)
469
- frame = ' #=#=#'.yellow
524
+ def display_required_code(opts, required_blocks)
525
+ frame = opts[:output_divider].send(opts[:output_divider_color].to_sym)
470
526
  fout frame
471
527
  required_blocks.each { |cb| fout cb }
472
528
  fout frame
@@ -523,21 +579,6 @@ module MarkdownExec
523
579
  fout "saved_filespec: #{@execute_script_filespec}" if @options[:output_saved_script_filename]
524
580
  end
525
581
 
526
- # standard output; not for debug
527
- #
528
- def fout(str)
529
- puts str
530
- end
531
-
532
- def fout_list(str)
533
- puts str
534
- end
535
-
536
- def fout_section(name, data)
537
- puts "# #{name}"
538
- puts data.to_yaml
539
- end
540
-
541
582
  # :reek:LongParameterList
542
583
  def get_block_summary(call_options = {}, headings:, block_title:, block_body:)
543
584
  opts = optsmerge call_options
@@ -561,19 +602,7 @@ module MarkdownExec
561
602
  call: call,
562
603
  reqs: reqs,
563
604
  stdin: stdin,
564
- stdout: stdout })].tap_inspect format: :yaml
565
- end
566
-
567
- def approved_fout?(level)
568
- level <= @options[:display_level]
569
- end
570
-
571
- # display output at level or lower than filter (DISPLAY_LEVEL_DEFAULT)
572
- #
573
- def lout(str, level: DISPLAY_LEVEL_BASE)
574
- return unless approved_fout? level
575
-
576
- fout level == DISPLAY_LEVEL_BASE ? str : @options[:display_level_xbase_prefix] + str
605
+ stdout: stdout })].tap_yaml
577
606
  end
578
607
 
579
608
  # :reek:DuplicateMethodCall
@@ -600,7 +629,7 @@ module MarkdownExec
600
629
 
601
630
  selected_messages = yield :filter
602
631
 
603
- File.readlines(opts[:filename]).each do |line|
632
+ @cfile.readlines(opts[:filename]).each do |line|
604
633
  continue unless line
605
634
 
606
635
  if opts[:menu_blocks_with_headings]
@@ -656,19 +685,32 @@ module MarkdownExec
656
685
  opts = optsmerge call_options, options_block
657
686
 
658
687
  blocks = []
688
+ if opts[:menu_initial_divider].present?
689
+ blocks += [{
690
+ name: format(opts[:menu_divider_format],
691
+ opts[:menu_initial_divider]).send(opts[:menu_divider_color].to_sym), disabled: ''
692
+ }]
693
+ end
659
694
  iter_blocks_in_file(opts) do |btype, headings, block_title, body|
660
695
  case btype
661
696
  when :filter
662
697
  %i[blocks line]
663
698
  when :line
664
699
  if opts[:menu_divider_match] && (mbody = body.match opts[:menu_divider_match])
665
- blocks += [{ name: (opts[:menu_divider_format] % mbody[:name]), disabled: '' }]
700
+ blocks += [{ name: format(opts[:menu_divider_format], mbody[:name]).send(opts[:menu_divider_color].to_sym),
701
+ disabled: '' }]
666
702
  end
667
703
  when :blocks
668
704
  blocks += get_block_summary opts, headings: headings, block_title: block_title, block_body: body
669
705
  end
670
706
  end
671
- blocks.tap_inspect format: :yaml
707
+ if opts[:menu_divider_format].present? && opts[:menu_final_divider].present?
708
+ blocks += [{
709
+ name: format(opts[:menu_divider_format],
710
+ opts[:menu_final_divider]).send(opts[:menu_divider_color].to_sym), disabled: ''
711
+ }]
712
+ end
713
+ blocks.tap_yaml
672
714
  end
673
715
 
674
716
  def list_default_env
@@ -706,22 +748,30 @@ module MarkdownExec
706
748
  def list_files_specified(specified_filename: nil, specified_folder: nil,
707
749
  default_filename: nil, default_folder: nil, filetree: nil)
708
750
  fn = File.join(if specified_filename&.present?
709
- if specified_folder&.present?
710
- [specified_folder, specified_filename]
711
- elsif specified_filename.start_with? '/'
751
+ # puts ' LFS 01'
752
+ if specified_filename.start_with? '/'
753
+ # puts ' LFS 02'
712
754
  [specified_filename]
755
+ elsif specified_folder&.present?
756
+ # puts ' LFS 03'
757
+ [specified_folder, specified_filename]
713
758
  else
759
+ # puts ' LFS 04'
714
760
  [default_folder, specified_filename]
715
761
  end
716
762
  elsif specified_folder&.present?
763
+ # puts ' LFS 05'
717
764
  if filetree
765
+ # puts ' LFS 06'
718
766
  [specified_folder, @options[:md_filename_match]]
719
767
  else
768
+ # puts ' LFS 07'
720
769
  [specified_folder, @options[:md_filename_glob]]
721
770
  end
722
771
  else
772
+ # puts ' LFS 08'
723
773
  [default_folder, default_filename]
724
- end)
774
+ end).tap_inspect name: :fn
725
775
  if filetree
726
776
  filetree.select { |filename| filename == fn || filename.match(/^#{fn}$/) || filename.match(%r{^#{fn}/.+$}) }
727
777
  else
@@ -738,11 +788,9 @@ module MarkdownExec
738
788
  blocks_in_file = list_blocks_in_file(opts.merge(struct: true))
739
789
  mdoc = MDoc.new(blocks_in_file)
740
790
 
741
- list_blocks_in_file(opts).map do |block|
742
- next if mdoc.hide_menu_block_per_options(opts, block)
743
-
744
- block
745
- end.compact.tap_inspect
791
+ list_blocks_in_file(opts).reject do |block|
792
+ mdoc.hide_menu_block_per_options(opts, block)
793
+ end.tap_inspect
746
794
  end
747
795
 
748
796
  def list_recent_output(saved_stdout_folder, saved_stdout_glob, list_count)
@@ -771,43 +819,43 @@ module MarkdownExec
771
819
  menu_item.merge(
772
820
  {
773
821
  opt_name: menu_item[:opt_name]&.to_sym,
774
- proc1: case menu_item[:proc1]
775
- when 'debug'
776
- lambda { |value|
777
- tap_config value: value
778
- }
779
- when 'exit'
780
- lambda { |_|
781
- exit
782
- }
783
- when 'help'
784
- lambda { |_|
785
- fout menu_help
786
- exit
787
- }
788
- when 'path'
789
- lambda { |value|
790
- read_configuration_file! options, value
791
- }
792
- when 'show_config'
793
- lambda { |_|
794
- options_finalize options
795
- fout options.sort_by_key.to_yaml
796
- }
797
- when 'val_as_bool'
798
- ->(value) { value.class.to_s == 'String' ? (value.chomp != '0') : value }
799
- when 'val_as_int'
800
- ->(value) { value.to_i }
801
- when 'val_as_str'
802
- ->(value) { value.to_s }
803
- when 'version'
804
- lambda { |_|
805
- fout MarkdownExec::VERSION
806
- exit
807
- }
808
- else
809
- menu_item[:proc1]
810
- end
822
+ proccode: case menu_item[:procname]
823
+ when 'debug'
824
+ lambda { |value|
825
+ tap_config value: value
826
+ }
827
+ when 'exit'
828
+ lambda { |_|
829
+ exit
830
+ }
831
+ when 'help'
832
+ lambda { |_|
833
+ fout menu_help
834
+ exit
835
+ }
836
+ when 'path'
837
+ lambda { |value|
838
+ read_configuration_file! options, value
839
+ }
840
+ when 'show_config'
841
+ lambda { |_|
842
+ options_finalize options
843
+ fout options.sort_by_key.to_yaml
844
+ }
845
+ when 'val_as_bool'
846
+ ->(value) { value.class.to_s == 'String' ? (value.chomp != '0') : value }
847
+ when 'val_as_int'
848
+ ->(value) { value.to_i }
849
+ when 'val_as_str'
850
+ ->(value) { value.to_s }
851
+ when 'version'
852
+ lambda { |_|
853
+ fout MarkdownExec::VERSION
854
+ exit
855
+ }
856
+ else
857
+ menu_item[:procname]
858
+ end
811
859
  }
812
860
  )
813
861
  end
@@ -829,7 +877,7 @@ module MarkdownExec
829
877
  menu += [summ[0][:name]]
830
878
  end
831
879
  end
832
- menu.tap_inspect format: :yaml
880
+ menu.tap_yaml
833
881
  end
834
882
 
835
883
  def menu_iter(data = menu_for_optparse, &block)
@@ -840,6 +888,33 @@ module MarkdownExec
840
888
  @option_parser.help
841
889
  end
842
890
 
891
+ def menu_option_append(opts, options, item)
892
+ return unless item[:long_name].present? || item[:short_name].present?
893
+
894
+ opts.on(*[
895
+ # long name
896
+ if item[:long_name].present?
897
+ "--#{item[:long_name]}#{item[:arg_name].present? ? " #{item[:arg_name]}" : ''}"
898
+ end,
899
+
900
+ # short name
901
+ item[:short_name].present? ? "-#{item[:short_name]}" : nil,
902
+
903
+ # description and default
904
+ [item[:description],
905
+ item[:default].present? ? "[#{value_for_cli item[:default]}]" : nil].compact.join(' '),
906
+
907
+ # apply proccode, if present, to value
908
+ # save value to options hash if option is named
909
+ #
910
+ lambda { |value|
911
+ (item[:proccode] ? item[:proccode].call(value) : value).tap do |converted|
912
+ options[item[:opt_name]] = converted if item[:opt_name]
913
+ end
914
+ }
915
+ ].compact)
916
+ end
917
+
843
918
  ## post-parse options configuration
844
919
  #
845
920
  def options_finalize(rest)
@@ -851,7 +926,7 @@ module MarkdownExec
851
926
  elsif File.exist?(pos)
852
927
  @options[:filename] = pos
853
928
  else
854
- raise "Invalid parameter: #{pos}"
929
+ raise FileMissingError, pos, caller
855
930
  end
856
931
  end
857
932
 
@@ -942,29 +1017,20 @@ module MarkdownExec
942
1017
  ].join("\n")
943
1018
 
944
1019
  menu_iter do |item|
945
- next unless item[:long_name].present? || item[:short_name].present?
946
-
947
- opts.on(*[if item[:long_name].present?
948
- "--#{item[:long_name]}#{item[:arg_name].present? ? " #{item[:arg_name]}" : ''}"
949
- end,
950
- item[:short_name].present? ? "-#{item[:short_name]}" : nil,
951
- [item[:description],
952
- item[:default].present? ? "[#{value_for_cli item[:default]}]" : nil].compact.join(' '),
953
- lambda { |value|
954
- # ret = item[:proc1].call(value)
955
- ret = item[:proc1] ? item[:proc1].call(value) : value
956
- options[item[:opt_name]] = ret if item[:opt_name]
957
- ret
958
- }].compact)
1020
+ item.tap_yaml 'item'
1021
+ menu_option_append opts, options, item
959
1022
  end
960
1023
  end
961
1024
  option_parser.load # filename defaults to basename of the program without suffix in a directory ~/.options
962
1025
  option_parser.environment # env defaults to the basename of the program.
963
1026
  rest = option_parser.parse! # (into: options)
964
1027
 
965
- options_finalize rest
966
-
967
- exec_block options, options[:block_name]
1028
+ begin
1029
+ options_finalize rest
1030
+ exec_block options, options[:block_name]
1031
+ rescue FileMissingError => e
1032
+ puts "File missing: #{e}"
1033
+ end
968
1034
  end
969
1035
 
970
1036
  def saved_name_split(name)
@@ -998,7 +1064,7 @@ module MarkdownExec
998
1064
  @options[:logged_stdout_filespec] = File.join @options[:saved_stdout_folder], @options[:logged_stdout_filename]
999
1065
  @logged_stdout_filespec = @options[:logged_stdout_filespec]
1000
1066
  (dirname = File.dirname(@options[:logged_stdout_filespec])).tap_inspect name: :dirname
1001
- Dir.mkdir dirname unless File.exist?(dirname)
1067
+ Dir.mkdir_p dirname
1002
1068
 
1003
1069
  ol = ["-STDOUT-\n"]
1004
1070
  ol += @execute_files&.fetch(EF_STDOUT, [])
@@ -1013,7 +1079,7 @@ module MarkdownExec
1013
1079
  def select_and_approve_block(call_options = {}, &options_block)
1014
1080
  opts = optsmerge call_options, options_block
1015
1081
  blocks_in_file = list_blocks_in_file(opts.merge(struct: true)).tap_inspect name: :blocks_in_file
1016
- mdoc = MDoc.new(blocks_in_file) { |nopts| opts.merge!(nopts).tap_inspect name: :infiled_opts, format: :yaml }
1082
+ mdoc = MDoc.new(blocks_in_file) { |nopts| opts.merge!(nopts).tap_yaml name: :infiled_opts }
1017
1083
  blocks_menu = mdoc.blocks_for_menu(opts.merge(struct: true)).tap_inspect name: :blocks_menu
1018
1084
 
1019
1085
  repeat_menu = true && !opts[:block_name].present?
@@ -1097,7 +1163,7 @@ module MarkdownExec
1097
1163
 
1098
1164
  def menu_export(data = menu_for_optparse)
1099
1165
  data.map do |item|
1100
- item.delete(:proc1)
1166
+ item.delete(:procname)
1101
1167
  item
1102
1168
  end.to_yaml
1103
1169
  end
@@ -1116,7 +1182,7 @@ module MarkdownExec
1116
1182
  else
1117
1183
  @options.merge! opts
1118
1184
  end
1119
- @options.tap_inspect format: :yaml
1185
+ @options.tap_yaml
1120
1186
  end
1121
1187
 
1122
1188
  def write_command_file(call_options, required_blocks)
@@ -1135,7 +1201,7 @@ module MarkdownExec
1135
1201
  File.join opts[:saved_script_folder], opts[:saved_script_filename]
1136
1202
 
1137
1203
  dirname = File.dirname(@options[:saved_filespec])
1138
- Dir.mkdir dirname unless File.exist?(dirname)
1204
+ Dir.mkdir_p dirname
1139
1205
  (shebang = if @options[:shebang]&.present?
1140
1206
  "#{@options[:shebang]} #{@options[:shell]}\n"
1141
1207
  else