markdown_exec 3.2.0 → 3.3.0
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/CHANGELOG.md +27 -0
- data/Gemfile.lock +1 -1
- data/Rakefile +3 -3
- data/bats/block-type-ux-auto.bats +1 -1
- data/bats/block-type-ux-default.bats +1 -1
- data/bats/block-type-ux-echo-hash-transform.bats +1 -1
- data/bats/block-type-ux-echo-hash.bats +2 -2
- data/bats/block-type-ux-exec-hash-transform.bats +8 -0
- data/bats/block-type-ux-exec-hash.bats +15 -0
- data/bats/block-type-ux-exec.bats +1 -1
- data/bats/block-type-ux-force.bats +9 -0
- data/bats/block-type-ux-formats.bats +8 -0
- data/bats/block-type-ux-readonly.bats +1 -1
- data/bats/block-type-ux-row-format.bats +1 -1
- data/bats/block-type-ux-transform.bats +1 -1
- data/bats/import-directive-parameter-symbols.bats +9 -0
- data/bats/import-duplicates.bats +4 -2
- data/bats/import-parameter-symbols.bats +8 -0
- data/bats/markup.bats +1 -1
- data/bats/options.bats +1 -1
- data/bin/tab_completion.sh +5 -1
- data/docs/dev/block-type-ux-echo-hash-transform.md +14 -12
- data/docs/dev/block-type-ux-exec-hash-transform.md +37 -0
- data/docs/dev/block-type-ux-exec-hash.md +93 -0
- data/docs/dev/block-type-ux-force.md +20 -0
- data/docs/dev/block-type-ux-formats.md +58 -0
- data/docs/dev/hexdump_format.md +267 -0
- data/docs/dev/import/parameter-symbols.md +6 -0
- data/docs/dev/import-directive-parameter-symbols.md +9 -0
- data/docs/dev/import-parameter-symbols-template.md +24 -0
- data/docs/dev/import-parameter-symbols.md +6 -0
- data/docs/dev/load-vars-state-demo.md +35 -0
- data/docs/ux-blocks-examples.md +2 -3
- data/examples/import_with_substitution_demo.md +130 -26
- data/examples/imports/organism_template.md +86 -29
- data/lib/cached_nested_file_reader.rb +265 -27
- data/lib/constants.rb +8 -1
- data/lib/env_interface.rb +13 -7
- data/lib/evaluate_shell_expressions.rb +1 -0
- data/lib/fcb.rb +120 -28
- data/lib/format_table.rb +56 -23
- data/lib/fout.rb +5 -0
- data/lib/hash_delegator.rb +1158 -347
- data/lib/markdown_exec/version.rb +1 -1
- data/lib/markdown_exec.rb +2 -0
- data/lib/mdoc.rb +13 -11
- data/lib/menu.src.yml +139 -34
- data/lib/menu.yml +116 -32
- data/lib/string_util.rb +80 -0
- data/lib/table_extractor.rb +170 -64
- data/lib/ww.rb +325 -29
- metadata +18 -2
data/lib/hash_delegator.rb
CHANGED
@@ -97,6 +97,33 @@ module HashDelegatorSelf
|
|
97
97
|
blocks.select { |item| item.send(msg) == value }
|
98
98
|
end
|
99
99
|
|
100
|
+
def chrome_block_criteria
|
101
|
+
[
|
102
|
+
{ center: :table_center, format: :menu_note_format,
|
103
|
+
match: :table_row_multi_line_match, type: BlockType::TEXT },
|
104
|
+
{ case_conversion: :upcase, center: :heading1_center,
|
105
|
+
collapse: :heading1_collapse, collapsible: :heading1_collapsible,
|
106
|
+
color: :menu_heading1_color, format: :menu_heading1_format, level: 1,
|
107
|
+
match: :heading1_match, type: BlockType::HEADING, wrap: true },
|
108
|
+
{ center: :heading2_center,
|
109
|
+
collapse: :heading2_collapse, collapsible: :heading2_collapsible,
|
110
|
+
color: :menu_heading2_color, format: :menu_heading2_format, level: 2,
|
111
|
+
match: :heading2_match, type: BlockType::HEADING, wrap: true },
|
112
|
+
{ case_conversion: :downcase, center: :heading3_center,
|
113
|
+
collapse: :heading3_collapse, collapsible: :heading3_collapsible,
|
114
|
+
color: :menu_heading3_color, format: :menu_heading3_format, level: 3,
|
115
|
+
match: :heading3_match, type: BlockType::HEADING, wrap: true },
|
116
|
+
{ center: :divider4_center,
|
117
|
+
collapse: :divider4_collapse, collapsible: :divider4_collapsible,
|
118
|
+
color: :menu_divider_color, format: :menu_divider_format, level: 4,
|
119
|
+
match: :divider_match, type: BlockType::DIVIDER },
|
120
|
+
{ color: :menu_note_color, format: :menu_note_format,
|
121
|
+
match: :menu_note_match, type: BlockType::TEXT, wrap: true },
|
122
|
+
{ color: :menu_task_color, format: :menu_task_format,
|
123
|
+
match: :menu_task_match, type: BlockType::TEXT, wrap: true }
|
124
|
+
]
|
125
|
+
end
|
126
|
+
|
100
127
|
def count_matches_in_lines(lines, regex)
|
101
128
|
lines.count { |line| line.to_s.match(regex) }
|
102
129
|
end
|
@@ -274,7 +301,9 @@ module HashDelegatorSelf
|
|
274
301
|
lines = blocks_menu.map(&:oname)
|
275
302
|
text_tables = TableExtractor.extract_tables(
|
276
303
|
lines,
|
277
|
-
regexp: delegate_object[:table_parse_regexp]
|
304
|
+
regexp: delegate_object[:table_parse_regexp],
|
305
|
+
multi_line_delimiter: delegate_object[:table_row_multi_line_delimiter],
|
306
|
+
single_line_delimiter: delegate_object[:table_row_single_line_delimiter]
|
278
307
|
)
|
279
308
|
return unless text_tables.count.positive?
|
280
309
|
|
@@ -287,11 +316,16 @@ module HashDelegatorSelf
|
|
287
316
|
column_count: table[:columns],
|
288
317
|
decorate: {
|
289
318
|
border: delegate_object[:table_border_color],
|
290
|
-
header_row:
|
319
|
+
header_row: if table[:rows] == 1
|
320
|
+
delegate_object[:table_row_color]
|
321
|
+
else
|
322
|
+
delegate_object[:table_header_row_color]
|
323
|
+
end,
|
291
324
|
row: delegate_object[:table_row_color],
|
292
325
|
separator_line: delegate_object[:table_separator_line_color]
|
293
326
|
},
|
294
327
|
lines: lines,
|
328
|
+
table: table,
|
295
329
|
table_width: screen_width_for_table,
|
296
330
|
truncate: $table_cell_truncate
|
297
331
|
)
|
@@ -390,11 +424,22 @@ module HashDelegatorSelf
|
|
390
424
|
# @param [String] line The line to be processed.
|
391
425
|
# @param [Array<Symbol>] selected_types A list of message types to check.
|
392
426
|
# @param [Proc] block The block to be called with the line data.
|
393
|
-
def yield_line_if_selected(
|
394
|
-
|
427
|
+
def yield_line_if_selected(
|
428
|
+
line, selected_types, all_fcbs: nil,
|
429
|
+
criteria: nil, source_id: '', &block
|
430
|
+
)
|
395
431
|
return unless block && block_type_selected?(selected_types, :line)
|
396
432
|
|
397
|
-
|
433
|
+
opts = {
|
434
|
+
body: [line],
|
435
|
+
id: source_id
|
436
|
+
}
|
437
|
+
# add style if it is a single line table
|
438
|
+
opts[:criteria] = criteria if criteria
|
439
|
+
|
440
|
+
block.call(:line, persist_fcb_self(all_fcbs, opts))
|
441
|
+
rescue StandardError
|
442
|
+
wwe 'YAML loading error', { body: body, error: $! }
|
398
443
|
end
|
399
444
|
|
400
445
|
def persist_fcb_self(all_fcbs, options)
|
@@ -626,6 +671,8 @@ module MarkdownExec
|
|
626
671
|
|
627
672
|
@compressed_ids = {}
|
628
673
|
@expanded_ids = {}
|
674
|
+
rescue StandardError
|
675
|
+
wwe $!
|
629
676
|
end
|
630
677
|
|
631
678
|
##
|
@@ -709,6 +756,22 @@ module MarkdownExec
|
|
709
756
|
)
|
710
757
|
end
|
711
758
|
|
759
|
+
def annotate_required_lines(name, lines, block_name:)
|
760
|
+
if @delegate_object[:required_lines_with_source_comments] && !lines.empty?
|
761
|
+
formatted = formatted_block_name(block_name,
|
762
|
+
:script_comment_block_name_format)
|
763
|
+
['',
|
764
|
+
"#‡¯¯¯ #{name} ¯¯¯ #{formatted}",
|
765
|
+
'',
|
766
|
+
*lines,
|
767
|
+
'',
|
768
|
+
"#‡___ #{name} ___ #{formatted}",
|
769
|
+
'']
|
770
|
+
else
|
771
|
+
lines || []
|
772
|
+
end
|
773
|
+
end
|
774
|
+
|
712
775
|
# Appends a chrome block, which is a menu option for Back or Exit
|
713
776
|
#
|
714
777
|
# @param all_blocks [Array] The current blocks in the menu
|
@@ -819,6 +882,7 @@ module MarkdownExec
|
|
819
882
|
# @param block_type_color_option [Symbol, nil] The shell color option to apply.
|
820
883
|
# @return [String] The colorized or original name string.
|
821
884
|
def apply_block_type_color_option(name, block_type_color_option)
|
885
|
+
### accept string for color
|
822
886
|
if block_type_color_option && @delegate_object[block_type_color_option].present?
|
823
887
|
string_send_color(name, block_type_color_option)
|
824
888
|
else
|
@@ -866,6 +930,7 @@ module MarkdownExec
|
|
866
930
|
results = {}
|
867
931
|
iter_blocks_from_nested_files do |btype, fcb|
|
868
932
|
count += 1
|
933
|
+
wwt :iter, 'count:', count, 'btype:', btype, 'fcb.id:', fcb&.id
|
869
934
|
case btype
|
870
935
|
when :blocks
|
871
936
|
result = SuccessResult.instance
|
@@ -903,7 +968,11 @@ module MarkdownExec
|
|
903
968
|
center: fcb0.center,
|
904
969
|
chrome: true,
|
905
970
|
collapse: false,
|
906
|
-
disabled: is_enabled_but_inactive
|
971
|
+
disabled: if is_enabled_but_inactive
|
972
|
+
TtyMenu::ENABLE
|
973
|
+
else
|
974
|
+
TtyMenu::DISABLE
|
975
|
+
end,
|
907
976
|
dname: fcb0.indent + menu_line,
|
908
977
|
id: "#{id_prefix}#{index}",
|
909
978
|
indent: fcb0.indent,
|
@@ -922,9 +991,11 @@ module MarkdownExec
|
|
922
991
|
end
|
923
992
|
|
924
993
|
result = fcb.for_menu!(
|
994
|
+
appopts: @delegate_object,
|
925
995
|
block_calls_scan: @delegate_object[:block_calls_scan],
|
926
996
|
block_name_match: @delegate_object[:block_name_match],
|
927
|
-
block_name_nick_match:
|
997
|
+
block_name_nick_match:
|
998
|
+
@delegate_object[:block_name_nick_match],
|
928
999
|
id: fcb.id,
|
929
1000
|
menu_format: @delegate_object[:menu_ux_row_format],
|
930
1001
|
prompt: @delegate_object[:prompt_ux_enter_a_value],
|
@@ -939,9 +1010,11 @@ module MarkdownExec
|
|
939
1010
|
else
|
940
1011
|
# prepare block for menu, may fail and call HashDelegator.error_handler
|
941
1012
|
result = fcb.for_menu!(
|
1013
|
+
appopts: @delegate_object,
|
942
1014
|
block_calls_scan: @delegate_object[:block_calls_scan],
|
943
1015
|
block_name_match: @delegate_object[:block_name_match],
|
944
|
-
block_name_nick_match:
|
1016
|
+
block_name_nick_match:
|
1017
|
+
@delegate_object[:block_name_nick_match],
|
945
1018
|
id: fcb.id,
|
946
1019
|
menu_format: @delegate_object[:menu_ux_row_format],
|
947
1020
|
prompt: @delegate_object[:prompt_ux_enter_a_value],
|
@@ -978,7 +1051,7 @@ module MarkdownExec
|
|
978
1051
|
end
|
979
1052
|
OpenStruct.new(blocks: blocks, results: results)
|
980
1053
|
rescue StandardError
|
981
|
-
wwe 'link_state:', link_state, 'source_id:', source_id, 'btype:', btype,
|
1054
|
+
wwe $!, 'link_state:', link_state, 'source_id:', source_id, 'btype:', btype,
|
982
1055
|
'fcb:', fcb
|
983
1056
|
end
|
984
1057
|
|
@@ -1027,7 +1100,28 @@ module MarkdownExec
|
|
1027
1100
|
|
1028
1101
|
def cfile
|
1029
1102
|
@cfile ||= CachedNestedFileReader.new(
|
1030
|
-
|
1103
|
+
import_directive_line_pattern:
|
1104
|
+
@delegate_object.fetch(:import_directive_line_pattern),
|
1105
|
+
import_directive_parameter_scan:
|
1106
|
+
Regexp.new(
|
1107
|
+
@delegate_object.fetch(:import_directive_parameter_scan, '')
|
1108
|
+
),
|
1109
|
+
import_parameter_variable_assignment:
|
1110
|
+
@delegate_object[:import_parameter_variable_assignment],
|
1111
|
+
shell:
|
1112
|
+
@delegate_object[:shell],
|
1113
|
+
shell_block_name:
|
1114
|
+
@delegate_object[:document_load_shell_block_name],
|
1115
|
+
symbol_command_substitution:
|
1116
|
+
@delegate_object[:import_symbol_command_substitution],
|
1117
|
+
symbol_evaluated_expression:
|
1118
|
+
@delegate_object[:import_symbol_evaluated_expression],
|
1119
|
+
symbol_force_quoted_literal:
|
1120
|
+
@delegate_object[:import_symbol_force_quoted_literal],
|
1121
|
+
symbol_raw_literal:
|
1122
|
+
@delegate_object[:import_symbol_raw_literal],
|
1123
|
+
symbol_variable_reference:
|
1124
|
+
@delegate_object[:import_symbol_variable_reference]
|
1031
1125
|
)
|
1032
1126
|
end
|
1033
1127
|
|
@@ -1045,48 +1139,130 @@ module MarkdownExec
|
|
1045
1139
|
true
|
1046
1140
|
end
|
1047
1141
|
|
1048
|
-
|
1049
|
-
|
1050
|
-
|
1051
|
-
|
1052
|
-
|
1053
|
-
|
1054
|
-
|
1055
|
-
|
1056
|
-
|
1057
|
-
|
1058
|
-
|
1059
|
-
|
1060
|
-
|
1061
|
-
|
1062
|
-
|
1063
|
-
|
1064
|
-
|
1065
|
-
|
1066
|
-
|
1067
|
-
|
1068
|
-
|
1069
|
-
|
1070
|
-
|
1071
|
-
|
1072
|
-
|
1142
|
+
# return code resulting from evaluating all automatic blocks in order
|
1143
|
+
def code_from_auto_blocks(all_blocks, mdoc: nil, default_only: true)
|
1144
|
+
shell_block_name = @delegate_object[:document_load_shell_block_name]
|
1145
|
+
vars_block_name = @delegate_object[:document_load_vars_block_name]
|
1146
|
+
|
1147
|
+
# do not reload the same document
|
1148
|
+
read_shell = @shell_most_recent_filename != @delegate_object[:filename]
|
1149
|
+
read_ux = @ux_most_recent_filename != @delegate_object[:filename]
|
1150
|
+
read_vars = @vars_most_recent_filename != @delegate_object[:filename]
|
1151
|
+
@shell_most_recent_filename = @delegate_object[:filename]
|
1152
|
+
@ux_most_recent_filename = @delegate_object[:filename]
|
1153
|
+
@vars_most_recent_filename = @delegate_object[:filename]
|
1154
|
+
|
1155
|
+
all_code = []
|
1156
|
+
all_blocks.each do |fcb|
|
1157
|
+
block_code = []
|
1158
|
+
if fcb.oname == shell_block_name
|
1159
|
+
if read_shell
|
1160
|
+
# collect code from shell block
|
1161
|
+
code = if mdoc
|
1162
|
+
mdoc.collect_recursively_required_code(
|
1163
|
+
anyname: fcb.id,
|
1164
|
+
### anyname: fcb.pub_name,
|
1165
|
+
label_format_above:
|
1166
|
+
@delegate_object[:shell_code_label_format_above],
|
1167
|
+
label_format_below:
|
1168
|
+
@delegate_object[:shell_code_label_format_below],
|
1169
|
+
block_source: block_source
|
1170
|
+
)[:code]
|
1171
|
+
else
|
1172
|
+
fcb.body
|
1173
|
+
end
|
1174
|
+
block_code = annotate_required_lines('blk:SHELL', code,
|
1175
|
+
block_name: fcb.id)
|
1176
|
+
end
|
1177
|
+
elsif fcb.oname == vars_block_name
|
1178
|
+
if read_vars
|
1179
|
+
block_code = code_from_vars_block_to_set_environment_variables(fcb)
|
1180
|
+
end
|
1181
|
+
elsif fcb.type == 'ux'
|
1182
|
+
if !read_ux
|
1183
|
+
# skip
|
1184
|
+
elsif fcb.is_split_rest?
|
1185
|
+
# ignore
|
1186
|
+
else
|
1187
|
+
command_result_w_e_t_nl =
|
1188
|
+
code_from_ux_block_to_set_environment_variables(
|
1189
|
+
fcb,
|
1190
|
+
mdoc,
|
1191
|
+
force: @delegate_object[:ux_auto_load_force_default],
|
1192
|
+
only_default: default_only,
|
1193
|
+
silent: true
|
1194
|
+
)
|
1195
|
+
block_code = if command_result_w_e_t_nl&.success?
|
1196
|
+
command_result_w_e_t_nl.new_lines
|
1197
|
+
else
|
1198
|
+
[]
|
1199
|
+
end
|
1200
|
+
end
|
1201
|
+
|
1202
|
+
else
|
1203
|
+
# do nothing
|
1204
|
+
end
|
1205
|
+
|
1206
|
+
wwt :code, 'block_code:', block_code unless block_code&.empty?
|
1207
|
+
all_code += block_code
|
1208
|
+
end
|
1209
|
+
|
1210
|
+
all_code.tap { wwt :code, _1 }
|
1211
|
+
rescue StandardError
|
1212
|
+
wwe 'all_blocks.count:', all_blocks.count
|
1073
1213
|
end
|
1074
1214
|
|
1075
|
-
|
1215
|
+
# return code resulting from evaluating all automatic SHELL blocks in order
|
1216
|
+
def code_from_auto_shell_blocks(all_blocks, mdoc: nil)
|
1217
|
+
# a block name is required
|
1218
|
+
# do not reload the most recent filename
|
1219
|
+
block_name = @delegate_object[:document_load_shell_block_name]
|
1220
|
+
unless block_name.present? &&
|
1221
|
+
@shell_most_recent_filename != @delegate_object[:filename]
|
1222
|
+
return
|
1223
|
+
end
|
1224
|
+
|
1225
|
+
@shell_most_recent_filename = @delegate_object[:filename]
|
1226
|
+
|
1227
|
+
# select the first block with the given name
|
1228
|
+
fcb = HashDelegator.block_find(all_blocks, :oname, block_name)
|
1229
|
+
return unless fcb
|
1230
|
+
|
1231
|
+
# collect code from shell block
|
1232
|
+
code = if mdoc
|
1233
|
+
mdoc.collect_recursively_required_code(
|
1234
|
+
anyname: fcb.pub_name,
|
1235
|
+
label_format_above:
|
1236
|
+
@delegate_object[:shell_code_label_format_above],
|
1237
|
+
label_format_below:
|
1238
|
+
@delegate_object[:shell_code_label_format_below],
|
1239
|
+
block_source: block_source
|
1240
|
+
)[:code]
|
1241
|
+
else
|
1242
|
+
fcb.body
|
1243
|
+
end
|
1244
|
+
annotate_required_lines('blk:SHELL', code, block_name: fcb.id)
|
1245
|
+
end
|
1246
|
+
|
1247
|
+
# return code resulting from evaluating all UX blocks in order
|
1248
|
+
def code_from_auto_ux_blocks(
|
1076
1249
|
all_blocks,
|
1077
1250
|
mdoc
|
1078
1251
|
)
|
1252
|
+
# do not reload the most recent filename
|
1079
1253
|
unless @ux_most_recent_filename != @delegate_object[:filename]
|
1080
1254
|
return
|
1081
1255
|
end
|
1082
1256
|
|
1257
|
+
@ux_most_recent_filename = @delegate_object[:filename]
|
1258
|
+
|
1259
|
+
# select all UX blocks, rejecting non-primary split
|
1083
1260
|
blocks = select_automatic_ux_blocks(
|
1084
1261
|
all_blocks.reject(&:is_split_rest?)
|
1085
1262
|
)
|
1086
1263
|
return if blocks.empty?
|
1087
1264
|
|
1088
|
-
|
1089
|
-
|
1265
|
+
# collect code from all ux blocks
|
1090
1266
|
(blocks.each.with_object([]) do |block, merged_options|
|
1091
1267
|
command_result_w_e_t_nl =
|
1092
1268
|
code_from_ux_block_to_set_environment_variables(
|
@@ -1097,6 +1273,7 @@ module MarkdownExec
|
|
1097
1273
|
silent: true
|
1098
1274
|
)
|
1099
1275
|
if command_result_w_e_t_nl.failure?
|
1276
|
+
# if a block fails, proceed with next block
|
1100
1277
|
merged_options
|
1101
1278
|
else
|
1102
1279
|
merged_options.push(command_result_w_e_t_nl.new_lines)
|
@@ -1104,8 +1281,39 @@ module MarkdownExec
|
|
1104
1281
|
end).to_a
|
1105
1282
|
end
|
1106
1283
|
|
1284
|
+
# return code resulting from evaluating all automatic VARS blocks in order
|
1285
|
+
def code_from_auto_vars_blocks(
|
1286
|
+
all_blocks,
|
1287
|
+
block_name: @delegate_object[:document_load_vars_block_name]
|
1288
|
+
)
|
1289
|
+
# a block name is required
|
1290
|
+
# do not reload the most recent filename
|
1291
|
+
unless block_name.present? &&
|
1292
|
+
@vars_most_recent_filename != @delegate_object[:filename]
|
1293
|
+
return
|
1294
|
+
end
|
1295
|
+
|
1296
|
+
@vars_most_recent_filename = @delegate_object[:filename]
|
1297
|
+
|
1298
|
+
# select all blocks with the given name
|
1299
|
+
blocks = HashDelegator.block_select(all_blocks, :oname, block_name)
|
1300
|
+
return if blocks.empty?
|
1301
|
+
|
1302
|
+
# collect code for vars from all blocks
|
1303
|
+
(blocks.each.with_object([]) do |block, merged_options|
|
1304
|
+
merged_options.push(
|
1305
|
+
code_from_vars_block_to_set_environment_variables(block)
|
1306
|
+
)
|
1307
|
+
end).to_a
|
1308
|
+
end
|
1309
|
+
|
1310
|
+
def selected_id_name(selected)
|
1311
|
+
selected.id
|
1312
|
+
end
|
1313
|
+
|
1107
1314
|
# parse YAML body defining the UX for a single variable
|
1108
1315
|
# set ENV value for the variable and return code lines for the same
|
1316
|
+
# for BlockType::UX
|
1109
1317
|
def code_from_ux_block_to_set_environment_variables(
|
1110
1318
|
selected, mdoc, inherited_code: nil, force: true, only_default: false,
|
1111
1319
|
silent:
|
@@ -1115,7 +1323,7 @@ module MarkdownExec
|
|
1115
1323
|
exit_prompt = @delegate_object[:prompt_filespec_back]
|
1116
1324
|
|
1117
1325
|
required = mdoc.collect_recursively_required_code(
|
1118
|
-
anyname: selected
|
1326
|
+
anyname: selected_id_name(selected),
|
1119
1327
|
label_format_above: @delegate_object[:shell_code_label_format_above],
|
1120
1328
|
label_format_below: @delegate_object[:shell_code_label_format_below],
|
1121
1329
|
block_source: block_source
|
@@ -1129,7 +1337,8 @@ module MarkdownExec
|
|
1129
1337
|
|
1130
1338
|
wwt :fcb, 'a required block', block
|
1131
1339
|
|
1132
|
-
|
1340
|
+
body1 = block.raw_body || block.body
|
1341
|
+
case data = safe_yaml_load(body1.join("\n"))
|
1133
1342
|
when Hash
|
1134
1343
|
export = parse_yaml_of_ux_block(
|
1135
1344
|
data,
|
@@ -1146,6 +1355,8 @@ module MarkdownExec
|
|
1146
1355
|
export.required&.each do |precondition|
|
1147
1356
|
required_variables.push "[[ -z $#{precondition} ]] && exit #{EXIT_STATUS_REQUIRED_EMPTY}"
|
1148
1357
|
end
|
1358
|
+
wwt :required_variables, 'required_variables',
|
1359
|
+
required_variables
|
1149
1360
|
|
1150
1361
|
eval_code = join_array_of_arrays(
|
1151
1362
|
inherited_code, # inherited code
|
@@ -1153,6 +1364,7 @@ module MarkdownExec
|
|
1153
1364
|
required_variables, # test conditions
|
1154
1365
|
required[:code] # current block code
|
1155
1366
|
)
|
1367
|
+
wwt :eval_code, 'eval_code:', eval_code
|
1156
1368
|
if only_default
|
1157
1369
|
command_result_w_e_t_nl =
|
1158
1370
|
ux_block_export_automatic(eval_code, export)
|
@@ -1163,7 +1375,9 @@ module MarkdownExec
|
|
1163
1375
|
command_result_w_e_t_nl =
|
1164
1376
|
ux_block_export_activated(eval_code, export, exit_prompt)
|
1165
1377
|
if command_result_w_e_t_nl.failure?
|
1166
|
-
|
1378
|
+
if command_result_w_e_t_nl.warning&.present? && !silent
|
1379
|
+
warn command_result_w_e_t_nl.warning
|
1380
|
+
end
|
1167
1381
|
return command_result_w_e_t_nl
|
1168
1382
|
end
|
1169
1383
|
end
|
@@ -1174,25 +1388,35 @@ module MarkdownExec
|
|
1174
1388
|
process_command_result_lines(command_result_w_e_t_nl, export,
|
1175
1389
|
required_lines)
|
1176
1390
|
required_lines.concat(command_result_w_e_t_nl.new_lines)
|
1391
|
+
|
1392
|
+
required_lines = annotate_required_lines(
|
1393
|
+
'blk:UX', required_lines, block_name: selected.id
|
1394
|
+
)
|
1395
|
+
|
1177
1396
|
command_result_w_e_t_nl.new_lines = required_lines
|
1178
1397
|
ret_command_result = command_result_w_e_t_nl
|
1179
1398
|
else
|
1180
1399
|
raise "Invalid data type: #{data.inspect}"
|
1181
1400
|
end
|
1182
1401
|
end
|
1402
|
+
wwt :required_lines, required_lines
|
1183
1403
|
|
1184
|
-
(ret_command_result || CommandResult.new(
|
1185
|
-
|
1404
|
+
(ret_command_result || CommandResult.new(
|
1405
|
+
stdout: annotate_required_lines(
|
1406
|
+
'blk:UX', required_lines, block_name: selected.id
|
1407
|
+
)
|
1408
|
+
)).tap do |ret|
|
1409
|
+
wwt :cr, ret, caller.deref
|
1186
1410
|
end
|
1187
1411
|
rescue StandardError
|
1188
1412
|
wwe 'selected:', selected, 'required:', required, 'block:', block,
|
1189
1413
|
'data:', data
|
1190
1414
|
end
|
1191
1415
|
|
1416
|
+
# def
|
1192
1417
|
# sets ENV
|
1193
1418
|
def code_from_vars_block_to_set_environment_variables(selected)
|
1194
1419
|
code_lines = []
|
1195
|
-
# code_lines << '# code_from_vars_block_to_set_environment_variables'
|
1196
1420
|
case data = YAML.load(selected.body.join("\n"))
|
1197
1421
|
when Hash
|
1198
1422
|
data.each do |key, value|
|
@@ -1201,12 +1425,15 @@ module MarkdownExec
|
|
1201
1425
|
|
1202
1426
|
next unless @delegate_object[:menu_vars_set_format].present?
|
1203
1427
|
|
1428
|
+
# in-menu display
|
1204
1429
|
formatted_string = format(@delegate_object[:menu_vars_set_format],
|
1205
1430
|
{ key: key, value: value })
|
1431
|
+
|
1432
|
+
# activity dump
|
1206
1433
|
print string_send_color(formatted_string, :menu_vars_set_color)
|
1207
1434
|
end
|
1208
1435
|
end
|
1209
|
-
code_lines
|
1436
|
+
annotate_required_lines('blk:VARS', code_lines, block_name: selected.id)
|
1210
1437
|
rescue StandardError
|
1211
1438
|
wwe 'selected:', selected, 'data:', data, 'key:', key, 'value:', value,
|
1212
1439
|
'code_lines:', code_lines, 'formatted_string:', formatted_string
|
@@ -1386,7 +1613,7 @@ module MarkdownExec
|
|
1386
1613
|
|
1387
1614
|
if allow_execution
|
1388
1615
|
execute_required_lines(
|
1389
|
-
blockname: selected
|
1616
|
+
blockname: selected_id_name(selected),
|
1390
1617
|
erls: { play_bin: play_bin,
|
1391
1618
|
shell: selected_shell(selected.shell) },
|
1392
1619
|
required_lines: required_lines,
|
@@ -1442,17 +1669,12 @@ module MarkdownExec
|
|
1442
1669
|
# Skip processing for shell-type blocks
|
1443
1670
|
next if exclude_types.include?(block.type)
|
1444
1671
|
|
1445
|
-
|
1446
|
-
|
1447
|
-
#
|
1448
|
-
|
1449
|
-
|
1450
|
-
|
1451
|
-
occurrence_count[id] += 1
|
1452
|
-
occurrence_expressions[id] = $LAST_MATCH_INFO['expression']
|
1453
|
-
end
|
1454
|
-
rescue Interrupt
|
1455
|
-
binding.irb
|
1672
|
+
# Scan each block name for matches of the pattern
|
1673
|
+
count_named_group_occurrences_block_body_fix_indent(block).scan(pattern) do |(_, _variable_name)|
|
1674
|
+
pattern.match($LAST_MATCH_INFO.to_s) # Reapply match for named groups
|
1675
|
+
id = $LAST_MATCH_INFO[group_name]
|
1676
|
+
occurrence_count[id] += 1
|
1677
|
+
occurrence_expressions[id] = $LAST_MATCH_INFO['expression']
|
1456
1678
|
end
|
1457
1679
|
end
|
1458
1680
|
|
@@ -1518,7 +1740,9 @@ module MarkdownExec
|
|
1518
1740
|
if wrap
|
1519
1741
|
line_caps = line_caps.flat_map do |line_cap|
|
1520
1742
|
text = line_cap[:text]
|
1521
|
-
wrapper = StringWrapper.new(
|
1743
|
+
wrapper = StringWrapper.new(
|
1744
|
+
width: screen_width_for_wrapping - line_cap[:indent].length
|
1745
|
+
)
|
1522
1746
|
|
1523
1747
|
if text.length > screen_width_for_wrapping
|
1524
1748
|
# Wrap this text and create line_cap objects for each part
|
@@ -1564,13 +1788,16 @@ module MarkdownExec
|
|
1564
1788
|
decorated = apply_tree_decorations(
|
1565
1789
|
oname, color_method, decor_patterns
|
1566
1790
|
)
|
1567
|
-
|
1568
1791
|
line_obj[:line] = line_obj[:indent] + line_obj[:text]
|
1569
1792
|
|
1570
1793
|
if use_fcb
|
1571
1794
|
fcb.center = center
|
1572
1795
|
fcb.chrome = true
|
1573
|
-
fcb.collapse = collapse.nil?
|
1796
|
+
fcb.collapse = if collapse.nil?
|
1797
|
+
(line_obj[:collapse] == COLLAPSIBLE_TOKEN_COLLAPSE)
|
1798
|
+
else
|
1799
|
+
collapse
|
1800
|
+
end
|
1574
1801
|
fcb.disabled = disabled ? TtyMenu::DISABLE : nil
|
1575
1802
|
fcb.dname = line_obj[:indent] + decorated
|
1576
1803
|
fcb.id = "#{id}.#{index}"
|
@@ -1588,7 +1815,12 @@ module MarkdownExec
|
|
1588
1815
|
fcb = persist_fcb(
|
1589
1816
|
center: center,
|
1590
1817
|
chrome: true,
|
1591
|
-
collapse:
|
1818
|
+
collapse:
|
1819
|
+
if collapse.nil?
|
1820
|
+
(line_obj[:collapse] == COLLAPSIBLE_TOKEN_COLLAPSE)
|
1821
|
+
else
|
1822
|
+
collapse
|
1823
|
+
end,
|
1592
1824
|
disabled: disabled ? TtyMenu::DISABLE : nil,
|
1593
1825
|
dname: line_obj[:indent] + decorated,
|
1594
1826
|
id: "#{id}.#{index}",
|
@@ -1618,53 +1850,65 @@ module MarkdownExec
|
|
1618
1850
|
# @param use_chrome [Boolean] Indicates if the chrome styling should
|
1619
1851
|
# be applied.
|
1620
1852
|
def create_and_add_chrome_blocks(blocks, fcb, id: '', init_ids: false)
|
1621
|
-
|
1622
|
-
|
1623
|
-
|
1624
|
-
|
1853
|
+
index = nil
|
1854
|
+
|
1855
|
+
unless (criteria = fcb.criteria)
|
1856
|
+
HashDelegator.chrome_block_criteria.each_with_index do |criteria1, index1|
|
1857
|
+
# rubocop:disable Lint/UselessAssignment
|
1858
|
+
if !@delegate_object[criteria1[:match]].present? ||
|
1859
|
+
!(match_data = fcb.body[0].match @delegate_object[criteria1[:match]])
|
1860
|
+
next
|
1861
|
+
end
|
1862
|
+
# rubocop:enable Lint/UselessAssignment
|
1863
|
+
|
1864
|
+
criteria = criteria1
|
1865
|
+
index = index1
|
1866
|
+
break
|
1625
1867
|
end
|
1868
|
+
end
|
1626
1869
|
|
1627
|
-
|
1628
|
-
# expand references only if block is recognized (not a comment)
|
1629
|
-
yield if block_given?
|
1870
|
+
return unless criteria
|
1630
1871
|
|
1631
|
-
|
1632
|
-
|
1633
|
-
|
1634
|
-
)
|
1635
|
-
end
|
1872
|
+
if block_given?
|
1873
|
+
# expand references only if block is recognized (not a comment)
|
1874
|
+
yield if block_given?
|
1636
1875
|
|
1637
|
-
|
1638
|
-
|
1639
|
-
|
1640
|
-
center: criteria[:center] &&
|
1641
|
-
@delegate_object[criteria[:center]],
|
1642
|
-
|
1643
|
-
collapse: case fcb.collapse_token
|
1644
|
-
when COLLAPSIBLE_TOKEN_COLLAPSE
|
1645
|
-
true
|
1646
|
-
when COLLAPSIBLE_TOKEN_EXPAND
|
1647
|
-
false
|
1648
|
-
else
|
1649
|
-
false
|
1650
|
-
end,
|
1651
|
-
|
1652
|
-
color_method: criteria[:color] &&
|
1653
|
-
@delegate_object[criteria[:color]].to_sym,
|
1654
|
-
decor_patterns:
|
1655
|
-
@decor_patterns_from_delegate_object_for_block_create,
|
1656
|
-
disabled: !(criteria[:collapsible] && @delegate_object[criteria[:collapsible]]),
|
1657
|
-
fcb: fcb,
|
1658
|
-
id: "#{id}.#{index}",
|
1659
|
-
format_option: criteria[:format] &&
|
1660
|
-
@delegate_object[criteria[:format]],
|
1661
|
-
level: criteria[:level],
|
1662
|
-
match_data: mbody,
|
1663
|
-
type: criteria[:type],
|
1664
|
-
wrap: criteria[:wrap]
|
1876
|
+
# parse multiline to capture output of variable expansion
|
1877
|
+
match_data = fcb.body[0].match Regexp.new(
|
1878
|
+
@delegate_object[criteria[:match]], Regexp::MULTILINE
|
1665
1879
|
)
|
1666
|
-
break
|
1667
1880
|
end
|
1881
|
+
|
1882
|
+
create_and_add_chrome_block(
|
1883
|
+
blocks: blocks,
|
1884
|
+
case_conversion: criteria[:case_conversion],
|
1885
|
+
center: criteria[:center] &&
|
1886
|
+
@delegate_object[criteria[:center]],
|
1887
|
+
|
1888
|
+
collapse: case fcb.collapse_token
|
1889
|
+
when COLLAPSIBLE_TOKEN_COLLAPSE
|
1890
|
+
true
|
1891
|
+
when COLLAPSIBLE_TOKEN_EXPAND
|
1892
|
+
false
|
1893
|
+
else
|
1894
|
+
false
|
1895
|
+
end,
|
1896
|
+
|
1897
|
+
color_method: criteria[:color] &&
|
1898
|
+
@delegate_object[criteria[:color]].to_sym,
|
1899
|
+
decor_patterns:
|
1900
|
+
@decor_patterns_from_delegate_object_for_block_create,
|
1901
|
+
disabled: !(criteria[:collapsible] &&
|
1902
|
+
@delegate_object[criteria[:collapsible]]),
|
1903
|
+
fcb: fcb,
|
1904
|
+
id: "#{id}.#{index}",
|
1905
|
+
format_option: criteria[:format] &&
|
1906
|
+
@delegate_object[criteria[:format]],
|
1907
|
+
level: criteria[:level],
|
1908
|
+
match_data: match_data,
|
1909
|
+
type: criteria[:type],
|
1910
|
+
wrap: criteria[:wrap]
|
1911
|
+
)
|
1668
1912
|
end
|
1669
1913
|
|
1670
1914
|
def create_divider(position, source_id: '')
|
@@ -1673,8 +1917,10 @@ module MarkdownExec
|
|
1673
1917
|
else
|
1674
1918
|
:menu_final_divider
|
1675
1919
|
end
|
1676
|
-
oname = format(
|
1677
|
-
|
1920
|
+
oname = format(
|
1921
|
+
@delegate_object[:menu_divider_format],
|
1922
|
+
HashDelegator.safeval(@delegate_object[divider_key])
|
1923
|
+
)
|
1678
1924
|
|
1679
1925
|
persist_fcb(
|
1680
1926
|
chrome: true,
|
@@ -2001,11 +2247,6 @@ module MarkdownExec
|
|
2001
2247
|
|
2002
2248
|
LoadFileLinkState.new(LoadFile::REUSE, link_state)
|
2003
2249
|
|
2004
|
-
# from CLI
|
2005
|
-
elsif selected.nickname == @delegate_object[:menu_option_exit_name][:line]
|
2006
|
-
debounce_reset
|
2007
|
-
LoadFileLinkState.new(LoadFile::EXIT, link_state)
|
2008
|
-
|
2009
2250
|
elsif @menu_user_clicked_back_link
|
2010
2251
|
debounce_reset
|
2011
2252
|
LoadFileLinkState.new(
|
@@ -2042,6 +2283,7 @@ module MarkdownExec
|
|
2042
2283
|
selected,
|
2043
2284
|
@dml_mdoc,
|
2044
2285
|
inherited_code: @dml_link_state.inherited_lines,
|
2286
|
+
only_default: false,
|
2045
2287
|
silent: true
|
2046
2288
|
)
|
2047
2289
|
### TBD if command_result_w_e_t_nl.failure?
|
@@ -2159,16 +2401,19 @@ module MarkdownExec
|
|
2159
2401
|
link_state: LinkState.new, block_source: {}
|
2160
2402
|
)
|
2161
2403
|
link_block_data = HashDelegator.parse_yaml_data_from_body(link_block_body)
|
2404
|
+
|
2162
2405
|
## collect blocks specified by block
|
2163
2406
|
#
|
2164
2407
|
if mdoc
|
2165
2408
|
code_info = mdoc.collect_recursively_required_code(
|
2166
|
-
anyname: selected
|
2409
|
+
anyname: selected_id_name(selected),
|
2410
|
+
block_source: block_source,
|
2167
2411
|
label_format_above: @delegate_object[:shell_code_label_format_above],
|
2168
|
-
label_format_below: @delegate_object[:shell_code_label_format_below]
|
2169
|
-
|
2412
|
+
label_format_below: @delegate_object[:shell_code_label_format_below]
|
2413
|
+
)
|
2414
|
+
code_lines = annotate_required_lines(
|
2415
|
+
'blk:LINK', code_info[:code], block_name: selected.id
|
2170
2416
|
)
|
2171
|
-
code_lines = code_info[:code]
|
2172
2417
|
block_names = code_info[:block_names]
|
2173
2418
|
dependencies = code_info[:dependencies]
|
2174
2419
|
else
|
@@ -2203,9 +2448,8 @@ module MarkdownExec
|
|
2203
2448
|
|
2204
2449
|
# if an eval link block, evaluate code_lines and return its standard output
|
2205
2450
|
#
|
2206
|
-
if link_block_data.fetch(LinkKeys::EVAL,
|
2207
|
-
|
2208
|
-
false)
|
2451
|
+
if link_block_data.fetch(LinkKeys::EVAL, false) ||
|
2452
|
+
link_block_data.fetch(LinkKeys::EXEC, false)
|
2209
2453
|
code_lines += link_block_data_eval(
|
2210
2454
|
link_state, code_lines, selected, link_block_data,
|
2211
2455
|
block_source: block_source,
|
@@ -2222,6 +2466,10 @@ module MarkdownExec
|
|
2222
2466
|
nil
|
2223
2467
|
) || link_block_data.fetch(LinkKeys::BLOCK, nil) || ''
|
2224
2468
|
|
2469
|
+
code_lines = annotate_required_lines(
|
2470
|
+
'blk:LINK', code_lines, block_name: selected.id
|
2471
|
+
)
|
2472
|
+
|
2225
2473
|
if link_block_data[LinkKeys::RETURN]
|
2226
2474
|
pop_add_current_code_to_head_and_trigger_load(
|
2227
2475
|
link_state, block_names, code_lines,
|
@@ -2234,9 +2482,9 @@ module MarkdownExec
|
|
2234
2482
|
curr_block_name: selected.pub_name,
|
2235
2483
|
curr_document_filename: @delegate_object[:filename],
|
2236
2484
|
inherited_block_names:
|
2237
|
-
|
2485
|
+
((link_state&.inherited_block_names || []) + block_names).sort.uniq,
|
2238
2486
|
inherited_dependencies:
|
2239
|
-
|
2487
|
+
(link_state&.inherited_dependencies || {}).merge(dependencies || {}), ### merge, not replace, key data
|
2240
2488
|
inherited_lines: HashDelegator.flatten_and_compact_arrays(
|
2241
2489
|
link_state&.inherited_lines, code_lines
|
2242
2490
|
),
|
@@ -2244,7 +2492,12 @@ module MarkdownExec
|
|
2244
2492
|
next_block_name: next_block_name,
|
2245
2493
|
next_document_filename: next_document_filename,
|
2246
2494
|
next_keep_code: next_keep_code,
|
2247
|
-
next_load_file:
|
2495
|
+
next_load_file:
|
2496
|
+
if next_document_filename == @delegate_object[:filename]
|
2497
|
+
LoadFile::REUSE
|
2498
|
+
else
|
2499
|
+
LoadFile::LOAD
|
2500
|
+
end
|
2248
2501
|
)
|
2249
2502
|
end
|
2250
2503
|
end
|
@@ -2284,7 +2537,9 @@ module MarkdownExec
|
|
2284
2537
|
block_data['view'] || view,
|
2285
2538
|
NamedCaptureExtractor.extract_named_group_match_data(
|
2286
2539
|
file.match(
|
2287
|
-
Regexp.new(
|
2540
|
+
Regexp.new(
|
2541
|
+
block_data['filename_pattern'] || filename_pattern
|
2542
|
+
)
|
2288
2543
|
)
|
2289
2544
|
)
|
2290
2545
|
),
|
@@ -2311,9 +2566,11 @@ module MarkdownExec
|
|
2311
2566
|
reason = 'default Load mode'
|
2312
2567
|
mode = LoadMode::APPEND
|
2313
2568
|
end
|
2569
|
+
wwt :state, '@dml_block_state:', @dml_block_state
|
2314
2570
|
|
2315
2571
|
OpenStruct.new(
|
2316
|
-
code: code,
|
2572
|
+
code: annotate_required_lines('blk:LOAD', code,
|
2573
|
+
block_name: selected.id),
|
2317
2574
|
mode: mode,
|
2318
2575
|
reason: reason
|
2319
2576
|
)
|
@@ -2330,7 +2587,7 @@ module MarkdownExec
|
|
2330
2587
|
def execute_block_type_port_code_lines(mdoc:, selected:, block_source:,
|
2331
2588
|
link_state: LinkState.new)
|
2332
2589
|
required = mdoc.collect_recursively_required_code(
|
2333
|
-
anyname: selected
|
2590
|
+
anyname: selected_id_name(selected),
|
2334
2591
|
label_format_above: @delegate_object[:shell_code_label_format_above],
|
2335
2592
|
label_format_below: @delegate_object[:shell_code_label_format_below],
|
2336
2593
|
block_source: block_source
|
@@ -2361,15 +2618,21 @@ module MarkdownExec
|
|
2361
2618
|
|
2362
2619
|
if selected[:type] == BlockType::OPTS
|
2363
2620
|
# body of blocks is returned as a list of lines to be read an YAML
|
2364
|
-
HashDelegator.flatten_and_compact_arrays(
|
2621
|
+
HashDelegator.flatten_and_compact_arrays(
|
2622
|
+
required[:blocks].map(&:body).flatten(1)
|
2623
|
+
)
|
2365
2624
|
else
|
2366
2625
|
code_lines = if selected.type == BlockType::VARS
|
2367
2626
|
code_from_vars_block_to_set_environment_variables(selected)
|
2368
2627
|
else
|
2369
2628
|
[]
|
2370
2629
|
end
|
2371
|
-
HashDelegator.flatten_and_compact_arrays(
|
2372
|
-
|
2630
|
+
HashDelegator.flatten_and_compact_arrays(
|
2631
|
+
link_state&.inherited_lines,
|
2632
|
+
annotate_required_lines(
|
2633
|
+
'blk:PORT', required[:code] + code_lines, block_name: selected.id
|
2634
|
+
)
|
2635
|
+
)
|
2373
2636
|
end
|
2374
2637
|
end
|
2375
2638
|
|
@@ -2388,6 +2651,11 @@ module MarkdownExec
|
|
2388
2651
|
save_filespec_from_expression(directory_glob).tap do |save_filespec|
|
2389
2652
|
if save_filespec && save_filespec != exit_prompt
|
2390
2653
|
begin
|
2654
|
+
if @delegate_object[:document_save_make_directory]
|
2655
|
+
# make directory if it doesn't exist
|
2656
|
+
FileUtils.mkdir_p(File.dirname(save_filespec))
|
2657
|
+
end
|
2658
|
+
|
2391
2659
|
File.write(save_filespec,
|
2392
2660
|
HashDelegator.join_code_lines(code_lines))
|
2393
2661
|
rescue Errno::ENOENT
|
@@ -2430,8 +2698,10 @@ module MarkdownExec
|
|
2430
2698
|
end
|
2431
2699
|
|
2432
2700
|
# Handle stdin stream
|
2433
|
-
input_thread = handle_stream(
|
2434
|
-
|
2701
|
+
input_thread = handle_stream(
|
2702
|
+
stream: $stdin,
|
2703
|
+
file_type: ExecutionStreams::STD_IN
|
2704
|
+
) do |line|
|
2435
2705
|
stdin.puts(line)
|
2436
2706
|
yield line, nil, nil, exec_thread if block_given?
|
2437
2707
|
end
|
@@ -2560,6 +2830,7 @@ module MarkdownExec
|
|
2560
2830
|
end
|
2561
2831
|
|
2562
2832
|
def expand_references!(fcb, link_state)
|
2833
|
+
wwt :expand_references, 'fcb.id', fcb.id, 'link_state:', link_state
|
2563
2834
|
# options expansions
|
2564
2835
|
expand_variable_references!(
|
2565
2836
|
blocks: [fcb],
|
@@ -2567,8 +2838,9 @@ module MarkdownExec
|
|
2567
2838
|
group_name: :payload,
|
2568
2839
|
initial_code_required: false,
|
2569
2840
|
link_state: link_state,
|
2570
|
-
pattern:
|
2571
|
-
|
2841
|
+
pattern:
|
2842
|
+
@delegate_object[:option_expansion_expression_regexp].present? &&
|
2843
|
+
Regexp.new(@delegate_object[:option_expansion_expression_regexp])
|
2572
2844
|
)
|
2573
2845
|
|
2574
2846
|
# variable expansions
|
@@ -2577,7 +2849,8 @@ module MarkdownExec
|
|
2577
2849
|
echo_formatter: lambda do |variable|
|
2578
2850
|
%(echo "$#{variable}")
|
2579
2851
|
end,
|
2580
|
-
group_name:
|
2852
|
+
group_name:
|
2853
|
+
@delegate_object[:variable_expansion_name_capture_group]&.to_sym,
|
2581
2854
|
initial_code_required: false,
|
2582
2855
|
link_state: link_state,
|
2583
2856
|
pattern: options_variable_expansion_regexp
|
@@ -2587,7 +2860,8 @@ module MarkdownExec
|
|
2587
2860
|
expand_variable_references!(
|
2588
2861
|
blocks: [fcb],
|
2589
2862
|
echo_formatter: lambda { |command| command },
|
2590
|
-
group_name:
|
2863
|
+
group_name:
|
2864
|
+
@delegate_object[:command_substitution_name_capture_group]&.to_sym,
|
2591
2865
|
initial_code_required: false,
|
2592
2866
|
link_state: link_state,
|
2593
2867
|
pattern: options_command_substitution_regexp
|
@@ -2630,29 +2904,37 @@ module MarkdownExec
|
|
2630
2904
|
# no return
|
2631
2905
|
end
|
2632
2906
|
|
2633
|
-
def
|
2634
|
-
bash_script_lines, export,
|
2907
|
+
def ux_block_eval_for_export(
|
2908
|
+
bash_script_lines, export,
|
2909
|
+
data:,
|
2910
|
+
first_only: false,
|
2911
|
+
force:,
|
2912
|
+
printf_expand: false,
|
2913
|
+
silent:,
|
2914
|
+
string: nil
|
2635
2915
|
)
|
2636
|
-
wwp
|
2637
2916
|
exportable = true
|
2638
2917
|
command_result = nil
|
2639
2918
|
new_lines = []
|
2640
|
-
export_string = string.nil? ?
|
2919
|
+
export_string = string.nil? ? data : string
|
2920
|
+
expander = ->(expression) { %(printf '%s' "#{expression}") }
|
2921
|
+
|
2641
2922
|
case export_string
|
2642
2923
|
when String, Integer, Float, TrueClass, FalseClass
|
2643
2924
|
command_result, exportable, = output_from_adhoc_bash_script_file(
|
2644
2925
|
join_array_of_arrays(
|
2645
2926
|
bash_script_lines,
|
2646
|
-
|
2927
|
+
printf_expand ? expander.call(export_string) : [export_string]
|
2647
2928
|
),
|
2648
2929
|
export,
|
2649
2930
|
force: force
|
2650
2931
|
)
|
2651
2932
|
if command_result.exit_status == EXIT_STATUS_REQUIRED_EMPTY
|
2652
2933
|
exportable = false
|
2653
|
-
|
2934
|
+
unless silent
|
2935
|
+
command_result.warning = warning_required_empty(export)
|
2936
|
+
end
|
2654
2937
|
else
|
2655
|
-
### TBD validate/transform?
|
2656
2938
|
# store the transformed value in ENV
|
2657
2939
|
EnvInterface.set(export.name, command_result.stdout.to_s)
|
2658
2940
|
|
@@ -2669,17 +2951,17 @@ module MarkdownExec
|
|
2669
2951
|
join_array_of_arrays(
|
2670
2952
|
bash_script_lines,
|
2671
2953
|
required_lines,
|
2672
|
-
|
2954
|
+
printf_expand ? expander.call(expression) : [expression]
|
2673
2955
|
),
|
2674
2956
|
export,
|
2675
2957
|
force: force
|
2676
2958
|
)
|
2677
2959
|
if command_result.exit_status == EXIT_STATUS_REQUIRED_EMPTY
|
2678
|
-
|
2960
|
+
unless silent
|
2961
|
+
command_result.warning = warning_required_empty(export)
|
2962
|
+
end
|
2679
2963
|
else
|
2680
2964
|
transformed = command_result.stdout.to_s
|
2681
|
-
### TBD validate/transform?
|
2682
|
-
# transformed = if command_result_w_e_t_nl.transformable transform_export_value(name_force[:text], export) else name_force[:text] end
|
2683
2965
|
|
2684
2966
|
# code for subsequent expression evaluations
|
2685
2967
|
required_lines << code_line_to_assign_a_variable(
|
@@ -2691,13 +2973,19 @@ module MarkdownExec
|
|
2691
2973
|
EnvInterface.set(name, transformed)
|
2692
2974
|
|
2693
2975
|
new_lines << { name: name, force: force,
|
2694
|
-
|
2976
|
+
text: command_result.stdout }
|
2695
2977
|
end
|
2696
2978
|
end
|
2979
|
+
|
2980
|
+
break if first_only
|
2697
2981
|
end
|
2982
|
+
else
|
2983
|
+
# do nothing
|
2698
2984
|
end
|
2699
2985
|
|
2700
2986
|
[command_result, exportable, new_lines]
|
2987
|
+
rescue StandardError
|
2988
|
+
wwe bash_script_lines, export, force, silent, string
|
2701
2989
|
end
|
2702
2990
|
|
2703
2991
|
# Retrieves a specific data symbol from the delegate object,
|
@@ -2737,8 +3025,13 @@ module MarkdownExec
|
|
2737
3025
|
# fallback to @dml_menu_blocks if not found.
|
2738
3026
|
def find_block_by_name(blocks, block_name)
|
2739
3027
|
match_block = ->(item) do
|
2740
|
-
[
|
2741
|
-
|
3028
|
+
[
|
3029
|
+
selected_id_name(item),
|
3030
|
+
item.pub_name,
|
3031
|
+
item.nickname,
|
3032
|
+
item.oname,
|
3033
|
+
item.s2title
|
3034
|
+
].include?(block_name)
|
2742
3035
|
end
|
2743
3036
|
|
2744
3037
|
@dml_blocks_in_file.find(&match_block) ||
|
@@ -2785,7 +3078,9 @@ module MarkdownExec
|
|
2785
3078
|
end
|
2786
3079
|
|
2787
3080
|
def format_echo_command(payload)
|
2788
|
-
payload_match = payload.match(
|
3081
|
+
payload_match = payload.match(
|
3082
|
+
@delegate_object[:option_expansion_payload_regexp]
|
3083
|
+
)
|
2789
3084
|
variable = payload_match[:option]
|
2790
3085
|
property = payload_match[:property]
|
2791
3086
|
|
@@ -2833,6 +3128,20 @@ module MarkdownExec
|
|
2833
3128
|
string_send_color(formatted_string, color_sym)
|
2834
3129
|
end
|
2835
3130
|
|
3131
|
+
# for inherited code comments
|
3132
|
+
# for external automation
|
3133
|
+
def formatted_block_name(block_name,
|
3134
|
+
format_sym = :publish_block_name_format)
|
3135
|
+
format(
|
3136
|
+
@delegate_object[format_sym],
|
3137
|
+
{ block: block_name,
|
3138
|
+
document: @delegate_object[:filename],
|
3139
|
+
time: Time.now.utc.strftime(
|
3140
|
+
@delegate_object[:publish_time_format]
|
3141
|
+
) }
|
3142
|
+
)
|
3143
|
+
end
|
3144
|
+
|
2836
3145
|
# Expand expression if it contains format specifiers
|
2837
3146
|
def formatted_expression(expr)
|
2838
3147
|
expr.include?('%{') ? format_expression(expr) : expr
|
@@ -3020,6 +3329,7 @@ module MarkdownExec
|
|
3020
3329
|
) do |nested_line|
|
3021
3330
|
next if nested_line.nil?
|
3022
3331
|
|
3332
|
+
wwt :iterlines, 'nested_line:', nested_line
|
3023
3333
|
update_line_and_block_state(
|
3024
3334
|
nested_line, state, selected_types,
|
3025
3335
|
source_id: "ItrBlkFrmNstFls:#{index}¤#{nested_line.filename}:#{nested_line.index}",
|
@@ -3028,6 +3338,8 @@ module MarkdownExec
|
|
3028
3338
|
|
3029
3339
|
index += 1
|
3030
3340
|
end
|
3341
|
+
rescue StandardError
|
3342
|
+
wwe $!, 'state:', state, 'nested_line:', nested_line
|
3031
3343
|
end
|
3032
3344
|
|
3033
3345
|
def iter_source_blocks(source, source_id: nil, &block)
|
@@ -3062,8 +3374,9 @@ module MarkdownExec
|
|
3062
3374
|
|
3063
3375
|
def link_block_data_eval(link_state, code_lines, selected, link_block_data,
|
3064
3376
|
block_source:, shell:)
|
3065
|
-
all_code = HashDelegator.flatten_and_compact_arrays(
|
3066
|
-
|
3377
|
+
all_code = HashDelegator.flatten_and_compact_arrays(
|
3378
|
+
link_state&.inherited_lines, code_lines
|
3379
|
+
)
|
3067
3380
|
output_lines = []
|
3068
3381
|
|
3069
3382
|
Tempfile.open do |file|
|
@@ -3197,9 +3510,10 @@ module MarkdownExec
|
|
3197
3510
|
|
3198
3511
|
# Loads and updates auto options for document blocks if the current filename has changed.
|
3199
3512
|
#
|
3200
|
-
# This method checks if the delegate object specifies a document load
|
3201
|
-
#
|
3202
|
-
#
|
3513
|
+
# This method checks if the delegate object specifies a document load
|
3514
|
+
# options block name and if the filename has been updated. It then
|
3515
|
+
# selects the appropriate blocks, collects their dependencies, processes
|
3516
|
+
# their options, and updates the menu base with the merged options.
|
3203
3517
|
#
|
3204
3518
|
# @param all_blocks [Array] An array of all block elements.
|
3205
3519
|
# @param mdoc [Object] The document object managing dependencies and options.
|
@@ -3237,27 +3551,6 @@ module MarkdownExec
|
|
3237
3551
|
true
|
3238
3552
|
end
|
3239
3553
|
|
3240
|
-
def load_auto_vars_block(
|
3241
|
-
all_blocks,
|
3242
|
-
block_name: @delegate_object[:document_load_vars_block_name]
|
3243
|
-
)
|
3244
|
-
unless block_name.present? &&
|
3245
|
-
@vars_most_recent_filename != @delegate_object[:filename]
|
3246
|
-
return
|
3247
|
-
end
|
3248
|
-
|
3249
|
-
blocks = HashDelegator.block_select(all_blocks, :oname, block_name)
|
3250
|
-
return if blocks.empty?
|
3251
|
-
|
3252
|
-
@vars_most_recent_filename = @delegate_object[:filename]
|
3253
|
-
|
3254
|
-
(blocks.each.with_object([]) do |block, merged_options|
|
3255
|
-
merged_options.push(
|
3256
|
-
code_from_vars_block_to_set_environment_variables(block)
|
3257
|
-
)
|
3258
|
-
end).to_a
|
3259
|
-
end
|
3260
|
-
|
3261
3554
|
def load_cli_or_user_selected_block(all_blocks: [], menu_blocks: [],
|
3262
3555
|
prior_answer: nil)
|
3263
3556
|
if @delegate_object[:block_name].present?
|
@@ -3278,30 +3571,6 @@ module MarkdownExec
|
|
3278
3571
|
SelectedBlockMenuState.new(block, source, state)
|
3279
3572
|
end
|
3280
3573
|
|
3281
|
-
def load_document_shell_block(all_blocks, mdoc: nil)
|
3282
|
-
block_name = @delegate_object[:document_load_shell_block_name]
|
3283
|
-
unless block_name.present? &&
|
3284
|
-
@shell_most_recent_filename != @delegate_object[:filename]
|
3285
|
-
return
|
3286
|
-
end
|
3287
|
-
|
3288
|
-
fcb = HashDelegator.block_find(all_blocks, :oname, block_name)
|
3289
|
-
return unless fcb
|
3290
|
-
|
3291
|
-
@shell_most_recent_filename = @delegate_object[:filename]
|
3292
|
-
|
3293
|
-
if mdoc
|
3294
|
-
mdoc.collect_recursively_required_code(
|
3295
|
-
anyname: fcb.id,####
|
3296
|
-
label_format_above: @delegate_object[:shell_code_label_format_above],
|
3297
|
-
label_format_below: @delegate_object[:shell_code_label_format_below],
|
3298
|
-
block_source: block_source
|
3299
|
-
)[:code]
|
3300
|
-
else
|
3301
|
-
fcb.body
|
3302
|
-
end
|
3303
|
-
end
|
3304
|
-
|
3305
3574
|
# format + glob + select for file in load block
|
3306
3575
|
# name has references to ENV vars and doc and batch vars
|
3307
3576
|
# incl. timestamp
|
@@ -3393,32 +3662,21 @@ module MarkdownExec
|
|
3393
3662
|
reload_blocks = true
|
3394
3663
|
end
|
3395
3664
|
|
3396
|
-
#
|
3397
|
-
#
|
3398
|
-
if (code_lines = load_document_shell_block(all_blocks, mdoc: mdoc))
|
3399
|
-
next_state_set_code(nil, link_state, code_lines)
|
3400
|
-
link_state.inherited_lines = code_lines
|
3401
|
-
reload_blocks = true
|
3402
|
-
end
|
3403
|
-
|
3404
|
-
# load document ux block
|
3665
|
+
# return code resulting from evaluating all SHELL, UX, VARS blocks;
|
3666
|
+
# each set in sequence; with its own order
|
3405
3667
|
#
|
3406
|
-
if (code_lines =
|
3407
|
-
|
3408
|
-
|
3409
|
-
|
3410
|
-
|
3411
|
-
|
3412
|
-
|
3413
|
-
|
3414
|
-
# load document vars block
|
3415
|
-
#
|
3416
|
-
if (code_lines = load_auto_vars_block(all_blocks))
|
3417
|
-
new_code = HashDelegator.flatten_and_compact_arrays(link_state.inherited_lines,
|
3418
|
-
code_lines)
|
3668
|
+
if (code_lines = code_from_auto_blocks(
|
3669
|
+
all_blocks,
|
3670
|
+
default_only: true,
|
3671
|
+
mdoc: mdoc
|
3672
|
+
))&.select_by(:empty?, false)&.compact&.count&.positive?
|
3673
|
+
new_code = code_lines
|
3674
|
+
wwt :code_lines, 'code_lines:', code_lines
|
3419
3675
|
next_state_set_code(nil, link_state, new_code)
|
3420
3676
|
link_state.inherited_lines = new_code
|
3421
3677
|
reload_blocks = true
|
3678
|
+
else
|
3679
|
+
link_state&.inherited_lines
|
3422
3680
|
end
|
3423
3681
|
|
3424
3682
|
if reload_blocks
|
@@ -3493,7 +3751,7 @@ module MarkdownExec
|
|
3493
3751
|
end
|
3494
3752
|
end
|
3495
3753
|
|
3496
|
-
def menu_add_disabled_option(document_glob)
|
3754
|
+
def menu_add_disabled_option(document_glob, id)
|
3497
3755
|
raise unless document_glob.present?
|
3498
3756
|
raise if @dml_menu_blocks.nil?
|
3499
3757
|
|
@@ -3503,13 +3761,16 @@ module MarkdownExec
|
|
3503
3761
|
#
|
3504
3762
|
return unless block.nil?
|
3505
3763
|
|
3764
|
+
dname = HashDelegator.new(@delegate_object).string_send_color(
|
3765
|
+
document_glob, :menu_inherited_lines_color
|
3766
|
+
)
|
3767
|
+
|
3506
3768
|
chrome_block = persist_fcb(
|
3507
3769
|
chrome: true,
|
3508
3770
|
disabled: TtyMenu::DISABLE,
|
3509
|
-
dname:
|
3510
|
-
document_glob, :menu_inherited_lines_color
|
3511
|
-
),
|
3771
|
+
dname: dname,
|
3512
3772
|
# 2025-01-03 menu item is disabled ∴ does not need a recall id
|
3773
|
+
id: id,
|
3513
3774
|
oname: formatted_name
|
3514
3775
|
)
|
3515
3776
|
|
@@ -3779,7 +4040,8 @@ module MarkdownExec
|
|
3779
4040
|
end
|
3780
4041
|
end
|
3781
4042
|
|
3782
|
-
# This method handles the back-link operation in
|
4043
|
+
# This method handles the back-link operation in
|
4044
|
+
# the Markdown execution context.
|
3783
4045
|
# It updates the history state for the next block.
|
3784
4046
|
#
|
3785
4047
|
# @return [LinkState] An object indicating the state for
|
@@ -3834,12 +4096,13 @@ module MarkdownExec
|
|
3834
4096
|
multiline = fcb.indented_decorated ||
|
3835
4097
|
(fcb.indent + (fcb.s1decorated || fcb.dname))
|
3836
4098
|
|
3837
|
-
fcb.name = multiline.
|
4099
|
+
fcb.name = multiline.split("\n",
|
4100
|
+
-1).each_with_index.map do |line, index|
|
3838
4101
|
if fcb.fetch(:disabled, nil).nil?
|
3839
4102
|
index.zero? ? active : inactive
|
3840
4103
|
else
|
3841
4104
|
inactive
|
3842
|
-
end + line
|
4105
|
+
end + line
|
3843
4106
|
end.join("\n")
|
3844
4107
|
|
3845
4108
|
fcb.value = fcb.id || fcb.name.split("\n").first
|
@@ -3885,8 +4148,10 @@ module MarkdownExec
|
|
3885
4148
|
raise StandardError, $!
|
3886
4149
|
end
|
3887
4150
|
|
3888
|
-
def process_string_array(
|
3889
|
-
|
4151
|
+
def process_string_array(
|
4152
|
+
arr, begin_pattern: nil, end_pattern: nil, scan1: nil,
|
4153
|
+
format1: nil, name: ''
|
4154
|
+
)
|
3890
4155
|
in_block = !begin_pattern.present?
|
3891
4156
|
collected_lines = []
|
3892
4157
|
|
@@ -3939,6 +4204,9 @@ module MarkdownExec
|
|
3939
4204
|
|
3940
4205
|
@allowed_execution_block = @prior_execution_block
|
3941
4206
|
true
|
4207
|
+
rescue TTY::Reader::InputInterrupt
|
4208
|
+
# treat as denial
|
4209
|
+
false
|
3942
4210
|
end
|
3943
4211
|
|
3944
4212
|
def prompt_for_command(prompt)
|
@@ -4022,6 +4290,9 @@ module MarkdownExec
|
|
4022
4290
|
end
|
4023
4291
|
|
4024
4292
|
sel == MenuOptions::YES
|
4293
|
+
rescue TTY::Reader::InputInterrupt
|
4294
|
+
# treat as denial
|
4295
|
+
false
|
4025
4296
|
end
|
4026
4297
|
|
4027
4298
|
def prompt_margin_left_text
|
@@ -4046,7 +4317,14 @@ module MarkdownExec
|
|
4046
4317
|
menu.choice @delegate_object[:prompt_yes]
|
4047
4318
|
menu.choice @delegate_object[:prompt_exit]
|
4048
4319
|
end
|
4049
|
-
sel == @delegate_object[:prompt_exit]
|
4320
|
+
sel == if @delegate_object[:prompt_exit]
|
4321
|
+
MenuState::EXIT
|
4322
|
+
else
|
4323
|
+
MenuState::CONTINUE
|
4324
|
+
end
|
4325
|
+
rescue TTY::Reader::InputInterrupt
|
4326
|
+
# treat as denial
|
4327
|
+
MenuState::EXIT
|
4050
4328
|
end
|
4051
4329
|
|
4052
4330
|
# public
|
@@ -4075,6 +4353,9 @@ module MarkdownExec
|
|
4075
4353
|
end
|
4076
4354
|
end
|
4077
4355
|
end
|
4356
|
+
rescue TTY::Reader::InputInterrupt
|
4357
|
+
# treat as no selection
|
4358
|
+
nil
|
4078
4359
|
end
|
4079
4360
|
|
4080
4361
|
# user prompt to exit if the menu will be displayed again
|
@@ -4111,15 +4392,6 @@ module MarkdownExec
|
|
4111
4392
|
end
|
4112
4393
|
end
|
4113
4394
|
|
4114
|
-
# # Handle expression with wildcard characters
|
4115
|
-
# # allow user to select or enter
|
4116
|
-
# def puts_gets_oprompt_(filespec)
|
4117
|
-
# puts format(@delegate_object[:prompt_show_expr_format],
|
4118
|
-
# { expr: filespec })
|
4119
|
-
# puts @delegate_object[:prompt_enter_filespec]
|
4120
|
-
# gets.chomp
|
4121
|
-
# end
|
4122
|
-
|
4123
4395
|
def read_saved_assets_for_history_table(
|
4124
4396
|
asset: nil,
|
4125
4397
|
filename: nil,
|
@@ -4353,7 +4625,9 @@ module MarkdownExec
|
|
4353
4625
|
required_lines:, selected:, shell:
|
4354
4626
|
)
|
4355
4627
|
write_command_file(
|
4356
|
-
required_lines: required_lines,
|
4628
|
+
required_lines: required_lines,
|
4629
|
+
blockname: selected.pub_name,
|
4630
|
+
shell: selected_shell(shell)
|
4357
4631
|
)
|
4358
4632
|
@fout.fout "File saved: #{@run_state.saved_filespec}"
|
4359
4633
|
end
|
@@ -4401,7 +4675,8 @@ module MarkdownExec
|
|
4401
4675
|
|
4402
4676
|
def screen_width_for_table
|
4403
4677
|
# menu adds newline after some lines if sized to the edge
|
4404
|
-
|
4678
|
+
# menu prompt symbol (1) + space (1) + gap (1)
|
4679
|
+
screen_width - prompt_margin_left_width - prompt_margin_right_width - 3
|
4405
4680
|
end
|
4406
4681
|
|
4407
4682
|
def screen_width_for_wrapping
|
@@ -4475,14 +4750,12 @@ module MarkdownExec
|
|
4475
4750
|
# no enabled options in page
|
4476
4751
|
return
|
4477
4752
|
end
|
4478
|
-
ww 'selection', selection
|
4479
4753
|
|
4480
4754
|
menu_list = opts.fetch(:match_dml, true) ? @dml_menu_blocks : menu_items
|
4481
4755
|
menu_list ||= tty_menu_items
|
4482
4756
|
selected = menu_list.find do |item|
|
4483
4757
|
if item.instance_of?(Hash)
|
4484
|
-
|
4485
|
-
item[:id] == selection
|
4758
|
+
[item[:id], item[:name], item[:dname]].include?(selection)
|
4486
4759
|
elsif item.instance_of?(MarkdownExec::FCB)
|
4487
4760
|
item.id == selection
|
4488
4761
|
else
|
@@ -4504,10 +4777,14 @@ module MarkdownExec
|
|
4504
4777
|
exit 1
|
4505
4778
|
end
|
4506
4779
|
|
4507
|
-
if
|
4780
|
+
if selected.oname == HashDelegator.safeval(
|
4781
|
+
@delegate_object.fetch(:menu_option_back_name, '')
|
4782
|
+
)[:line]
|
4508
4783
|
selected.option = selection
|
4509
4784
|
selected.type = BlockType::LINK
|
4510
|
-
elsif
|
4785
|
+
elsif selected.oname == HashDelegator.safeval(
|
4786
|
+
@delegate_object.fetch(:menu_option_exit_name, '')
|
4787
|
+
)[:line]
|
4511
4788
|
selected.option = selection
|
4512
4789
|
else
|
4513
4790
|
selected.selected = selection
|
@@ -4648,6 +4925,7 @@ module MarkdownExec
|
|
4648
4925
|
# color_sym is not found in @delegate_object.
|
4649
4926
|
# @return [String] The string with the applied color method.
|
4650
4927
|
def string_send_color(string, color_sym)
|
4928
|
+
### accept string with color as well as symbol for color_hash
|
4651
4929
|
HashDelegator.apply_color_from_hash(string, @delegate_object, color_sym)
|
4652
4930
|
end
|
4653
4931
|
|
@@ -4737,12 +5015,23 @@ module MarkdownExec
|
|
4737
5015
|
@delegate_object[:menu_include_imported_notes]
|
4738
5016
|
# add line if it is depth 0 or option allows it
|
4739
5017
|
#
|
5018
|
+
criteria = nil
|
5019
|
+
if @delegate_object[:table_row_single_line_match]&.present? &&
|
5020
|
+
line.match(@delegate_object[:table_row_single_line_match])
|
5021
|
+
criteria = {
|
5022
|
+
center: :table_center,
|
5023
|
+
match: :table_row_single_line_match
|
5024
|
+
}
|
5025
|
+
end
|
4740
5026
|
HashDelegator.yield_line_if_selected(
|
4741
5027
|
line, selected_types,
|
4742
5028
|
all_fcbs: @fcb_store,
|
5029
|
+
criteria: criteria,
|
4743
5030
|
source_id: source_id, &block
|
4744
5031
|
)
|
4745
5032
|
end
|
5033
|
+
rescue StandardError
|
5034
|
+
wwe $!, 'state:', state, 'nested_line:', nested_line
|
4746
5035
|
end
|
4747
5036
|
|
4748
5037
|
## apply options to current state
|
@@ -4775,10 +5064,13 @@ module MarkdownExec
|
|
4775
5064
|
|
4776
5065
|
case export.allow
|
4777
5066
|
when :echo, ExportValueSource::ECHO
|
4778
|
-
command_result, exportable, new_lines =
|
5067
|
+
command_result, exportable, new_lines = ux_block_eval_for_export(
|
4779
5068
|
bash_script_lines,
|
4780
5069
|
export,
|
5070
|
+
data: export.echo,
|
5071
|
+
first_only: true,
|
4781
5072
|
force: force,
|
5073
|
+
printf_expand: true,
|
4782
5074
|
silent: silent
|
4783
5075
|
)
|
4784
5076
|
|
@@ -4786,15 +5078,20 @@ module MarkdownExec
|
|
4786
5078
|
command_result
|
4787
5079
|
else
|
4788
5080
|
command_result = CommandResult.new(
|
4789
|
-
stdout: menu_from_list_with_back(
|
5081
|
+
stdout: menu_from_list_with_back(
|
5082
|
+
command_result.stdout.split("\n")
|
5083
|
+
)
|
4790
5084
|
)
|
4791
5085
|
end
|
4792
5086
|
|
4793
5087
|
when :exec, UxActSource::EXEC
|
4794
|
-
command_result, =
|
4795
|
-
|
5088
|
+
command_result, exportable, new_lines = ux_block_eval_for_export(
|
5089
|
+
bash_script_lines,
|
4796
5090
|
export,
|
4797
|
-
|
5091
|
+
data: export.exec,
|
5092
|
+
first_only: true,
|
5093
|
+
force: force,
|
5094
|
+
silent: silent
|
4798
5095
|
)
|
4799
5096
|
|
4800
5097
|
if command_result.exit_status == EXIT_STATUS_REQUIRED_EMPTY
|
@@ -4809,10 +5106,13 @@ module MarkdownExec
|
|
4809
5106
|
|
4810
5107
|
else
|
4811
5108
|
export_init = menu_from_list_with_back(export.allow)
|
4812
|
-
command_result, exportable, new_lines =
|
5109
|
+
command_result, exportable, new_lines = ux_block_eval_for_export(
|
4813
5110
|
[assign_key_value_in_bash(export.name, export_init)],
|
4814
5111
|
export,
|
5112
|
+
data: export.echo,
|
5113
|
+
first_only: true,
|
4815
5114
|
force: force,
|
5115
|
+
printf_expand: true,
|
4816
5116
|
silent: silent,
|
4817
5117
|
string: export_init
|
4818
5118
|
)
|
@@ -4820,11 +5120,12 @@ module MarkdownExec
|
|
4820
5120
|
end
|
4821
5121
|
|
4822
5122
|
when :echo, UxActSource::ECHO
|
4823
|
-
|
4824
|
-
command_result, exportable, new_lines = export_echo_with_code(
|
5123
|
+
command_result, exportable, new_lines = ux_block_eval_for_export(
|
4825
5124
|
bash_script_lines,
|
4826
5125
|
export,
|
5126
|
+
data: export.echo,
|
4827
5127
|
force: force,
|
5128
|
+
printf_expand: true,
|
4828
5129
|
silent: silent
|
4829
5130
|
)
|
4830
5131
|
|
@@ -4854,10 +5155,12 @@ module MarkdownExec
|
|
4854
5155
|
command_result = CommandResult.new(stdout: output)
|
4855
5156
|
|
4856
5157
|
when :exec, UxActSource::EXEC
|
4857
|
-
command_result, exportable, new_lines =
|
4858
|
-
|
5158
|
+
command_result, exportable, new_lines = ux_block_eval_for_export(
|
5159
|
+
bash_script_lines,
|
4859
5160
|
export,
|
4860
|
-
|
5161
|
+
data: export.exec,
|
5162
|
+
force: force,
|
5163
|
+
silent: silent
|
4861
5164
|
)
|
4862
5165
|
|
4863
5166
|
else
|
@@ -4875,6 +5178,8 @@ module MarkdownExec
|
|
4875
5178
|
command_result.transformable = transformable
|
4876
5179
|
command_result.new_lines = new_lines
|
4877
5180
|
command_result
|
5181
|
+
rescue StandardError
|
5182
|
+
wwe bash_script_lines, export, exit_prompt
|
4878
5183
|
end
|
4879
5184
|
|
4880
5185
|
def ux_block_export_automatic(
|
@@ -4898,36 +5203,47 @@ module MarkdownExec
|
|
4898
5203
|
|
4899
5204
|
case export.allow
|
4900
5205
|
when :echo, ExportValueSource::ECHO
|
4901
|
-
cr_echo, =
|
4902
|
-
|
4903
|
-
bash_script_lines,
|
4904
|
-
%(printf '%s' "#{export.echo}")
|
4905
|
-
),
|
5206
|
+
cr_echo, = ux_block_eval_for_export(
|
5207
|
+
bash_script_lines,
|
4906
5208
|
export,
|
4907
|
-
|
5209
|
+
data: export.echo,
|
5210
|
+
first_only: true,
|
5211
|
+
force: force,
|
5212
|
+
printf_expand: true,
|
5213
|
+
silent: silent
|
4908
5214
|
)
|
4909
5215
|
export_init = cr_echo.stdout.split("\n").first
|
4910
|
-
|
5216
|
+
|
5217
|
+
command_result, exportable, new_lines = ux_block_eval_for_export(
|
4911
5218
|
[assign_key_value_in_bash(export.name, export_init)],
|
4912
5219
|
export,
|
5220
|
+
data: export.echo,
|
5221
|
+
first_only: true,
|
4913
5222
|
force: force,
|
5223
|
+
printf_expand: true,
|
4914
5224
|
silent: silent,
|
4915
5225
|
string: export_init
|
4916
5226
|
)
|
4917
5227
|
|
4918
5228
|
when :exec, ExportValueSource::EXEC
|
4919
5229
|
# extract first line from 'exec' output
|
4920
|
-
command_result, exportable, new_lines =
|
4921
|
-
|
5230
|
+
command_result, exportable, new_lines = ux_block_eval_for_export(
|
5231
|
+
bash_script_lines,
|
4922
5232
|
export,
|
4923
|
-
|
5233
|
+
data: export.exec,
|
5234
|
+
first_only: true,
|
5235
|
+
force: force,
|
5236
|
+
silent: silent
|
4924
5237
|
)
|
5238
|
+
|
4925
5239
|
unless command_result.failure?
|
4926
5240
|
export_init = command_result.stdout.split("\n").first
|
4927
|
-
command_result, exportable, new_lines =
|
5241
|
+
command_result, exportable, new_lines = ux_block_eval_for_export(
|
4928
5242
|
[assign_key_value_in_bash(export.name, export_init)],
|
4929
5243
|
export,
|
5244
|
+
data: export.exec,
|
4930
5245
|
force: force,
|
5246
|
+
printf_expand: true,
|
4931
5247
|
silent: silent,
|
4932
5248
|
string: export_init
|
4933
5249
|
)
|
@@ -4936,10 +5252,12 @@ module MarkdownExec
|
|
4936
5252
|
else
|
4937
5253
|
# first item from 'allow' list
|
4938
5254
|
export_init = export.allow.first
|
4939
|
-
command_result, exportable, new_lines =
|
5255
|
+
command_result, exportable, new_lines = ux_block_eval_for_export(
|
4940
5256
|
[assign_key_value_in_bash(export.name, export_init)],
|
4941
5257
|
export,
|
5258
|
+
data: export.allow,
|
4942
5259
|
force: force,
|
5260
|
+
printf_expand: true,
|
4943
5261
|
silent: silent,
|
4944
5262
|
string: export_init
|
4945
5263
|
)
|
@@ -4953,32 +5271,37 @@ module MarkdownExec
|
|
4953
5271
|
when :echo, UxActSource::ECHO
|
4954
5272
|
raise unless export.echo.present?
|
4955
5273
|
|
4956
|
-
command_result, exportable, new_lines =
|
5274
|
+
command_result, exportable, new_lines = ux_block_eval_for_export(
|
4957
5275
|
bash_script_lines,
|
4958
5276
|
export,
|
5277
|
+
data: export.echo,
|
4959
5278
|
force: force,
|
5279
|
+
printf_expand: true,
|
4960
5280
|
silent: silent
|
4961
5281
|
)
|
4962
5282
|
|
4963
5283
|
when :exec, UxActSource::EXEC
|
4964
5284
|
raise unless export.exec.present?
|
4965
5285
|
|
4966
|
-
command_result, exportable, new_lines =
|
4967
|
-
|
5286
|
+
command_result, exportable, new_lines = ux_block_eval_for_export(
|
5287
|
+
bash_script_lines,
|
4968
5288
|
export,
|
4969
|
-
|
5289
|
+
data: export.exec,
|
5290
|
+
force: force,
|
5291
|
+
silent: silent
|
4970
5292
|
)
|
4971
5293
|
|
4972
5294
|
else
|
4973
5295
|
export_init = export.init.to_s
|
4974
|
-
command_result, exportable, new_lines =
|
5296
|
+
command_result, exportable, new_lines = ux_block_eval_for_export(
|
4975
5297
|
[assign_key_value_in_bash(export.name, export_init)],
|
4976
5298
|
export,
|
5299
|
+
data: export.exec,
|
4977
5300
|
force: force,
|
5301
|
+
printf_expand: true,
|
4978
5302
|
silent: silent,
|
4979
5303
|
string: export_init
|
4980
5304
|
)
|
4981
|
-
# raise "Unknown FCB.init_source(export) #{FCB.init_source(export)}"
|
4982
5305
|
end
|
4983
5306
|
|
4984
5307
|
# add message for required variables
|
@@ -4991,6 +5314,8 @@ module MarkdownExec
|
|
4991
5314
|
command_result.transformable = transformable
|
4992
5315
|
command_result.new_lines = new_lines
|
4993
5316
|
command_result
|
5317
|
+
rescue StandardError
|
5318
|
+
wwe bash_script_lines, export
|
4994
5319
|
end
|
4995
5320
|
|
4996
5321
|
# true if the variable is exported in a series of evaluations
|
@@ -5001,7 +5326,7 @@ module MarkdownExec
|
|
5001
5326
|
return true if local_name_pattern.empty?
|
5002
5327
|
|
5003
5328
|
# export if it its name does not match the rule
|
5004
|
-
|
5329
|
+
name !~ Regexp.new(local_name_pattern)
|
5005
5330
|
end
|
5006
5331
|
|
5007
5332
|
def vux_await_user_selection(prior_answer: @dml_block_selection)
|
@@ -5020,17 +5345,119 @@ module MarkdownExec
|
|
5020
5345
|
end
|
5021
5346
|
|
5022
5347
|
def vux_clear_menu_state
|
5348
|
+
@dml_block_selection = @dml_block_state.block
|
5023
5349
|
@dml_block_state = SelectedBlockMenuState.new
|
5024
5350
|
@delegate_object[:block_name] = nil
|
5025
5351
|
end
|
5026
5352
|
|
5027
5353
|
def vux_edit_inherited
|
5028
5354
|
edited = edit_text(@dml_link_state.inherited_lines_block)
|
5029
|
-
|
5355
|
+
return unless edited
|
5356
|
+
|
5357
|
+
@dml_link_state.inherited_lines =
|
5358
|
+
annotate_required_lines(
|
5359
|
+
'blk:EDIT', edited.split("\n"), block_name: 'EDIT'
|
5360
|
+
)
|
5361
|
+
end
|
5362
|
+
|
5363
|
+
def block_is_back(fcb)
|
5364
|
+
fcb.oname == HashDelegator.safeval(
|
5365
|
+
@delegate_object[:menu_option_back_name]
|
5366
|
+
)[:line]
|
5367
|
+
end
|
5368
|
+
|
5369
|
+
def block_is_edit(fcb)
|
5370
|
+
fcb.oname == HashDelegator.safeval(
|
5371
|
+
@delegate_object[:menu_option_edit_name]
|
5372
|
+
)[:line]
|
5373
|
+
end
|
5374
|
+
|
5375
|
+
def block_is_exit(fcb)
|
5376
|
+
fcb.oname == HashDelegator.safeval(
|
5377
|
+
@delegate_object[:menu_option_exit_name]
|
5378
|
+
)[:line]
|
5379
|
+
end
|
5380
|
+
|
5381
|
+
def block_is_history(fcb)
|
5382
|
+
fcb.oname == HashDelegator.safeval(
|
5383
|
+
@delegate_object[:menu_option_history_name]
|
5384
|
+
)[:line]
|
5385
|
+
end
|
5386
|
+
|
5387
|
+
def block_is_load(fcb)
|
5388
|
+
fcb.oname == HashDelegator.safeval(
|
5389
|
+
@delegate_object[:menu_option_load_name]
|
5390
|
+
)[:line]
|
5391
|
+
end
|
5392
|
+
|
5393
|
+
def block_is_save(fcb)
|
5394
|
+
fcb.oname == HashDelegator.safeval(
|
5395
|
+
@delegate_object[:menu_option_save_name]
|
5396
|
+
)[:line]
|
5397
|
+
end
|
5398
|
+
|
5399
|
+
def block_is_shell(fcb)
|
5400
|
+
fcb.oname == HashDelegator.safeval(
|
5401
|
+
@delegate_object[:menu_option_shell_name]
|
5402
|
+
)[:line]
|
5403
|
+
end
|
5404
|
+
|
5405
|
+
def block_is_view(fcb)
|
5406
|
+
fcb.oname == HashDelegator.safeval(
|
5407
|
+
@delegate_object[:menu_option_view_name]
|
5408
|
+
)[:line]
|
5030
5409
|
end
|
5031
5410
|
|
5032
5411
|
def vux_execute_and_prompt(block_name)
|
5033
5412
|
@dml_block_state = find_block_state_by_name(block_name)
|
5413
|
+
|
5414
|
+
if @dml_block_state.block
|
5415
|
+
if block_is_back(@dml_block_state.block)
|
5416
|
+
debounce_reset
|
5417
|
+
vux_navigate_back_for_ls
|
5418
|
+
return
|
5419
|
+
|
5420
|
+
elsif block_is_edit(@dml_block_state.block)
|
5421
|
+
debounce_reset
|
5422
|
+
vux_edit_inherited
|
5423
|
+
return pause_user_exit ? :break : nil
|
5424
|
+
|
5425
|
+
elsif block_is_exit(@dml_block_state.block)
|
5426
|
+
debounce_reset
|
5427
|
+
### LoadFileLinkState.new(LoadFile::EXIT, link_state)
|
5428
|
+
return :break
|
5429
|
+
|
5430
|
+
elsif block_is_history(@dml_block_state.block)
|
5431
|
+
debounce_reset
|
5432
|
+
return :break unless (files_table_rows = vux_history_files_table_rows)
|
5433
|
+
|
5434
|
+
execute_history_select(files_table_rows, stream: $stderr)
|
5435
|
+
return :break if pause_user_exit
|
5436
|
+
|
5437
|
+
return
|
5438
|
+
|
5439
|
+
elsif block_is_load(@dml_block_state.block)
|
5440
|
+
debounce_reset
|
5441
|
+
vux_load_inherited
|
5442
|
+
return pause_user_exit ? :break : nil
|
5443
|
+
|
5444
|
+
elsif block_is_save(@dml_block_state.block)
|
5445
|
+
debounce_reset
|
5446
|
+
return execute_inherited_save == :break ? :break : nil
|
5447
|
+
|
5448
|
+
elsif block_is_shell(@dml_block_state.block)
|
5449
|
+
debounce_reset
|
5450
|
+
vux_input_and_execute_shell_commands(stream: $stderr, shell: shell)
|
5451
|
+
return pause_user_exit ? :break : nil
|
5452
|
+
|
5453
|
+
elsif block_is_view(@dml_block_state.block)
|
5454
|
+
debounce_reset
|
5455
|
+
vux_view_inherited(stream: $stderr)
|
5456
|
+
return pause_user_exit ? :break : nil
|
5457
|
+
|
5458
|
+
end
|
5459
|
+
end
|
5460
|
+
|
5034
5461
|
if @dml_block_state.block &&
|
5035
5462
|
@dml_block_state.block.type == BlockType::OPTS
|
5036
5463
|
debounce_reset
|
@@ -5071,62 +5498,12 @@ module MarkdownExec
|
|
5071
5498
|
end
|
5072
5499
|
|
5073
5500
|
def vux_execute_block_per_type(block_name, formatted_choice_ostructs)
|
5074
|
-
|
5075
|
-
when formatted_choice_ostructs[:back].pub_name
|
5076
|
-
debounce_reset
|
5077
|
-
vux_navigate_back_for_ls
|
5078
|
-
|
5079
|
-
when formatted_choice_ostructs[:edit].pub_name
|
5080
|
-
debounce_reset
|
5081
|
-
vux_edit_inherited
|
5082
|
-
return :break if pause_user_exit
|
5083
|
-
|
5084
|
-
InputSequencer.next_link_state(prior_block_was_link: true)
|
5085
|
-
|
5086
|
-
when formatted_choice_ostructs[:history].pub_name
|
5087
|
-
debounce_reset
|
5088
|
-
return :break unless (files_table_rows = vux_history_files_table_rows)
|
5089
|
-
|
5090
|
-
execute_history_select(files_table_rows, stream: $stderr)
|
5091
|
-
return :break if pause_user_exit
|
5092
|
-
|
5093
|
-
InputSequencer.next_link_state(prior_block_was_link: true)
|
5094
|
-
|
5095
|
-
when formatted_choice_ostructs[:load].pub_name
|
5096
|
-
debounce_reset
|
5097
|
-
vux_load_inherited
|
5098
|
-
return :break if pause_user_exit
|
5099
|
-
|
5100
|
-
InputSequencer.next_link_state(prior_block_was_link: true)
|
5101
|
-
|
5102
|
-
when formatted_choice_ostructs[:save].pub_name
|
5103
|
-
debounce_reset
|
5104
|
-
return :break if execute_inherited_save == :break
|
5105
|
-
|
5106
|
-
InputSequencer.next_link_state(prior_block_was_link: true)
|
5107
|
-
|
5108
|
-
when formatted_choice_ostructs[:shell].pub_name
|
5109
|
-
debounce_reset
|
5110
|
-
vux_input_and_execute_shell_commands(stream: $stderr, shell: shell)
|
5111
|
-
return :break if pause_user_exit
|
5112
|
-
|
5113
|
-
InputSequencer.next_link_state(prior_block_was_link: true)
|
5114
|
-
|
5115
|
-
when formatted_choice_ostructs[:view].pub_name
|
5116
|
-
debounce_reset
|
5117
|
-
vux_view_inherited(stream: $stderr)
|
5118
|
-
return :break if pause_user_exit
|
5501
|
+
return :break if vux_execute_and_prompt(block_name) == :break
|
5119
5502
|
|
5120
|
-
|
5121
|
-
|
5122
|
-
|
5123
|
-
|
5124
|
-
|
5125
|
-
InputSequencer.next_link_state(
|
5126
|
-
block_name: @dml_link_state.block_name,
|
5127
|
-
prior_block_was_link: @dml_block_state.block.type != BlockType::SHELL
|
5128
|
-
)
|
5129
|
-
end
|
5503
|
+
InputSequencer.next_link_state(
|
5504
|
+
block_name: @dml_link_state.block_name,
|
5505
|
+
prior_block_was_link: @dml_block_state.block.type != BlockType::SHELL
|
5506
|
+
)
|
5130
5507
|
end
|
5131
5508
|
|
5132
5509
|
def vux_formatted_names_for_state_chrome_blocks(
|
@@ -5276,10 +5653,13 @@ module MarkdownExec
|
|
5276
5653
|
block_list
|
5277
5654
|
).run do |msg, data|
|
5278
5655
|
count += 1
|
5656
|
+
wwt :id, 'count:', count, 'msg:', msg, 'data:', data
|
5279
5657
|
case msg
|
5280
5658
|
when :parse_document # once for each menu
|
5281
5659
|
count = 0
|
5282
|
-
vux_parse_document(
|
5660
|
+
vux_parse_document(
|
5661
|
+
source_id: "#{@delegate_object[:filename]}¤VuxMainLoop®PrsDoc"
|
5662
|
+
)
|
5283
5663
|
vux_menu_append_history_files(
|
5284
5664
|
formatted_choice_ostructs,
|
5285
5665
|
source_id: "#{@delegate_object[:filename]}¤VuxMainLoop®HstFls"
|
@@ -5293,8 +5673,19 @@ module MarkdownExec
|
|
5293
5673
|
when :end_of_cli
|
5294
5674
|
# yield :end_of_cli, @delegate_object
|
5295
5675
|
|
5296
|
-
if @delegate_object[:
|
5297
|
-
|
5676
|
+
if @delegate_object[:blocks].present?
|
5677
|
+
@delegate_object[:list_blocks_message] =
|
5678
|
+
@delegate_object[:blocks].to_sym
|
5679
|
+
@delegate_object[:list_blocks_type] = 3
|
5680
|
+
|
5681
|
+
list_blocks(
|
5682
|
+
source_id: "#{@delegate_object[:filename]}¤VuxMainLoop®EndCLI"
|
5683
|
+
)
|
5684
|
+
:exit
|
5685
|
+
elsif @delegate_object[:list_blocks]
|
5686
|
+
list_blocks(
|
5687
|
+
source_id: "#{@delegate_object[:filename]}¤VuxMainLoop®EndCLI"
|
5688
|
+
)
|
5298
5689
|
:exit
|
5299
5690
|
end
|
5300
5691
|
|
@@ -5365,7 +5756,7 @@ module MarkdownExec
|
|
5365
5756
|
|
5366
5757
|
# add menu items (glob, load, save) and enable selectively
|
5367
5758
|
if files.count.positive? || lines_count.positive?
|
5368
|
-
menu_add_disabled_option(document_glob)
|
5759
|
+
menu_add_disabled_option(document_glob, "#{source_id}_vmahf_glob")
|
5369
5760
|
end
|
5370
5761
|
if files.count.positive?
|
5371
5762
|
dml_menu_append_chrome_item(
|
@@ -5446,14 +5837,7 @@ module MarkdownExec
|
|
5446
5837
|
|
5447
5838
|
def vux_publish_block_name_for_external_automation(block_name)
|
5448
5839
|
publish_for_external_automation(
|
5449
|
-
message:
|
5450
|
-
@delegate_object[:publish_block_name_format],
|
5451
|
-
{ block: block_name,
|
5452
|
-
document: @delegate_object[:filename],
|
5453
|
-
time: Time.now.utc.strftime(
|
5454
|
-
@delegate_object[:publish_time_format]
|
5455
|
-
) }
|
5456
|
-
)
|
5840
|
+
message: formatted_block_name(block_name)
|
5457
5841
|
)
|
5458
5842
|
end
|
5459
5843
|
|
@@ -5489,7 +5873,7 @@ module MarkdownExec
|
|
5489
5873
|
return :break if @dml_block_state.block.nil? # no block matched
|
5490
5874
|
end
|
5491
5875
|
# puts "! - Executing block: #{data}"
|
5492
|
-
@dml_block_state.block&.
|
5876
|
+
@dml_block_state.block&.id
|
5493
5877
|
end
|
5494
5878
|
|
5495
5879
|
def vux_view_inherited(stream:)
|
@@ -5532,11 +5916,12 @@ module MarkdownExec
|
|
5532
5916
|
nil
|
5533
5917
|
when String
|
5534
5918
|
menu_blocks.find do |block|
|
5535
|
-
block.
|
5919
|
+
block.id == prior_answer
|
5536
5920
|
end&.name
|
5537
5921
|
when Struct, MarkdownExec::FCB
|
5538
5922
|
if prior_answer.id
|
5539
|
-
# when switching documents,
|
5923
|
+
# when switching documents,
|
5924
|
+
# the prior answer will not be found
|
5540
5925
|
(menu_blocks.find_index do |block|
|
5541
5926
|
block[:id] == prior_answer.id
|
5542
5927
|
end || 0) + 1
|
@@ -5638,8 +6023,10 @@ module MarkdownExec
|
|
5638
6023
|
if save_expr.present?
|
5639
6024
|
save_filespec = save_filespec_from_expression(save_expr)
|
5640
6025
|
if save_filespec.present?
|
5641
|
-
File.write(
|
5642
|
-
|
6026
|
+
File.write(
|
6027
|
+
save_filespec,
|
6028
|
+
HashDelegator.join_code_lines(link_state&.inherited_lines)
|
6029
|
+
)
|
5643
6030
|
@delegate_object[:filename]
|
5644
6031
|
else
|
5645
6032
|
link_block_data[LinkKeys::FILE] || @delegate_object[:filename]
|
@@ -5650,6 +6037,7 @@ module MarkdownExec
|
|
5650
6037
|
end
|
5651
6038
|
|
5652
6039
|
def safe_yaml_load(body)
|
6040
|
+
caller.deref(12)
|
5653
6041
|
return {} unless body&.present?
|
5654
6042
|
|
5655
6043
|
YAML.load(body.to_s)
|
@@ -6773,4 +7161,427 @@ module MarkdownExec
|
|
6773
7161
|
end
|
6774
7162
|
end
|
6775
7163
|
end
|
7164
|
+
|
7165
|
+
# Comprehensive tests for ux_block_eval_for_export function
|
7166
|
+
class TestUxBlockEvalForExport < Minitest::Test
|
7167
|
+
def setup
|
7168
|
+
@hd = HashDelegator.new
|
7169
|
+
@bash_script_lines = ['#!/bin/bash', 'set -e']
|
7170
|
+
@export = OpenStruct.new(name: 'TEST_VAR', required: ['TEST_VAR'])
|
7171
|
+
@mock_result = OpenStruct.new(
|
7172
|
+
exit_status: 0,
|
7173
|
+
stdout: 'test_output',
|
7174
|
+
stderr: '',
|
7175
|
+
warning: nil
|
7176
|
+
)
|
7177
|
+
end
|
7178
|
+
|
7179
|
+
def teardown
|
7180
|
+
# Clean up environment variables set during tests
|
7181
|
+
ENV.delete('TEST_VAR')
|
7182
|
+
ENV.delete('VAR1')
|
7183
|
+
ENV.delete('VAR2')
|
7184
|
+
end
|
7185
|
+
|
7186
|
+
# Test string input - typical case
|
7187
|
+
def test_string_input_success
|
7188
|
+
@hd.stubs(:output_from_adhoc_bash_script_file).returns([@mock_result,
|
7189
|
+
true])
|
7190
|
+
@hd.stubs(:variable_is_exportable).returns(true)
|
7191
|
+
|
7192
|
+
result = @hd.ux_block_eval_for_export(
|
7193
|
+
@bash_script_lines, @export,
|
7194
|
+
data: 'echo "hello"',
|
7195
|
+
force: false,
|
7196
|
+
silent: false
|
7197
|
+
)
|
7198
|
+
|
7199
|
+
command_result, exportable, new_lines = result
|
7200
|
+
assert_equal @mock_result, command_result
|
7201
|
+
assert_equal true, exportable
|
7202
|
+
assert_equal 1, new_lines.length
|
7203
|
+
assert_equal 'TEST_VAR', new_lines.first[:name]
|
7204
|
+
assert_equal 'test_output', new_lines.first[:text]
|
7205
|
+
end
|
7206
|
+
|
7207
|
+
# Test string input with printf_expand
|
7208
|
+
def test_string_input_with_printf_expand
|
7209
|
+
@hd.stubs(:output_from_adhoc_bash_script_file).returns([@mock_result,
|
7210
|
+
true])
|
7211
|
+
@hd.stubs(:variable_is_exportable).returns(true)
|
7212
|
+
|
7213
|
+
@hd.ux_block_eval_for_export(
|
7214
|
+
@bash_script_lines, @export,
|
7215
|
+
data: 'test_value',
|
7216
|
+
force: false,
|
7217
|
+
printf_expand: true,
|
7218
|
+
silent: false
|
7219
|
+
)
|
7220
|
+
|
7221
|
+
# Verify that join_array_of_arrays was called with printf wrapped expression
|
7222
|
+
# This tests that the expander lambda is applied correctly
|
7223
|
+
end
|
7224
|
+
|
7225
|
+
# Test integer input
|
7226
|
+
def test_integer_input
|
7227
|
+
@hd.stubs(:output_from_adhoc_bash_script_file).returns([@mock_result,
|
7228
|
+
true])
|
7229
|
+
@hd.stubs(:variable_is_exportable).returns(true)
|
7230
|
+
|
7231
|
+
result = @hd.ux_block_eval_for_export(
|
7232
|
+
@bash_script_lines, @export,
|
7233
|
+
data: 42,
|
7234
|
+
force: true,
|
7235
|
+
silent: false
|
7236
|
+
)
|
7237
|
+
|
7238
|
+
command_result, exportable, new_lines = result
|
7239
|
+
assert_equal @mock_result, command_result
|
7240
|
+
assert_equal true, exportable
|
7241
|
+
assert_equal 1, new_lines.length
|
7242
|
+
end
|
7243
|
+
|
7244
|
+
# Test boolean inputs
|
7245
|
+
def test_boolean_true_input
|
7246
|
+
@hd.stubs(:output_from_adhoc_bash_script_file).returns([@mock_result,
|
7247
|
+
true])
|
7248
|
+
@hd.stubs(:variable_is_exportable).returns(true)
|
7249
|
+
|
7250
|
+
result = @hd.ux_block_eval_for_export(
|
7251
|
+
@bash_script_lines, @export,
|
7252
|
+
data: true,
|
7253
|
+
force: false,
|
7254
|
+
silent: false
|
7255
|
+
)
|
7256
|
+
|
7257
|
+
command_result, exportable, = result
|
7258
|
+
assert_equal @mock_result, command_result
|
7259
|
+
assert_equal true, exportable
|
7260
|
+
end
|
7261
|
+
|
7262
|
+
def test_boolean_false_input
|
7263
|
+
@hd.stubs(:output_from_adhoc_bash_script_file).returns([@mock_result,
|
7264
|
+
true])
|
7265
|
+
@hd.stubs(:variable_is_exportable).returns(true)
|
7266
|
+
|
7267
|
+
result = @hd.ux_block_eval_for_export(
|
7268
|
+
@bash_script_lines, @export,
|
7269
|
+
data: false,
|
7270
|
+
force: false,
|
7271
|
+
silent: false
|
7272
|
+
)
|
7273
|
+
|
7274
|
+
command_result, exportable, = result
|
7275
|
+
assert_equal @mock_result, command_result
|
7276
|
+
assert_equal true, exportable
|
7277
|
+
end
|
7278
|
+
|
7279
|
+
# Test float input
|
7280
|
+
def test_float_input
|
7281
|
+
@hd.stubs(:output_from_adhoc_bash_script_file).returns([@mock_result,
|
7282
|
+
true])
|
7283
|
+
@hd.stubs(:variable_is_exportable).returns(true)
|
7284
|
+
|
7285
|
+
result = @hd.ux_block_eval_for_export(
|
7286
|
+
@bash_script_lines, @export,
|
7287
|
+
data: 3.14,
|
7288
|
+
force: false,
|
7289
|
+
silent: false
|
7290
|
+
)
|
7291
|
+
|
7292
|
+
command_result, exportable, = result
|
7293
|
+
assert_equal @mock_result, command_result
|
7294
|
+
assert_equal true, exportable
|
7295
|
+
end
|
7296
|
+
|
7297
|
+
# Test hash input - typical case
|
7298
|
+
def test_hash_input_success
|
7299
|
+
hash_data = { 'VAR1' => 'value1', 'VAR2' => 'value2' }
|
7300
|
+
@hd.stubs(:output_from_adhoc_bash_script_file).returns([@mock_result,
|
7301
|
+
true])
|
7302
|
+
@hd.stubs(:variable_is_exportable).returns(true)
|
7303
|
+
@hd.stubs(:code_line_to_assign_a_variable).returns('VAR1=value1')
|
7304
|
+
|
7305
|
+
result = @hd.ux_block_eval_for_export(
|
7306
|
+
@bash_script_lines, @export,
|
7307
|
+
data: hash_data,
|
7308
|
+
force: false,
|
7309
|
+
silent: false
|
7310
|
+
)
|
7311
|
+
|
7312
|
+
command_result, exportable, new_lines = result
|
7313
|
+
assert_equal @mock_result, command_result
|
7314
|
+
assert_equal true, exportable
|
7315
|
+
assert_equal 2, new_lines.length
|
7316
|
+
assert_equal 'VAR1', new_lines.first[:name]
|
7317
|
+
assert_equal 'VAR2', new_lines.last[:name]
|
7318
|
+
end
|
7319
|
+
|
7320
|
+
# Test hash input with first_only flag
|
7321
|
+
def test_hash_input_first_only
|
7322
|
+
hash_data = { 'VAR1' => 'value1', 'VAR2' => 'value2' }
|
7323
|
+
@hd.stubs(:output_from_adhoc_bash_script_file).returns([@mock_result,
|
7324
|
+
true])
|
7325
|
+
@hd.stubs(:variable_is_exportable).returns(true)
|
7326
|
+
@hd.stubs(:code_line_to_assign_a_variable).returns('VAR1=value1')
|
7327
|
+
|
7328
|
+
result = @hd.ux_block_eval_for_export(
|
7329
|
+
@bash_script_lines, @export,
|
7330
|
+
data: hash_data,
|
7331
|
+
first_only: true,
|
7332
|
+
force: false,
|
7333
|
+
silent: false
|
7334
|
+
)
|
7335
|
+
|
7336
|
+
command_result, _, new_lines = result
|
7337
|
+
assert_equal @mock_result, command_result
|
7338
|
+
assert_equal 1, new_lines.length
|
7339
|
+
assert_equal 'VAR1', new_lines.first[:name]
|
7340
|
+
end
|
7341
|
+
|
7342
|
+
# Test hash with non-exportable variables
|
7343
|
+
def test_hash_input_non_exportable_variables
|
7344
|
+
hash_data = { 'LOCAL_VAR' => 'value1' }
|
7345
|
+
@hd.stubs(:output_from_adhoc_bash_script_file).returns([@mock_result,
|
7346
|
+
true])
|
7347
|
+
@hd.stubs(:variable_is_exportable).returns(false)
|
7348
|
+
@hd.stubs(:code_line_to_assign_a_variable).returns('LOCAL_VAR=value1')
|
7349
|
+
|
7350
|
+
result = @hd.ux_block_eval_for_export(
|
7351
|
+
@bash_script_lines, @export,
|
7352
|
+
data: hash_data,
|
7353
|
+
force: false,
|
7354
|
+
silent: false
|
7355
|
+
)
|
7356
|
+
|
7357
|
+
command_result, _, new_lines = result
|
7358
|
+
assert_equal @mock_result, command_result
|
7359
|
+
assert_equal 0, new_lines.length # No exportable variables
|
7360
|
+
end
|
7361
|
+
|
7362
|
+
# Test EXIT_STATUS_REQUIRED_EMPTY handling
|
7363
|
+
def test_exit_status_required_empty_with_warning
|
7364
|
+
failed_result = OpenStruct.new(
|
7365
|
+
exit_status: 248, # EXIT_STATUS_REQUIRED_EMPTY
|
7366
|
+
stdout: '',
|
7367
|
+
stderr: 'Required variable empty',
|
7368
|
+
warning: nil
|
7369
|
+
)
|
7370
|
+
@hd.stubs(:output_from_adhoc_bash_script_file).returns([failed_result,
|
7371
|
+
false])
|
7372
|
+
@hd.stubs(:warning_required_empty).returns('Warning: required empty')
|
7373
|
+
|
7374
|
+
result = @hd.ux_block_eval_for_export(
|
7375
|
+
@bash_script_lines, @export,
|
7376
|
+
data: 'echo ""',
|
7377
|
+
force: false,
|
7378
|
+
silent: false
|
7379
|
+
)
|
7380
|
+
|
7381
|
+
command_result, exportable, new_lines = result
|
7382
|
+
assert_equal failed_result, command_result
|
7383
|
+
assert_equal false, exportable
|
7384
|
+
assert_equal 0, new_lines.length
|
7385
|
+
assert_equal 'Warning: required empty', command_result.warning
|
7386
|
+
end
|
7387
|
+
|
7388
|
+
# Test EXIT_STATUS_REQUIRED_EMPTY handling with silent flag
|
7389
|
+
def test_exit_status_required_empty_silent
|
7390
|
+
failed_result = OpenStruct.new(
|
7391
|
+
exit_status: 248,
|
7392
|
+
stdout: '',
|
7393
|
+
stderr: 'Required variable empty',
|
7394
|
+
warning: nil
|
7395
|
+
)
|
7396
|
+
@hd.stubs(:output_from_adhoc_bash_script_file).returns([failed_result,
|
7397
|
+
false])
|
7398
|
+
|
7399
|
+
result = @hd.ux_block_eval_for_export(
|
7400
|
+
@bash_script_lines, @export,
|
7401
|
+
data: 'echo ""',
|
7402
|
+
force: false,
|
7403
|
+
silent: true
|
7404
|
+
)
|
7405
|
+
|
7406
|
+
command_result, exportable, = result
|
7407
|
+
assert_equal failed_result, command_result
|
7408
|
+
assert_equal false, exportable
|
7409
|
+
assert_nil command_result.warning # No warning when silent
|
7410
|
+
end
|
7411
|
+
|
7412
|
+
# Test string parameter override
|
7413
|
+
def test_string_parameter_override
|
7414
|
+
@hd.stubs(:output_from_adhoc_bash_script_file).returns([@mock_result,
|
7415
|
+
true])
|
7416
|
+
@hd.stubs(:variable_is_exportable).returns(true)
|
7417
|
+
|
7418
|
+
result = @hd.ux_block_eval_for_export(
|
7419
|
+
@bash_script_lines, @export,
|
7420
|
+
data: 'original_data',
|
7421
|
+
string: 'override_string',
|
7422
|
+
force: false,
|
7423
|
+
silent: false
|
7424
|
+
)
|
7425
|
+
|
7426
|
+
# The function should use string parameter instead of data
|
7427
|
+
command_result, exportable, = result
|
7428
|
+
assert_equal @mock_result, command_result
|
7429
|
+
assert_equal true, exportable
|
7430
|
+
end
|
7431
|
+
|
7432
|
+
# Edge case: empty string
|
7433
|
+
def test_empty_string_input
|
7434
|
+
@hd.stubs(:output_from_adhoc_bash_script_file).returns([@mock_result,
|
7435
|
+
true])
|
7436
|
+
@hd.stubs(:variable_is_exportable).returns(true)
|
7437
|
+
|
7438
|
+
result = @hd.ux_block_eval_for_export(
|
7439
|
+
@bash_script_lines, @export,
|
7440
|
+
data: '',
|
7441
|
+
force: false,
|
7442
|
+
silent: false
|
7443
|
+
)
|
7444
|
+
|
7445
|
+
command_result, exportable, = result
|
7446
|
+
assert_equal @mock_result, command_result
|
7447
|
+
assert_equal true, exportable
|
7448
|
+
end
|
7449
|
+
|
7450
|
+
# Edge case: nil data (uses string.nil? check)
|
7451
|
+
def test_nil_data_input
|
7452
|
+
@hd.stubs(:output_from_adhoc_bash_script_file).returns([@mock_result,
|
7453
|
+
true])
|
7454
|
+
@hd.stubs(:variable_is_exportable).returns(true)
|
7455
|
+
|
7456
|
+
result = @hd.ux_block_eval_for_export(
|
7457
|
+
@bash_script_lines, @export,
|
7458
|
+
data: 'd1',
|
7459
|
+
force: false,
|
7460
|
+
silent: false
|
7461
|
+
)
|
7462
|
+
|
7463
|
+
command_result, exportable, = result
|
7464
|
+
assert_equal @mock_result, command_result
|
7465
|
+
assert_equal true, exportable
|
7466
|
+
end
|
7467
|
+
|
7468
|
+
# Edge case: empty hash
|
7469
|
+
def test_empty_hash_input
|
7470
|
+
result = @hd.ux_block_eval_for_export(
|
7471
|
+
@bash_script_lines, @export,
|
7472
|
+
data: {},
|
7473
|
+
force: false,
|
7474
|
+
silent: false
|
7475
|
+
)
|
7476
|
+
|
7477
|
+
command_result, exportable, new_lines = result
|
7478
|
+
assert_nil command_result # No iterations, so command_result remains nil
|
7479
|
+
assert_equal true, exportable # Initial value
|
7480
|
+
assert_equal 0, new_lines.length
|
7481
|
+
end
|
7482
|
+
|
7483
|
+
# Edge case: hash with nil values
|
7484
|
+
def test_hash_with_nil_values
|
7485
|
+
hash_data = { 'VAR1' => nil, 'VAR2' => 'value2' }
|
7486
|
+
@hd.stubs(:output_from_adhoc_bash_script_file).returns([@mock_result,
|
7487
|
+
true])
|
7488
|
+
@hd.stubs(:variable_is_exportable).returns(true)
|
7489
|
+
@hd.stubs(:code_line_to_assign_a_variable).returns('VAR1=')
|
7490
|
+
|
7491
|
+
result = @hd.ux_block_eval_for_export(
|
7492
|
+
@bash_script_lines, @export,
|
7493
|
+
data: hash_data,
|
7494
|
+
force: false,
|
7495
|
+
silent: false
|
7496
|
+
)
|
7497
|
+
|
7498
|
+
command_result, exportable, new_lines = result
|
7499
|
+
assert_equal @mock_result, command_result
|
7500
|
+
assert_equal true, exportable
|
7501
|
+
assert_equal 2, new_lines.length
|
7502
|
+
end
|
7503
|
+
|
7504
|
+
# Edge case: unsupported input type (Array)
|
7505
|
+
def test_unsupported_input_type_array
|
7506
|
+
result = @hd.ux_block_eval_for_export(
|
7507
|
+
@bash_script_lines, @export,
|
7508
|
+
data: %w[item1 item2],
|
7509
|
+
force: false,
|
7510
|
+
silent: false
|
7511
|
+
)
|
7512
|
+
|
7513
|
+
command_result, exportable, new_lines = result
|
7514
|
+
assert_nil command_result # No processing for unsupported types
|
7515
|
+
assert_equal true, exportable # Initial value
|
7516
|
+
assert_equal 0, new_lines.length
|
7517
|
+
end
|
7518
|
+
|
7519
|
+
# Edge case: unsupported input type (custom object)
|
7520
|
+
def test_unsupported_input_type_object
|
7521
|
+
custom_object = Object.new
|
7522
|
+
result = @hd.ux_block_eval_for_export(
|
7523
|
+
@bash_script_lines, @export,
|
7524
|
+
data: custom_object,
|
7525
|
+
force: false,
|
7526
|
+
silent: false
|
7527
|
+
)
|
7528
|
+
|
7529
|
+
command_result, exportable, new_lines = result
|
7530
|
+
assert_nil command_result # No processing for unsupported types
|
7531
|
+
assert_equal true, exportable # Initial value
|
7532
|
+
assert_equal 0, new_lines.length
|
7533
|
+
end
|
7534
|
+
|
7535
|
+
# Test error handling - StandardError rescue
|
7536
|
+
def test_standard_error_rescue
|
7537
|
+
# Should not raise, but return nil due to rescue block
|
7538
|
+
result = @hd.ux_block_eval_for_export(
|
7539
|
+
@bash_script_lines, @export,
|
7540
|
+
data: 'test_data',
|
7541
|
+
force: false,
|
7542
|
+
silent: false
|
7543
|
+
)
|
7544
|
+
|
7545
|
+
command_result, = result
|
7546
|
+
assert_equal 127, command_result.exit_status
|
7547
|
+
end
|
7548
|
+
|
7549
|
+
# Test environment variable setting
|
7550
|
+
def test_environment_variable_setting
|
7551
|
+
@hd.stubs(:output_from_adhoc_bash_script_file).returns([@mock_result,
|
7552
|
+
true])
|
7553
|
+
@hd.stubs(:variable_is_exportable).returns(true)
|
7554
|
+
|
7555
|
+
# Mock EnvInterface.set to verify it's called
|
7556
|
+
EnvInterface.expects(:set).with('TEST_VAR', 'test_output')
|
7557
|
+
|
7558
|
+
@hd.ux_block_eval_for_export(
|
7559
|
+
@bash_script_lines, @export,
|
7560
|
+
data: 'echo "test"',
|
7561
|
+
force: false,
|
7562
|
+
silent: false
|
7563
|
+
)
|
7564
|
+
end
|
7565
|
+
|
7566
|
+
# Test join_array_of_arrays is called correctly
|
7567
|
+
def test_join_array_of_arrays_called
|
7568
|
+
@hd.stubs(:output_from_adhoc_bash_script_file).returns([@mock_result,
|
7569
|
+
true])
|
7570
|
+
@hd.stubs(:variable_is_exportable).returns(true)
|
7571
|
+
|
7572
|
+
# Mock join_array_of_arrays to verify it's called with correct parameters
|
7573
|
+
@hd.expects(:join_array_of_arrays).with(
|
7574
|
+
@bash_script_lines,
|
7575
|
+
['test_data']
|
7576
|
+
).returns(['combined_script_lines'])
|
7577
|
+
|
7578
|
+
@hd.ux_block_eval_for_export(
|
7579
|
+
@bash_script_lines, @export,
|
7580
|
+
data: 'test_data',
|
7581
|
+
force: false,
|
7582
|
+
printf_expand: false,
|
7583
|
+
silent: false
|
7584
|
+
)
|
7585
|
+
end
|
7586
|
+
end
|
6776
7587
|
end # module MarkdownExec
|