markdown_exec 1.8.7 → 1.8.8

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.
@@ -1,6 +1,8 @@
1
- # encoding=utf-8
1
+ #!/usr/bin/env bundle exec ruby
2
2
  # frozen_string_literal: true
3
3
 
4
+ # encoding=utf-8
5
+
4
6
  require 'English'
5
7
  require 'clipboard'
6
8
  require 'fileutils'
@@ -142,9 +144,9 @@ module HashDelegatorSelf
142
144
  # HashDelegator.remove_file_without_standard_errors(temp_blocks_file_path)
143
145
  # end
144
146
 
145
- def error_handler(name = '', opts = {})
147
+ def error_handler(name = '', opts = {}, error: $!)
146
148
  Exceptions.error_handler(
147
- "HashDelegator.#{name} -- #{$!}",
149
+ "HashDelegator.#{name} -- #{error}",
148
150
  opts
149
151
  )
150
152
  end
@@ -555,6 +557,22 @@ module MarkdownExec
555
557
 
556
558
  # private
557
559
 
560
+ def calc_logged_stdout_filename
561
+ return unless @delegate_object[:saved_stdout_folder]
562
+
563
+ @delegate_object[:logged_stdout_filename] =
564
+ SavedAsset.stdout_name(blockname: @delegate_object[:block_name],
565
+ filename: File.basename(@delegate_object[:filename],
566
+ '.*'),
567
+ prefix: @delegate_object[:logged_stdout_filename_prefix],
568
+ time: Time.now.utc)
569
+
570
+ @logged_stdout_filespec =
571
+ @delegate_object[:logged_stdout_filespec] =
572
+ File.join @delegate_object[:saved_stdout_folder],
573
+ @delegate_object[:logged_stdout_filename]
574
+ end
575
+
558
576
  def cfile
559
577
  @cfile ||= CachedNestedFileReader.new(
560
578
  import_pattern: @delegate_object.fetch(:import_pattern) #, "^ *@import +(?<name>.+?) *$")
@@ -585,7 +603,7 @@ module MarkdownExec
585
603
  set_environment_variables_for_block(selected) if selected[:shell] == BlockType::VARS
586
604
 
587
605
  required = mdoc.collect_recursively_required_code(
588
- @delegate_object[:block_name],
606
+ selected[:nickname] || selected[:oname],
589
607
  label_format_above: @delegate_object[:shell_code_label_format_above],
590
608
  label_format_below: @delegate_object[:shell_code_label_format_below],
591
609
  block_source: block_source
@@ -599,7 +617,8 @@ module MarkdownExec
599
617
  warn format_and_highlight_dependencies(dependencies,
600
618
  highlight: required[:unmet_dependencies])
601
619
  runtime_exception(:runtime_exception_error_level,
602
- 'unmet_dependencies, flag: runtime_exception_error_level', required[:unmet_dependencies])
620
+ 'unmet_dependencies, flag: runtime_exception_error_level',
621
+ required[:unmet_dependencies])
603
622
  elsif true
604
623
  warn format_and_highlight_dependencies(dependencies,
605
624
  highlight: [@delegate_object[:block_name]])
@@ -613,26 +632,54 @@ module MarkdownExec
613
632
  @run_state.options = @delegate_object
614
633
  @run_state.started_at = Time.now.utc
615
634
 
616
- Open3.popen3(@delegate_object[:shell],
617
- '-c', command,
618
- @delegate_object[:filename],
619
- *args) do |stdin, stdout, stderr, exec_thr|
620
- handle_stream(stdout, ExecutionStreams::StdOut) do |line|
621
- yield nil, line, nil, exec_thr if block_given?
622
- end
623
- handle_stream(stderr, ExecutionStreams::StdErr) do |line|
624
- yield nil, nil, line, exec_thr if block_given?
625
- end
635
+ if @delegate_object[:execute_in_own_window] &&
636
+ @delegate_object[:execute_command_format].present? &&
637
+ @run_state.saved_filespec.present?
638
+ @run_state.in_own_window = true
639
+ system(
640
+ format(
641
+ @delegate_object[:execute_command_format],
642
+ {
643
+ batch_index: @run_state.batch_index,
644
+ batch_random: @run_state.batch_random,
645
+ block_name: @delegate_object[:block_name],
646
+ document_filename: File.basename(@delegate_object[:filename]),
647
+ document_filespec: @delegate_object[:filename],
648
+ home: Dir.pwd,
649
+ output_filename: File.basename(@delegate_object[:logged_stdout_filespec]),
650
+ output_filespec: @delegate_object[:logged_stdout_filespec],
651
+ script_filename: @run_state.saved_filespec,
652
+ script_filespec: File.join(Dir.pwd, @run_state.saved_filespec),
653
+ started_at: @run_state.started_at.strftime(
654
+ @delegate_object[:execute_command_title_time_format]
655
+ )
656
+ }
657
+ )
658
+ )
626
659
 
627
- in_thr = handle_stream($stdin, ExecutionStreams::StdIn) do |line|
628
- stdin.puts(line)
629
- yield line, nil, nil, exec_thr if block_given?
630
- end
660
+ else
661
+ @run_state.in_own_window = false
662
+ Open3.popen3(@delegate_object[:shell],
663
+ '-c', command,
664
+ @delegate_object[:filename],
665
+ *args) do |stdin, stdout, stderr, exec_thr|
666
+ handle_stream(stdout, ExecutionStreams::StdOut) do |line|
667
+ yield nil, line, nil, exec_thr if block_given?
668
+ end
669
+ handle_stream(stderr, ExecutionStreams::StdErr) do |line|
670
+ yield nil, nil, line, exec_thr if block_given?
671
+ end
672
+
673
+ in_thr = handle_stream($stdin, ExecutionStreams::StdIn) do |line|
674
+ stdin.puts(line)
675
+ yield line, nil, nil, exec_thr if block_given?
676
+ end
631
677
 
632
- wait_for_stream_processing
633
- exec_thr.join
634
- sleep 0.1
635
- in_thr.kill if in_thr&.alive?
678
+ wait_for_stream_processing
679
+ exec_thr.join
680
+ sleep 0.1
681
+ in_thr.kill if in_thr&.alive?
682
+ end
636
683
  end
637
684
 
638
685
  @run_state.completed_at = Time.now.utc
@@ -681,9 +728,13 @@ module MarkdownExec
681
728
  block_source: block_source)
682
729
  output_or_approval = @delegate_object[:output_script] || @delegate_object[:user_must_approve]
683
730
  display_required_code(required_lines) if output_or_approval
684
- allow_execution = @delegate_object[:user_must_approve] ? prompt_for_user_approval(required_lines) : true
731
+ allow_execution = if @delegate_object[:user_must_approve]
732
+ prompt_for_user_approval(required_lines, selected)
733
+ else
734
+ true
735
+ end
685
736
 
686
- execute_required_lines(required_lines) if allow_execution
737
+ execute_required_lines(required_lines, selected) if allow_execution
687
738
 
688
739
  link_state.block_name = nil
689
740
  LoadFileLinkState.new(LoadFile::Reuse, link_state)
@@ -704,7 +755,8 @@ module MarkdownExec
704
755
  # @return [Integer] The count of fenced code blocks in the file.
705
756
  def count_blocks_in_filename
706
757
  regex = Regexp.new(@delegate_object[:fenced_start_and_end_regex])
707
- lines = cfile.readlines(@delegate_object[:filename])
758
+ lines = cfile.readlines(@delegate_object[:filename],
759
+ import_paths: @delegate_object[:import_paths]&.split(':'))
708
760
  HashDelegator.count_matches_in_lines(lines, regex) / 2
709
761
  end
710
762
 
@@ -734,14 +786,14 @@ module MarkdownExec
734
786
  # @param use_chrome [Boolean] Indicates if the chrome styling should be applied.
735
787
  def create_and_add_chrome_blocks(blocks, fcb)
736
788
  match_criteria = [
737
- { match: :heading1_match, format: :menu_heading1_format, color: :menu_heading1_color },
738
- { match: :heading2_match, format: :menu_heading2_format, color: :menu_heading2_color },
739
- { match: :heading3_match, format: :menu_heading3_format, color: :menu_heading3_color },
740
- { match: :menu_divider_match, format: :menu_divider_format,
741
- color: :menu_divider_color },
742
- { match: :menu_note_match, format: :menu_note_format, color: :menu_note_color },
743
- { match: :menu_task_match, format: :menu_task_format, color: :menu_task_color }
789
+ { color: :menu_heading1_color, format: :menu_heading1_format, match: :heading1_match },
790
+ { color: :menu_heading2_color, format: :menu_heading2_format, match: :heading2_match },
791
+ { color: :menu_heading3_color, format: :menu_heading3_format, match: :heading3_match },
792
+ { color: :menu_divider_color, format: :menu_divider_format, match: :menu_divider_match },
793
+ { color: :menu_note_color, format: :menu_note_format, match: :menu_note_match },
794
+ { color: :menu_task_color, format: :menu_task_format, match: :menu_task_match }
744
795
  ]
796
+ # rubocop:enable Style/UnlessElse
745
797
  match_criteria.each do |criteria|
746
798
  unless @delegate_object[criteria[:match]].present? &&
747
799
  (mbody = fcb.body[0].match @delegate_object[criteria[:match]])
@@ -767,6 +819,29 @@ module MarkdownExec
767
819
  )
768
820
  end
769
821
 
822
+ # Prompts user if named block is the same as the prior execution.
823
+ #
824
+ # @return [Boolean] Execute the named block.
825
+ def debounce_allows
826
+ return true unless @delegate_object[:debounce_execution]
827
+
828
+ # filter block if selected in menu
829
+ return true if @run_state.block_name_from_cli
830
+
831
+ # return false if @prior_execution_block == @delegate_object[:block_name]
832
+ if @prior_execution_block == @delegate_object[:block_name]
833
+ return @allowed_execution_block == @prior_execution_block || prompt_approve_repeat
834
+ end
835
+
836
+ @prior_execution_block = @delegate_object[:block_name]
837
+ @allowed_execution_block = nil
838
+ true
839
+ end
840
+
841
+ def debounce_reset
842
+ @prior_execution_block = nil
843
+ end
844
+
770
845
  # Determines the state of a selected block in the menu based on the selected option.
771
846
  # It categorizes the selected option into either EXIT, BACK, or CONTINUE state.
772
847
  #
@@ -803,15 +878,23 @@ module MarkdownExec
803
878
  @delegate_object[:menu_divider_format].present? && @delegate_object[divider_key].present?
804
879
  end
805
880
 
881
+ def do_save_execution_output
882
+ return unless @delegate_object[:save_execution_output]
883
+ return if @run_state.in_own_window
884
+
885
+ HashDelegator.write_execution_output_to_file(@run_state.files,
886
+ @delegate_object[:logged_stdout_filespec])
887
+ end
888
+
806
889
  # Executes a block of code that has been approved for execution.
807
890
  # It sets the script block name, writes command files if required, and handles the execution
808
891
  # including output formatting and summarization.
809
892
  #
810
893
  # @param required_lines [Array<String>] The lines of code to be executed.
811
894
  # @param selected [FCB] The selected functional code block object.
812
- def execute_required_lines(required_lines = [])
813
- # @run_state.script_block_name = selected[:oname]
814
- write_command_file(required_lines) if @delegate_object[:save_executed_script]
895
+ def execute_required_lines(required_lines = [], selected = FCB.new)
896
+ write_command_file(required_lines, selected) if @delegate_object[:save_executed_script]
897
+ calc_logged_stdout_filename
815
898
  format_and_execute_command(required_lines)
816
899
  post_execution_process
817
900
  end
@@ -828,21 +911,26 @@ module MarkdownExec
828
911
  def execute_shell_type(selected, mdoc, link_state = LinkState.new,
829
912
  block_source:)
830
913
  if selected.fetch(:shell, '') == BlockType::LINK
914
+ debounce_reset
831
915
  push_link_history_and_trigger_load(selected.fetch(:body, ''), mdoc, selected,
832
916
  link_state)
833
917
 
834
918
  elsif @menu_user_clicked_back_link
919
+ debounce_reset
835
920
  pop_link_history_and_trigger_load
836
921
 
837
922
  elsif selected[:shell] == BlockType::OPTS
923
+ debounce_reset
838
924
  options_state = read_show_options_and_trigger_reuse(selected, link_state)
839
925
  @menu_base_options.merge!(options_state.options)
840
926
  @delegate_object.merge!(options_state.options)
841
927
  options_state.load_file_link_state
842
928
 
843
- else
929
+ elsif debounce_allows
844
930
  compile_execute_and_trigger_reuse(mdoc, selected, link_state,
845
931
  block_source: block_source)
932
+ else
933
+ LoadFileLinkState.new(LoadFile::Reuse, link_state)
846
934
  end
847
935
  end
848
936
 
@@ -904,12 +992,31 @@ module MarkdownExec
904
992
  @delegate_object[:block_stdout_scan])
905
993
 
906
994
  shell_color_option = SHELL_COLOR_OPTIONS[fcb[:shell]]
907
- fcb.title = fcb.oname = bm && bm[1] ? bm[:title] : titlexcall
908
- fcb.dname = apply_shell_color_option(fcb.oname, shell_color_option)
909
995
 
996
+ if @delegate_object[:block_name_nick_match].present? && fcb.oname =~ Regexp.new(@delegate_object[:block_name_nick_match])
997
+ fcb.nickname = $~[0]
998
+ fcb.title = fcb.oname = format_multiline_body_as_title(fcb.body)
999
+ else
1000
+ fcb.title = fcb.oname = bm && bm[1] ? bm[:title] : titlexcall
1001
+ end
1002
+
1003
+ fcb.dname = HashDelegator.indent_all_lines(
1004
+ apply_shell_color_option(fcb.oname, shell_color_option),
1005
+ fcb.fetch(:indent, nil)
1006
+ )
910
1007
  fcb
911
1008
  end
912
1009
 
1010
+ # Formats multiline body content as a title string.
1011
+ # indents all but first line with two spaces so it displays correctly in menu
1012
+ # @param body_lines [Array<String>] The lines of body content.
1013
+ # @return [String] Formatted title.
1014
+ def format_multiline_body_as_title(body_lines)
1015
+ body_lines.map.with_index do |line, index|
1016
+ index.zero? ? line : " #{line}"
1017
+ end.join("\n") + "\n"
1018
+ end
1019
+
913
1020
  # Updates the delegate object's state based on the provided block state.
914
1021
  # It sets the block name and determines if the user clicked the back link in the menu.
915
1022
  #
@@ -962,25 +1069,6 @@ module MarkdownExec
962
1069
  }
963
1070
  end
964
1071
 
965
- def initialize_and_save_execution_output
966
- return unless @delegate_object[:save_execution_output]
967
-
968
- @delegate_object[:logged_stdout_filename] =
969
- SavedAsset.stdout_name(blockname: @delegate_object[:block_name],
970
- filename: File.basename(@delegate_object[:filename],
971
- '.*'),
972
- prefix: @delegate_object[:logged_stdout_filename_prefix],
973
- time: Time.now.utc)
974
-
975
- @logged_stdout_filespec =
976
- @delegate_object[:logged_stdout_filespec] =
977
- File.join @delegate_object[:saved_stdout_folder],
978
- @delegate_object[:logged_stdout_filename]
979
- @logged_stdout_filespec = @delegate_object[:logged_stdout_filespec]
980
- HashDelegator.write_execution_output_to_file(@run_state.files,
981
- @delegate_object[:logged_stdout_filespec])
982
- end
983
-
984
1072
  # Iterates through blocks in a file, applying the provided block to each line.
985
1073
  # The iteration only occurs if the file exists.
986
1074
  # @yield [Symbol] :filter Yields to obtain selected messages for processing.
@@ -989,8 +1077,8 @@ module MarkdownExec
989
1077
 
990
1078
  state = initial_state
991
1079
  selected_messages = yield :filter
992
-
993
- cfile.readlines(@delegate_object[:filename]).each do |nested_line|
1080
+ cfile.readlines(@delegate_object[:filename],
1081
+ import_paths: @delegate_object[:import_paths]&.split(':')).each do |nested_line|
994
1082
  if nested_line
995
1083
  update_line_and_block_state(nested_line, state, selected_messages,
996
1084
  &block)
@@ -998,6 +1086,65 @@ module MarkdownExec
998
1086
  end
999
1087
  end
1000
1088
 
1089
+ def link_block_data_eval(link_state, code_lines, selected, link_block_data)
1090
+ all_code = HashDelegator.code_merge(link_state&.inherited_lines, code_lines)
1091
+
1092
+ if link_block_data.fetch(LinkDataKeys::Exec, false)
1093
+ @run_state.files = Hash.new([])
1094
+ output_lines = []
1095
+
1096
+ Open3.popen3(
1097
+ @delegate_object[:shell],
1098
+ '-c', all_code.join("\n")
1099
+ ) do |stdin, stdout, stderr, _exec_thr|
1100
+ handle_stream(stdout, ExecutionStreams::StdOut) do |line|
1101
+ output_lines.push(line)
1102
+ end
1103
+ handle_stream(stderr, ExecutionStreams::StdErr) do |line|
1104
+ output_lines.push(line)
1105
+ end
1106
+
1107
+ in_thr = handle_stream($stdin, ExecutionStreams::StdIn) do |line|
1108
+ stdin.puts(line)
1109
+ end
1110
+
1111
+ wait_for_stream_processing
1112
+ sleep 0.1
1113
+ in_thr.kill if in_thr&.alive?
1114
+ end
1115
+
1116
+ ## select output_lines that look like assignment or match other specs
1117
+ #
1118
+ output_lines = process_string_array(
1119
+ output_lines,
1120
+ begin_pattern: @delegate_object.fetch(:output_assignment_begin, nil),
1121
+ end_pattern: @delegate_object.fetch(:output_assignment_end, nil),
1122
+ scan1: @delegate_object.fetch(:output_assignment_match, nil),
1123
+ format1: @delegate_object.fetch(:output_assignment_format, nil)
1124
+ )
1125
+
1126
+ else
1127
+ output_lines = `#{all_code.join("\n")}`.split("\n")
1128
+ end
1129
+
1130
+ unless output_lines
1131
+ HashDelegator.error_handler('all_code eval output_lines is nil', { abort: true })
1132
+ end
1133
+
1134
+ label_format_above = @delegate_object[:shell_code_label_format_above]
1135
+ label_format_below = @delegate_object[:shell_code_label_format_below]
1136
+ block_source = { document_filename: link_state&.document_filename }
1137
+
1138
+ [label_format_above && format(label_format_above,
1139
+ block_source.merge({ block_name: selected[:oname] }))] +
1140
+ output_lines.map do |line|
1141
+ re = Regexp.new(link_block_data.fetch('pattern', '(?<line>.*)'))
1142
+ re.gsub_format(line, link_block_data.fetch('format', '%{line}')) if re =~ line
1143
+ end.compact +
1144
+ [label_format_below && format(label_format_below,
1145
+ block_source.merge({ block_name: selected[:oname] }))]
1146
+ end
1147
+
1001
1148
  def link_history_push_and_next(
1002
1149
  curr_block_name:, curr_document_filename:,
1003
1150
  inherited_block_names:, inherited_dependencies:, inherited_lines:,
@@ -1165,23 +1312,38 @@ module MarkdownExec
1165
1312
  ), level: level
1166
1313
  end
1167
1314
 
1168
- def pop_add_current_code_to_head_and_trigger_load(_link_state, block_names, code_lines,
1169
- dependencies)
1315
+ def pop_add_current_code_to_head_and_trigger_load(link_state, block_names, code_lines,
1316
+ dependencies, selected)
1170
1317
  pop = @link_history.pop # updatable
1171
- next_state = LinkState.new(
1172
- block_name: pop.block_name,
1173
- document_filename: pop.document_filename,
1174
- inherited_block_names:
1175
- (pop.inherited_block_names + block_names).sort.uniq,
1176
- inherited_dependencies:
1177
- dependencies.merge(pop.inherited_dependencies || {}), ### merge, not replace, key data
1178
- inherited_lines:
1179
- HashDelegator.code_merge(pop.inherited_lines, code_lines)
1180
- )
1181
- @link_history.push(next_state)
1318
+ if pop.document_filename
1319
+ next_state = LinkState.new(
1320
+ block_name: pop.block_name,
1321
+ document_filename: pop.document_filename,
1322
+ inherited_block_names:
1323
+ (pop.inherited_block_names + block_names).sort.uniq,
1324
+ inherited_dependencies:
1325
+ dependencies.merge(pop.inherited_dependencies || {}), ### merge, not replace, key data
1326
+ inherited_lines:
1327
+ HashDelegator.code_merge(pop.inherited_lines, code_lines)
1328
+ )
1329
+ @link_history.push(next_state)
1182
1330
 
1183
- next_state.block_name = nil
1184
- LoadFileLinkState.new(LoadFile::Load, next_state)
1331
+ next_state.block_name = nil
1332
+ LoadFileLinkState.new(LoadFile::Load, next_state)
1333
+ else
1334
+ # no history exists; must have been called independently => retain script
1335
+ link_history_push_and_next(
1336
+ curr_block_name: selected[:oname],
1337
+ curr_document_filename: @delegate_object[:filename],
1338
+ inherited_block_names: ((link_state&.inherited_block_names || []) + block_names).sort.uniq,
1339
+ inherited_dependencies: (link_state&.inherited_dependencies || {}).merge(dependencies || {}), ### merge, not replace, key data
1340
+ inherited_lines: HashDelegator.code_merge(link_state&.inherited_lines, code_lines),
1341
+ next_block_name: '', # not link_block_data['block'] || ''
1342
+ next_document_filename: @delegate_object[:filename], # not next_document_filename
1343
+ next_load_file: LoadFile::Reuse # not next_document_filename == @delegate_object[:filename] ? LoadFile::Reuse : LoadFile::Load
1344
+ )
1345
+ # LoadFileLinkState.new(LoadFile::Reuse, link_state)
1346
+ end
1185
1347
  end
1186
1348
 
1187
1349
  # This method handles the back-link operation in the Markdown execution context.
@@ -1200,7 +1362,7 @@ module MarkdownExec
1200
1362
  end
1201
1363
 
1202
1364
  def post_execution_process
1203
- initialize_and_save_execution_output
1365
+ do_save_execution_output
1204
1366
  output_execution_summary
1205
1367
  output_execution_result
1206
1368
  end
@@ -1216,7 +1378,7 @@ module MarkdownExec
1216
1378
  %i[block_name_include_match block_name_wrapper_match])
1217
1379
 
1218
1380
  fcb.merge!(
1219
- name: HashDelegator.indent_all_lines(fcb.dname, fcb.fetch(:indent, nil)),
1381
+ name: fcb.dname,
1220
1382
  label: BlockLabel.make(
1221
1383
  body: fcb[:body],
1222
1384
  filename: @delegate_object[:filename],
@@ -1250,6 +1412,61 @@ module MarkdownExec
1250
1412
  end
1251
1413
  end
1252
1414
 
1415
+ def process_string_array(arr, begin_pattern: nil, end_pattern: nil, scan1: nil,
1416
+ format1: nil)
1417
+ in_block = !begin_pattern.present?
1418
+ collected_lines = []
1419
+
1420
+ arr.each do |line|
1421
+ if in_block
1422
+ if end_pattern.present? && line.match?(end_pattern)
1423
+ in_block = false
1424
+ elsif scan1.present?
1425
+ if format1.present?
1426
+ caps = extract_named_captures_from_option(line, scan1)
1427
+ if caps
1428
+ formatted = format(format1, caps)
1429
+ collected_lines << formatted
1430
+ end
1431
+ else
1432
+ caps = line.match(scan1)
1433
+ if caps
1434
+ formatted = caps[0]
1435
+ collected_lines << formatted
1436
+ end
1437
+ end
1438
+ else
1439
+ collected_lines << line
1440
+ end
1441
+ elsif begin_pattern.present? && line.match?(begin_pattern)
1442
+ in_block = true
1443
+ end
1444
+ end
1445
+
1446
+ collected_lines
1447
+ end
1448
+
1449
+ def prompt_approve_repeat
1450
+ sel = @prompt.select(
1451
+ string_send_color(@delegate_object[:prompt_debounce],
1452
+ :prompt_color_after_script_execution),
1453
+ default: @delegate_object[:prompt_no],
1454
+ filter: true,
1455
+ quiet: true
1456
+ ) do |menu|
1457
+ menu.choice @delegate_object[:prompt_yes]
1458
+ menu.choice @delegate_object[:prompt_no]
1459
+ menu.choice @delegate_object[:prompt_uninterrupted]
1460
+ end
1461
+ return false if sel == @delegate_object[:prompt_no]
1462
+ return true if sel == @delegate_object[:prompt_yes]
1463
+
1464
+ @allowed_execution_block = @prior_execution_block
1465
+ true
1466
+ rescue TTY::Reader::InputInterrupt
1467
+ exit 1
1468
+ end
1469
+
1253
1470
  ##
1254
1471
  # Presents a menu to the user for approving an action and performs additional tasks based on the selection.
1255
1472
  # The function provides options for approval, rejection, copying data to clipboard, or saving data to a file.
@@ -1265,7 +1482,7 @@ module MarkdownExec
1265
1482
  #
1266
1483
  # @return [Boolean] Returns true if the user approves (selects 'Yes'), false otherwise.
1267
1484
  ##
1268
- def prompt_for_user_approval(required_lines)
1485
+ def prompt_for_user_approval(required_lines, selected)
1269
1486
  # Present a selection menu for user approval.
1270
1487
  sel = @prompt.select(
1271
1488
  string_send_color(@delegate_object[:prompt_approve_block],
@@ -1285,7 +1502,7 @@ module MarkdownExec
1285
1502
  if sel == MenuOptions::SCRIPT_TO_CLIPBOARD
1286
1503
  copy_to_clipboard(required_lines)
1287
1504
  elsif sel == MenuOptions::SAVE_SCRIPT
1288
- save_to_file(required_lines)
1505
+ save_to_file(required_lines, selected)
1289
1506
  end
1290
1507
 
1291
1508
  sel == MenuOptions::YES
@@ -1326,6 +1543,7 @@ module MarkdownExec
1326
1543
  #
1327
1544
  (link_block_data['vars'] || []).each do |(key, value)|
1328
1545
  ENV[key] = value.to_s
1546
+ ### add to inherited_lines
1329
1547
  end
1330
1548
 
1331
1549
  ## collect blocks specified by block
@@ -1347,31 +1565,22 @@ module MarkdownExec
1347
1565
  end
1348
1566
  next_document_filename = link_block_data['file'] || @delegate_object[:filename]
1349
1567
 
1350
- # if an eval link block, evaluate code_lines and return its standard output
1568
+ ## append blocks loaded per LinkDataKeys::Load
1351
1569
  #
1352
- if link_block_data.fetch('eval', false)
1353
- all_code = HashDelegator.code_merge(link_state&.inherited_lines, code_lines)
1354
- output = `#{all_code.join("\n")}`.split("\n")
1355
- label_format_above = @delegate_object[:shell_code_label_format_above]
1356
- label_format_below = @delegate_object[:shell_code_label_format_below]
1357
- block_source = { document_filename: link_state&.document_filename }
1358
-
1359
- code_lines = [label_format_above && format(label_format_above,
1360
- block_source.merge({ block_name: selected[:oname] }))] +
1361
- output.map do |line|
1362
- re = Regexp.new(link_block_data.fetch('pattern', '(?<line>.*)'))
1363
- if re =~ line
1364
- re.gsub_format(line, link_block_data.fetch('format', '%{line}'))
1365
- end
1366
- end.compact +
1367
- [label_format_below && format(label_format_below,
1368
- block_source.merge({ block_name: selected[:oname] }))]
1570
+ if (load_filespec = link_block_data.fetch(LinkDataKeys::Load, '')).present?
1571
+ code_lines += File.readlines(load_filespec, chomp: true)
1572
+ end
1369
1573
 
1574
+ # if an eval link block, evaluate code_lines and return its standard output
1575
+ #
1576
+ if link_block_data.fetch(LinkDataKeys::Eval,
1577
+ false) || link_block_data.fetch(LinkDataKeys::Exec, false)
1578
+ code_lines = link_block_data_eval(link_state, code_lines, selected, link_block_data)
1370
1579
  end
1371
1580
 
1372
- if link_block_data['return']
1581
+ if link_block_data[LinkDataKeys::Return]
1373
1582
  pop_add_current_code_to_head_and_trigger_load(link_state, block_names, code_lines,
1374
- dependencies)
1583
+ dependencies, selected)
1375
1584
 
1376
1585
  else
1377
1586
  link_history_push_and_next(
@@ -1406,8 +1615,8 @@ module MarkdownExec
1406
1615
  exit @delegate_object[exception_sym]
1407
1616
  end
1408
1617
 
1409
- def save_to_file(required_lines)
1410
- write_command_file(required_lines)
1618
+ def save_to_file(required_lines, selected)
1619
+ write_command_file(required_lines, selected)
1411
1620
  @fout.fout "File saved: #{@run_state.saved_filespec}"
1412
1621
  end
1413
1622
 
@@ -1423,21 +1632,27 @@ module MarkdownExec
1423
1632
  block_name: @delegate_object[:block_name],
1424
1633
  document_filename: @delegate_object[:filename]
1425
1634
  )
1426
- block_name_from_cli = link_state.block_name.present?
1635
+ @run_state.block_name_from_cli = link_state.block_name.present?
1427
1636
  @cli_block_name = link_state.block_name
1428
- now_using_cli = block_name_from_cli
1637
+ now_using_cli = @run_state.block_name_from_cli
1429
1638
  menu_default_dname = nil
1430
1639
 
1640
+ @run_state.batch_random = Random.new.rand
1641
+ @run_state.batch_index = 0
1642
+
1431
1643
  loop do
1644
+ @run_state.batch_index += 1
1645
+ @run_state.in_own_window = false
1646
+
1432
1647
  # &bsp 'loop', block_name_from_cli, @cli_block_name
1433
- block_name_from_cli, now_using_cli, blocks_in_file, menu_blocks, mdoc = \
1434
- set_delobj_menu_loop_vars(block_name_from_cli, now_using_cli, link_state)
1648
+ @run_state.block_name_from_cli, now_using_cli, blocks_in_file, menu_blocks, mdoc = \
1649
+ set_delobj_menu_loop_vars(@run_state.block_name_from_cli, now_using_cli, link_state)
1435
1650
 
1436
1651
  # cli or user selection
1437
1652
  #
1438
1653
  block_state = load_cli_or_user_selected_block(blocks_in_file, menu_blocks,
1439
1654
  menu_default_dname)
1440
- # &bsp 'block_name_from_cli:',block_name_from_cli
1655
+ # &bsp '@run_state.block_name_from_cli:',@run_state.block_name_from_cli
1441
1656
  if !block_state
1442
1657
  HashDelegator.error_handler('block_state missing', { abort: true })
1443
1658
  elsif block_state.state == MenuState::EXIT
@@ -1448,12 +1663,12 @@ module MarkdownExec
1448
1663
  dump_and_warn_block_state(block_state.block)
1449
1664
  link_state, menu_default_dname = exec_bash_next_state(block_state.block, mdoc,
1450
1665
  link_state)
1451
- if prompt_user_exit(block_name_from_cli, block_state.block)
1666
+ if prompt_user_exit(@run_state.block_name_from_cli, block_state.block)
1452
1667
  # &bsp 'prompt_user_exit -> break'
1453
1668
  break
1454
1669
  end
1455
1670
 
1456
- link_state.block_name, block_name_from_cli, cli_break = \
1671
+ link_state.block_name, @run_state.block_name_from_cli, cli_break = \
1457
1672
  HashDelegator.next_link_state(!shift_cli_argument, now_using_cli, block_state)
1458
1673
 
1459
1674
  if !block_state.block[:block_name_from_ui] && cli_break
@@ -1572,11 +1787,16 @@ module MarkdownExec
1572
1787
  selection = @prompt.select(prompt_text,
1573
1788
  names,
1574
1789
  opts.merge(filter: true))
1790
+
1575
1791
  item = if names.first.instance_of?(String)
1576
1792
  { dname: selection }
1577
1793
  else
1578
1794
  names.find { |item| item[:dname] == selection }
1579
1795
  end
1796
+ unless item
1797
+ HashDelegator.error_handler('select_option_with_metadata', error: 'menu item not found')
1798
+ exit 1
1799
+ end
1580
1800
 
1581
1801
  item.merge(
1582
1802
  if selection == menu_chrome_colored_option(:menu_option_back_name)
@@ -1594,7 +1814,7 @@ module MarkdownExec
1594
1814
  end
1595
1815
 
1596
1816
  def set_environment_variables_for_block(selected)
1597
- YAML.load(selected[:body].join("\n")).each do |key, value|
1817
+ YAML.load(selected[:body].join("\n"))&.each do |key, value|
1598
1818
  ENV[key] = value.to_s
1599
1819
  next unless @delegate_object[:menu_vars_set_format].present?
1600
1820
 
@@ -1623,13 +1843,22 @@ module MarkdownExec
1623
1843
  !name.match(Regexp.new(@delegate_object[:block_name_wrapper_match]))
1624
1844
  end
1625
1845
 
1846
+ dname = oname = title = ''
1847
+ nickname = nil
1848
+ if @delegate_object[:block_name_nick_match].present? && oname =~ Regexp.new(@delegate_object[:block_name_nick_match])
1849
+ nickname = $~[0]
1850
+ else
1851
+ dname = oname = title = fcb_title_groups.fetch(:name, '')
1852
+ end
1853
+
1626
1854
  MarkdownExec::FCB.new(
1627
1855
  body: [],
1628
1856
  call: rest.match(Regexp.new(@delegate_object[:block_calls_scan]))&.to_a&.first,
1629
- dname: fcb_title_groups.fetch(:name, ''),
1857
+ dname: dname,
1630
1858
  headings: headings,
1631
1859
  indent: fcb_title_groups.fetch(:indent, ''),
1632
- oname: fcb_title_groups.fetch(:name, ''),
1860
+ nickname: nickname,
1861
+ oname: oname,
1633
1862
  reqs: reqs,
1634
1863
  shell: fcb_title_groups.fetch(:shell, ''),
1635
1864
  stdin: if (tn = rest.match(/<(?<type>\$)?(?<name>[A-Za-z_-]\S+)/))
@@ -1638,7 +1867,7 @@ module MarkdownExec
1638
1867
  stdout: if (tn = rest.match(/>(?<type>\$)?(?<name>[A-Za-z_\-.\w]+)/))
1639
1868
  tn.named_captures.sym_keys
1640
1869
  end,
1641
- title: fcb_title_groups.fetch(:name, ''),
1870
+ title: title,
1642
1871
  wraps: wraps
1643
1872
  )
1644
1873
  end
@@ -1767,15 +1996,17 @@ module MarkdownExec
1767
1996
  end
1768
1997
 
1769
1998
  # Handles the core logic for generating the command file's metadata and content.
1770
- def write_command_file(required_lines)
1999
+ def write_command_file(required_lines, selected)
1771
2000
  return unless @delegate_object[:save_executed_script]
1772
2001
 
1773
2002
  time_now = Time.now.utc
1774
2003
  @run_state.saved_script_filename =
1775
- SavedAsset.script_name(blockname: @delegate_object[:block_name],
1776
- filename: @delegate_object[:filename],
1777
- prefix: @delegate_object[:saved_script_filename_prefix],
1778
- time: time_now)
2004
+ SavedAsset.script_name(
2005
+ blockname: selected[:nickname] || selected[:oname],
2006
+ filename: @delegate_object[:filename],
2007
+ prefix: @delegate_object[:saved_script_filename_prefix],
2008
+ time: time_now
2009
+ )
1779
2010
  @run_state.saved_filespec =
1780
2011
  File.join(@delegate_object[:saved_script_folder],
1781
2012
  @run_state.saved_script_filename)
@@ -1824,848 +2055,850 @@ module MarkdownExec
1824
2055
  end
1825
2056
  end
1826
2057
 
1827
- if $PROGRAM_NAME == __FILE__
1828
- require 'bundler/setup'
1829
- Bundler.require(:default)
2058
+ return if $PROGRAM_NAME != __FILE__
1830
2059
 
1831
- require 'minitest/autorun'
1832
- require 'mocha/minitest'
2060
+ require 'bundler/setup'
2061
+ Bundler.require(:default)
1833
2062
 
1834
- module MarkdownExec
1835
- class TestHashDelegator < Minitest::Test
1836
- def setup
1837
- @hd = HashDelegator.new
1838
- @mdoc = mock('MarkdownDocument')
1839
- end
2063
+ require 'minitest/autorun'
2064
+ require 'mocha/minitest'
1840
2065
 
1841
- def test_calling_execute_required_lines_calls_command_execute_with_argument_args_value
1842
- pigeon = 'E'
1843
- obj = {
1844
- output_execution_label_format: '',
1845
- output_execution_label_name_color: 'plain',
1846
- output_execution_label_value_color: 'plain'
1847
- }
2066
+ module MarkdownExec
2067
+ class TestHashDelegator < Minitest::Test
2068
+ def setup
2069
+ @hd = HashDelegator.new
2070
+ @mdoc = mock('MarkdownDocument')
2071
+ end
2072
+
2073
+ def test_calling_execute_required_lines_calls_command_execute_with_argument_args_value
2074
+ pigeon = 'E'
2075
+ obj = {
2076
+ output_execution_label_format: '',
2077
+ output_execution_label_name_color: 'plain',
2078
+ output_execution_label_value_color: 'plain'
2079
+ }
1848
2080
 
1849
- c = MarkdownExec::HashDelegator.new(obj)
1850
- c.pass_args = pigeon
2081
+ c = MarkdownExec::HashDelegator.new(obj)
2082
+ c.pass_args = pigeon
1851
2083
 
1852
- # Expect that method opts_command_execute is called with argument args having value pigeon
1853
- c.expects(:command_execute).with(
1854
- '',
1855
- args: pigeon
1856
- )
2084
+ # Expect that method opts_command_execute is called with argument args having value pigeon
2085
+ c.expects(:command_execute).with(
2086
+ '',
2087
+ args: pigeon
2088
+ )
1857
2089
 
1858
- # Call method opts_execute_required_lines
1859
- c.execute_required_lines([])
1860
- end
2090
+ # Call method opts_execute_required_lines
2091
+ c.execute_required_lines
2092
+ end
1861
2093
 
1862
- # Test case for empty body
1863
- def test_push_link_history_and_trigger_load_with_empty_body
1864
- assert_equal LoadFile::Reuse,
1865
- @hd.push_link_history_and_trigger_load([], nil, FCB.new).load_file
1866
- end
2094
+ # Test case for empty body
2095
+ def test_push_link_history_and_trigger_load_with_empty_body
2096
+ assert_equal LoadFile::Reuse,
2097
+ @hd.push_link_history_and_trigger_load([], nil, FCB.new).load_file
2098
+ end
1867
2099
 
1868
- # Test case for non-empty body without 'file' key
1869
- def test_push_link_history_and_trigger_load_without_file_key
1870
- body = ["vars:\n KEY: VALUE"]
1871
- assert_equal LoadFile::Reuse,
1872
- @hd.push_link_history_and_trigger_load(body, nil, FCB.new).load_file
1873
- end
2100
+ # Test case for non-empty body without 'file' key
2101
+ def test_push_link_history_and_trigger_load_without_file_key
2102
+ body = ["vars:\n KEY: VALUE"]
2103
+ assert_equal LoadFile::Reuse,
2104
+ @hd.push_link_history_and_trigger_load(body, nil, FCB.new).load_file
2105
+ end
1874
2106
 
1875
- # Test case for non-empty body with 'file' key
1876
- def test_push_link_history_and_trigger_load_with_file_key
1877
- body = ["file: sample_file\nblock: sample_block\nvars:\n KEY: VALUE"]
1878
- expected_result = LoadFileLinkState.new(LoadFile::Load,
1879
- LinkState.new(block_name: 'sample_block',
1880
- document_filename: 'sample_file',
1881
- inherited_dependencies: {},
1882
- inherited_lines: []))
1883
- assert_equal expected_result,
1884
- @hd.push_link_history_and_trigger_load(body, nil, FCB.new(block_name: 'sample_block',
1885
- filename: 'sample_file'))
1886
- end
2107
+ # Test case for non-empty body with 'file' key
2108
+ def test_push_link_history_and_trigger_load_with_file_key
2109
+ body = ["file: sample_file\nblock: sample_block\nvars:\n KEY: VALUE"]
2110
+ expected_result = LoadFileLinkState.new(LoadFile::Load,
2111
+ LinkState.new(block_name: 'sample_block',
2112
+ document_filename: 'sample_file',
2113
+ inherited_dependencies: {},
2114
+ inherited_lines: []))
2115
+ assert_equal expected_result,
2116
+ @hd.push_link_history_and_trigger_load(body, nil, FCB.new(block_name: 'sample_block',
2117
+ filename: 'sample_file'))
2118
+ end
1887
2119
 
1888
- def test_indent_all_lines_with_indent
1889
- body = "Line 1\nLine 2"
1890
- indent = ' ' # Two spaces
1891
- expected_result = " Line 1\n Line 2"
1892
- assert_equal expected_result, HashDelegator.indent_all_lines(body, indent)
1893
- end
2120
+ def test_indent_all_lines_with_indent
2121
+ body = "Line 1\nLine 2"
2122
+ indent = ' ' # Two spaces
2123
+ expected_result = " Line 1\n Line 2"
2124
+ assert_equal expected_result, HashDelegator.indent_all_lines(body, indent)
2125
+ end
1894
2126
 
1895
- def test_indent_all_lines_without_indent
1896
- body = "Line 1\nLine 2"
1897
- indent = nil
2127
+ def test_indent_all_lines_without_indent
2128
+ body = "Line 1\nLine 2"
2129
+ indent = nil
1898
2130
 
1899
- assert_equal body, HashDelegator.indent_all_lines(body, indent)
1900
- end
2131
+ assert_equal body, HashDelegator.indent_all_lines(body, indent)
2132
+ end
1901
2133
 
1902
- def test_indent_all_lines_with_empty_indent
1903
- body = "Line 1\nLine 2"
1904
- indent = ''
2134
+ def test_indent_all_lines_with_empty_indent
2135
+ body = "Line 1\nLine 2"
2136
+ indent = ''
1905
2137
 
1906
- assert_equal body, HashDelegator.indent_all_lines(body, indent)
1907
- end
2138
+ assert_equal body, HashDelegator.indent_all_lines(body, indent)
2139
+ end
1908
2140
 
1909
- def test_safeval_successful_evaluation
1910
- assert_equal 4, HashDelegator.safeval('2 + 2')
1911
- end
2141
+ def test_safeval_successful_evaluation
2142
+ assert_equal 4, HashDelegator.safeval('2 + 2')
2143
+ end
1912
2144
 
1913
- def test_safeval_rescue_from_error
1914
- HashDelegator.stubs(:error_handler).with('safeval')
1915
- assert_nil HashDelegator.safeval('invalid code')
1916
- end
2145
+ def test_safeval_rescue_from_error
2146
+ HashDelegator.stubs(:error_handler).with('safeval')
2147
+ assert_nil HashDelegator.safeval('invalid code')
2148
+ end
1917
2149
 
1918
- def test_set_fcb_title
1919
- # sample input and output data for testing default_block_title_from_body method
1920
- input_output_data = [
1921
- {
1922
- input: MarkdownExec::FCB.new(title: nil,
1923
- body: ["puts 'Hello, world!'"]),
1924
- output: "puts 'Hello, world!'"
1925
- },
1926
- {
1927
- input: MarkdownExec::FCB.new(title: '',
1928
- body: ['def add(x, y)',
1929
- ' x + y', 'end']),
1930
- output: "def add(x, y)\n x + y\n end\n"
1931
- },
1932
- {
1933
- input: MarkdownExec::FCB.new(title: 'foo', body: %w[bar baz]),
1934
- output: 'foo' # expect the title to remain unchanged
1935
- }
1936
- ]
2150
+ def test_set_fcb_title
2151
+ # sample input and output data for testing default_block_title_from_body method
2152
+ input_output_data = [
2153
+ {
2154
+ input: MarkdownExec::FCB.new(title: nil,
2155
+ body: ["puts 'Hello, world!'"]),
2156
+ output: "puts 'Hello, world!'"
2157
+ },
2158
+ {
2159
+ input: MarkdownExec::FCB.new(title: '',
2160
+ body: ['def add(x, y)',
2161
+ ' x + y', 'end']),
2162
+ output: "def add(x, y)\n x + y\n end\n"
2163
+ },
2164
+ {
2165
+ input: MarkdownExec::FCB.new(title: 'foo', body: %w[bar baz]),
2166
+ output: 'foo' # expect the title to remain unchanged
2167
+ }
2168
+ ]
1937
2169
 
1938
- # iterate over the input and output data and
1939
- # assert that the method sets the title as expected
1940
- input_output_data.each do |data|
1941
- input = data[:input]
1942
- output = data[:output]
1943
- HashDelegator.default_block_title_from_body(input)
1944
- assert_equal output, input.title
1945
- end
2170
+ # iterate over the input and output data and
2171
+ # assert that the method sets the title as expected
2172
+ input_output_data.each do |data|
2173
+ input = data[:input]
2174
+ output = data[:output]
2175
+ HashDelegator.default_block_title_from_body(input)
2176
+ assert_equal output, input.title
1946
2177
  end
2178
+ end
1947
2179
 
1948
- class TestHashDelegatorAppendDivider < Minitest::Test
1949
- def setup
1950
- @hd = HashDelegator.new
1951
- @hd.instance_variable_set(:@delegate_object, {
1952
- menu_divider_format: 'Format',
1953
- menu_initial_divider: 'Initial Divider',
1954
- menu_final_divider: 'Final Divider',
1955
- menu_divider_color: :color
1956
- })
1957
- @hd.stubs(:string_send_color).returns('Formatted Divider')
1958
- HashDelegator.stubs(:safeval).returns('Safe Value')
1959
- end
2180
+ class TestHashDelegatorAppendDivider < Minitest::Test
2181
+ def setup
2182
+ @hd = HashDelegator.new
2183
+ @hd.instance_variable_set(:@delegate_object, {
2184
+ menu_divider_format: 'Format',
2185
+ menu_initial_divider: 'Initial Divider',
2186
+ menu_final_divider: 'Final Divider',
2187
+ menu_divider_color: :color
2188
+ })
2189
+ @hd.stubs(:string_send_color).returns('Formatted Divider')
2190
+ HashDelegator.stubs(:safeval).returns('Safe Value')
2191
+ end
1960
2192
 
1961
- def test_append_divider_initial
1962
- menu_blocks = []
1963
- @hd.append_divider(menu_blocks, :initial)
2193
+ def test_append_divider_initial
2194
+ menu_blocks = []
2195
+ @hd.append_divider(menu_blocks, :initial)
1964
2196
 
1965
- assert_equal 1, menu_blocks.size
1966
- assert_equal 'Formatted Divider', menu_blocks.first.dname
1967
- end
2197
+ assert_equal 1, menu_blocks.size
2198
+ assert_equal 'Formatted Divider', menu_blocks.first.dname
2199
+ end
1968
2200
 
1969
- def test_append_divider_final
1970
- menu_blocks = []
1971
- @hd.append_divider(menu_blocks, :final)
2201
+ def test_append_divider_final
2202
+ menu_blocks = []
2203
+ @hd.append_divider(menu_blocks, :final)
1972
2204
 
1973
- assert_equal 1, menu_blocks.size
1974
- assert_equal 'Formatted Divider', menu_blocks.last.dname
1975
- end
2205
+ assert_equal 1, menu_blocks.size
2206
+ assert_equal 'Formatted Divider', menu_blocks.last.dname
2207
+ end
1976
2208
 
1977
- def test_append_divider_without_format
1978
- @hd.instance_variable_set(:@delegate_object, {})
1979
- menu_blocks = []
1980
- @hd.append_divider(menu_blocks, :initial)
2209
+ def test_append_divider_without_format
2210
+ @hd.instance_variable_set(:@delegate_object, {})
2211
+ menu_blocks = []
2212
+ @hd.append_divider(menu_blocks, :initial)
1981
2213
 
1982
- assert_empty menu_blocks
1983
- end
2214
+ assert_empty menu_blocks
1984
2215
  end
2216
+ end
1985
2217
 
1986
- class TestHashDelegatorBlockFind < Minitest::Test
1987
- def setup
1988
- @hd = HashDelegator.new
1989
- end
2218
+ class TestHashDelegatorBlockFind < Minitest::Test
2219
+ def setup
2220
+ @hd = HashDelegator.new
2221
+ end
1990
2222
 
1991
- def test_block_find_with_match
1992
- blocks = [{ key: 'value1' }, { key: 'value2' }]
1993
- result = HashDelegator.block_find(blocks, :key, 'value1')
1994
- assert_equal({ key: 'value1' }, result)
1995
- end
2223
+ def test_block_find_with_match
2224
+ blocks = [{ key: 'value1' }, { key: 'value2' }]
2225
+ result = HashDelegator.block_find(blocks, :key, 'value1')
2226
+ assert_equal({ key: 'value1' }, result)
2227
+ end
1996
2228
 
1997
- def test_block_find_without_match
1998
- blocks = [{ key: 'value1' }, { key: 'value2' }]
1999
- result = HashDelegator.block_find(blocks, :key, 'value3')
2000
- assert_nil result
2001
- end
2229
+ def test_block_find_without_match
2230
+ blocks = [{ key: 'value1' }, { key: 'value2' }]
2231
+ result = HashDelegator.block_find(blocks, :key, 'value3')
2232
+ assert_nil result
2233
+ end
2002
2234
 
2003
- def test_block_find_with_default
2004
- blocks = [{ key: 'value1' }, { key: 'value2' }]
2005
- result = HashDelegator.block_find(blocks, :key, 'value3', 'default')
2006
- assert_equal 'default', result
2007
- end
2235
+ def test_block_find_with_default
2236
+ blocks = [{ key: 'value1' }, { key: 'value2' }]
2237
+ result = HashDelegator.block_find(blocks, :key, 'value3', 'default')
2238
+ assert_equal 'default', result
2008
2239
  end
2240
+ end
2009
2241
 
2010
- class TestHashDelegatorBlocksFromNestedFiles < Minitest::Test
2011
- def setup
2012
- @hd = HashDelegator.new
2013
- @hd.stubs(:iter_blocks_from_nested_files).yields(:blocks, FCB.new)
2014
- @hd.stubs(:get_block_summary).returns(FCB.new)
2015
- @hd.stubs(:create_and_add_chrome_blocks)
2016
- @hd.instance_variable_set(:@delegate_object, {})
2017
- HashDelegator.stubs(:error_handler)
2018
- end
2242
+ class TestHashDelegatorBlocksFromNestedFiles < Minitest::Test
2243
+ def setup
2244
+ @hd = HashDelegator.new
2245
+ @hd.stubs(:iter_blocks_from_nested_files).yields(:blocks, FCB.new)
2246
+ @hd.stubs(:get_block_summary).returns(FCB.new)
2247
+ @hd.stubs(:create_and_add_chrome_blocks)
2248
+ @hd.instance_variable_set(:@delegate_object, {})
2249
+ HashDelegator.stubs(:error_handler)
2250
+ end
2019
2251
 
2020
- def test_blocks_from_nested_files
2021
- result = @hd.blocks_from_nested_files
2252
+ def test_blocks_from_nested_files
2253
+ result = @hd.blocks_from_nested_files
2022
2254
 
2023
- assert_kind_of Array, result
2024
- assert_kind_of FCB, result.first
2025
- end
2255
+ assert_kind_of Array, result
2256
+ assert_kind_of FCB, result.first
2257
+ end
2026
2258
 
2027
- def test_blocks_from_nested_files_with_no_chrome
2028
- @hd.instance_variable_set(:@delegate_object, { no_chrome: true })
2029
- @hd.expects(:create_and_add_chrome_blocks).never
2259
+ def test_blocks_from_nested_files_with_no_chrome
2260
+ @hd.instance_variable_set(:@delegate_object, { no_chrome: true })
2261
+ @hd.expects(:create_and_add_chrome_blocks).never
2030
2262
 
2031
- result = @hd.blocks_from_nested_files
2263
+ result = @hd.blocks_from_nested_files
2032
2264
 
2033
- assert_kind_of Array, result
2034
- end
2265
+ assert_kind_of Array, result
2035
2266
  end
2267
+ end
2036
2268
 
2037
- class TestHashDelegatorCollectRequiredCodeLines < Minitest::Test
2038
- def setup
2039
- @hd = HashDelegator.new
2040
- @hd.instance_variable_set(:@delegate_object, {})
2041
- @mdoc = mock('YourMDocClass')
2042
- @selected = { shell: BlockType::VARS, body: ['key: value'] }
2043
- HashDelegator.stubs(:read_required_blocks_from_temp_file).returns([])
2044
- @hd.stubs(:string_send_color)
2045
- @hd.stubs(:print)
2046
- end
2269
+ class TestHashDelegatorCollectRequiredCodeLines < Minitest::Test
2270
+ def setup
2271
+ @hd = HashDelegator.new
2272
+ @hd.instance_variable_set(:@delegate_object, {})
2273
+ @mdoc = mock('YourMDocClass')
2274
+ @selected = { shell: BlockType::VARS, body: ['key: value'] }
2275
+ HashDelegator.stubs(:read_required_blocks_from_temp_file).returns([])
2276
+ @hd.stubs(:string_send_color)
2277
+ @hd.stubs(:print)
2278
+ end
2047
2279
 
2048
- def test_collect_required_code_lines_with_vars
2049
- YAML.stubs(:load).returns({ 'key' => 'value' })
2050
- @mdoc.stubs(:collect_recursively_required_code).returns({ code: ['code line'] })
2051
- result = @hd.collect_required_code_lines(@mdoc, @selected, block_source: {})
2280
+ def test_collect_required_code_lines_with_vars
2281
+ YAML.stubs(:load).returns({ 'key' => 'value' })
2282
+ @mdoc.stubs(:collect_recursively_required_code).returns({ code: ['code line'] })
2283
+ result = @hd.collect_required_code_lines(@mdoc, @selected, block_source: {})
2052
2284
 
2053
- assert_equal ['code line'], result
2054
- end
2285
+ assert_equal ['code line'], result
2055
2286
  end
2287
+ end
2056
2288
 
2057
- class TestHashDelegatorCommandOrUserSelectedBlock < Minitest::Test
2058
- def setup
2059
- @hd = HashDelegator.new
2060
- @hd.instance_variable_set(:@delegate_object, {})
2061
- HashDelegator.stubs(:error_handler)
2062
- @hd.stubs(:wait_for_user_selected_block)
2063
- end
2289
+ class TestHashDelegatorCommandOrUserSelectedBlock < Minitest::Test
2290
+ def setup
2291
+ @hd = HashDelegator.new
2292
+ @hd.instance_variable_set(:@delegate_object, {})
2293
+ HashDelegator.stubs(:error_handler)
2294
+ @hd.stubs(:wait_for_user_selected_block)
2295
+ end
2064
2296
 
2065
- def test_command_selected_block
2066
- all_blocks = [{ oname: 'block1' }, { oname: 'block2' }]
2067
- @hd.instance_variable_set(:@delegate_object,
2068
- { block_name: 'block1' })
2297
+ def test_command_selected_block
2298
+ all_blocks = [{ oname: 'block1' }, { oname: 'block2' }]
2299
+ @hd.instance_variable_set(:@delegate_object,
2300
+ { block_name: 'block1' })
2069
2301
 
2070
- result = @hd.load_cli_or_user_selected_block(all_blocks, [], nil)
2302
+ result = @hd.load_cli_or_user_selected_block(all_blocks, [], nil)
2071
2303
 
2072
- assert_equal all_blocks.first.merge(block_name_from_ui: false), result.block
2073
- assert_nil result.state
2074
- end
2304
+ assert_equal all_blocks.first.merge(block_name_from_ui: false), result.block
2305
+ assert_nil result.state
2306
+ end
2075
2307
 
2076
- def test_user_selected_block
2077
- block_state = SelectedBlockMenuState.new({ oname: 'block2' },
2078
- :some_state)
2079
- @hd.stubs(:wait_for_user_selected_block).returns(block_state)
2308
+ def test_user_selected_block
2309
+ block_state = SelectedBlockMenuState.new({ oname: 'block2' },
2310
+ :some_state)
2311
+ @hd.stubs(:wait_for_user_selected_block).returns(block_state)
2080
2312
 
2081
- result = @hd.load_cli_or_user_selected_block([], [], nil)
2313
+ result = @hd.load_cli_or_user_selected_block([], [], nil)
2082
2314
 
2083
- assert_equal block_state.block.merge(block_name_from_ui: true), result.block
2084
- assert_equal :some_state, result.state
2085
- end
2315
+ assert_equal block_state.block.merge(block_name_from_ui: true), result.block
2316
+ assert_equal :some_state, result.state
2086
2317
  end
2318
+ end
2087
2319
 
2088
- class TestHashDelegatorCountBlockInFilename < Minitest::Test
2089
- def setup
2090
- @hd = HashDelegator.new
2091
- @hd.instance_variable_set(:@delegate_object,
2092
- { fenced_start_and_end_regex: '^```',
2093
- filename: '/path/to/file' })
2094
- @hd.stubs(:cfile).returns(mock('cfile'))
2095
- end
2320
+ class TestHashDelegatorCountBlockInFilename < Minitest::Test
2321
+ def setup
2322
+ @hd = HashDelegator.new
2323
+ @hd.instance_variable_set(:@delegate_object,
2324
+ { fenced_start_and_end_regex: '^```',
2325
+ filename: '/path/to/file' })
2326
+ @hd.stubs(:cfile).returns(mock('cfile'))
2327
+ end
2096
2328
 
2097
- def test_count_blocks_in_filename
2098
- file_content = ["```ruby\n", "puts 'Hello'\n", "```\n",
2099
- "```python\n", "print('Hello')\n", "```\n"]
2100
- @hd.cfile.stubs(:readlines).with('/path/to/file').returns(file_content)
2329
+ def test_count_blocks_in_filename
2330
+ file_content = ["```ruby\n", "puts 'Hello'\n", "```\n",
2331
+ "```python\n", "print('Hello')\n", "```\n"]
2332
+ @hd.cfile.stubs(:readlines).with('/path/to/file',
2333
+ import_paths: nil).returns(file_content)
2101
2334
 
2102
- count = @hd.count_blocks_in_filename
2335
+ count = @hd.count_blocks_in_filename
2103
2336
 
2104
- assert_equal 2, count
2105
- end
2337
+ assert_equal 2, count
2338
+ end
2106
2339
 
2107
- def test_count_blocks_in_filename_with_no_matches
2108
- file_content = ["puts 'Hello'\n", "print('Hello')\n"]
2109
- @hd.cfile.stubs(:readlines).with('/path/to/file').returns(file_content)
2340
+ def test_count_blocks_in_filename_with_no_matches
2341
+ file_content = ["puts 'Hello'\n", "print('Hello')\n"]
2342
+ @hd.cfile.stubs(:readlines).with('/path/to/file',
2343
+ import_paths: nil).returns(file_content)
2110
2344
 
2111
- count = @hd.count_blocks_in_filename
2345
+ count = @hd.count_blocks_in_filename
2112
2346
 
2113
- assert_equal 0, count
2114
- end
2347
+ assert_equal 0, count
2115
2348
  end
2349
+ end
2116
2350
 
2117
- class TestHashDelegatorCreateAndWriteFile < Minitest::Test
2118
- def setup
2119
- @hd = HashDelegator.new
2120
- HashDelegator.stubs(:error_handler)
2121
- FileUtils.stubs(:mkdir_p)
2122
- File.stubs(:write)
2123
- File.stubs(:chmod)
2124
- end
2351
+ class TestHashDelegatorCreateAndWriteFile < Minitest::Test
2352
+ def setup
2353
+ @hd = HashDelegator.new
2354
+ HashDelegator.stubs(:error_handler)
2355
+ FileUtils.stubs(:mkdir_p)
2356
+ File.stubs(:write)
2357
+ File.stubs(:chmod)
2358
+ end
2125
2359
 
2126
- def test_create_file_and_write_string_with_permissions
2127
- file_path = '/path/to/file'
2128
- content = 'sample content'
2129
- chmod_value = 0o644
2360
+ def test_create_file_and_write_string_with_permissions
2361
+ file_path = '/path/to/file'
2362
+ content = 'sample content'
2363
+ chmod_value = 0o644
2130
2364
 
2131
- FileUtils.expects(:mkdir_p).with('/path/to').once
2132
- File.expects(:write).with(file_path, content).once
2133
- File.expects(:chmod).with(chmod_value, file_path).once
2365
+ FileUtils.expects(:mkdir_p).with('/path/to').once
2366
+ File.expects(:write).with(file_path, content).once
2367
+ File.expects(:chmod).with(chmod_value, file_path).once
2134
2368
 
2135
- HashDelegator.create_file_and_write_string_with_permissions(file_path, content,
2136
- chmod_value)
2369
+ HashDelegator.create_file_and_write_string_with_permissions(file_path, content,
2370
+ chmod_value)
2137
2371
 
2138
- assert true # Placeholder for actual test assertions
2139
- end
2372
+ assert true # Placeholder for actual test assertions
2373
+ end
2140
2374
 
2141
- def test_create_and_write_file_without_chmod
2142
- file_path = '/path/to/file'
2143
- content = 'sample content'
2144
- chmod_value = 0
2375
+ def test_create_and_write_file_without_chmod
2376
+ file_path = '/path/to/file'
2377
+ content = 'sample content'
2378
+ chmod_value = 0
2145
2379
 
2146
- FileUtils.expects(:mkdir_p).with('/path/to').once
2147
- File.expects(:write).with(file_path, content).once
2148
- File.expects(:chmod).never
2380
+ FileUtils.expects(:mkdir_p).with('/path/to').once
2381
+ File.expects(:write).with(file_path, content).once
2382
+ File.expects(:chmod).never
2149
2383
 
2150
- HashDelegator.create_file_and_write_string_with_permissions(file_path, content,
2151
- chmod_value)
2384
+ HashDelegator.create_file_and_write_string_with_permissions(file_path, content,
2385
+ chmod_value)
2152
2386
 
2153
- assert true # Placeholder for actual test assertions
2154
- end
2387
+ assert true # Placeholder for actual test assertions
2155
2388
  end
2389
+ end
2156
2390
 
2157
- class TestHashDelegatorDetermineBlockState < Minitest::Test
2158
- def setup
2159
- @hd = HashDelegator.new
2160
- @hd.stubs(:menu_chrome_formatted_option).returns('Formatted Option')
2161
- end
2162
-
2163
- def test_determine_block_state_exit
2164
- selected_option = { oname: 'Formatted Option' }
2165
- @hd.stubs(:menu_chrome_formatted_option).with(:menu_option_exit_name).returns('Formatted Option')
2166
-
2167
- result = @hd.determine_block_state(selected_option)
2168
-
2169
- assert_equal MenuState::EXIT, result.state
2170
- assert_nil result.block
2171
- end
2391
+ class TestHashDelegatorDetermineBlockState < Minitest::Test
2392
+ def setup
2393
+ @hd = HashDelegator.new
2394
+ @hd.stubs(:menu_chrome_formatted_option).returns('Formatted Option')
2395
+ end
2172
2396
 
2173
- def test_determine_block_state_back
2174
- selected_option = { oname: 'Formatted Back Option' }
2175
- @hd.stubs(:menu_chrome_formatted_option).with(:menu_option_back_name).returns('Formatted Back Option')
2176
- result = @hd.determine_block_state(selected_option)
2397
+ def test_determine_block_state_exit
2398
+ selected_option = { oname: 'Formatted Option' }
2399
+ @hd.stubs(:menu_chrome_formatted_option).with(:menu_option_exit_name).returns('Formatted Option')
2177
2400
 
2178
- assert_equal MenuState::BACK, result.state
2179
- assert_equal selected_option, result.block
2180
- end
2401
+ result = @hd.determine_block_state(selected_option)
2181
2402
 
2182
- def test_determine_block_state_continue
2183
- selected_option = { oname: 'Other Option' }
2403
+ assert_equal MenuState::EXIT, result.state
2404
+ assert_nil result.block
2405
+ end
2184
2406
 
2185
- result = @hd.determine_block_state(selected_option)
2407
+ def test_determine_block_state_back
2408
+ selected_option = { oname: 'Formatted Back Option' }
2409
+ @hd.stubs(:menu_chrome_formatted_option).with(:menu_option_back_name).returns('Formatted Back Option')
2410
+ result = @hd.determine_block_state(selected_option)
2186
2411
 
2187
- assert_equal MenuState::CONTINUE, result.state
2188
- assert_equal selected_option, result.block
2189
- end
2412
+ assert_equal MenuState::BACK, result.state
2413
+ assert_equal selected_option, result.block
2190
2414
  end
2191
2415
 
2192
- class TestHashDelegatorDisplayRequiredCode < Minitest::Test
2193
- def setup
2194
- @hd = HashDelegator.new
2195
- @hd.instance_variable_set(:@fout, mock('fout'))
2196
- @hd.instance_variable_set(:@delegate_object, {})
2197
- @hd.stubs(:string_send_color)
2198
- end
2416
+ def test_determine_block_state_continue
2417
+ selected_option = { oname: 'Other Option' }
2199
2418
 
2200
- def test_display_required_code
2201
- required_lines = %w[line1 line2]
2202
- @hd.instance_variable_get(:@delegate_object).stubs(:[]).with(:script_preview_head).returns('Header')
2203
- @hd.instance_variable_get(:@delegate_object).stubs(:[]).with(:script_preview_tail).returns('Footer')
2204
- @hd.instance_variable_get(:@fout).expects(:fout).times(4)
2419
+ result = @hd.determine_block_state(selected_option)
2205
2420
 
2206
- @hd.display_required_code(required_lines)
2421
+ assert_equal MenuState::CONTINUE, result.state
2422
+ assert_equal selected_option, result.block
2423
+ end
2424
+ end
2207
2425
 
2208
- # Verifying that fout is called for each line and for header & footer
2209
- assert true # Placeholder for actual test assertions
2210
- end
2426
+ class TestHashDelegatorDisplayRequiredCode < Minitest::Test
2427
+ def setup
2428
+ @hd = HashDelegator.new
2429
+ @hd.instance_variable_set(:@fout, mock('fout'))
2430
+ @hd.instance_variable_set(:@delegate_object, {})
2431
+ @hd.stubs(:string_send_color)
2211
2432
  end
2212
2433
 
2213
- class TestHashDelegatorFetchColor < Minitest::Test
2214
- def setup
2215
- @hd = HashDelegator.new
2216
- @hd.instance_variable_set(:@delegate_object, {})
2217
- end
2434
+ def test_display_required_code
2435
+ required_lines = %w[line1 line2]
2436
+ @hd.instance_variable_get(:@delegate_object).stubs(:[]).with(:script_preview_head).returns('Header')
2437
+ @hd.instance_variable_get(:@delegate_object).stubs(:[]).with(:script_preview_tail).returns('Footer')
2438
+ @hd.instance_variable_get(:@fout).expects(:fout).times(4)
2218
2439
 
2219
- def test_fetch_color_with_valid_data
2220
- @hd.instance_variable_get(:@delegate_object).stubs(:fetch).with(
2221
- :execution_report_preview_head, ''
2222
- ).returns('Data String')
2223
- @hd.stubs(:string_send_color).with('Data String',
2224
- :execution_report_preview_frame_color).returns('Colored Data String')
2440
+ @hd.display_required_code(required_lines)
2225
2441
 
2226
- result = @hd.fetch_color
2442
+ # Verifying that fout is called for each line and for header & footer
2443
+ assert true # Placeholder for actual test assertions
2444
+ end
2445
+ end
2227
2446
 
2228
- assert_equal 'Colored Data String', result
2229
- end
2447
+ class TestHashDelegatorFetchColor < Minitest::Test
2448
+ def setup
2449
+ @hd = HashDelegator.new
2450
+ @hd.instance_variable_set(:@delegate_object, {})
2451
+ end
2230
2452
 
2231
- def test_fetch_color_with_missing_data
2232
- @hd.instance_variable_get(:@delegate_object).stubs(:fetch).with(
2233
- :execution_report_preview_head, ''
2234
- ).returns('')
2235
- @hd.stubs(:string_send_color).with('',
2236
- :execution_report_preview_frame_color).returns('Default Colored String')
2453
+ def test_fetch_color_with_valid_data
2454
+ @hd.instance_variable_get(:@delegate_object).stubs(:fetch).with(
2455
+ :execution_report_preview_head, ''
2456
+ ).returns('Data String')
2457
+ @hd.stubs(:string_send_color).with('Data String',
2458
+ :execution_report_preview_frame_color).returns('Colored Data String')
2237
2459
 
2238
- result = @hd.fetch_color
2460
+ result = @hd.fetch_color
2239
2461
 
2240
- assert_equal 'Default Colored String', result
2241
- end
2462
+ assert_equal 'Colored Data String', result
2242
2463
  end
2243
2464
 
2244
- class TestHashDelegatorFormatReferencesSendColor < Minitest::Test
2245
- def setup
2246
- @hd = HashDelegator.new
2247
- @hd.instance_variable_set(:@delegate_object, {})
2248
- end
2465
+ def test_fetch_color_with_missing_data
2466
+ @hd.instance_variable_get(:@delegate_object).stubs(:fetch).with(
2467
+ :execution_report_preview_head, ''
2468
+ ).returns('')
2469
+ @hd.stubs(:string_send_color).with('',
2470
+ :execution_report_preview_frame_color).returns('Default Colored String')
2249
2471
 
2250
- def test_format_references_send_color_with_valid_data
2251
- @hd.instance_variable_get(:@delegate_object).stubs(:fetch).with(
2252
- :output_execution_label_format, ''
2253
- ).returns('Formatted: %{key}')
2254
- @hd.stubs(:string_send_color).returns('Colored String')
2472
+ result = @hd.fetch_color
2255
2473
 
2256
- result = @hd.format_references_send_color(context: { key: 'value' },
2257
- color_sym: :execution_report_preview_frame_color)
2474
+ assert_equal 'Default Colored String', result
2475
+ end
2476
+ end
2258
2477
 
2259
- assert_equal 'Colored String', result
2260
- end
2478
+ class TestHashDelegatorFormatReferencesSendColor < Minitest::Test
2479
+ def setup
2480
+ @hd = HashDelegator.new
2481
+ @hd.instance_variable_set(:@delegate_object, {})
2482
+ end
2261
2483
 
2262
- def test_format_references_send_color_with_missing_format
2263
- @hd.instance_variable_get(:@delegate_object).stubs(:fetch).with(
2264
- :output_execution_label_format, ''
2265
- ).returns('')
2266
- @hd.stubs(:string_send_color).returns('Default Colored String')
2484
+ def test_format_references_send_color_with_valid_data
2485
+ @hd.instance_variable_get(:@delegate_object).stubs(:fetch).with(
2486
+ :output_execution_label_format, ''
2487
+ ).returns('Formatted: %{key}')
2488
+ @hd.stubs(:string_send_color).returns('Colored String')
2267
2489
 
2268
- result = @hd.format_references_send_color(context: { key: 'value' },
2269
- color_sym: :execution_report_preview_frame_color)
2490
+ result = @hd.format_references_send_color(context: { key: 'value' },
2491
+ color_sym: :execution_report_preview_frame_color)
2270
2492
 
2271
- assert_equal 'Default Colored String', result
2272
- end
2493
+ assert_equal 'Colored String', result
2273
2494
  end
2274
2495
 
2275
- class TestHashDelegatorFormatExecutionStreams < Minitest::Test
2276
- def setup
2277
- @hd = HashDelegator.new
2278
- @hd.instance_variable_set(:@run_state, mock('run_state'))
2279
- end
2496
+ def test_format_references_send_color_with_missing_format
2497
+ @hd.instance_variable_get(:@delegate_object).stubs(:fetch).with(
2498
+ :output_execution_label_format, ''
2499
+ ).returns('')
2500
+ @hd.stubs(:string_send_color).returns('Default Colored String')
2280
2501
 
2281
- def test_format_execution_streams_with_valid_key
2282
- result = HashDelegator.format_execution_streams(:stdout,
2283
- { stdout: %w[output1 output2] })
2502
+ result = @hd.format_references_send_color(context: { key: 'value' },
2503
+ color_sym: :execution_report_preview_frame_color)
2284
2504
 
2285
- assert_equal 'output1output2', result
2286
- end
2505
+ assert_equal 'Default Colored String', result
2506
+ end
2507
+ end
2287
2508
 
2288
- def test_format_execution_streams_with_empty_key
2289
- @hd.instance_variable_get(:@run_state).stubs(:files).returns({})
2509
+ class TestHashDelegatorFormatExecutionStreams < Minitest::Test
2510
+ def setup
2511
+ @hd = HashDelegator.new
2512
+ @hd.instance_variable_set(:@run_state, mock('run_state'))
2513
+ end
2290
2514
 
2291
- result = HashDelegator.format_execution_streams(:stderr)
2515
+ def test_format_execution_streams_with_valid_key
2516
+ result = HashDelegator.format_execution_streams(:stdout,
2517
+ { stdout: %w[output1 output2] })
2292
2518
 
2293
- assert_equal '', result
2294
- end
2519
+ assert_equal 'output1output2', result
2520
+ end
2295
2521
 
2296
- def test_format_execution_streams_with_nil_files
2297
- @hd.instance_variable_get(:@run_state).stubs(:files).returns(nil)
2522
+ def test_format_execution_streams_with_empty_key
2523
+ @hd.instance_variable_get(:@run_state).stubs(:files).returns({})
2298
2524
 
2299
- result = HashDelegator.format_execution_streams(:stdin)
2525
+ result = HashDelegator.format_execution_streams(:stderr)
2300
2526
 
2301
- assert_equal '', result
2302
- end
2527
+ assert_equal '', result
2303
2528
  end
2304
2529
 
2305
- class TestHashDelegatorHandleBackLink < Minitest::Test
2306
- def setup
2307
- @hd = HashDelegator.new
2308
- @hd.stubs(:history_state_pop)
2309
- end
2530
+ def test_format_execution_streams_with_nil_files
2531
+ @hd.instance_variable_get(:@run_state).stubs(:files).returns(nil)
2310
2532
 
2311
- def test_pop_link_history_and_trigger_load
2312
- # Verifying that history_state_pop is called
2313
- # @hd.expects(:history_state_pop).once
2533
+ result = HashDelegator.format_execution_streams(:stdin)
2314
2534
 
2315
- result = @hd.pop_link_history_and_trigger_load
2535
+ assert_equal '', result
2536
+ end
2537
+ end
2316
2538
 
2317
- # Asserting the result is an instance of LoadFileLinkState
2318
- assert_instance_of LoadFileLinkState, result
2319
- assert_equal LoadFile::Load, result.load_file
2320
- assert_nil result.link_state.block_name
2321
- end
2539
+ class TestHashDelegatorHandleBackLink < Minitest::Test
2540
+ def setup
2541
+ @hd = HashDelegator.new
2542
+ @hd.stubs(:history_state_pop)
2322
2543
  end
2323
2544
 
2324
- class TestHashDelegatorHandleBlockState < Minitest::Test
2325
- def setup
2326
- @hd = HashDelegator.new
2327
- @mock_block_state = mock('block_state')
2328
- end
2545
+ def test_pop_link_history_and_trigger_load
2546
+ # Verifying that history_state_pop is called
2547
+ # @hd.expects(:history_state_pop).once
2329
2548
 
2330
- def test_handle_back_or_continue_with_back
2331
- @mock_block_state.stubs(:state).returns(MenuState::BACK)
2332
- @mock_block_state.stubs(:block).returns({ oname: 'sample_block' })
2549
+ result = @hd.pop_link_history_and_trigger_load
2333
2550
 
2334
- @hd.handle_back_or_continue(@mock_block_state)
2551
+ # Asserting the result is an instance of LoadFileLinkState
2552
+ assert_instance_of LoadFileLinkState, result
2553
+ assert_equal LoadFile::Load, result.load_file
2554
+ assert_nil result.link_state.block_name
2555
+ end
2556
+ end
2335
2557
 
2336
- assert_equal 'sample_block',
2337
- @hd.instance_variable_get(:@delegate_object)[:block_name]
2338
- assert @hd.instance_variable_get(:@menu_user_clicked_back_link)
2339
- end
2558
+ class TestHashDelegatorHandleBlockState < Minitest::Test
2559
+ def setup
2560
+ @hd = HashDelegator.new
2561
+ @mock_block_state = mock('block_state')
2562
+ end
2340
2563
 
2341
- def test_handle_back_or_continue_with_continue
2342
- @mock_block_state.stubs(:state).returns(MenuState::CONTINUE)
2343
- @mock_block_state.stubs(:block).returns({ oname: 'another_block' })
2564
+ def test_handle_back_or_continue_with_back
2565
+ @mock_block_state.stubs(:state).returns(MenuState::BACK)
2566
+ @mock_block_state.stubs(:block).returns({ oname: 'sample_block' })
2344
2567
 
2345
- @hd.handle_back_or_continue(@mock_block_state)
2568
+ @hd.handle_back_or_continue(@mock_block_state)
2346
2569
 
2347
- assert_equal 'another_block',
2348
- @hd.instance_variable_get(:@delegate_object)[:block_name]
2349
- refute @hd.instance_variable_get(:@menu_user_clicked_back_link)
2350
- end
2570
+ assert_equal 'sample_block',
2571
+ @hd.instance_variable_get(:@delegate_object)[:block_name]
2572
+ assert @hd.instance_variable_get(:@menu_user_clicked_back_link)
2573
+ end
2351
2574
 
2352
- def test_handle_back_or_continue_with_other
2353
- @mock_block_state.stubs(:state).returns(nil) # MenuState::OTHER
2354
- @mock_block_state.stubs(:block).returns({ oname: 'other_block' })
2575
+ def test_handle_back_or_continue_with_continue
2576
+ @mock_block_state.stubs(:state).returns(MenuState::CONTINUE)
2577
+ @mock_block_state.stubs(:block).returns({ oname: 'another_block' })
2355
2578
 
2356
- @hd.handle_back_or_continue(@mock_block_state)
2579
+ @hd.handle_back_or_continue(@mock_block_state)
2357
2580
 
2358
- assert_nil @hd.instance_variable_get(:@delegate_object)[:block_name]
2359
- assert_nil @hd.instance_variable_get(:@menu_user_clicked_back_link)
2360
- end
2581
+ assert_equal 'another_block',
2582
+ @hd.instance_variable_get(:@delegate_object)[:block_name]
2583
+ refute @hd.instance_variable_get(:@menu_user_clicked_back_link)
2361
2584
  end
2362
2585
 
2363
- class TestHashDelegatorHandleGenericBlock < Minitest::Test
2364
- def setup
2365
- @hd = HashDelegator.new
2366
- @mock_document = mock('MarkdownDocument')
2367
- @selected_item = mock('FCB')
2368
- end
2369
-
2370
- def test_compile_execute_and_trigger_reuse_without_user_approval
2371
- # Mock the delegate object configuration
2372
- @hd.instance_variable_set(:@delegate_object,
2373
- { output_script: false,
2374
- user_must_approve: false })
2586
+ def test_handle_back_or_continue_with_other
2587
+ @mock_block_state.stubs(:state).returns(nil) # MenuState::OTHER
2588
+ @mock_block_state.stubs(:block).returns({ oname: 'other_block' })
2375
2589
 
2376
- # Test the method without user approval
2377
- # Expectations and assertions go here
2378
- end
2590
+ @hd.handle_back_or_continue(@mock_block_state)
2379
2591
 
2380
- def test_compile_execute_and_trigger_reuse_with_user_approval
2381
- # Mock the delegate object configuration
2382
- @hd.instance_variable_set(:@delegate_object,
2383
- { output_script: false,
2384
- user_must_approve: true })
2592
+ assert_nil @hd.instance_variable_get(:@delegate_object)[:block_name]
2593
+ assert_nil @hd.instance_variable_get(:@menu_user_clicked_back_link)
2594
+ end
2595
+ end
2385
2596
 
2386
- # Test the method with user approval
2387
- # Expectations and assertions go here
2388
- end
2597
+ class TestHashDelegatorHandleGenericBlock < Minitest::Test
2598
+ def setup
2599
+ @hd = HashDelegator.new
2600
+ @mock_document = mock('MarkdownDocument')
2601
+ @selected_item = mock('FCB')
2602
+ end
2389
2603
 
2390
- def test_compile_execute_and_trigger_reuse_with_output_script
2391
- # Mock the delegate object configuration
2392
- @hd.instance_variable_set(:@delegate_object,
2393
- { output_script: true,
2394
- user_must_approve: false })
2604
+ def test_compile_execute_and_trigger_reuse_without_user_approval
2605
+ # Mock the delegate object configuration
2606
+ @hd.instance_variable_set(:@delegate_object,
2607
+ { output_script: false,
2608
+ user_must_approve: false })
2395
2609
 
2396
- # Test the method with output script option
2397
- # Expectations and assertions go here
2398
- end
2610
+ # Test the method without user approval
2611
+ # Expectations and assertions go here
2399
2612
  end
2400
2613
 
2401
- # require 'stringio'
2614
+ def test_compile_execute_and_trigger_reuse_with_user_approval
2615
+ # Mock the delegate object configuration
2616
+ @hd.instance_variable_set(:@delegate_object,
2617
+ { output_script: false,
2618
+ user_must_approve: true })
2402
2619
 
2403
- class TestHashDelegatorHandleStream < Minitest::Test
2404
- def setup
2405
- @hd = HashDelegator.new
2406
- @hd.instance_variable_set(:@run_state,
2407
- OpenStruct.new(files: { stdout: [] }))
2408
- @hd.instance_variable_set(:@delegate_object,
2409
- { output_stdout: true })
2410
- end
2620
+ # Test the method with user approval
2621
+ # Expectations and assertions go here
2622
+ end
2411
2623
 
2412
- def test_handle_stream
2413
- stream = StringIO.new("line 1\nline 2\n")
2414
- file_type = :stdout
2624
+ def test_compile_execute_and_trigger_reuse_with_output_script
2625
+ # Mock the delegate object configuration
2626
+ @hd.instance_variable_set(:@delegate_object,
2627
+ { output_script: true,
2628
+ user_must_approve: false })
2415
2629
 
2416
- Thread.new { @hd.handle_stream(stream, file_type) }
2630
+ # Test the method with output script option
2631
+ # Expectations and assertions go here
2632
+ end
2633
+ end
2417
2634
 
2418
- @hd.wait_for_stream_processing
2635
+ # require 'stringio'
2419
2636
 
2420
- assert_equal ['line 1', 'line 2'],
2421
- @hd.instance_variable_get(:@run_state).files[:stdout]
2422
- end
2637
+ class TestHashDelegatorHandleStream < Minitest::Test
2638
+ def setup
2639
+ @hd = HashDelegator.new
2640
+ @hd.instance_variable_set(:@run_state,
2641
+ OpenStruct.new(files: { stdout: [] }))
2642
+ @hd.instance_variable_set(:@delegate_object,
2643
+ { output_stdout: true })
2644
+ end
2423
2645
 
2424
- def test_handle_stream_with_io_error
2425
- stream = StringIO.new("line 1\nline 2\n")
2426
- file_type = :stdout
2427
- stream.stubs(:each_line).raises(IOError)
2646
+ def test_handle_stream
2647
+ stream = StringIO.new("line 1\nline 2\n")
2648
+ file_type = :stdout
2428
2649
 
2429
- Thread.new { @hd.handle_stream(stream, file_type) }
2650
+ Thread.new { @hd.handle_stream(stream, file_type) }
2430
2651
 
2431
- @hd.wait_for_stream_processing
2652
+ @hd.wait_for_stream_processing
2432
2653
 
2433
- assert_equal [],
2434
- @hd.instance_variable_get(:@run_state).files[:stdout]
2435
- end
2654
+ assert_equal ['line 1', 'line 2'],
2655
+ @hd.instance_variable_get(:@run_state).files[:stdout]
2436
2656
  end
2437
2657
 
2438
- class TestHashDelegatorIterBlocksFromNestedFiles < Minitest::Test
2439
- def setup
2440
- @hd = HashDelegator.new
2441
- @hd.instance_variable_set(:@delegate_object,
2442
- { filename: 'test.md' })
2443
- @hd.stubs(:check_file_existence).with('test.md').returns(true)
2444
- @hd.stubs(:initial_state).returns({})
2445
- @hd.stubs(:cfile).returns(Minitest::Mock.new)
2446
- @hd.stubs(:update_line_and_block_state)
2447
- end
2448
-
2449
- def test_iter_blocks_from_nested_files
2450
- @hd.cfile.expect(:readlines, ['line 1', 'line 2'], ['test.md'])
2451
- selected_messages = ['filtered message']
2658
+ def test_handle_stream_with_io_error
2659
+ stream = StringIO.new("line 1\nline 2\n")
2660
+ file_type = :stdout
2661
+ stream.stubs(:each_line).raises(IOError)
2452
2662
 
2453
- result = @hd.iter_blocks_from_nested_files { selected_messages }
2454
- assert_equal ['line 1', 'line 2'], result
2663
+ Thread.new { @hd.handle_stream(stream, file_type) }
2455
2664
 
2456
- @hd.cfile.verify
2457
- end
2665
+ @hd.wait_for_stream_processing
2458
2666
 
2459
- def test_iter_blocks_from_nested_files_with_no_file
2460
- @hd.stubs(:check_file_existence).with('test.md').returns(false)
2667
+ assert_equal [],
2668
+ @hd.instance_variable_get(:@run_state).files[:stdout]
2669
+ end
2670
+ end
2461
2671
 
2462
- assert_nil(@hd.iter_blocks_from_nested_files do
2463
- ['filtered message']
2464
- end)
2465
- end
2672
+ class TestHashDelegatorIterBlocksFromNestedFiles < Minitest::Test
2673
+ def setup
2674
+ @hd = HashDelegator.new
2675
+ @hd.instance_variable_set(:@delegate_object,
2676
+ { filename: 'test.md' })
2677
+ @hd.stubs(:check_file_existence).with('test.md').returns(true)
2678
+ @hd.stubs(:initial_state).returns({})
2679
+ @hd.stubs(:cfile).returns(Minitest::Mock.new)
2680
+ @hd.stubs(:update_line_and_block_state)
2466
2681
  end
2467
2682
 
2468
- class TestHashDelegatorMenuChromeColoredOption < Minitest::Test
2469
- def setup
2470
- @hd = HashDelegator.new
2471
- @hd.instance_variable_set(:@delegate_object, {
2472
- menu_option_back_name: 'Back',
2473
- menu_chrome_color: :red,
2474
- menu_chrome_format: '-- %s --'
2475
- })
2476
- @hd.stubs(:menu_chrome_formatted_option).with(:menu_option_back_name).returns('-- Back --')
2477
- @hd.stubs(:string_send_color).with('-- Back --',
2478
- :menu_chrome_color).returns('-- Back --'.red)
2479
- end
2683
+ def test_iter_blocks_from_nested_files
2684
+ @hd.cfile.expect(:readlines, ['line 1', 'line 2'], ['test.md'], import_paths: nil)
2685
+ selected_messages = ['filtered message']
2480
2686
 
2481
- def test_menu_chrome_colored_option_with_color
2482
- assert_equal '-- Back --'.red,
2483
- @hd.menu_chrome_colored_option(:menu_option_back_name)
2484
- end
2687
+ result = @hd.iter_blocks_from_nested_files { selected_messages }
2688
+ assert_equal ['line 1', 'line 2'], result
2485
2689
 
2486
- def test_menu_chrome_colored_option_without_color
2487
- @hd.instance_variable_set(:@delegate_object,
2488
- { menu_option_back_name: 'Back' })
2489
- assert_equal '-- Back --',
2490
- @hd.menu_chrome_colored_option(:menu_option_back_name)
2491
- end
2690
+ @hd.cfile.verify
2492
2691
  end
2493
2692
 
2494
- class TestHashDelegatorMenuChromeFormattedOptionWithoutFormat < Minitest::Test
2495
- def setup
2496
- @hd = HashDelegator.new
2497
- @hd.instance_variable_set(:@delegate_object, {
2498
- menu_option_back_name: "'Back'",
2499
- menu_chrome_format: '-- %s --'
2500
- })
2501
- HashDelegator.stubs(:safeval).with("'Back'").returns('Back')
2502
- end
2503
-
2504
- def test_menu_chrome_formatted_option_with_format
2505
- assert_equal '-- Back --',
2506
- @hd.menu_chrome_formatted_option(:menu_option_back_name)
2507
- end
2693
+ def test_iter_blocks_from_nested_files_with_no_file
2694
+ @hd.stubs(:check_file_existence).with('test.md').returns(false)
2508
2695
 
2509
- def test_menu_chrome_formatted_option_without_format
2510
- @hd.instance_variable_set(:@delegate_object,
2511
- { menu_option_back_name: "'Back'" })
2512
- assert_equal 'Back',
2513
- @hd.menu_chrome_formatted_option(:menu_option_back_name)
2514
- end
2696
+ assert_nil(@hd.iter_blocks_from_nested_files do
2697
+ ['filtered message']
2698
+ end)
2515
2699
  end
2700
+ end
2516
2701
 
2517
- class TestHashDelegatorStartFencedBlock < Minitest::Test
2518
- def setup
2519
- @hd = HashDelegator.new({
2520
- block_name_wrapper_match: 'WRAPPER_REGEX',
2521
- block_calls_scan: 'CALLS_REGEX'
2702
+ class TestHashDelegatorMenuChromeColoredOption < Minitest::Test
2703
+ def setup
2704
+ @hd = HashDelegator.new
2705
+ @hd.instance_variable_set(:@delegate_object, {
2706
+ menu_option_back_name: 'Back',
2707
+ menu_chrome_color: :red,
2708
+ menu_chrome_format: '-- %s --'
2522
2709
  })
2523
- end
2524
-
2525
- def test_start_fenced_block
2526
- line = '```fenced'
2527
- headings = ['Heading 1']
2528
- regex = /```(?<name>\w+)(?<rest>.*)/
2529
-
2530
- fcb = @hd.start_fenced_block(line, headings, regex)
2531
-
2532
- assert_instance_of MarkdownExec::FCB, fcb
2533
- assert_equal headings, fcb.headings
2534
- assert_equal 'fenced', fcb.dname
2535
- end
2710
+ @hd.stubs(:menu_chrome_formatted_option).with(:menu_option_back_name).returns('-- Back --')
2711
+ @hd.stubs(:string_send_color).with('-- Back --',
2712
+ :menu_chrome_color).returns('-- Back --'.red)
2536
2713
  end
2537
2714
 
2538
- class TestHashDelegatorStringSendColor < Minitest::Test
2539
- def setup
2540
- @hd = HashDelegator.new
2541
- @hd.instance_variable_set(:@delegate_object,
2542
- { red: 'red', green: 'green' })
2543
- end
2715
+ def test_menu_chrome_colored_option_with_color
2716
+ assert_equal '-- Back --'.red,
2717
+ @hd.menu_chrome_colored_option(:menu_option_back_name)
2718
+ end
2544
2719
 
2545
- def test_string_send_color
2546
- assert_equal 'Hello'.red, @hd.string_send_color('Hello', :red)
2547
- assert_equal 'World'.green,
2548
- @hd.string_send_color('World', :green)
2549
- assert_equal 'Default'.plain,
2550
- @hd.string_send_color('Default', :blue)
2551
- end
2720
+ def test_menu_chrome_colored_option_without_color
2721
+ @hd.instance_variable_set(:@delegate_object,
2722
+ { menu_option_back_name: 'Back' })
2723
+ assert_equal '-- Back --',
2724
+ @hd.menu_chrome_colored_option(:menu_option_back_name)
2552
2725
  end
2726
+ end
2553
2727
 
2554
- def test_yield_line_if_selected_with_line
2555
- block_called = false
2556
- HashDelegator.yield_line_if_selected('Test line', [:line]) do |type, content|
2557
- block_called = true
2558
- assert_equal :line, type
2559
- assert_equal 'Test line', content.body[0]
2560
- end
2561
- assert block_called
2728
+ class TestHashDelegatorMenuChromeFormattedOptionWithoutFormat < Minitest::Test
2729
+ def setup
2730
+ @hd = HashDelegator.new
2731
+ @hd.instance_variable_set(:@delegate_object, {
2732
+ menu_option_back_name: "'Back'",
2733
+ menu_chrome_format: '-- %s --'
2734
+ })
2735
+ HashDelegator.stubs(:safeval).with("'Back'").returns('Back')
2562
2736
  end
2563
2737
 
2564
- def test_yield_line_if_selected_without_line
2565
- block_called = false
2566
- HashDelegator.yield_line_if_selected('Test line', [:other]) do |_|
2567
- block_called = true
2568
- end
2569
- refute block_called
2738
+ def test_menu_chrome_formatted_option_with_format
2739
+ assert_equal '-- Back --',
2740
+ @hd.menu_chrome_formatted_option(:menu_option_back_name)
2570
2741
  end
2571
2742
 
2572
- def test_yield_line_if_selected_without_block
2573
- result = HashDelegator.yield_line_if_selected('Test line', [:line])
2574
- assert_nil result
2743
+ def test_menu_chrome_formatted_option_without_format
2744
+ @hd.instance_variable_set(:@delegate_object,
2745
+ { menu_option_back_name: "'Back'" })
2746
+ assert_equal 'Back',
2747
+ @hd.menu_chrome_formatted_option(:menu_option_back_name)
2575
2748
  end
2576
2749
  end
2577
2750
 
2578
- class TestHashDelegatorUpdateMenuAttribYieldSelectedWithBody < Minitest::Test
2751
+ class TestHashDelegatorStartFencedBlock < Minitest::Test
2579
2752
  def setup
2580
- @hd = HashDelegator.new
2581
- @fcb = mock('Fcb')
2582
- @fcb.stubs(:body).returns(true)
2583
- HashDelegator.stubs(:initialize_fcb_names)
2584
- HashDelegator.stubs(:default_block_title_from_body)
2585
- Filter.stubs(:yield_to_block_if_applicable)
2753
+ @hd = HashDelegator.new({
2754
+ block_name_wrapper_match: 'WRAPPER_REGEX',
2755
+ block_calls_scan: 'CALLS_REGEX'
2756
+ })
2586
2757
  end
2587
2758
 
2588
- def test_update_menu_attrib_yield_selected_with_body
2589
- HashDelegator.expects(:initialize_fcb_names).with(@fcb)
2590
- HashDelegator.expects(:default_block_title_from_body).with(@fcb)
2591
- Filter.expects(:yield_to_block_if_applicable).with(@fcb, [:some_message], {})
2759
+ def test_start_fenced_block
2760
+ line = '```fenced'
2761
+ headings = ['Heading 1']
2762
+ regex = /```(?<name>\w+)(?<rest>.*)/
2592
2763
 
2593
- HashDelegator.update_menu_attrib_yield_selected(@fcb, [:some_message])
2594
- end
2764
+ fcb = @hd.start_fenced_block(line, headings, regex)
2595
2765
 
2596
- def test_update_menu_attrib_yield_selected_without_body
2597
- @fcb.stubs(:body).returns(nil)
2598
- HashDelegator.expects(:initialize_fcb_names).with(@fcb)
2599
- HashDelegator.update_menu_attrib_yield_selected(@fcb, [:some_message])
2766
+ assert_instance_of MarkdownExec::FCB, fcb
2767
+ assert_equal headings, fcb.headings
2768
+ assert_equal 'fenced', fcb.dname
2600
2769
  end
2601
2770
  end
2602
2771
 
2603
- class TestHashDelegatorWaitForUserSelectedBlock < Minitest::Test
2772
+ class TestHashDelegatorStringSendColor < Minitest::Test
2604
2773
  def setup
2605
2774
  @hd = HashDelegator.new
2606
- HashDelegator.stubs(:error_handler)
2775
+ @hd.instance_variable_set(:@delegate_object,
2776
+ { red: 'red', green: 'green' })
2607
2777
  end
2608
2778
 
2609
- def test_wait_for_user_selected_block_with_back_state
2610
- mock_block_state = Struct.new(:state, :block).new(MenuState::BACK,
2611
- { oname: 'back_block' })
2612
- @hd.stubs(:wait_for_user_selection).returns(mock_block_state)
2779
+ def test_string_send_color
2780
+ assert_equal 'Hello'.red, @hd.string_send_color('Hello', :red)
2781
+ assert_equal 'World'.green,
2782
+ @hd.string_send_color('World', :green)
2783
+ assert_equal 'Default'.plain,
2784
+ @hd.string_send_color('Default', :blue)
2785
+ end
2786
+ end
2613
2787
 
2614
- result = @hd.wait_for_user_selected_block([], ['Block 1', 'Block 2'],
2615
- nil)
2788
+ def test_yield_line_if_selected_with_line
2789
+ block_called = false
2790
+ HashDelegator.yield_line_if_selected('Test line', [:line]) do |type, content|
2791
+ block_called = true
2792
+ assert_equal :line, type
2793
+ assert_equal 'Test line', content.body[0]
2794
+ end
2795
+ assert block_called
2796
+ end
2616
2797
 
2617
- assert_equal 'back_block',
2618
- @hd.instance_variable_get(:@delegate_object)[:block_name]
2619
- assert @hd.instance_variable_get(:@menu_user_clicked_back_link)
2620
- assert_equal mock_block_state, result
2798
+ def test_yield_line_if_selected_without_line
2799
+ block_called = false
2800
+ HashDelegator.yield_line_if_selected('Test line', [:other]) do |_|
2801
+ block_called = true
2621
2802
  end
2803
+ refute block_called
2804
+ end
2622
2805
 
2623
- def test_wait_for_user_selected_block_with_continue_state
2624
- mock_block_state = Struct.new(:state, :block).new(
2625
- MenuState::CONTINUE, { oname: 'continue_block' }
2626
- )
2627
- @hd.stubs(:wait_for_user_selection).returns(mock_block_state)
2806
+ def test_yield_line_if_selected_without_block
2807
+ result = HashDelegator.yield_line_if_selected('Test line', [:line])
2808
+ assert_nil result
2809
+ end
2810
+ end
2628
2811
 
2629
- result = @hd.wait_for_user_selected_block([], ['Block 1', 'Block 2'],
2630
- nil)
2812
+ class TestHashDelegatorUpdateMenuAttribYieldSelectedWithBody < Minitest::Test
2813
+ def setup
2814
+ @hd = HashDelegator.new
2815
+ @fcb = mock('Fcb')
2816
+ @fcb.stubs(:body).returns(true)
2817
+ HashDelegator.stubs(:initialize_fcb_names)
2818
+ HashDelegator.stubs(:default_block_title_from_body)
2819
+ Filter.stubs(:yield_to_block_if_applicable)
2820
+ end
2631
2821
 
2632
- assert_equal 'continue_block',
2633
- @hd.instance_variable_get(:@delegate_object)[:block_name]
2634
- refute @hd.instance_variable_get(:@menu_user_clicked_back_link)
2635
- assert_equal mock_block_state, result
2636
- end
2822
+ def test_update_menu_attrib_yield_selected_with_body
2823
+ HashDelegator.expects(:initialize_fcb_names).with(@fcb)
2824
+ HashDelegator.expects(:default_block_title_from_body).with(@fcb)
2825
+ Filter.expects(:yield_to_block_if_applicable).with(@fcb, [:some_message], {})
2826
+
2827
+ HashDelegator.update_menu_attrib_yield_selected(@fcb, [:some_message])
2637
2828
  end
2638
2829
 
2639
- class TestHashDelegatorYieldToBlock < Minitest::Test
2640
- def setup
2641
- @hd = HashDelegator.new
2642
- @fcb = mock('Fcb')
2643
- MarkdownExec::Filter.stubs(:fcb_select?).returns(true)
2644
- end
2830
+ def test_update_menu_attrib_yield_selected_without_body
2831
+ @fcb.stubs(:body).returns(nil)
2832
+ HashDelegator.expects(:initialize_fcb_names).with(@fcb)
2833
+ HashDelegator.update_menu_attrib_yield_selected(@fcb, [:some_message])
2834
+ end
2835
+ end
2645
2836
 
2646
- def test_yield_to_block_if_applicable_with_correct_conditions
2647
- block_called = false
2648
- Filter.yield_to_block_if_applicable(@fcb, [:blocks]) do |type, fcb|
2649
- block_called = true
2650
- assert_equal :blocks, type
2651
- assert_equal @fcb, fcb
2652
- end
2653
- assert block_called
2654
- end
2837
+ class TestHashDelegatorWaitForUserSelectedBlock < Minitest::Test
2838
+ def setup
2839
+ @hd = HashDelegator.new
2840
+ HashDelegator.stubs(:error_handler)
2841
+ end
2655
2842
 
2656
- def test_yield_to_block_if_applicable_without_block
2657
- result = Filter.yield_to_block_if_applicable(@fcb, [:blocks])
2658
- assert_nil result
2843
+ def test_wait_for_user_selected_block_with_back_state
2844
+ mock_block_state = Struct.new(:state, :block).new(MenuState::BACK,
2845
+ { oname: 'back_block' })
2846
+ @hd.stubs(:wait_for_user_selection).returns(mock_block_state)
2847
+
2848
+ result = @hd.wait_for_user_selected_block([], ['Block 1', 'Block 2'],
2849
+ nil)
2850
+
2851
+ assert_equal 'back_block',
2852
+ @hd.instance_variable_get(:@delegate_object)[:block_name]
2853
+ assert @hd.instance_variable_get(:@menu_user_clicked_back_link)
2854
+ assert_equal mock_block_state, result
2855
+ end
2856
+
2857
+ def test_wait_for_user_selected_block_with_continue_state
2858
+ mock_block_state = Struct.new(:state, :block).new(
2859
+ MenuState::CONTINUE, { oname: 'continue_block' }
2860
+ )
2861
+ @hd.stubs(:wait_for_user_selection).returns(mock_block_state)
2862
+
2863
+ result = @hd.wait_for_user_selected_block([], ['Block 1', 'Block 2'],
2864
+ nil)
2865
+
2866
+ assert_equal 'continue_block',
2867
+ @hd.instance_variable_get(:@delegate_object)[:block_name]
2868
+ refute @hd.instance_variable_get(:@menu_user_clicked_back_link)
2869
+ assert_equal mock_block_state, result
2870
+ end
2871
+ end
2872
+
2873
+ class TestHashDelegatorYieldToBlock < Minitest::Test
2874
+ def setup
2875
+ @hd = HashDelegator.new
2876
+ @fcb = mock('Fcb')
2877
+ MarkdownExec::Filter.stubs(:fcb_select?).returns(true)
2878
+ end
2879
+
2880
+ def test_yield_to_block_if_applicable_with_correct_conditions
2881
+ block_called = false
2882
+ Filter.yield_to_block_if_applicable(@fcb, [:blocks]) do |type, fcb|
2883
+ block_called = true
2884
+ assert_equal :blocks, type
2885
+ assert_equal @fcb, fcb
2659
2886
  end
2887
+ assert block_called
2888
+ end
2660
2889
 
2661
- def test_yield_to_block_if_applicable_with_incorrect_conditions
2662
- block_called = false
2663
- MarkdownExec::Filter.stubs(:fcb_select?).returns(false)
2664
- Filter.yield_to_block_if_applicable(@fcb, [:non_blocks]) do |_|
2665
- block_called = true
2666
- end
2667
- refute block_called
2890
+ def test_yield_to_block_if_applicable_without_block
2891
+ result = Filter.yield_to_block_if_applicable(@fcb, [:blocks])
2892
+ assert_nil result
2893
+ end
2894
+
2895
+ def test_yield_to_block_if_applicable_with_incorrect_conditions
2896
+ block_called = false
2897
+ MarkdownExec::Filter.stubs(:fcb_select?).returns(false)
2898
+ Filter.yield_to_block_if_applicable(@fcb, [:non_blocks]) do |_|
2899
+ block_called = true
2668
2900
  end
2901
+ refute block_called
2669
2902
  end
2670
- end # module MarkdownExec
2671
- end
2903
+ end
2904
+ end # module MarkdownExec