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.
- checksums.yaml +4 -4
- data/.rubocop.yml +3 -0
- data/CHANGELOG.md +33 -3
- data/Gemfile +1 -0
- data/Gemfile.lock +7 -1
- data/Rakefile +1 -0
- data/bin/bmde +1 -1
- data/bin/tab_completion.sh +4 -4
- data/examples/colors.md +2 -1
- data/examples/indent.md +66 -0
- data/examples/linked.md +20 -1
- data/examples/load1.sh +5 -0
- data/examples/load2.sh +5 -0
- data/examples/nickname.md +26 -0
- data/lib/array.rb +4 -0
- data/lib/cached_nested_file_reader.rb +47 -43
- data/lib/ce_get_cost_and_usage.rb +22 -0
- data/lib/constants.rb +7 -0
- data/lib/exceptions.rb +6 -4
- data/lib/fcb.rb +5 -2
- data/lib/filter.rb +6 -8
- data/lib/find_files.rb +99 -0
- data/lib/hash_delegator.rb +1001 -768
- data/lib/markdown_exec/version.rb +1 -1
- data/lib/mdoc.rb +27 -28
- data/lib/menu.src.yml +129 -17
- data/lib/menu.yml +94 -7
- metadata +8 -6
- data/lib/method_sorter.rb +0 -78
- data/lib/pty1.rb +0 -26
- data/lib/regexp_replacer.rb +0 -58
- data/lib/sort_yaml_gpt4.rb +0 -32
data/lib/hash_delegator.rb
CHANGED
@@ -1,6 +1,8 @@
|
|
1
|
-
|
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
|
-
|
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',
|
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
|
-
|
617
|
-
|
618
|
-
|
619
|
-
|
620
|
-
|
621
|
-
|
622
|
-
|
623
|
-
|
624
|
-
|
625
|
-
|
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
|
-
|
628
|
-
|
629
|
-
|
630
|
-
|
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
|
-
|
633
|
-
|
634
|
-
|
635
|
-
|
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]
|
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
|
-
{
|
738
|
-
{
|
739
|
-
{
|
740
|
-
{
|
741
|
-
|
742
|
-
{
|
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
|
-
|
814
|
-
|
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
|
-
|
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
|
-
|
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(
|
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
|
-
|
1172
|
-
|
1173
|
-
|
1174
|
-
|
1175
|
-
|
1176
|
-
|
1177
|
-
|
1178
|
-
|
1179
|
-
|
1180
|
-
|
1181
|
-
|
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
|
-
|
1184
|
-
|
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
|
-
|
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:
|
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
|
-
|
1568
|
+
## append blocks loaded per LinkDataKeys::Load
|
1351
1569
|
#
|
1352
|
-
if link_block_data.fetch('
|
1353
|
-
|
1354
|
-
|
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[
|
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:'
|
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"))
|
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:
|
1857
|
+
dname: dname,
|
1630
1858
|
headings: headings,
|
1631
1859
|
indent: fcb_title_groups.fetch(:indent, ''),
|
1632
|
-
|
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:
|
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(
|
1776
|
-
|
1777
|
-
|
1778
|
-
|
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
|
1828
|
-
require 'bundler/setup'
|
1829
|
-
Bundler.require(:default)
|
2058
|
+
return if $PROGRAM_NAME != __FILE__
|
1830
2059
|
|
1831
|
-
|
1832
|
-
|
2060
|
+
require 'bundler/setup'
|
2061
|
+
Bundler.require(:default)
|
1833
2062
|
|
1834
|
-
|
1835
|
-
|
1836
|
-
def setup
|
1837
|
-
@hd = HashDelegator.new
|
1838
|
-
@mdoc = mock('MarkdownDocument')
|
1839
|
-
end
|
2063
|
+
require 'minitest/autorun'
|
2064
|
+
require 'mocha/minitest'
|
1840
2065
|
|
1841
|
-
|
1842
|
-
|
1843
|
-
|
1844
|
-
|
1845
|
-
|
1846
|
-
|
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
|
-
|
1850
|
-
|
2081
|
+
c = MarkdownExec::HashDelegator.new(obj)
|
2082
|
+
c.pass_args = pigeon
|
1851
2083
|
|
1852
|
-
|
1853
|
-
|
1854
|
-
|
1855
|
-
|
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
|
-
|
1859
|
-
|
1860
|
-
|
2090
|
+
# Call method opts_execute_required_lines
|
2091
|
+
c.execute_required_lines
|
2092
|
+
end
|
1861
2093
|
|
1862
|
-
|
1863
|
-
|
1864
|
-
|
1865
|
-
|
1866
|
-
|
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
|
-
|
1869
|
-
|
1870
|
-
|
1871
|
-
|
1872
|
-
|
1873
|
-
|
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
|
-
|
1876
|
-
|
1877
|
-
|
1878
|
-
|
1879
|
-
|
1880
|
-
|
1881
|
-
|
1882
|
-
|
1883
|
-
|
1884
|
-
|
1885
|
-
|
1886
|
-
|
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
|
-
|
1889
|
-
|
1890
|
-
|
1891
|
-
|
1892
|
-
|
1893
|
-
|
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
|
-
|
1896
|
-
|
1897
|
-
|
2127
|
+
def test_indent_all_lines_without_indent
|
2128
|
+
body = "Line 1\nLine 2"
|
2129
|
+
indent = nil
|
1898
2130
|
|
1899
|
-
|
1900
|
-
|
2131
|
+
assert_equal body, HashDelegator.indent_all_lines(body, indent)
|
2132
|
+
end
|
1901
2133
|
|
1902
|
-
|
1903
|
-
|
1904
|
-
|
2134
|
+
def test_indent_all_lines_with_empty_indent
|
2135
|
+
body = "Line 1\nLine 2"
|
2136
|
+
indent = ''
|
1905
2137
|
|
1906
|
-
|
1907
|
-
|
2138
|
+
assert_equal body, HashDelegator.indent_all_lines(body, indent)
|
2139
|
+
end
|
1908
2140
|
|
1909
|
-
|
1910
|
-
|
1911
|
-
|
2141
|
+
def test_safeval_successful_evaluation
|
2142
|
+
assert_equal 4, HashDelegator.safeval('2 + 2')
|
2143
|
+
end
|
1912
2144
|
|
1913
|
-
|
1914
|
-
|
1915
|
-
|
1916
|
-
|
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
|
-
|
1919
|
-
|
1920
|
-
|
1921
|
-
|
1922
|
-
|
1923
|
-
|
1924
|
-
|
1925
|
-
|
1926
|
-
|
1927
|
-
|
1928
|
-
|
1929
|
-
|
1930
|
-
|
1931
|
-
|
1932
|
-
|
1933
|
-
|
1934
|
-
|
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
|
-
|
1939
|
-
|
1940
|
-
|
1941
|
-
|
1942
|
-
|
1943
|
-
|
1944
|
-
|
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
|
-
|
1949
|
-
|
1950
|
-
|
1951
|
-
|
1952
|
-
|
1953
|
-
|
1954
|
-
|
1955
|
-
|
1956
|
-
|
1957
|
-
|
1958
|
-
|
1959
|
-
|
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
|
-
|
1962
|
-
|
1963
|
-
|
2193
|
+
def test_append_divider_initial
|
2194
|
+
menu_blocks = []
|
2195
|
+
@hd.append_divider(menu_blocks, :initial)
|
1964
2196
|
|
1965
|
-
|
1966
|
-
|
1967
|
-
|
2197
|
+
assert_equal 1, menu_blocks.size
|
2198
|
+
assert_equal 'Formatted Divider', menu_blocks.first.dname
|
2199
|
+
end
|
1968
2200
|
|
1969
|
-
|
1970
|
-
|
1971
|
-
|
2201
|
+
def test_append_divider_final
|
2202
|
+
menu_blocks = []
|
2203
|
+
@hd.append_divider(menu_blocks, :final)
|
1972
2204
|
|
1973
|
-
|
1974
|
-
|
1975
|
-
|
2205
|
+
assert_equal 1, menu_blocks.size
|
2206
|
+
assert_equal 'Formatted Divider', menu_blocks.last.dname
|
2207
|
+
end
|
1976
2208
|
|
1977
|
-
|
1978
|
-
|
1979
|
-
|
1980
|
-
|
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
|
-
|
1983
|
-
end
|
2214
|
+
assert_empty menu_blocks
|
1984
2215
|
end
|
2216
|
+
end
|
1985
2217
|
|
1986
|
-
|
1987
|
-
|
1988
|
-
|
1989
|
-
|
2218
|
+
class TestHashDelegatorBlockFind < Minitest::Test
|
2219
|
+
def setup
|
2220
|
+
@hd = HashDelegator.new
|
2221
|
+
end
|
1990
2222
|
|
1991
|
-
|
1992
|
-
|
1993
|
-
|
1994
|
-
|
1995
|
-
|
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
|
-
|
1998
|
-
|
1999
|
-
|
2000
|
-
|
2001
|
-
|
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
|
-
|
2004
|
-
|
2005
|
-
|
2006
|
-
|
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
|
-
|
2011
|
-
|
2012
|
-
|
2013
|
-
|
2014
|
-
|
2015
|
-
|
2016
|
-
|
2017
|
-
|
2018
|
-
|
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
|
-
|
2021
|
-
|
2252
|
+
def test_blocks_from_nested_files
|
2253
|
+
result = @hd.blocks_from_nested_files
|
2022
2254
|
|
2023
|
-
|
2024
|
-
|
2025
|
-
|
2255
|
+
assert_kind_of Array, result
|
2256
|
+
assert_kind_of FCB, result.first
|
2257
|
+
end
|
2026
2258
|
|
2027
|
-
|
2028
|
-
|
2029
|
-
|
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
|
-
|
2263
|
+
result = @hd.blocks_from_nested_files
|
2032
2264
|
|
2033
|
-
|
2034
|
-
end
|
2265
|
+
assert_kind_of Array, result
|
2035
2266
|
end
|
2267
|
+
end
|
2036
2268
|
|
2037
|
-
|
2038
|
-
|
2039
|
-
|
2040
|
-
|
2041
|
-
|
2042
|
-
|
2043
|
-
|
2044
|
-
|
2045
|
-
|
2046
|
-
|
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
|
-
|
2049
|
-
|
2050
|
-
|
2051
|
-
|
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
|
-
|
2054
|
-
end
|
2285
|
+
assert_equal ['code line'], result
|
2055
2286
|
end
|
2287
|
+
end
|
2056
2288
|
|
2057
|
-
|
2058
|
-
|
2059
|
-
|
2060
|
-
|
2061
|
-
|
2062
|
-
|
2063
|
-
|
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
|
-
|
2066
|
-
|
2067
|
-
|
2068
|
-
|
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
|
-
|
2302
|
+
result = @hd.load_cli_or_user_selected_block(all_blocks, [], nil)
|
2071
2303
|
|
2072
|
-
|
2073
|
-
|
2074
|
-
|
2304
|
+
assert_equal all_blocks.first.merge(block_name_from_ui: false), result.block
|
2305
|
+
assert_nil result.state
|
2306
|
+
end
|
2075
2307
|
|
2076
|
-
|
2077
|
-
|
2078
|
-
|
2079
|
-
|
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
|
-
|
2313
|
+
result = @hd.load_cli_or_user_selected_block([], [], nil)
|
2082
2314
|
|
2083
|
-
|
2084
|
-
|
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
|
-
|
2089
|
-
|
2090
|
-
|
2091
|
-
|
2092
|
-
|
2093
|
-
|
2094
|
-
|
2095
|
-
|
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
|
-
|
2098
|
-
|
2099
|
-
|
2100
|
-
|
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
|
-
|
2335
|
+
count = @hd.count_blocks_in_filename
|
2103
2336
|
|
2104
|
-
|
2105
|
-
|
2337
|
+
assert_equal 2, count
|
2338
|
+
end
|
2106
2339
|
|
2107
|
-
|
2108
|
-
|
2109
|
-
|
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
|
-
|
2345
|
+
count = @hd.count_blocks_in_filename
|
2112
2346
|
|
2113
|
-
|
2114
|
-
end
|
2347
|
+
assert_equal 0, count
|
2115
2348
|
end
|
2349
|
+
end
|
2116
2350
|
|
2117
|
-
|
2118
|
-
|
2119
|
-
|
2120
|
-
|
2121
|
-
|
2122
|
-
|
2123
|
-
|
2124
|
-
|
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
|
-
|
2127
|
-
|
2128
|
-
|
2129
|
-
|
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
|
-
|
2132
|
-
|
2133
|
-
|
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
|
-
|
2136
|
-
|
2369
|
+
HashDelegator.create_file_and_write_string_with_permissions(file_path, content,
|
2370
|
+
chmod_value)
|
2137
2371
|
|
2138
|
-
|
2139
|
-
|
2372
|
+
assert true # Placeholder for actual test assertions
|
2373
|
+
end
|
2140
2374
|
|
2141
|
-
|
2142
|
-
|
2143
|
-
|
2144
|
-
|
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
|
-
|
2147
|
-
|
2148
|
-
|
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
|
-
|
2151
|
-
|
2384
|
+
HashDelegator.create_file_and_write_string_with_permissions(file_path, content,
|
2385
|
+
chmod_value)
|
2152
2386
|
|
2153
|
-
|
2154
|
-
end
|
2387
|
+
assert true # Placeholder for actual test assertions
|
2155
2388
|
end
|
2389
|
+
end
|
2156
2390
|
|
2157
|
-
|
2158
|
-
|
2159
|
-
|
2160
|
-
|
2161
|
-
|
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
|
-
|
2174
|
-
|
2175
|
-
|
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
|
-
|
2179
|
-
assert_equal selected_option, result.block
|
2180
|
-
end
|
2401
|
+
result = @hd.determine_block_state(selected_option)
|
2181
2402
|
|
2182
|
-
|
2183
|
-
|
2403
|
+
assert_equal MenuState::EXIT, result.state
|
2404
|
+
assert_nil result.block
|
2405
|
+
end
|
2184
2406
|
|
2185
|
-
|
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
|
-
|
2188
|
-
|
2189
|
-
end
|
2412
|
+
assert_equal MenuState::BACK, result.state
|
2413
|
+
assert_equal selected_option, result.block
|
2190
2414
|
end
|
2191
2415
|
|
2192
|
-
|
2193
|
-
|
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
|
-
|
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
|
-
|
2421
|
+
assert_equal MenuState::CONTINUE, result.state
|
2422
|
+
assert_equal selected_option, result.block
|
2423
|
+
end
|
2424
|
+
end
|
2207
2425
|
|
2208
|
-
|
2209
|
-
|
2210
|
-
|
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
|
-
|
2214
|
-
|
2215
|
-
|
2216
|
-
|
2217
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
2229
|
-
|
2447
|
+
class TestHashDelegatorFetchColor < Minitest::Test
|
2448
|
+
def setup
|
2449
|
+
@hd = HashDelegator.new
|
2450
|
+
@hd.instance_variable_set(:@delegate_object, {})
|
2451
|
+
end
|
2230
2452
|
|
2231
|
-
|
2232
|
-
|
2233
|
-
|
2234
|
-
|
2235
|
-
|
2236
|
-
|
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
|
-
|
2460
|
+
result = @hd.fetch_color
|
2239
2461
|
|
2240
|
-
|
2241
|
-
end
|
2462
|
+
assert_equal 'Colored Data String', result
|
2242
2463
|
end
|
2243
2464
|
|
2244
|
-
|
2245
|
-
|
2246
|
-
|
2247
|
-
|
2248
|
-
|
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
|
-
|
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
|
-
|
2257
|
-
|
2474
|
+
assert_equal 'Default Colored String', result
|
2475
|
+
end
|
2476
|
+
end
|
2258
2477
|
|
2259
|
-
|
2260
|
-
|
2478
|
+
class TestHashDelegatorFormatReferencesSendColor < Minitest::Test
|
2479
|
+
def setup
|
2480
|
+
@hd = HashDelegator.new
|
2481
|
+
@hd.instance_variable_set(:@delegate_object, {})
|
2482
|
+
end
|
2261
2483
|
|
2262
|
-
|
2263
|
-
|
2264
|
-
|
2265
|
-
|
2266
|
-
|
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
|
-
|
2269
|
-
|
2490
|
+
result = @hd.format_references_send_color(context: { key: 'value' },
|
2491
|
+
color_sym: :execution_report_preview_frame_color)
|
2270
2492
|
|
2271
|
-
|
2272
|
-
end
|
2493
|
+
assert_equal 'Colored String', result
|
2273
2494
|
end
|
2274
2495
|
|
2275
|
-
|
2276
|
-
|
2277
|
-
|
2278
|
-
|
2279
|
-
|
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
|
-
|
2282
|
-
|
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
|
-
|
2286
|
-
|
2505
|
+
assert_equal 'Default Colored String', result
|
2506
|
+
end
|
2507
|
+
end
|
2287
2508
|
|
2288
|
-
|
2289
|
-
|
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
|
-
|
2515
|
+
def test_format_execution_streams_with_valid_key
|
2516
|
+
result = HashDelegator.format_execution_streams(:stdout,
|
2517
|
+
{ stdout: %w[output1 output2] })
|
2292
2518
|
|
2293
|
-
|
2294
|
-
|
2519
|
+
assert_equal 'output1output2', result
|
2520
|
+
end
|
2295
2521
|
|
2296
|
-
|
2297
|
-
|
2522
|
+
def test_format_execution_streams_with_empty_key
|
2523
|
+
@hd.instance_variable_get(:@run_state).stubs(:files).returns({})
|
2298
2524
|
|
2299
|
-
|
2525
|
+
result = HashDelegator.format_execution_streams(:stderr)
|
2300
2526
|
|
2301
|
-
|
2302
|
-
end
|
2527
|
+
assert_equal '', result
|
2303
2528
|
end
|
2304
2529
|
|
2305
|
-
|
2306
|
-
|
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
|
-
|
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
|
-
|
2535
|
+
assert_equal '', result
|
2536
|
+
end
|
2537
|
+
end
|
2316
2538
|
|
2317
|
-
|
2318
|
-
|
2319
|
-
|
2320
|
-
|
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
|
-
|
2325
|
-
|
2326
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
2337
|
-
|
2338
|
-
|
2339
|
-
|
2558
|
+
class TestHashDelegatorHandleBlockState < Minitest::Test
|
2559
|
+
def setup
|
2560
|
+
@hd = HashDelegator.new
|
2561
|
+
@mock_block_state = mock('block_state')
|
2562
|
+
end
|
2340
2563
|
|
2341
|
-
|
2342
|
-
|
2343
|
-
|
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
|
-
|
2568
|
+
@hd.handle_back_or_continue(@mock_block_state)
|
2346
2569
|
|
2347
|
-
|
2348
|
-
|
2349
|
-
|
2350
|
-
|
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
|
-
|
2353
|
-
|
2354
|
-
|
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
|
-
|
2579
|
+
@hd.handle_back_or_continue(@mock_block_state)
|
2357
2580
|
|
2358
|
-
|
2359
|
-
|
2360
|
-
|
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
|
-
|
2364
|
-
|
2365
|
-
|
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
|
-
|
2377
|
-
# Expectations and assertions go here
|
2378
|
-
end
|
2590
|
+
@hd.handle_back_or_continue(@mock_block_state)
|
2379
2591
|
|
2380
|
-
|
2381
|
-
|
2382
|
-
|
2383
|
-
|
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
|
-
|
2387
|
-
|
2388
|
-
|
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
|
-
|
2391
|
-
|
2392
|
-
|
2393
|
-
|
2394
|
-
|
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
|
-
|
2397
|
-
|
2398
|
-
end
|
2610
|
+
# Test the method without user approval
|
2611
|
+
# Expectations and assertions go here
|
2399
2612
|
end
|
2400
2613
|
|
2401
|
-
|
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
|
-
|
2404
|
-
|
2405
|
-
|
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
|
-
|
2413
|
-
|
2414
|
-
|
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
|
-
|
2630
|
+
# Test the method with output script option
|
2631
|
+
# Expectations and assertions go here
|
2632
|
+
end
|
2633
|
+
end
|
2417
2634
|
|
2418
|
-
|
2635
|
+
# require 'stringio'
|
2419
2636
|
|
2420
|
-
|
2421
|
-
|
2422
|
-
|
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
|
-
|
2425
|
-
|
2426
|
-
|
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
|
-
|
2650
|
+
Thread.new { @hd.handle_stream(stream, file_type) }
|
2430
2651
|
|
2431
|
-
|
2652
|
+
@hd.wait_for_stream_processing
|
2432
2653
|
|
2433
|
-
|
2434
|
-
|
2435
|
-
end
|
2654
|
+
assert_equal ['line 1', 'line 2'],
|
2655
|
+
@hd.instance_variable_get(:@run_state).files[:stdout]
|
2436
2656
|
end
|
2437
2657
|
|
2438
|
-
|
2439
|
-
|
2440
|
-
|
2441
|
-
|
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
|
-
|
2454
|
-
assert_equal ['line 1', 'line 2'], result
|
2663
|
+
Thread.new { @hd.handle_stream(stream, file_type) }
|
2455
2664
|
|
2456
|
-
|
2457
|
-
end
|
2665
|
+
@hd.wait_for_stream_processing
|
2458
2666
|
|
2459
|
-
|
2460
|
-
|
2667
|
+
assert_equal [],
|
2668
|
+
@hd.instance_variable_get(:@run_state).files[:stdout]
|
2669
|
+
end
|
2670
|
+
end
|
2461
2671
|
|
2462
|
-
|
2463
|
-
|
2464
|
-
|
2465
|
-
|
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
|
-
|
2469
|
-
|
2470
|
-
|
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
|
-
|
2482
|
-
|
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
|
-
|
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
|
-
|
2495
|
-
|
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
|
-
|
2510
|
-
|
2511
|
-
|
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
|
-
|
2518
|
-
|
2519
|
-
|
2520
|
-
|
2521
|
-
|
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
|
-
|
2524
|
-
|
2525
|
-
|
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
|
-
|
2539
|
-
|
2540
|
-
|
2541
|
-
|
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
|
-
|
2546
|
-
|
2547
|
-
|
2548
|
-
|
2549
|
-
|
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
|
-
|
2555
|
-
|
2556
|
-
HashDelegator.
|
2557
|
-
|
2558
|
-
|
2559
|
-
|
2560
|
-
|
2561
|
-
|
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
|
2565
|
-
|
2566
|
-
|
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
|
2573
|
-
|
2574
|
-
|
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
|
2751
|
+
class TestHashDelegatorStartFencedBlock < Minitest::Test
|
2579
2752
|
def setup
|
2580
|
-
@hd = HashDelegator.new
|
2581
|
-
|
2582
|
-
|
2583
|
-
|
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
|
2589
|
-
|
2590
|
-
|
2591
|
-
|
2759
|
+
def test_start_fenced_block
|
2760
|
+
line = '```fenced'
|
2761
|
+
headings = ['Heading 1']
|
2762
|
+
regex = /```(?<name>\w+)(?<rest>.*)/
|
2592
2763
|
|
2593
|
-
|
2594
|
-
end
|
2764
|
+
fcb = @hd.start_fenced_block(line, headings, regex)
|
2595
2765
|
|
2596
|
-
|
2597
|
-
|
2598
|
-
|
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
|
2772
|
+
class TestHashDelegatorStringSendColor < Minitest::Test
|
2604
2773
|
def setup
|
2605
2774
|
@hd = HashDelegator.new
|
2606
|
-
|
2775
|
+
@hd.instance_variable_set(:@delegate_object,
|
2776
|
+
{ red: 'red', green: 'green' })
|
2607
2777
|
end
|
2608
2778
|
|
2609
|
-
def
|
2610
|
-
|
2611
|
-
|
2612
|
-
|
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
|
-
|
2615
|
-
|
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
|
-
|
2618
|
-
|
2619
|
-
|
2620
|
-
|
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
|
-
|
2624
|
-
|
2625
|
-
|
2626
|
-
|
2627
|
-
|
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
|
-
|
2630
|
-
|
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
|
-
|
2633
|
-
|
2634
|
-
|
2635
|
-
|
2636
|
-
|
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
|
-
|
2640
|
-
|
2641
|
-
|
2642
|
-
|
2643
|
-
|
2644
|
-
|
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
|
-
|
2647
|
-
|
2648
|
-
|
2649
|
-
|
2650
|
-
|
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
|
-
|
2657
|
-
|
2658
|
-
|
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
|
-
|
2662
|
-
|
2663
|
-
|
2664
|
-
|
2665
|
-
|
2666
|
-
|
2667
|
-
|
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
|
2671
|
-
end
|
2903
|
+
end
|
2904
|
+
end # module MarkdownExec
|