markdown_exec 1.3.0 → 1.3.2

Sign up to get free protection for your applications and to get access to all the features.
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