markdown_exec 3.5.1 → 3.6.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/.ai-agent-instructions +54 -0
- data/.cursorrules +198 -0
- data/.rubocop.wide.yml +5 -0
- data/.rubocop.yml +7 -2
- data/CHANGELOG.md +19 -1
- data/Gemfile.lock +1 -1
- data/README.md +1 -1
- data/Rakefile +2 -0
- data/ai-principles.md +516 -0
- data/architecture-decisions.md +190 -0
- data/bats/block-hide.bats +1 -1
- data/bats/block-type-bash.bats +5 -5
- data/bats/block-type-link.bats +1 -1
- data/bats/block-type-opts.bats +3 -3
- data/bats/block-type-port.bats +2 -2
- data/bats/block-type-shell-context-eval.bats +48 -0
- data/bats/block-type-shell-require-ux.bats +2 -2
- data/bats/block-type-ux-allowed.bats +4 -4
- data/bats/block-type-ux-auto.bats +1 -1
- data/bats/block-type-ux-chained.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-echo.bats +4 -4
- data/bats/block-type-ux-exec-hash-transform.bats +1 -1
- data/bats/block-type-ux-exec-hash.bats +2 -2
- data/bats/block-type-ux-exec.bats +1 -1
- data/bats/block-type-ux-force.bats +2 -2
- data/bats/block-type-ux-formats.bats +1 -1
- data/bats/block-type-ux-hidden.bats +1 -1
- data/bats/block-type-ux-invalid.bats +2 -2
- data/bats/block-type-ux-readonly.bats +1 -1
- data/bats/block-type-ux-require-chained.bats +2 -2
- data/bats/block-type-ux-require-context.bats +2 -2
- data/bats/block-type-ux-require.bats +3 -3
- data/bats/block-type-ux-required-variables.bats +1 -1
- data/bats/block-type-ux-row-format.bats +1 -1
- data/bats/block-type-ux-sources.bats +4 -4
- data/bats/block-type-ux-transform.bats +1 -1
- data/bats/block-type-vars.bats +3 -3
- data/bats/border.bats +1 -1
- data/bats/cli.bats +11 -11
- data/bats/command-substitution-options.bats +2 -2
- data/bats/command-substitution.bats +1 -1
- data/bats/document-shell.bats +3 -3
- data/bats/history.bats +5 -5
- data/bats/import-conflict.bats +1 -1
- data/bats/import-directive-line-continuation.bats +1 -1
- data/bats/import-directive-parameter-symbols.bats +1 -1
- data/bats/import-duplicates.bats +6 -6
- data/bats/import-parameter-symbols.bats +1 -1
- data/bats/import-with-text-substitution.bats +1 -1
- data/bats/import.bats +4 -4
- data/bats/indented-block-type-vars.bats +1 -1
- data/bats/indented-multi-line-output.bats +1 -1
- data/bats/line-decor-dynamic.bats +1 -1
- data/bats/line-wrapping.bats +1 -1
- data/bats/load-vars-state-demo.bats +8 -8
- data/bats/markup.bats +4 -4
- data/bats/mde.bats +4 -4
- data/bats/option-expansion.bats +1 -1
- data/bats/options-collapse.bats +4 -4
- data/bats/options.bats +47 -17
- data/bats/plain.bats +1 -1
- data/bats/publish.bats +2 -2
- data/bats/table-column-truncate.bats +1 -1
- data/bats/table.bats +2 -2
- data/bats/variable-expansion-multiline.bats +1 -1
- data/bats/variable-expansion.bats +6 -6
- data/bin/tab_completion.sh +3 -3
- data/conversation-template.md +611 -0
- data/docs/block-execution-modes.md +177 -0
- data/docs/block-filtering.md +252 -0
- data/docs/block-naming-patterns.md +210 -0
- data/docs/block-scanning-patterns.md +248 -0
- data/docs/cli-reference.md +370 -0
- data/docs/dev/bats-document-configuration.md +1 -1
- data/docs/dev/block-hide.md +1 -1
- data/docs/dev/block-type-shell-context-eval.md +52 -0
- data/docs/dev/block-type-shell-require-ux.md +6 -2
- data/docs/dev/block-type-ux-echo.md +3 -3
- data/docs/dev/block-type-ux-force.md +1 -1
- data/docs/dev/block-type-ux-require-chained.md +1 -1
- data/docs/dev/block-type-ux-require.md +2 -2
- data/docs/dev/block-type-ux-transform.md +5 -4
- data/docs/dev/import-parameter-symbols.md +1 -1
- data/docs/dev/linked-file.md +1 -1
- data/docs/dev/load-vars-state-demo.md +1 -1
- data/docs/dev/print_bytes.md +3 -0
- data/docs/dev/requiring-blocks.md +1 -1
- data/docs/dev/shebang.md +6 -0
- data/docs/dev/specs.md +2 -2
- data/docs/docker-testing.md +5 -0
- data/docs/execution-control.md +384 -0
- data/docs/getting-started.md +209 -0
- data/docs/import-options.md +391 -0
- data/docs/shell-script-evaluation.md +78 -0
- data/docs/tab-completion.md +7 -0
- data/docs/ux-blocks.md +376 -0
- data/examples/link-blocks-vars.md +2 -2
- data/examples/linked.md +1 -1
- data/examples/linked1.md +1 -1
- data/examples/opts-blocks.md +2 -2
- data/examples/port-blocks.md +1 -1
- data/examples/variable-expansion.md +1 -1
- data/implementation-decisions.md +212 -0
- data/lib/cached_nested_file_reader.rb +145 -5
- data/lib/command_result.rb +27 -6
- data/lib/executed_shell_command.rb +512 -0
- data/lib/filter.rb +7 -7
- data/lib/hash_delegator.rb +699 -605
- data/lib/input_sequencer.rb +4 -3
- data/lib/link_history.rb +95 -36
- data/lib/markdown_exec/version.rb +1 -1
- data/lib/mdoc.rb +138 -51
- data/lib/menu.src.yml +115 -88
- data/lib/menu.yml +154 -88
- data/lib/transformed_shell_command.rb +449 -0
- data/lib/wl.rb +15 -0
- data/lib/ww.rb +17 -6
- data/requirements.md +111 -0
- data/semantic-tokens.md +132 -0
- data/tasks.md +69 -0
- metadata +29 -4
- data/docs/ux-blocks-examples.md +0 -120
- data/docs/ux-blocks-init-act.md +0 -100
data/lib/hash_delegator.rb
CHANGED
|
@@ -27,6 +27,7 @@ require_relative 'constants'
|
|
|
27
27
|
require_relative 'directory_searcher'
|
|
28
28
|
require_relative 'error_reporting'
|
|
29
29
|
require_relative 'evaluate_shell_expressions'
|
|
30
|
+
require_relative 'executed_shell_command'
|
|
30
31
|
require_relative 'exceptions'
|
|
31
32
|
require_relative 'fcb'
|
|
32
33
|
require_relative 'filter'
|
|
@@ -43,12 +44,12 @@ require_relative 'streams_out'
|
|
|
43
44
|
require_relative 'string_util'
|
|
44
45
|
require_relative 'table_extractor'
|
|
45
46
|
require_relative 'text_analyzer'
|
|
47
|
+
require_relative 'transformed_shell_command'
|
|
46
48
|
require_relative 'value_or_exception'
|
|
47
49
|
require_relative 'env_interface'
|
|
48
50
|
|
|
49
51
|
$pd = false unless defined?($pd)
|
|
50
52
|
$table_cell_truncate = true
|
|
51
|
-
EXIT_STATUS_REQUIRED_EMPTY = 248
|
|
52
53
|
|
|
53
54
|
module HashDelegatorSelf
|
|
54
55
|
# Applies an ANSI color method to a string using a specified color key.
|
|
@@ -164,8 +165,7 @@ module HashDelegatorSelf
|
|
|
164
165
|
|
|
165
166
|
# delete the current line if it is empty and the previous is also empty
|
|
166
167
|
def delete_consecutive_blank_lines!(blocks_menu)
|
|
167
|
-
blocks_menu.process_and_conditionally_delete! do
|
|
168
|
-
|prev_item, current_item, _next_item|
|
|
168
|
+
blocks_menu.process_and_conditionally_delete! do |prev_item, current_item, _next_item|
|
|
169
169
|
!current_item.is_split? &&
|
|
170
170
|
prev_item&.fetch(:chrome, nil) &&
|
|
171
171
|
!(prev_item && prev_item.oname.present?) &&
|
|
@@ -181,6 +181,125 @@ module HashDelegatorSelf
|
|
|
181
181
|
)
|
|
182
182
|
end
|
|
183
183
|
|
|
184
|
+
# Executes a bash script from an array of lines and optionally exports the result.
|
|
185
|
+
#
|
|
186
|
+
# Creates a temporary executable file from the provided bash script lines,
|
|
187
|
+
# executes it using the configured shell, and optionally archives the script
|
|
188
|
+
# if archiving is enabled. The result can be marked as exportable based on
|
|
189
|
+
# the export configuration and command success status.
|
|
190
|
+
#
|
|
191
|
+
# @param bash_script_lines [Array<String>] An array of strings representing
|
|
192
|
+
# the lines of the bash script to execute.
|
|
193
|
+
# @param export [Object, nil] An export configuration object that determines
|
|
194
|
+
# whether the result should be exported. If provided, must respond to:
|
|
195
|
+
# - `exportable` [Boolean, nil] Whether the result is exportable (nil defaults to true)
|
|
196
|
+
# - `name` [String] The name of the variable to export the result to
|
|
197
|
+
# If nil, the result will not be exported.
|
|
198
|
+
# @param force [Boolean] Whether to force the export even if the variable
|
|
199
|
+
# already exists. This is included in the new_lines hash if exportable.
|
|
200
|
+
#
|
|
201
|
+
# @return [Array, nil] Returns an array with three elements:
|
|
202
|
+
# - [0] [CommandResult] The result of executing the script, containing
|
|
203
|
+
# stdout and exit_status
|
|
204
|
+
# - [1] [Boolean] Whether the result is exportable (true if export is nil
|
|
205
|
+
# or export.exportable is nil, otherwise based on export.exportable and
|
|
206
|
+
# command success)
|
|
207
|
+
# - [2] [Array<Hash>] An array of hashes representing new lines to export.
|
|
208
|
+
# Each hash contains:
|
|
209
|
+
# - `:name` [String] The variable name
|
|
210
|
+
# - `:force` [Boolean] Whether to force the export
|
|
211
|
+
# - `:text` [String] The text content to export
|
|
212
|
+
# Returns nil if an error occurs during execution.
|
|
213
|
+
#
|
|
214
|
+
# @note The method creates a temporary file with mode 0755 (executable) and
|
|
215
|
+
# automatically cleans it up after execution. If `@delegate_object[:archive_ad_hoc_scripts]`
|
|
216
|
+
# is true, the script will be copied to an archive location before execution.
|
|
217
|
+
#
|
|
218
|
+
# @example Basic execution without export
|
|
219
|
+
# result, exportable, new_lines = execute_bash_script_lines(
|
|
220
|
+
# transient_code: ["echo 'Hello'", "echo 'World'"],
|
|
221
|
+
# export: nil,
|
|
222
|
+
# force: false
|
|
223
|
+
# )
|
|
224
|
+
# # => [CommandResult, true, []]
|
|
225
|
+
#
|
|
226
|
+
# @example Execution with export
|
|
227
|
+
# export = OpenStruct.new(name: "MY_VAR", exportable: true)
|
|
228
|
+
# result, exportable, new_lines = execute_bash_script_lines(
|
|
229
|
+
# transient_code: ["echo 'Hello World'"],
|
|
230
|
+
# export: export,
|
|
231
|
+
# force: true
|
|
232
|
+
# )
|
|
233
|
+
# # => [CommandResult, true, [{name: "MY_VAR", force: true, text: "Hello World\n"}]]
|
|
234
|
+
#
|
|
235
|
+
def execute_bash_script_lines(
|
|
236
|
+
transient_code: [],
|
|
237
|
+
export: nil,
|
|
238
|
+
export_name:,
|
|
239
|
+
force: false,
|
|
240
|
+
shell:,
|
|
241
|
+
archive_script: false, # @delegate_object[:archive_ad_hoc_scripts]
|
|
242
|
+
archive_path_format: nil, # @delegate_object[:archive_path_format],
|
|
243
|
+
archive_time_format: nil # @delegate_object[:archive_time_format]
|
|
244
|
+
)
|
|
245
|
+
Tempfile.create('script_exec') do |temp_file|
|
|
246
|
+
temp_file.write(join_code_lines(transient_code))
|
|
247
|
+
temp_file.close # Close the file before chmod and execution
|
|
248
|
+
File.chmod(0o755, temp_file.path)
|
|
249
|
+
|
|
250
|
+
if archive_script && archive_path_format && archive_time_format
|
|
251
|
+
archive_filename = format(
|
|
252
|
+
archive_path_format,
|
|
253
|
+
time: Time.now.strftime(archive_time_format)
|
|
254
|
+
)
|
|
255
|
+
`cp #{temp_file.path} #{archive_filename}`
|
|
256
|
+
end
|
|
257
|
+
|
|
258
|
+
tsc = TransformedShellCommand.new(
|
|
259
|
+
"#{shell} #{temp_file.path}",
|
|
260
|
+
regex: export.validate,
|
|
261
|
+
format: export.transform
|
|
262
|
+
)
|
|
263
|
+
exportable = if export&.exportable.nil?
|
|
264
|
+
true
|
|
265
|
+
else
|
|
266
|
+
(export ? export.exportable : false)
|
|
267
|
+
end
|
|
268
|
+
new_lines = []
|
|
269
|
+
|
|
270
|
+
if false
|
|
271
|
+
# optional comment
|
|
272
|
+
new_lines << { comment: 'execute_bash_script_lines' }
|
|
273
|
+
end
|
|
274
|
+
|
|
275
|
+
exportable_success = exportable && tsc.success?
|
|
276
|
+
if exportable_success
|
|
277
|
+
new_lines << { name: export_name, force: force,
|
|
278
|
+
text: tsc.transformed_output }
|
|
279
|
+
end
|
|
280
|
+
|
|
281
|
+
CommandResult.new(
|
|
282
|
+
exit_status: tsc.exit_code,
|
|
283
|
+
exportable: exportable_success,
|
|
284
|
+
new_lines: new_lines,
|
|
285
|
+
script: transient_code,
|
|
286
|
+
stdout: tsc.transformed_output,
|
|
287
|
+
transformed_shell_command: tsc
|
|
288
|
+
)
|
|
289
|
+
end
|
|
290
|
+
rescue StandardError
|
|
291
|
+
wwe $!, 'transient_code:', transient_code, 'export:', export
|
|
292
|
+
# warn "Error executing script: #{err.message}"
|
|
293
|
+
# return failure result
|
|
294
|
+
CommandResult.new(
|
|
295
|
+
exit_status: CommandResult::EXIT_STATUS_FAIL,
|
|
296
|
+
exportable: false,
|
|
297
|
+
new_lines: [],
|
|
298
|
+
script: transient_code,
|
|
299
|
+
stdout: ''
|
|
300
|
+
)
|
|
301
|
+
end
|
|
302
|
+
|
|
184
303
|
# Takes multiple arrays as arguments, flattens them into a single array, and removes nil values.
|
|
185
304
|
# @param args [Array<Array>] Variable number of arrays to be processed
|
|
186
305
|
# @return [Array] A single flattened array with nil values removed, or an empty array if the result is empty
|
|
@@ -207,6 +326,8 @@ module HashDelegatorSelf
|
|
|
207
326
|
|
|
208
327
|
def join_code_lines(lines)
|
|
209
328
|
((lines || []) + ['']).join("\n")
|
|
329
|
+
rescue StandardError
|
|
330
|
+
wwe $!, 'lines:', lines
|
|
210
331
|
end
|
|
211
332
|
|
|
212
333
|
def next_link_state(
|
|
@@ -448,14 +569,14 @@ module HashDelegatorSelf
|
|
|
448
569
|
|
|
449
570
|
# if the id is present, update the existing fcb
|
|
450
571
|
if options[:id]
|
|
451
|
-
fcb = all_fcbs.find {
|
|
572
|
+
fcb = all_fcbs.find { _1.id == options[:id] }
|
|
452
573
|
if fcb
|
|
453
574
|
fcb.update(options)
|
|
454
575
|
return fcb
|
|
455
576
|
end
|
|
456
577
|
end
|
|
457
|
-
MarkdownExec::FCB.new(options).tap do
|
|
458
|
-
all_fcbs <<
|
|
578
|
+
MarkdownExec::FCB.new(options).tap do
|
|
579
|
+
all_fcbs << _1
|
|
459
580
|
end
|
|
460
581
|
end
|
|
461
582
|
end
|
|
@@ -656,11 +777,11 @@ module MarkdownExec
|
|
|
656
777
|
source: OpenStruct.new
|
|
657
778
|
)
|
|
658
779
|
@link_history = LinkHistory.new
|
|
659
|
-
@fout = FOut.new(@delegate_object)
|
|
780
|
+
@fout = FOut.new(@delegate_object)
|
|
660
781
|
|
|
661
782
|
@process_mutex = Mutex.new
|
|
662
783
|
@process_cv = ConditionVariable.new
|
|
663
|
-
@dml_link_state = Struct.new(:document_filename, :
|
|
784
|
+
@dml_link_state = Struct.new(:document_filename, :context_code)
|
|
664
785
|
.new(@delegate_object[:filename], [])
|
|
665
786
|
@dml_menu_blocks = []
|
|
666
787
|
@fcb_store = [] # all fcbs created
|
|
@@ -729,7 +850,7 @@ module MarkdownExec
|
|
|
729
850
|
add_inherited_lines(
|
|
730
851
|
link_state: link_state,
|
|
731
852
|
menu_blocks: menu_blocks
|
|
732
|
-
) if @delegate_object[:
|
|
853
|
+
) if @delegate_object[:menu_with_context_code]
|
|
733
854
|
|
|
734
855
|
# back before exit
|
|
735
856
|
add_back_option(
|
|
@@ -848,10 +969,10 @@ module MarkdownExec
|
|
|
848
969
|
# @param menu_blocks [Array] The array of menu block elements.
|
|
849
970
|
# @param position [Symbol] The position to insert the divider (:initial or :final).
|
|
850
971
|
def append_inherited_lines(link_state:, menu_blocks:, position: top)
|
|
851
|
-
return unless link_state.
|
|
972
|
+
return unless link_state.context_code_present?
|
|
852
973
|
|
|
853
974
|
insert_at_top = @delegate_object[:menu_inherited_lines_at_top]
|
|
854
|
-
chrome_blocks = link_state.
|
|
975
|
+
chrome_blocks = link_state.context_code_map do |line|
|
|
855
976
|
formatted = format(@delegate_object[:menu_inherited_lines_format],
|
|
856
977
|
{ line: line })
|
|
857
978
|
persist_fcb(
|
|
@@ -883,7 +1004,6 @@ module MarkdownExec
|
|
|
883
1004
|
# @param block_type_color_option [Symbol, nil] The shell color option to apply.
|
|
884
1005
|
# @return [String] The colorized or original name string.
|
|
885
1006
|
def apply_block_type_color_option(name, block_type_color_option)
|
|
886
|
-
### accept string for color
|
|
887
1007
|
if block_type_color_option && @delegate_object[block_type_color_option].present?
|
|
888
1008
|
string_send_color(name, block_type_color_option)
|
|
889
1009
|
else
|
|
@@ -1070,7 +1190,7 @@ module MarkdownExec
|
|
|
1070
1190
|
occurrence_expressions: nil
|
|
1071
1191
|
)
|
|
1072
1192
|
evaluate_shell_expressions(
|
|
1073
|
-
(link_state&.
|
|
1193
|
+
(link_state&.context_code_block || ''),
|
|
1074
1194
|
commands,
|
|
1075
1195
|
initial_code_required: initial_code_required,
|
|
1076
1196
|
occurrence_expressions: occurrence_expressions
|
|
@@ -1089,7 +1209,7 @@ module MarkdownExec
|
|
|
1089
1209
|
exts: '.out.txt',
|
|
1090
1210
|
saved_asset_format:
|
|
1091
1211
|
shell_escape_asset_format(
|
|
1092
|
-
|
|
1212
|
+
transient_code: @dml_link_state.context_code,
|
|
1093
1213
|
shell: ShellType::BASH
|
|
1094
1214
|
)
|
|
1095
1215
|
).generate_name
|
|
@@ -1123,7 +1243,9 @@ module MarkdownExec
|
|
|
1123
1243
|
symbol_raw_literal:
|
|
1124
1244
|
@delegate_object[:import_symbol_raw_literal],
|
|
1125
1245
|
symbol_variable_reference:
|
|
1126
|
-
@delegate_object[:import_symbol_variable_reference]
|
|
1246
|
+
@delegate_object[:import_symbol_variable_reference],
|
|
1247
|
+
hide_shebang:
|
|
1248
|
+
@delegate_object.fetch(:hide_shebang, true)
|
|
1127
1249
|
)
|
|
1128
1250
|
end
|
|
1129
1251
|
|
|
@@ -1142,7 +1264,9 @@ module MarkdownExec
|
|
|
1142
1264
|
end
|
|
1143
1265
|
|
|
1144
1266
|
# return code resulting from evaluating all automatic blocks in order
|
|
1145
|
-
def
|
|
1267
|
+
def inherited_lines_from_auto_blocks(
|
|
1268
|
+
all_blocks, mdoc: nil, default_only: true, context_code: []
|
|
1269
|
+
)
|
|
1146
1270
|
shell_block_name = @delegate_object[:document_load_shell_block_name]
|
|
1147
1271
|
vars_block_name = @delegate_object[:document_load_vars_block_name]
|
|
1148
1272
|
|
|
@@ -1155,21 +1279,26 @@ module MarkdownExec
|
|
|
1155
1279
|
@vars_most_recent_filename = @delegate_object[:filename]
|
|
1156
1280
|
|
|
1157
1281
|
all_code = []
|
|
1282
|
+
all_inherit = []
|
|
1158
1283
|
all_blocks.each do |fcb|
|
|
1159
1284
|
block_code = []
|
|
1285
|
+
block_inherit = []
|
|
1160
1286
|
if fcb.oname == shell_block_name
|
|
1161
1287
|
if read_shell
|
|
1162
1288
|
# collect code from shell block
|
|
1163
1289
|
code = if mdoc
|
|
1164
|
-
mdoc.collect_recursively_required_code(
|
|
1290
|
+
required_code = mdoc.collect_recursively_required_code(
|
|
1165
1291
|
anyname: fcb.id,
|
|
1166
|
-
### anyname: fcb.pub_name,
|
|
1167
1292
|
label_format_above:
|
|
1168
1293
|
@delegate_object[:shell_code_label_format_above],
|
|
1169
1294
|
label_format_below:
|
|
1170
1295
|
@delegate_object[:shell_code_label_format_below],
|
|
1171
|
-
block_source: block_source
|
|
1172
|
-
|
|
1296
|
+
block_source: block_source,
|
|
1297
|
+
context_code: context_code
|
|
1298
|
+
)
|
|
1299
|
+
block_inherit = required_code[:context_code]
|
|
1300
|
+
|
|
1301
|
+
required_code[:transient_code]
|
|
1173
1302
|
else
|
|
1174
1303
|
fcb.body
|
|
1175
1304
|
end
|
|
@@ -1207,80 +1336,12 @@ module MarkdownExec
|
|
|
1207
1336
|
|
|
1208
1337
|
wwt :code, 'block_code:', block_code unless block_code&.empty?
|
|
1209
1338
|
all_code += block_code
|
|
1339
|
+
all_inherit += block_inherit
|
|
1210
1340
|
end
|
|
1211
1341
|
|
|
1212
|
-
all_code.tap {
|
|
1342
|
+
all_code.tap { wwr _1 }
|
|
1213
1343
|
rescue StandardError
|
|
1214
|
-
wwe 'all_blocks.count:', all_blocks.count
|
|
1215
|
-
end
|
|
1216
|
-
|
|
1217
|
-
# return code resulting from evaluating all automatic SHELL blocks in order
|
|
1218
|
-
def code_from_auto_shell_blocks(all_blocks, mdoc: nil)
|
|
1219
|
-
# a block name is required
|
|
1220
|
-
# do not reload the most recent filename
|
|
1221
|
-
block_name = @delegate_object[:document_load_shell_block_name]
|
|
1222
|
-
unless block_name.present? &&
|
|
1223
|
-
@shell_most_recent_filename != @delegate_object[:filename]
|
|
1224
|
-
return
|
|
1225
|
-
end
|
|
1226
|
-
|
|
1227
|
-
@shell_most_recent_filename = @delegate_object[:filename]
|
|
1228
|
-
|
|
1229
|
-
# select the first block with the given name
|
|
1230
|
-
fcb = HashDelegator.block_find(all_blocks, :oname, block_name)
|
|
1231
|
-
return unless fcb
|
|
1232
|
-
|
|
1233
|
-
# collect code from shell block
|
|
1234
|
-
code = if mdoc
|
|
1235
|
-
mdoc.collect_recursively_required_code(
|
|
1236
|
-
anyname: fcb.pub_name,
|
|
1237
|
-
label_format_above:
|
|
1238
|
-
@delegate_object[:shell_code_label_format_above],
|
|
1239
|
-
label_format_below:
|
|
1240
|
-
@delegate_object[:shell_code_label_format_below],
|
|
1241
|
-
block_source: block_source
|
|
1242
|
-
)[:code]
|
|
1243
|
-
else
|
|
1244
|
-
fcb.body
|
|
1245
|
-
end
|
|
1246
|
-
annotate_required_lines('blk:SHELL', code, block_name: fcb.id)
|
|
1247
|
-
end
|
|
1248
|
-
|
|
1249
|
-
# return code resulting from evaluating all UX blocks in order
|
|
1250
|
-
def code_from_auto_ux_blocks(
|
|
1251
|
-
all_blocks,
|
|
1252
|
-
mdoc
|
|
1253
|
-
)
|
|
1254
|
-
# do not reload the most recent filename
|
|
1255
|
-
unless @ux_most_recent_filename != @delegate_object[:filename]
|
|
1256
|
-
return
|
|
1257
|
-
end
|
|
1258
|
-
|
|
1259
|
-
@ux_most_recent_filename = @delegate_object[:filename]
|
|
1260
|
-
|
|
1261
|
-
# select all UX blocks, rejecting non-primary split
|
|
1262
|
-
blocks = select_automatic_ux_blocks(
|
|
1263
|
-
all_blocks.reject(&:is_split_rest?)
|
|
1264
|
-
)
|
|
1265
|
-
return if blocks.empty?
|
|
1266
|
-
|
|
1267
|
-
# collect code from all ux blocks
|
|
1268
|
-
(blocks.each.with_object([]) do |block, merged_options|
|
|
1269
|
-
command_result_w_e_t_nl =
|
|
1270
|
-
code_from_ux_block_to_set_environment_variables(
|
|
1271
|
-
block,
|
|
1272
|
-
mdoc,
|
|
1273
|
-
force: @delegate_object[:ux_auto_load_force_default],
|
|
1274
|
-
only_default: true,
|
|
1275
|
-
silent: true
|
|
1276
|
-
)
|
|
1277
|
-
if command_result_w_e_t_nl.failure?
|
|
1278
|
-
# if a block fails, proceed with next block
|
|
1279
|
-
merged_options
|
|
1280
|
-
else
|
|
1281
|
-
merged_options.push(command_result_w_e_t_nl.new_lines)
|
|
1282
|
-
end
|
|
1283
|
-
end).to_a
|
|
1344
|
+
wwe $!, 'all_blocks.count:', all_blocks.count
|
|
1284
1345
|
end
|
|
1285
1346
|
|
|
1286
1347
|
# return code resulting from evaluating all automatic VARS blocks in order
|
|
@@ -1317,91 +1378,101 @@ module MarkdownExec
|
|
|
1317
1378
|
# set ENV value for the variable and return code lines for the same
|
|
1318
1379
|
# for BlockType::UX
|
|
1319
1380
|
def code_from_ux_block_to_set_environment_variables(
|
|
1320
|
-
selected, mdoc,
|
|
1321
|
-
required:
|
|
1381
|
+
selected, mdoc, context_code: nil, force: true, only_default: false,
|
|
1382
|
+
required: OpenStruct.new(context_code: [], transient_code: []),
|
|
1383
|
+
silent:
|
|
1322
1384
|
)
|
|
1323
1385
|
wwt :fcb, 'selected:', selected
|
|
1386
|
+
wwt :context_code, context_code
|
|
1324
1387
|
ret_command_result = nil
|
|
1325
1388
|
exit_prompt = @delegate_object[:prompt_filespec_back]
|
|
1326
1389
|
|
|
1327
|
-
required
|
|
1390
|
+
wwt :required, required
|
|
1391
|
+
required_code = mdoc&.collect_recursively_required_code(
|
|
1328
1392
|
anyname: selected_id_name(selected),
|
|
1329
1393
|
label_format_above: @delegate_object[:shell_code_label_format_above],
|
|
1330
1394
|
label_format_below: @delegate_object[:shell_code_label_format_below],
|
|
1331
|
-
block_source: block_source
|
|
1395
|
+
block_source: block_source,
|
|
1396
|
+
context_code: context_code
|
|
1332
1397
|
)
|
|
1333
|
-
wwt :
|
|
1398
|
+
wwt :required_code, required_code
|
|
1399
|
+
# new_inherited_lines = []
|
|
1334
1400
|
|
|
1335
1401
|
# process each ux block in sequence, setting ENV and collecting lines
|
|
1336
1402
|
concatenated_code_from_required_blocks = []
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1403
|
+
if required_code # exclude for tests
|
|
1404
|
+
required_code[:blocks]&.each do |block|
|
|
1405
|
+
next if block.type != BlockType::UX
|
|
1406
|
+
|
|
1407
|
+
wwt :fcb, 'a required block', block
|
|
1408
|
+
|
|
1409
|
+
body1 = block.raw_body || block.body
|
|
1410
|
+
case data = safe_yaml_load(body1.join("\n"))
|
|
1411
|
+
when Hash
|
|
1412
|
+
export = parse_yaml_of_ux_block(
|
|
1413
|
+
data,
|
|
1414
|
+
prompt: @delegate_object[:prompt_ux_enter_a_value],
|
|
1415
|
+
validate: '^(?<name>[^ ].*)$'
|
|
1416
|
+
)
|
|
1417
|
+
block.export = export
|
|
1418
|
+
block.export_act = FCB.act_source(export)
|
|
1419
|
+
block.export_init = FCB.init_source(export)
|
|
1420
|
+
|
|
1421
|
+
# required_code are variable names that must be set before the UX block is executed.
|
|
1422
|
+
# if any precondition is not set, the sequence is aborted.
|
|
1423
|
+
required_variables = []
|
|
1424
|
+
export.required&.each do |precondition|
|
|
1425
|
+
required_variables.push "[[ -z $#{precondition} ]] && exit #{CommandResult::EXIT_STATUS_REQUIRED_EMPTY}"
|
|
1426
|
+
end
|
|
1427
|
+
wwt :required_variables, 'required_variables',
|
|
1428
|
+
required_variables
|
|
1429
|
+
|
|
1430
|
+
eval_code = join_array_of_arrays(
|
|
1431
|
+
required[:context_code],
|
|
1432
|
+
context_code, # inherited code
|
|
1433
|
+
concatenated_code_from_required_blocks, # current block requirements
|
|
1434
|
+
required_variables, # test conditions
|
|
1435
|
+
required[:transient_code],
|
|
1436
|
+
required_code[:transient_code] # required by selected
|
|
1437
|
+
)
|
|
1438
|
+
wwt :eval_code, 'eval_code:', eval_code
|
|
1439
|
+
if only_default
|
|
1440
|
+
command_result_w_e_t_nl =
|
|
1441
|
+
ux_block_export_automatic(eval_code, export)
|
|
1442
|
+
# do not display warnings on initializing call
|
|
1443
|
+
return command_result_w_e_t_nl if command_result_w_e_t_nl.failure?
|
|
1375
1444
|
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1445
|
+
else
|
|
1446
|
+
command_result_w_e_t_nl =
|
|
1447
|
+
ux_block_export_activated(eval_code, export, exit_prompt)
|
|
1448
|
+
if command_result_w_e_t_nl.failure?
|
|
1449
|
+
if command_result_w_e_t_nl.warning&.present? && !silent
|
|
1450
|
+
warn command_result_w_e_t_nl.warning
|
|
1451
|
+
end
|
|
1452
|
+
return command_result_w_e_t_nl
|
|
1382
1453
|
end
|
|
1383
|
-
return command_result_w_e_t_nl
|
|
1384
1454
|
end
|
|
1385
|
-
|
|
1386
|
-
return command_result_w_e_t_nl if command_result_w_e_t_nl.failure?
|
|
1455
|
+
return command_result_w_e_t_nl if command_result_w_e_t_nl.failure?
|
|
1387
1456
|
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1457
|
+
# update the required lines for this and subsequent blocks
|
|
1458
|
+
command_result_w_e_t_nl.new_lines =
|
|
1459
|
+
process_command_result_lines(command_result_w_e_t_nl, export,
|
|
1460
|
+
concatenated_code_from_required_blocks)
|
|
1461
|
+
concatenated_code_from_required_blocks.concat(command_result_w_e_t_nl.new_lines)
|
|
1393
1462
|
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1463
|
+
concatenated_code_from_required_blocks = annotate_required_lines(
|
|
1464
|
+
'blk:UX', concatenated_code_from_required_blocks, block_name: selected.id
|
|
1465
|
+
)
|
|
1397
1466
|
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1467
|
+
command_result_w_e_t_nl.new_lines = concatenated_code_from_required_blocks
|
|
1468
|
+
ret_command_result = command_result_w_e_t_nl
|
|
1469
|
+
else
|
|
1470
|
+
raise "Invalid data type: #{data.inspect}"
|
|
1471
|
+
end
|
|
1402
1472
|
end
|
|
1403
1473
|
end
|
|
1404
|
-
wwt :concatenated_code_from_required_blocks,
|
|
1474
|
+
wwt :concatenated_code_from_required_blocks,
|
|
1475
|
+
concatenated_code_from_required_blocks
|
|
1405
1476
|
|
|
1406
1477
|
(ret_command_result || CommandResult.new(
|
|
1407
1478
|
stdout: annotate_required_lines(
|
|
@@ -1411,19 +1482,19 @@ module MarkdownExec
|
|
|
1411
1482
|
wwt :cr, ret, caller.deref
|
|
1412
1483
|
end
|
|
1413
1484
|
rescue StandardError
|
|
1414
|
-
wwe 'selected:', selected, '
|
|
1485
|
+
wwe $!, 'selected:', selected, 'required_code:', required_code, 'block:', block,
|
|
1415
1486
|
'data:', data
|
|
1416
1487
|
end
|
|
1417
1488
|
|
|
1418
1489
|
# def
|
|
1419
1490
|
# sets ENV
|
|
1420
1491
|
def code_from_vars_block_to_set_environment_variables(selected)
|
|
1421
|
-
|
|
1492
|
+
transient_code = []
|
|
1422
1493
|
case data = YAML.load(selected.body.join("\n"))
|
|
1423
1494
|
when Hash
|
|
1424
1495
|
data.each do |key, value|
|
|
1425
1496
|
EnvInterface.set(key, value.to_s)
|
|
1426
|
-
|
|
1497
|
+
transient_code << assign_key_value_in_bash(key, value)
|
|
1427
1498
|
|
|
1428
1499
|
next unless @delegate_object[:menu_vars_set_format].present?
|
|
1429
1500
|
|
|
@@ -1435,10 +1506,10 @@ module MarkdownExec
|
|
|
1435
1506
|
print string_send_color(formatted_string, :menu_vars_set_color)
|
|
1436
1507
|
end
|
|
1437
1508
|
end
|
|
1438
|
-
annotate_required_lines('blk:VARS',
|
|
1509
|
+
annotate_required_lines('blk:VARS', transient_code, block_name: selected.id)
|
|
1439
1510
|
rescue StandardError
|
|
1440
1511
|
wwe 'selected:', selected, 'data:', data, 'key:', key, 'value:', value,
|
|
1441
|
-
'
|
|
1512
|
+
'transient_code:', transient_code, 'formatted_string:', formatted_string
|
|
1442
1513
|
end
|
|
1443
1514
|
|
|
1444
1515
|
# make a single line of shell code to assign an escaped value to a variable
|
|
@@ -1495,7 +1566,8 @@ module MarkdownExec
|
|
|
1495
1566
|
else
|
|
1496
1567
|
@run_state.in_own_window = false
|
|
1497
1568
|
command_execute_in_process(
|
|
1498
|
-
args: args,
|
|
1569
|
+
args: args,
|
|
1570
|
+
command: command,
|
|
1499
1571
|
erls: erls,
|
|
1500
1572
|
filename: @delegate_object[:filename],
|
|
1501
1573
|
shell: shell
|
|
@@ -1577,8 +1649,7 @@ module MarkdownExec
|
|
|
1577
1649
|
# containing code blocks.
|
|
1578
1650
|
# @param selected [Hash] The selected item from the menu
|
|
1579
1651
|
# to be executed.
|
|
1580
|
-
# @return [
|
|
1581
|
-
# the next block or reuse the current one.
|
|
1652
|
+
# @return [Array] context_code
|
|
1582
1653
|
def compile_execute_and_trigger_reuse(
|
|
1583
1654
|
mdoc:, selected:, block_source:, link_state:
|
|
1584
1655
|
)
|
|
@@ -1595,18 +1666,18 @@ module MarkdownExec
|
|
|
1595
1666
|
end
|
|
1596
1667
|
end
|
|
1597
1668
|
|
|
1598
|
-
|
|
1669
|
+
required_code = execute_block_type_port_code_lines(
|
|
1599
1670
|
mdoc: mdoc, selected: selected,
|
|
1600
1671
|
link_state: link_state, block_source: block_source
|
|
1601
1672
|
)
|
|
1602
1673
|
output_or_approval = @delegate_object[:output_script] ||
|
|
1603
1674
|
@delegate_object[:user_must_approve]
|
|
1604
1675
|
if output_or_approval
|
|
1605
|
-
display_required_code(required_lines:
|
|
1676
|
+
display_required_code(required_lines: required_code[:transient_code])
|
|
1606
1677
|
end
|
|
1607
1678
|
allow_execution = if @delegate_object[:user_must_approve]
|
|
1608
1679
|
prompt_for_user_approval(
|
|
1609
|
-
required_lines:
|
|
1680
|
+
required_lines: required_code[:transient_code],
|
|
1610
1681
|
selected: selected
|
|
1611
1682
|
)
|
|
1612
1683
|
else
|
|
@@ -1614,16 +1685,28 @@ module MarkdownExec
|
|
|
1614
1685
|
end
|
|
1615
1686
|
|
|
1616
1687
|
if allow_execution
|
|
1688
|
+
script_lines = ( #HashDelegator.join_code_lines(
|
|
1689
|
+
# ['# prior context'] +
|
|
1690
|
+
(link_state&.context_code || []) +
|
|
1691
|
+
# ['# new context'] +
|
|
1692
|
+
required_code[:context_code] +
|
|
1693
|
+
# ['# new transient'] +
|
|
1694
|
+
required_code[:transient_code]
|
|
1695
|
+
)
|
|
1617
1696
|
execute_required_lines(
|
|
1618
1697
|
blockname: selected_id_name(selected),
|
|
1619
1698
|
erls: { play_bin: play_bin,
|
|
1620
1699
|
shell: selected_shell(selected.shell) },
|
|
1621
|
-
|
|
1700
|
+
script_lines: script_lines,
|
|
1622
1701
|
shell: selected_shell(selected.shell)
|
|
1623
1702
|
)
|
|
1624
1703
|
end
|
|
1625
1704
|
|
|
1626
1705
|
link_state.block_name = nil
|
|
1706
|
+
|
|
1707
|
+
required_code[:context_code]
|
|
1708
|
+
rescue StandardError
|
|
1709
|
+
wwe $!
|
|
1627
1710
|
end
|
|
1628
1711
|
|
|
1629
1712
|
# Check if the expression contains wildcard characters
|
|
@@ -1887,16 +1970,7 @@ module MarkdownExec
|
|
|
1887
1970
|
case_conversion: criteria[:case_conversion],
|
|
1888
1971
|
center: criteria[:center] &&
|
|
1889
1972
|
@delegate_object[criteria[:center]],
|
|
1890
|
-
|
|
1891
|
-
collapse: case fcb.collapse_token
|
|
1892
|
-
when COLLAPSIBLE_TOKEN_COLLAPSE
|
|
1893
|
-
true
|
|
1894
|
-
when COLLAPSIBLE_TOKEN_EXPAND
|
|
1895
|
-
false
|
|
1896
|
-
else
|
|
1897
|
-
false
|
|
1898
|
-
end,
|
|
1899
|
-
|
|
1973
|
+
collapse: fcb.collapse_token == COLLAPSIBLE_TOKEN_COLLAPSE,
|
|
1900
1974
|
color_method: criteria[:color] &&
|
|
1901
1975
|
@delegate_object[criteria[:color]].to_sym,
|
|
1902
1976
|
decor_patterns:
|
|
@@ -1943,6 +2017,8 @@ module MarkdownExec
|
|
|
1943
2017
|
# filter block if selected in menu
|
|
1944
2018
|
return true if @run_state.source.block_name_from_cli
|
|
1945
2019
|
|
|
2020
|
+
return true if @delegate_object[:block_name].empty?
|
|
2021
|
+
|
|
1946
2022
|
# return false if @prior_execution_block == @delegate_object[:block_name]
|
|
1947
2023
|
if @prior_execution_block == @delegate_object[:block_name]
|
|
1948
2024
|
return @allowed_execution_block == @prior_execution_block ||
|
|
@@ -2119,10 +2195,10 @@ module MarkdownExec
|
|
|
2119
2195
|
warn format_and_highlight_lines(link_state.inherited_dependencies,
|
|
2120
2196
|
label: 'inherited_dependencies')
|
|
2121
2197
|
end
|
|
2122
|
-
return unless @delegate_object[:
|
|
2198
|
+
return unless @delegate_object[:dump_context_code]
|
|
2123
2199
|
|
|
2124
|
-
warn format_and_highlight_lines(link_state.
|
|
2125
|
-
label: '
|
|
2200
|
+
warn format_and_highlight_lines(link_state.context_code,
|
|
2201
|
+
label: 'context_code')
|
|
2126
2202
|
end
|
|
2127
2203
|
|
|
2128
2204
|
# Opens text in an editor for user modification and
|
|
@@ -2208,7 +2284,7 @@ module MarkdownExec
|
|
|
2208
2284
|
vux_edit_inherited
|
|
2209
2285
|
return :break if pause_user_exit
|
|
2210
2286
|
|
|
2211
|
-
next_state_append_code(selected, link_state, [])
|
|
2287
|
+
next_state_append_code(selected, link_state, context_code: [])
|
|
2212
2288
|
|
|
2213
2289
|
elsif selected.type == BlockType::HISTORY
|
|
2214
2290
|
debounce_reset
|
|
@@ -2221,23 +2297,25 @@ module MarkdownExec
|
|
|
2221
2297
|
|
|
2222
2298
|
elsif selected.type == BlockType::LINK
|
|
2223
2299
|
debounce_reset
|
|
2224
|
-
execute_block_type_link_with_state(
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
|
|
2300
|
+
execute_block_type_link_with_state(
|
|
2301
|
+
link_block_body: selected.body,
|
|
2302
|
+
mdoc: mdoc,
|
|
2303
|
+
selected: selected,
|
|
2304
|
+
link_state: link_state,
|
|
2305
|
+
block_source: block_source
|
|
2306
|
+
)
|
|
2229
2307
|
|
|
2230
2308
|
elsif selected.type == BlockType::LOAD
|
|
2231
2309
|
debounce_reset
|
|
2232
2310
|
load_result = execute_block_type_load_code_lines(selected)
|
|
2233
|
-
next_state_append_code(selected, link_state, load_result.code,
|
|
2234
|
-
|
|
2311
|
+
next_state_append_code(selected, link_state, context_code: load_result.code,
|
|
2312
|
+
mode: load_result.mode)
|
|
2235
2313
|
|
|
2236
2314
|
elsif selected.type == BlockType::SAVE
|
|
2237
2315
|
debounce_reset
|
|
2238
2316
|
|
|
2239
2317
|
execute_block_type_save(
|
|
2240
|
-
|
|
2318
|
+
transient_code: link_state&.context_code,
|
|
2241
2319
|
selected: selected
|
|
2242
2320
|
)
|
|
2243
2321
|
|
|
@@ -2259,7 +2337,7 @@ module MarkdownExec
|
|
|
2259
2337
|
|
|
2260
2338
|
elsif selected.type == BlockType::OPTS
|
|
2261
2339
|
debounce_reset
|
|
2262
|
-
|
|
2340
|
+
transient_code = []
|
|
2263
2341
|
options_state = read_show_options_and_trigger_reuse(
|
|
2264
2342
|
link_state: link_state,
|
|
2265
2343
|
mdoc: @dml_mdoc,
|
|
@@ -2268,7 +2346,7 @@ module MarkdownExec
|
|
|
2268
2346
|
update_menu_base(options_state.options)
|
|
2269
2347
|
|
|
2270
2348
|
link_state = LinkState.new
|
|
2271
|
-
next_state_append_code(selected, link_state,
|
|
2349
|
+
next_state_append_code(selected, link_state, context_code: transient_code)
|
|
2272
2350
|
|
|
2273
2351
|
elsif selected.type == BlockType::PORT
|
|
2274
2352
|
debounce_reset
|
|
@@ -2277,23 +2355,22 @@ module MarkdownExec
|
|
|
2277
2355
|
selected: selected,
|
|
2278
2356
|
link_state: link_state,
|
|
2279
2357
|
block_source: block_source
|
|
2280
|
-
)
|
|
2281
|
-
|
|
2358
|
+
)[:context_code]
|
|
2359
|
+
next_state_append_code(selected, link_state, context_code: required_lines)
|
|
2282
2360
|
|
|
2283
2361
|
elsif selected.type == BlockType::UX
|
|
2284
2362
|
debounce_reset
|
|
2285
2363
|
command_result_w_e_t_nl = code_from_ux_block_to_set_environment_variables(
|
|
2286
2364
|
selected,
|
|
2287
2365
|
@dml_mdoc,
|
|
2288
|
-
|
|
2366
|
+
context_code: @dml_link_state.context_code,
|
|
2289
2367
|
only_default: false,
|
|
2290
2368
|
silent: true
|
|
2291
2369
|
)
|
|
2292
|
-
### TBD if command_result_w_e_t_nl.failure?
|
|
2293
2370
|
next_state_append_code(
|
|
2294
2371
|
selected,
|
|
2295
2372
|
link_state,
|
|
2296
|
-
command_result_w_e_t_nl.failure? ? [] : command_result_w_e_t_nl.new_lines
|
|
2373
|
+
context_code: command_result_w_e_t_nl.failure? ? [] : command_result_w_e_t_nl.new_lines
|
|
2297
2374
|
)
|
|
2298
2375
|
|
|
2299
2376
|
elsif selected.type == BlockType::VARS
|
|
@@ -2301,7 +2378,7 @@ module MarkdownExec
|
|
|
2301
2378
|
next_state_append_code(
|
|
2302
2379
|
selected,
|
|
2303
2380
|
link_state,
|
|
2304
|
-
code_from_vars_block_to_set_environment_variables(selected)
|
|
2381
|
+
context_code: code_from_vars_block_to_set_environment_variables(selected)
|
|
2305
2382
|
)
|
|
2306
2383
|
|
|
2307
2384
|
elsif COLLAPSIBLE_TYPES.include?(selected.type)
|
|
@@ -2310,11 +2387,14 @@ module MarkdownExec
|
|
|
2310
2387
|
LoadFileLinkState.new(LoadFile::REUSE, link_state)
|
|
2311
2388
|
|
|
2312
2389
|
elsif debounce_allows
|
|
2313
|
-
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
|
|
2390
|
+
# SHELL type
|
|
2391
|
+
context_code = compile_execute_and_trigger_reuse(
|
|
2392
|
+
mdoc: mdoc,
|
|
2393
|
+
selected: selected,
|
|
2394
|
+
link_state: link_state,
|
|
2395
|
+
block_source: block_source
|
|
2396
|
+
)
|
|
2397
|
+
next_state_set_code(selected, link_state, context_code)
|
|
2318
2398
|
|
|
2319
2399
|
else
|
|
2320
2400
|
LoadFileLinkState.new(LoadFile::REUSE, link_state)
|
|
@@ -2408,29 +2488,31 @@ module MarkdownExec
|
|
|
2408
2488
|
## collect blocks specified by block
|
|
2409
2489
|
#
|
|
2410
2490
|
if mdoc
|
|
2411
|
-
|
|
2491
|
+
required_code = mdoc.collect_recursively_required_code(
|
|
2412
2492
|
anyname: selected_id_name(selected),
|
|
2413
2493
|
block_source: block_source,
|
|
2414
2494
|
label_format_above: @delegate_object[:shell_code_label_format_above],
|
|
2415
|
-
label_format_below: @delegate_object[:shell_code_label_format_below]
|
|
2495
|
+
label_format_below: @delegate_object[:shell_code_label_format_below],
|
|
2496
|
+
context_code: link_state&.context_code || []
|
|
2416
2497
|
)
|
|
2417
|
-
|
|
2418
|
-
|
|
2498
|
+
|
|
2499
|
+
context_code = annotate_required_lines(
|
|
2500
|
+
'blk:LINK', required_code[:context_code], block_name: selected.id
|
|
2419
2501
|
)
|
|
2420
|
-
block_names =
|
|
2421
|
-
dependencies =
|
|
2502
|
+
block_names = required_code[:block_names]
|
|
2503
|
+
dependencies = required_code[:dependencies]
|
|
2422
2504
|
else
|
|
2423
2505
|
block_names = []
|
|
2424
|
-
|
|
2506
|
+
context_code = []
|
|
2425
2507
|
dependencies = {}
|
|
2426
2508
|
end
|
|
2427
2509
|
|
|
2428
2510
|
# load key and values from link block into current environment
|
|
2429
2511
|
#
|
|
2430
2512
|
if link_block_data[LinkKeys::VARS]
|
|
2431
|
-
|
|
2513
|
+
context_code << BashCommentFormatter.format_comment(selected.pub_name)
|
|
2432
2514
|
link_block_data[LinkKeys::VARS].each do |key, value|
|
|
2433
|
-
|
|
2515
|
+
context_code << assign_key_value_in_bash(key, value)
|
|
2434
2516
|
EnvInterface.set(key, value.to_s)
|
|
2435
2517
|
end
|
|
2436
2518
|
end
|
|
@@ -2441,20 +2523,20 @@ module MarkdownExec
|
|
|
2441
2523
|
load_filespec = load_filespec_from_expression(load_expr)
|
|
2442
2524
|
if load_filespec
|
|
2443
2525
|
begin
|
|
2444
|
-
|
|
2445
|
-
|
|
2526
|
+
context_code += File.readlines(load_filespec,
|
|
2527
|
+
chomp: true)
|
|
2446
2528
|
rescue Errno::ENOENT
|
|
2447
2529
|
report_error($ERROR_INFO)
|
|
2448
2530
|
end
|
|
2449
2531
|
end
|
|
2450
2532
|
end
|
|
2451
2533
|
|
|
2452
|
-
# if an eval link block, evaluate
|
|
2534
|
+
# if an eval link block, evaluate context_code and return its standard output
|
|
2453
2535
|
#
|
|
2454
2536
|
if link_block_data.fetch(LinkKeys::EVAL, false) ||
|
|
2455
2537
|
link_block_data.fetch(LinkKeys::EXEC, false)
|
|
2456
|
-
|
|
2457
|
-
link_state,
|
|
2538
|
+
context_code = link_block_data_eval(
|
|
2539
|
+
link_state, context_code, selected, link_block_data,
|
|
2458
2540
|
block_source: block_source,
|
|
2459
2541
|
shell: @delegate_object[:block_type_default]
|
|
2460
2542
|
)
|
|
@@ -2469,13 +2551,16 @@ module MarkdownExec
|
|
|
2469
2551
|
nil
|
|
2470
2552
|
) || link_block_data.fetch(LinkKeys::BLOCK, nil) || ''
|
|
2471
2553
|
|
|
2472
|
-
|
|
2473
|
-
'blk:LINK',
|
|
2554
|
+
context_code = annotate_required_lines(
|
|
2555
|
+
'blk:LINK', context_code, block_name: selected.id
|
|
2556
|
+
)
|
|
2557
|
+
context_code = annotate_required_lines(
|
|
2558
|
+
'blk:LINK', context_code, block_name: selected.id
|
|
2474
2559
|
)
|
|
2475
2560
|
|
|
2476
2561
|
if link_block_data[LinkKeys::RETURN]
|
|
2477
2562
|
pop_add_current_code_to_head_and_trigger_load(
|
|
2478
|
-
link_state, block_names,
|
|
2563
|
+
link_state, block_names, context_code,
|
|
2479
2564
|
dependencies, selected, next_block_name: next_block_name
|
|
2480
2565
|
)
|
|
2481
2566
|
|
|
@@ -2488,8 +2573,8 @@ module MarkdownExec
|
|
|
2488
2573
|
((link_state&.inherited_block_names || []) + block_names).sort.uniq,
|
|
2489
2574
|
inherited_dependencies:
|
|
2490
2575
|
(link_state&.inherited_dependencies || {}).merge(dependencies || {}), ### merge, not replace, key data
|
|
2491
|
-
|
|
2492
|
-
link_state&.
|
|
2576
|
+
context_code: HashDelegator.flatten_and_compact_arrays(
|
|
2577
|
+
link_state&.context_code, context_code
|
|
2493
2578
|
),
|
|
2494
2579
|
keep_code: link_state&.keep_code,
|
|
2495
2580
|
next_block_name: next_block_name,
|
|
@@ -2586,31 +2671,34 @@ module MarkdownExec
|
|
|
2586
2671
|
#
|
|
2587
2672
|
# @param mdoc [YourMDocClass] An instance of the MDoc class.
|
|
2588
2673
|
# @param selected [Hash] The selected block.
|
|
2589
|
-
# @return [
|
|
2674
|
+
# @return [OpenStruct] context and transient code
|
|
2590
2675
|
def execute_block_type_port_code_lines(mdoc:, selected:, block_source:,
|
|
2591
2676
|
link_state: LinkState.new)
|
|
2592
|
-
|
|
2677
|
+
required_code = mdoc.collect_recursively_required_code(
|
|
2593
2678
|
anyname: selected_id_name(selected),
|
|
2594
2679
|
label_format_above: @delegate_object[:shell_code_label_format_above],
|
|
2595
2680
|
label_format_below: @delegate_object[:shell_code_label_format_below],
|
|
2596
|
-
block_source: block_source
|
|
2597
|
-
|
|
2681
|
+
block_source: block_source,
|
|
2682
|
+
context_code: link_state&.context_code || []
|
|
2683
|
+
) # !!t 'required_code'
|
|
2598
2684
|
dependencies = (
|
|
2599
2685
|
link_state&.inherited_dependencies || {}
|
|
2600
|
-
).merge(
|
|
2601
|
-
|
|
2602
|
-
|
|
2686
|
+
).merge(required_code[:dependencies] || {})
|
|
2687
|
+
|
|
2688
|
+
required_code[:unmet_dependencies] = (
|
|
2689
|
+
required_code[:unmet_dependencies] || []
|
|
2603
2690
|
) - (link_state&.inherited_block_names || [])
|
|
2604
|
-
|
|
2691
|
+
|
|
2692
|
+
if required_code[:unmet_dependencies].present?
|
|
2605
2693
|
### filter against link_state.inherited_block_names
|
|
2606
2694
|
|
|
2607
2695
|
warn format_and_highlight_dependencies(
|
|
2608
|
-
dependencies, highlight:
|
|
2696
|
+
dependencies, highlight: required_code[:unmet_dependencies]
|
|
2609
2697
|
)
|
|
2610
2698
|
runtime_exception(
|
|
2611
2699
|
:runtime_exception_error_level,
|
|
2612
2700
|
'unmet_dependencies, flag: runtime_exception_error_level',
|
|
2613
|
-
|
|
2701
|
+
required_code[:unmet_dependencies]
|
|
2614
2702
|
)
|
|
2615
2703
|
elsif @delegate_object[:dump_dependencies]
|
|
2616
2704
|
warn format_and_highlight_dependencies(
|
|
@@ -2621,43 +2709,55 @@ module MarkdownExec
|
|
|
2621
2709
|
|
|
2622
2710
|
if selected[:type] == BlockType::OPTS
|
|
2623
2711
|
# body of blocks is returned as a list of lines to be read an YAML
|
|
2624
|
-
|
|
2625
|
-
|
|
2712
|
+
OpenStruct.new(
|
|
2713
|
+
context_code: HashDelegator.flatten_and_compact_arrays(
|
|
2714
|
+
required_code[:blocks].map(&:body).flatten(1)
|
|
2715
|
+
),
|
|
2716
|
+
transient_code: []
|
|
2626
2717
|
)
|
|
2627
2718
|
else
|
|
2628
2719
|
# code from the selected VARS block
|
|
2629
2720
|
vars_code = if selected.type == BlockType::VARS
|
|
2630
|
-
|
|
2631
|
-
|
|
2632
|
-
|
|
2633
|
-
|
|
2721
|
+
code_from_vars_block_to_set_environment_variables(selected)
|
|
2722
|
+
else
|
|
2723
|
+
[]
|
|
2724
|
+
end
|
|
2634
2725
|
|
|
2635
|
-
# activate UX blocks in the
|
|
2726
|
+
# activate UX blocks in the required_code list
|
|
2636
2727
|
command_result_w_e_t_nl = code_from_ux_block_to_set_environment_variables(
|
|
2637
2728
|
selected,
|
|
2638
2729
|
@dml_mdoc,
|
|
2639
|
-
|
|
2730
|
+
context_code: required_code[:context_code] + required_code[:transient_code],
|
|
2640
2731
|
only_default: false,
|
|
2641
|
-
required:
|
|
2732
|
+
required:
|
|
2733
|
+
OpenStruct.new(context_code: [], transient_code: vars_code),
|
|
2642
2734
|
silent: false
|
|
2643
2735
|
)
|
|
2644
2736
|
ux_code = command_result_w_e_t_nl.failure? ? [] : command_result_w_e_t_nl.new_lines
|
|
2645
2737
|
|
|
2646
|
-
|
|
2647
|
-
|
|
2648
|
-
|
|
2649
|
-
|
|
2650
|
-
|
|
2651
|
-
|
|
2738
|
+
OpenStruct.new(
|
|
2739
|
+
context_code: HashDelegator.flatten_and_compact_arrays(
|
|
2740
|
+
link_state&.context_code,
|
|
2741
|
+
annotate_required_lines(
|
|
2742
|
+
'blk:PORT',
|
|
2743
|
+
(required_code[:context_code] || []) + vars_code + ux_code,
|
|
2744
|
+
block_name: selected.id
|
|
2745
|
+
)
|
|
2746
|
+
),
|
|
2747
|
+
transient_code: HashDelegator.flatten_and_compact_arrays(
|
|
2748
|
+
annotate_required_lines(
|
|
2749
|
+
'blk:PORT',
|
|
2750
|
+
required_code[:transient_code],
|
|
2751
|
+
block_name: selected.id
|
|
2752
|
+
)
|
|
2652
2753
|
)
|
|
2653
2754
|
)
|
|
2654
2755
|
end
|
|
2655
|
-
|
|
2656
2756
|
rescue StandardError
|
|
2657
|
-
wwe(
|
|
2757
|
+
wwe(required_code, ux_code, { error: $!, callback: $@[0] })
|
|
2658
2758
|
end
|
|
2659
2759
|
|
|
2660
|
-
def execute_block_type_save(
|
|
2760
|
+
def execute_block_type_save(transient_code:, selected:)
|
|
2661
2761
|
block_data = HashDelegator.parse_yaml_data_from_body(selected.body)
|
|
2662
2762
|
directory_glob = if block_data['directory']
|
|
2663
2763
|
File.join(
|
|
@@ -2678,7 +2778,7 @@ module MarkdownExec
|
|
|
2678
2778
|
end
|
|
2679
2779
|
|
|
2680
2780
|
File.write(save_filespec,
|
|
2681
|
-
HashDelegator.join_code_lines(
|
|
2781
|
+
HashDelegator.join_code_lines(transient_code))
|
|
2682
2782
|
rescue Errno::ENOENT
|
|
2683
2783
|
report_error($ERROR_INFO)
|
|
2684
2784
|
end
|
|
@@ -2773,14 +2873,14 @@ module MarkdownExec
|
|
|
2773
2873
|
end
|
|
2774
2874
|
|
|
2775
2875
|
def execute_inherited_save(
|
|
2776
|
-
|
|
2876
|
+
transient_code: @dml_link_state.context_code
|
|
2777
2877
|
)
|
|
2778
2878
|
return unless (save_filespec = save_filespec_from_expression(
|
|
2779
2879
|
document_name_in_glob_as_file_name
|
|
2780
2880
|
))
|
|
2781
2881
|
|
|
2782
2882
|
unless write_file_with_directory_creation(
|
|
2783
|
-
content: HashDelegator.join_code_lines(
|
|
2883
|
+
content: HashDelegator.join_code_lines(transient_code),
|
|
2784
2884
|
filespec: save_filespec
|
|
2785
2885
|
)
|
|
2786
2886
|
:break
|
|
@@ -2791,14 +2891,14 @@ module MarkdownExec
|
|
|
2791
2891
|
@menu_user_clicked_back_link = true
|
|
2792
2892
|
|
|
2793
2893
|
keep_code = @dml_link_state.keep_code
|
|
2794
|
-
|
|
2894
|
+
context_code = keep_code ? @dml_link_state.context_code_block : nil
|
|
2795
2895
|
|
|
2796
2896
|
@dml_link_state = pop_link_history_new_state
|
|
2797
2897
|
|
|
2798
2898
|
{
|
|
2799
2899
|
block_name: @dml_link_state.block_name,
|
|
2800
2900
|
document_filename: @dml_link_state.document_filename,
|
|
2801
|
-
|
|
2901
|
+
context_code: context_code,
|
|
2802
2902
|
keep_code: keep_code
|
|
2803
2903
|
}
|
|
2804
2904
|
end
|
|
@@ -2814,23 +2914,25 @@ module MarkdownExec
|
|
|
2814
2914
|
def execute_required_lines(
|
|
2815
2915
|
blockname: '',
|
|
2816
2916
|
erls: {},
|
|
2817
|
-
|
|
2917
|
+
script_lines: [],
|
|
2818
2918
|
shell:
|
|
2819
2919
|
)
|
|
2820
2920
|
if @delegate_object[:save_executed_script]
|
|
2821
2921
|
write_command_file(blockname: blockname,
|
|
2822
|
-
required_lines:
|
|
2922
|
+
required_lines: script_lines,
|
|
2823
2923
|
shell: selected_shell(shell))
|
|
2824
2924
|
end
|
|
2825
2925
|
if @dml_block_state
|
|
2826
2926
|
calc_logged_stdout_filename(block_name: @dml_block_state.block.oname)
|
|
2827
2927
|
end
|
|
2828
2928
|
format_and_execute_command(
|
|
2829
|
-
|
|
2929
|
+
script_lines: script_lines,
|
|
2830
2930
|
erls: erls,
|
|
2831
2931
|
shell: selected_shell(shell)
|
|
2832
2932
|
)
|
|
2833
2933
|
post_execution_process
|
|
2934
|
+
rescue StandardError
|
|
2935
|
+
wwe $!
|
|
2834
2936
|
end
|
|
2835
2937
|
|
|
2836
2938
|
def expand_blocks_with_replacements(
|
|
@@ -2926,7 +3028,8 @@ module MarkdownExec
|
|
|
2926
3028
|
end
|
|
2927
3029
|
|
|
2928
3030
|
def ux_block_eval_for_export(
|
|
2929
|
-
bash_script_lines,
|
|
3031
|
+
bash_script_lines,
|
|
3032
|
+
export,
|
|
2930
3033
|
data:,
|
|
2931
3034
|
first_only: false,
|
|
2932
3035
|
force:,
|
|
@@ -2934,68 +3037,90 @@ module MarkdownExec
|
|
|
2934
3037
|
silent:,
|
|
2935
3038
|
string: nil
|
|
2936
3039
|
)
|
|
2937
|
-
exportable = true
|
|
2938
3040
|
command_result = nil
|
|
2939
3041
|
new_lines = []
|
|
3042
|
+
required_lines = []
|
|
2940
3043
|
export_string = string.nil? ? data : string
|
|
2941
3044
|
expander = ->(expression) { %(printf '%s' "#{expression}") }
|
|
3045
|
+
exportable = true
|
|
2942
3046
|
|
|
2943
3047
|
case export_string
|
|
2944
3048
|
when String, Integer, Float, TrueClass, FalseClass
|
|
2945
|
-
command_result
|
|
2946
|
-
join_array_of_arrays(
|
|
3049
|
+
command_result = HashDelegator.execute_bash_script_lines(
|
|
3050
|
+
transient_code: join_array_of_arrays(
|
|
2947
3051
|
bash_script_lines,
|
|
2948
3052
|
printf_expand ? expander.call(export_string) : [export_string]
|
|
2949
3053
|
),
|
|
2950
|
-
export,
|
|
2951
|
-
|
|
3054
|
+
export: export,
|
|
3055
|
+
export_name: export.name,
|
|
3056
|
+
force: force,
|
|
3057
|
+
shell: @delegate_object[:shell],
|
|
3058
|
+
archive_script: @delegate_object[:archive_ad_hoc_scripts],
|
|
3059
|
+
archive_path_format: @delegate_object[:archive_path_format],
|
|
3060
|
+
archive_time_format: @delegate_object[:archive_time_format]
|
|
2952
3061
|
)
|
|
2953
|
-
|
|
3062
|
+
exportable = command_result&.exportable
|
|
3063
|
+
|
|
3064
|
+
if command_result&.exit_status == CommandResult::EXIT_STATUS_REQUIRED_EMPTY
|
|
2954
3065
|
exportable = false
|
|
2955
3066
|
unless silent
|
|
2956
3067
|
command_result.warning = warning_required_empty(export)
|
|
2957
3068
|
end
|
|
3069
|
+
elsif command_result.nil? || command_result.failure?
|
|
3070
|
+
exportable = false
|
|
3071
|
+
unless silent
|
|
3072
|
+
command_result.warning = warning_failure(export)
|
|
3073
|
+
end
|
|
2958
3074
|
else
|
|
2959
|
-
|
|
2960
|
-
|
|
2961
|
-
|
|
2962
|
-
|
|
2963
|
-
|
|
3075
|
+
out = command_result.stdout.to_s
|
|
3076
|
+
if export_environment_variable(export.name, out)
|
|
3077
|
+
new_lines << {
|
|
3078
|
+
name: export.name, force: force, text: out
|
|
3079
|
+
}
|
|
3080
|
+
required_lines << code_line_to_assign_a_variable(
|
|
3081
|
+
export.name, out, force: force
|
|
3082
|
+
)
|
|
3083
|
+
end
|
|
2964
3084
|
end
|
|
2965
3085
|
|
|
2966
3086
|
when Hash
|
|
2967
|
-
required_lines = []
|
|
2968
3087
|
|
|
2969
3088
|
# each item in the hash is a variable name and value
|
|
2970
3089
|
export_string.each do |name, expression|
|
|
2971
|
-
command_result
|
|
2972
|
-
join_array_of_arrays(
|
|
3090
|
+
command_result = HashDelegator.execute_bash_script_lines(
|
|
3091
|
+
transient_code: join_array_of_arrays(
|
|
2973
3092
|
bash_script_lines,
|
|
2974
3093
|
required_lines,
|
|
2975
3094
|
printf_expand ? expander.call(expression) : [expression]
|
|
2976
3095
|
),
|
|
2977
|
-
export,
|
|
2978
|
-
|
|
2979
|
-
|
|
2980
|
-
|
|
3096
|
+
export: export,
|
|
3097
|
+
export_name: name,
|
|
3098
|
+
force: force,
|
|
3099
|
+
shell: @delegate_object[:shell],
|
|
3100
|
+
archive_script: @delegate_object[:archive_ad_hoc_scripts],
|
|
3101
|
+
archive_path_format: @delegate_object[:archive_path_format],
|
|
3102
|
+
archive_time_format: @delegate_object[:archive_time_format]
|
|
3103
|
+
).tap { ww _1 }
|
|
3104
|
+
if command_result.exit_status == CommandResult::EXIT_STATUS_REQUIRED_EMPTY
|
|
3105
|
+
exportable = false
|
|
2981
3106
|
unless silent
|
|
2982
3107
|
command_result.warning = warning_required_empty(export)
|
|
2983
3108
|
end
|
|
3109
|
+
elsif command_result.failure?
|
|
3110
|
+
exportable = false
|
|
3111
|
+
unless silent
|
|
3112
|
+
command_result.warning = warning_failure(export)
|
|
3113
|
+
end
|
|
2984
3114
|
else
|
|
2985
|
-
|
|
2986
|
-
|
|
2987
|
-
|
|
3115
|
+
out = command_result.stdout.to_s
|
|
3116
|
+
if export_environment_variable(name, out)
|
|
3117
|
+
new_lines << {
|
|
3118
|
+
name: name, force: force, text: out
|
|
3119
|
+
}
|
|
3120
|
+
end
|
|
2988
3121
|
required_lines << code_line_to_assign_a_variable(
|
|
2989
|
-
name,
|
|
3122
|
+
name, out, force: force
|
|
2990
3123
|
)
|
|
2991
|
-
|
|
2992
|
-
if variable_is_exportable(name)
|
|
2993
|
-
# store the transformed value in ENV
|
|
2994
|
-
EnvInterface.set(name, transformed)
|
|
2995
|
-
|
|
2996
|
-
new_lines << { name: name, force: force,
|
|
2997
|
-
text: command_result.stdout }
|
|
2998
|
-
end
|
|
2999
3124
|
end
|
|
3000
3125
|
|
|
3001
3126
|
break if first_only
|
|
@@ -3004,9 +3129,23 @@ module MarkdownExec
|
|
|
3004
3129
|
# do nothing
|
|
3005
3130
|
end
|
|
3006
3131
|
|
|
3007
|
-
|
|
3132
|
+
if command_result
|
|
3133
|
+
command_result.exportable = exportable
|
|
3134
|
+
command_result.new_lines = new_lines
|
|
3135
|
+
command_result.required_lines = required_lines
|
|
3136
|
+
end
|
|
3137
|
+
|
|
3138
|
+
command_result
|
|
3008
3139
|
rescue StandardError
|
|
3009
|
-
wwe bash_script_lines, export, force, silent, string
|
|
3140
|
+
wwe $!, bash_script_lines, export, force, silent, string
|
|
3141
|
+
end
|
|
3142
|
+
|
|
3143
|
+
def export_environment_variable(export_name, stdout)
|
|
3144
|
+
return unless variable_is_exportable(export_name)
|
|
3145
|
+
|
|
3146
|
+
EnvInterface.set(export_name, stdout)
|
|
3147
|
+
|
|
3148
|
+
true
|
|
3010
3149
|
end
|
|
3011
3150
|
|
|
3012
3151
|
# Retrieves a specific data symbol from the delegate object,
|
|
@@ -3080,11 +3219,11 @@ module MarkdownExec
|
|
|
3080
3219
|
end
|
|
3081
3220
|
|
|
3082
3221
|
def format_and_execute_command(
|
|
3083
|
-
|
|
3222
|
+
script_lines:,
|
|
3084
3223
|
erls:,
|
|
3085
3224
|
shell:
|
|
3086
3225
|
)
|
|
3087
|
-
formatted_command =
|
|
3226
|
+
formatted_command = script_lines.flatten.join("\n")
|
|
3088
3227
|
@fout.fout fetch_color(data_sym: :script_execution_head,
|
|
3089
3228
|
color_sym: :script_execution_frame_color)
|
|
3090
3229
|
|
|
@@ -3353,7 +3492,7 @@ module MarkdownExec
|
|
|
3353
3492
|
wwt :iterlines, 'nested_line:', nested_line
|
|
3354
3493
|
update_line_and_block_state(
|
|
3355
3494
|
nested_line, state, selected_types,
|
|
3356
|
-
source_id: "
|
|
3495
|
+
source_id: "IBNF:#{index}¤#{nested_line.filename}:#{nested_line.index}",
|
|
3357
3496
|
&block
|
|
3358
3497
|
)
|
|
3359
3498
|
|
|
@@ -3393,10 +3532,10 @@ module MarkdownExec
|
|
|
3393
3532
|
end.compact.flatten(1)
|
|
3394
3533
|
end
|
|
3395
3534
|
|
|
3396
|
-
def link_block_data_eval(link_state,
|
|
3535
|
+
def link_block_data_eval(link_state, transient_code, selected, link_block_data,
|
|
3397
3536
|
block_source:, shell:)
|
|
3398
3537
|
all_code = HashDelegator.flatten_and_compact_arrays(
|
|
3399
|
-
link_state&.
|
|
3538
|
+
link_state&.context_code, transient_code
|
|
3400
3539
|
)
|
|
3401
3540
|
output_lines = []
|
|
3402
3541
|
|
|
@@ -3415,34 +3554,34 @@ module MarkdownExec
|
|
|
3415
3554
|
output_lines.push(line) if line
|
|
3416
3555
|
end
|
|
3417
3556
|
|
|
3418
|
-
if link_block_data.fetch(LinkKeys::EVAL, true)
|
|
3419
|
-
|
|
3420
|
-
|
|
3421
|
-
|
|
3422
|
-
|
|
3423
|
-
|
|
3424
|
-
|
|
3425
|
-
|
|
3426
|
-
|
|
3427
|
-
|
|
3428
|
-
|
|
3429
|
-
|
|
3430
|
-
|
|
3431
|
-
|
|
3557
|
+
output_lines = if link_block_data.fetch(LinkKeys::EVAL, true)
|
|
3558
|
+
# eval: true
|
|
3559
|
+
|
|
3560
|
+
## select output_lines that look like assignment or match other specs
|
|
3561
|
+
#
|
|
3562
|
+
process_string_array(
|
|
3563
|
+
output_lines,
|
|
3564
|
+
begin_pattern: @delegate_object.fetch(:output_assignment_begin,
|
|
3565
|
+
nil),
|
|
3566
|
+
end_pattern: @delegate_object.fetch(:output_assignment_end, nil),
|
|
3567
|
+
scan1: @delegate_object.fetch(:output_assignment_match, nil),
|
|
3568
|
+
format1: @delegate_object.fetch(:output_assignment_format, nil),
|
|
3569
|
+
name: ''
|
|
3570
|
+
)
|
|
3432
3571
|
|
|
3433
|
-
|
|
3434
|
-
|
|
3435
|
-
|
|
3436
|
-
|
|
3437
|
-
|
|
3438
|
-
|
|
3439
|
-
|
|
3440
|
-
|
|
3441
|
-
|
|
3442
|
-
|
|
3443
|
-
|
|
3444
|
-
|
|
3445
|
-
|
|
3572
|
+
else
|
|
3573
|
+
# eval: false
|
|
3574
|
+
|
|
3575
|
+
## select all output_lines
|
|
3576
|
+
#
|
|
3577
|
+
process_string_array(
|
|
3578
|
+
output_lines,
|
|
3579
|
+
begin_pattern: @delegate_object.fetch(:output_assignment_begin,
|
|
3580
|
+
nil),
|
|
3581
|
+
end_pattern: @delegate_object.fetch(:output_assignment_end, nil),
|
|
3582
|
+
name: ''
|
|
3583
|
+
)
|
|
3584
|
+
end
|
|
3446
3585
|
else
|
|
3447
3586
|
output_lines = `bash #{file.path}`.split("\n")
|
|
3448
3587
|
end
|
|
@@ -3489,7 +3628,7 @@ module MarkdownExec
|
|
|
3489
3628
|
|
|
3490
3629
|
def link_history_push_and_next(
|
|
3491
3630
|
curr_block_name:, curr_document_filename:,
|
|
3492
|
-
inherited_block_names:, inherited_dependencies:,
|
|
3631
|
+
inherited_block_names:, inherited_dependencies:, context_code:,
|
|
3493
3632
|
keep_code:,
|
|
3494
3633
|
next_block_name:, next_document_filename:,
|
|
3495
3634
|
next_keep_code:,
|
|
@@ -3501,7 +3640,7 @@ module MarkdownExec
|
|
|
3501
3640
|
document_filename: curr_document_filename,
|
|
3502
3641
|
inherited_block_names: inherited_block_names,
|
|
3503
3642
|
inherited_dependencies: inherited_dependencies,
|
|
3504
|
-
|
|
3643
|
+
context_code: context_code,
|
|
3505
3644
|
keep_code: keep_code
|
|
3506
3645
|
)
|
|
3507
3646
|
)
|
|
@@ -3512,7 +3651,7 @@ module MarkdownExec
|
|
|
3512
3651
|
document_filename: next_document_filename,
|
|
3513
3652
|
inherited_block_names: inherited_block_names,
|
|
3514
3653
|
inherited_dependencies: inherited_dependencies,
|
|
3515
|
-
|
|
3654
|
+
context_code: context_code,
|
|
3516
3655
|
keep_code: next_keep_code
|
|
3517
3656
|
)
|
|
3518
3657
|
)
|
|
@@ -3702,21 +3841,27 @@ module MarkdownExec
|
|
|
3702
3841
|
reload_blocks = true
|
|
3703
3842
|
end
|
|
3704
3843
|
|
|
3844
|
+
link_state_context_code = link_state&.context_code || []
|
|
3845
|
+
|
|
3705
3846
|
# return code resulting from evaluating all SHELL, UX, VARS blocks;
|
|
3706
3847
|
# each set in sequence; with its own order
|
|
3707
3848
|
#
|
|
3708
|
-
if (
|
|
3849
|
+
if (transient_code = inherited_lines_from_auto_blocks(
|
|
3709
3850
|
all_blocks,
|
|
3710
3851
|
default_only: true,
|
|
3711
|
-
mdoc: mdoc
|
|
3852
|
+
mdoc: mdoc,
|
|
3853
|
+
context_code: link_state_context_code
|
|
3712
3854
|
))&.select_by(:empty?, false)&.compact&.count&.positive?
|
|
3713
|
-
|
|
3714
|
-
|
|
3855
|
+
wwt :transient_code, 'transient_code:', transient_code
|
|
3856
|
+
|
|
3857
|
+
# prepend context code to new transient code
|
|
3858
|
+
new_code = link_state_context_code + transient_code
|
|
3715
3859
|
next_state_set_code(nil, link_state, new_code)
|
|
3716
|
-
link_state.
|
|
3860
|
+
link_state.context_code = new_code
|
|
3861
|
+
|
|
3717
3862
|
reload_blocks = true
|
|
3718
3863
|
else
|
|
3719
|
-
link_state&.
|
|
3864
|
+
link_state&.context_code
|
|
3720
3865
|
end
|
|
3721
3866
|
|
|
3722
3867
|
if reload_blocks
|
|
@@ -3876,6 +4021,14 @@ module MarkdownExec
|
|
|
3876
4021
|
end
|
|
3877
4022
|
end
|
|
3878
4023
|
|
|
4024
|
+
# Define respond_to_missing? to match method_missing behavior
|
|
4025
|
+
def respond_to_missing?(method_name, include_private = false)
|
|
4026
|
+
return true if @delegate_object.respond_to?(method_name, include_private)
|
|
4027
|
+
return true if method_name.to_s.end_with?('=')
|
|
4028
|
+
|
|
4029
|
+
true # Any other method name is treated as a key accessor
|
|
4030
|
+
end
|
|
4031
|
+
|
|
3879
4032
|
# If a method is missing, treat it as a key for the @delegate_object.
|
|
3880
4033
|
def method_missing(method_name, *args, &block)
|
|
3881
4034
|
if @delegate_object.respond_to?(method_name)
|
|
@@ -3895,19 +4048,19 @@ module MarkdownExec
|
|
|
3895
4048
|
list[(index + 1) % list.size] # Get the next item, wrap around if at the end
|
|
3896
4049
|
end
|
|
3897
4050
|
|
|
3898
|
-
def next_state_append_code(selected, link_state,
|
|
4051
|
+
def next_state_append_code(selected, link_state, context_code:,
|
|
3899
4052
|
mode: LoadMode::APPEND)
|
|
3900
4053
|
next_state_set_code(
|
|
3901
4054
|
selected,
|
|
3902
4055
|
link_state,
|
|
3903
4056
|
HashDelegator.flatten_and_compact_arrays(
|
|
3904
|
-
mode == LoadMode::APPEND ? link_state&.
|
|
3905
|
-
|
|
4057
|
+
mode == LoadMode::APPEND ? link_state&.context_code : [],
|
|
4058
|
+
context_code.is_a?(Array) ? context_code : [] # no code for :ux_exec_prohibited
|
|
3906
4059
|
)
|
|
3907
4060
|
)
|
|
3908
4061
|
end
|
|
3909
4062
|
|
|
3910
|
-
def next_state_set_code(selected, link_state,
|
|
4063
|
+
def next_state_set_code(selected, link_state, context_code)
|
|
3911
4064
|
block_names = []
|
|
3912
4065
|
dependencies = {}
|
|
3913
4066
|
link_history_push_and_next(
|
|
@@ -3917,7 +4070,7 @@ module MarkdownExec
|
|
|
3917
4070
|
((link_state&.inherited_block_names || []) + block_names).sort.uniq,
|
|
3918
4071
|
inherited_dependencies:
|
|
3919
4072
|
(link_state&.inherited_dependencies || {}).merge(dependencies || {}), ### merge, not replace, key data
|
|
3920
|
-
|
|
4073
|
+
context_code: HashDelegator.flatten_and_compact_arrays(context_code),
|
|
3921
4074
|
keep_code: link_state&.keep_code,
|
|
3922
4075
|
next_block_name: '',
|
|
3923
4076
|
next_document_filename: @delegate_object[:filename],
|
|
@@ -3961,60 +4114,6 @@ module MarkdownExec
|
|
|
3961
4114
|
}
|
|
3962
4115
|
end
|
|
3963
4116
|
|
|
3964
|
-
def output_from_adhoc_bash_script_file(
|
|
3965
|
-
bash_script_lines,
|
|
3966
|
-
export = nil,
|
|
3967
|
-
force:
|
|
3968
|
-
)
|
|
3969
|
-
Tempfile.create('script_exec') do |temp_file|
|
|
3970
|
-
temp_file.write(
|
|
3971
|
-
HashDelegator.join_code_lines(
|
|
3972
|
-
bash_script_lines
|
|
3973
|
-
)
|
|
3974
|
-
)
|
|
3975
|
-
temp_file.close # Close the file before chmod and execution
|
|
3976
|
-
File.chmod(0o755, temp_file.path)
|
|
3977
|
-
|
|
3978
|
-
if @delegate_object[:archive_ad_hoc_scripts]
|
|
3979
|
-
archive_filename = format(
|
|
3980
|
-
@delegate_object[:archive_path_format],
|
|
3981
|
-
time: Time.now.strftime(@delegate_object[:archive_time_format])
|
|
3982
|
-
)
|
|
3983
|
-
`cp #{temp_file.path} #{archive_filename}`
|
|
3984
|
-
end
|
|
3985
|
-
|
|
3986
|
-
output = `#{shell} #{temp_file.path}`
|
|
3987
|
-
|
|
3988
|
-
exportable = if export&.exportable.nil?
|
|
3989
|
-
true
|
|
3990
|
-
else
|
|
3991
|
-
(export ? export.exportable : false)
|
|
3992
|
-
end
|
|
3993
|
-
new_lines = []
|
|
3994
|
-
# new_lines << { comment: 'output_from_adhoc_bash_script_file' }
|
|
3995
|
-
|
|
3996
|
-
command_result = CommandResult.new(
|
|
3997
|
-
stdout: output,
|
|
3998
|
-
exit_status: $?.exitstatus
|
|
3999
|
-
)
|
|
4000
|
-
exportable &&= command_result.success?
|
|
4001
|
-
if exportable
|
|
4002
|
-
new_lines << { name: export.name, force: force,
|
|
4003
|
-
text: command_result.stdout }
|
|
4004
|
-
end
|
|
4005
|
-
|
|
4006
|
-
[
|
|
4007
|
-
command_result,
|
|
4008
|
-
exportable,
|
|
4009
|
-
new_lines
|
|
4010
|
-
]
|
|
4011
|
-
end
|
|
4012
|
-
rescue StandardError => err
|
|
4013
|
-
# wwe 'bash_script_lines:', bash_script_lines, 'export:', export
|
|
4014
|
-
warn "Error executing script: #{err.message}"
|
|
4015
|
-
nil
|
|
4016
|
-
end
|
|
4017
|
-
|
|
4018
4117
|
def output_labeled_value(label, value, level)
|
|
4019
4118
|
@fout.lout format_references_send_color(
|
|
4020
4119
|
context: {
|
|
@@ -4036,7 +4135,7 @@ module MarkdownExec
|
|
|
4036
4135
|
end
|
|
4037
4136
|
|
|
4038
4137
|
def pop_add_current_code_to_head_and_trigger_load(
|
|
4039
|
-
link_state, block_names,
|
|
4138
|
+
link_state, block_names, transient_code,
|
|
4040
4139
|
dependencies, selected, next_block_name: nil
|
|
4041
4140
|
)
|
|
4042
4141
|
pop = @link_history.pop # updatable
|
|
@@ -4048,9 +4147,9 @@ module MarkdownExec
|
|
|
4048
4147
|
(pop.inherited_block_names + block_names).sort.uniq,
|
|
4049
4148
|
inherited_dependencies:
|
|
4050
4149
|
dependencies.merge(pop.inherited_dependencies || {}), ### merge, not replace, key data
|
|
4051
|
-
|
|
4052
|
-
HashDelegator.flatten_and_compact_arrays(pop.
|
|
4053
|
-
|
|
4150
|
+
context_code:
|
|
4151
|
+
HashDelegator.flatten_and_compact_arrays(pop.context_code,
|
|
4152
|
+
transient_code)
|
|
4054
4153
|
)
|
|
4055
4154
|
@link_history.push(next_state)
|
|
4056
4155
|
|
|
@@ -4066,9 +4165,9 @@ module MarkdownExec
|
|
|
4066
4165
|
((link_state&.inherited_block_names || []) + block_names).sort.uniq,
|
|
4067
4166
|
inherited_dependencies:
|
|
4068
4167
|
(link_state&.inherited_dependencies || {}).merge(dependencies || {}), ### merge, not replace, key data
|
|
4069
|
-
|
|
4168
|
+
context_code:
|
|
4070
4169
|
HashDelegator.flatten_and_compact_arrays(
|
|
4071
|
-
link_state&.
|
|
4170
|
+
link_state&.context_code, transient_code
|
|
4072
4171
|
),
|
|
4073
4172
|
keep_code: link_state&.keep_code,
|
|
4074
4173
|
next_block_name: next_block_name,
|
|
@@ -4093,7 +4192,7 @@ module MarkdownExec
|
|
|
4093
4192
|
document_filename: pop.document_filename,
|
|
4094
4193
|
inherited_block_names: peek.inherited_block_names,
|
|
4095
4194
|
inherited_dependencies: peek.inherited_dependencies,
|
|
4096
|
-
|
|
4195
|
+
context_code: peek.context_code
|
|
4097
4196
|
)
|
|
4098
4197
|
end
|
|
4099
4198
|
|
|
@@ -4108,7 +4207,7 @@ module MarkdownExec
|
|
|
4108
4207
|
blocks.select { |item| item.type == 'ux' }
|
|
4109
4208
|
end
|
|
4110
4209
|
|
|
4111
|
-
# Filter blocks per
|
|
4210
|
+
# Filter blocks per block_name_hidden_match, block_name_wrapper_match.
|
|
4112
4211
|
#
|
|
4113
4212
|
# @param all_blocks [Array<Hash>] The list of blocks from the file.
|
|
4114
4213
|
def select_blocks(menu_blocks)
|
|
@@ -4116,12 +4215,12 @@ module MarkdownExec
|
|
|
4116
4215
|
Filter.prepared_not_in_menu?(
|
|
4117
4216
|
@delegate_object,
|
|
4118
4217
|
fcb,
|
|
4119
|
-
%i[
|
|
4218
|
+
%i[block_name_hidden_match block_name_wrapper_match]
|
|
4120
4219
|
)
|
|
4121
4220
|
end
|
|
4122
4221
|
end
|
|
4123
4222
|
|
|
4124
|
-
# Filter blocks per
|
|
4223
|
+
# Filter blocks per block_name_hidden_match, block_name_wrapper_match.
|
|
4125
4224
|
# Set name displayed by tty-prompt.
|
|
4126
4225
|
#
|
|
4127
4226
|
# @param all_blocks [Array<Hash>] The list of blocks from the file.
|
|
@@ -4167,11 +4266,7 @@ module MarkdownExec
|
|
|
4167
4266
|
if name.empty?
|
|
4168
4267
|
"# #{comment}" unless comment.empty?
|
|
4169
4268
|
else
|
|
4170
|
-
transformed =
|
|
4171
|
-
transform_export_value(name_force[:text], export)
|
|
4172
|
-
else
|
|
4173
|
-
name_force[:text]
|
|
4174
|
-
end
|
|
4269
|
+
transformed = name_force[:text]
|
|
4175
4270
|
|
|
4176
4271
|
# store the transformed value in ENV
|
|
4177
4272
|
EnvInterface.set(name, transformed)
|
|
@@ -4473,11 +4568,13 @@ module MarkdownExec
|
|
|
4473
4568
|
obj = {}
|
|
4474
4569
|
|
|
4475
4570
|
# concatenated body of all required blocks loaded a YAML
|
|
4571
|
+
|
|
4572
|
+
rc = execute_block_type_port_code_lines(
|
|
4573
|
+
mdoc: mdoc, selected: selected,
|
|
4574
|
+
link_state: link_state, block_source: {}
|
|
4575
|
+
)
|
|
4476
4576
|
data = (YAML.load(
|
|
4477
|
-
|
|
4478
|
-
mdoc: mdoc, selected: selected,
|
|
4479
|
-
link_state: link_state, block_source: {}
|
|
4480
|
-
).join("\n")
|
|
4577
|
+
rc[:context_code].join("\n")
|
|
4481
4578
|
) || {}).transform_keys(&:to_sym)
|
|
4482
4579
|
|
|
4483
4580
|
if selected.type == BlockType::OPTS
|
|
@@ -4592,7 +4689,7 @@ module MarkdownExec
|
|
|
4592
4689
|
@delegate_object.respond_to?(:[]=, include_private)
|
|
4593
4690
|
true
|
|
4594
4691
|
else
|
|
4595
|
-
|
|
4692
|
+
false
|
|
4596
4693
|
end
|
|
4597
4694
|
end
|
|
4598
4695
|
|
|
@@ -4677,8 +4774,8 @@ module MarkdownExec
|
|
|
4677
4774
|
filename: filename,
|
|
4678
4775
|
saved_asset_format:
|
|
4679
4776
|
shell_escape_asset_format(
|
|
4680
|
-
|
|
4681
|
-
shell: selected_shell(shell)
|
|
4777
|
+
transient_code: link_state&.context_code,
|
|
4778
|
+
shell: selected_shell(@delegate_object[:shell])
|
|
4682
4779
|
)
|
|
4683
4780
|
).generate_name
|
|
4684
4781
|
end
|
|
@@ -4846,7 +4943,7 @@ module MarkdownExec
|
|
|
4846
4943
|
end
|
|
4847
4944
|
|
|
4848
4945
|
def shell_escape_asset_format(
|
|
4849
|
-
|
|
4946
|
+
transient_code:,
|
|
4850
4947
|
enable: @delegate_object[:shell_parameter_expansion],
|
|
4851
4948
|
raw: @delegate_object[:saved_asset_format],
|
|
4852
4949
|
shell:
|
|
@@ -4861,7 +4958,7 @@ module MarkdownExec
|
|
|
4861
4958
|
|
|
4862
4959
|
marker = Random.new.rand.to_s
|
|
4863
4960
|
|
|
4864
|
-
code = (
|
|
4961
|
+
code = (transient_code || []) + ["echo -n \"#{marker}#{raw}\""]
|
|
4865
4962
|
File.write filespec, HashDelegator.join_code_lines(code)
|
|
4866
4963
|
File.chmod 0o755, filespec
|
|
4867
4964
|
|
|
@@ -4966,7 +5063,6 @@ module MarkdownExec
|
|
|
4966
5063
|
# color_sym is not found in @delegate_object.
|
|
4967
5064
|
# @return [String] The string with the applied color method.
|
|
4968
5065
|
def string_send_color(string, color_sym)
|
|
4969
|
-
### accept string with color as well as symbol for color_hash
|
|
4970
5066
|
HashDelegator.apply_color_from_hash(string, @delegate_object, color_sym)
|
|
4971
5067
|
end
|
|
4972
5068
|
|
|
@@ -5094,21 +5190,20 @@ module MarkdownExec
|
|
|
5094
5190
|
force = export.force.nil? ? true : export.force
|
|
5095
5191
|
new_lines = []
|
|
5096
5192
|
silent = false
|
|
5097
|
-
transformable = true
|
|
5098
5193
|
|
|
5099
5194
|
case FCB.act_source(export)
|
|
5100
5195
|
when false, UxActSource::FALSE
|
|
5101
5196
|
# read-only
|
|
5102
|
-
command_result = CommandResult.new
|
|
5103
|
-
|
|
5104
|
-
|
|
5197
|
+
command_result = CommandResult.new(
|
|
5198
|
+
exportable: false
|
|
5199
|
+
)
|
|
5105
5200
|
|
|
5106
5201
|
when :allow, UxActSource::ALLOW
|
|
5107
5202
|
raise unless export.allow.present?
|
|
5108
5203
|
|
|
5109
5204
|
case export.allow
|
|
5110
5205
|
when :echo, ExportValueSource::ECHO
|
|
5111
|
-
command_result
|
|
5206
|
+
command_result = ux_block_eval_for_export(
|
|
5112
5207
|
bash_script_lines,
|
|
5113
5208
|
export,
|
|
5114
5209
|
data: export.echo,
|
|
@@ -5118,18 +5213,15 @@ module MarkdownExec
|
|
|
5118
5213
|
silent: silent
|
|
5119
5214
|
)
|
|
5120
5215
|
|
|
5121
|
-
if command_result.
|
|
5122
|
-
command_result
|
|
5123
|
-
|
|
5124
|
-
|
|
5125
|
-
stdout: menu_from_list_with_back(
|
|
5126
|
-
command_result.stdout.split("\n")
|
|
5127
|
-
)
|
|
5216
|
+
if command_result.success?
|
|
5217
|
+
command_result.exportable = true
|
|
5218
|
+
command_result.stdout = menu_from_list_with_back(
|
|
5219
|
+
com_exp_cod.command_result.stdout.split("\n")
|
|
5128
5220
|
)
|
|
5129
5221
|
end
|
|
5130
5222
|
|
|
5131
5223
|
when :exec, UxActSource::EXEC
|
|
5132
|
-
command_result
|
|
5224
|
+
command_result = ux_block_eval_for_export(
|
|
5133
5225
|
bash_script_lines,
|
|
5134
5226
|
export,
|
|
5135
5227
|
data: export.exec,
|
|
@@ -5138,19 +5230,19 @@ module MarkdownExec
|
|
|
5138
5230
|
silent: silent
|
|
5139
5231
|
)
|
|
5140
5232
|
|
|
5141
|
-
if command_result.exit_status ==
|
|
5233
|
+
if command_result.exit_status ==
|
|
5234
|
+
CommandResult::EXIT_STATUS_REQUIRED_EMPTY
|
|
5142
5235
|
command_result
|
|
5143
5236
|
else
|
|
5144
|
-
command_result =
|
|
5145
|
-
|
|
5146
|
-
|
|
5147
|
-
)
|
|
5237
|
+
command_result.exportable = true
|
|
5238
|
+
command_result.stdout = menu_from_list_with_back(
|
|
5239
|
+
command_result.stdout.split("\n")
|
|
5148
5240
|
)
|
|
5149
5241
|
end
|
|
5150
5242
|
|
|
5151
5243
|
else
|
|
5152
5244
|
export_init = menu_from_list_with_back(export.allow)
|
|
5153
|
-
command_result
|
|
5245
|
+
command_result = ux_block_eval_for_export(
|
|
5154
5246
|
[assign_key_value_in_bash(export.name, export_init)],
|
|
5155
5247
|
export,
|
|
5156
5248
|
data: export.echo,
|
|
@@ -5160,11 +5252,13 @@ module MarkdownExec
|
|
|
5160
5252
|
silent: silent,
|
|
5161
5253
|
string: export_init
|
|
5162
5254
|
)
|
|
5163
|
-
|
|
5255
|
+
if command_result.success?
|
|
5256
|
+
command_result.exportable = true
|
|
5257
|
+
end
|
|
5164
5258
|
end
|
|
5165
5259
|
|
|
5166
5260
|
when :echo, UxActSource::ECHO
|
|
5167
|
-
command_result
|
|
5261
|
+
command_result = ux_block_eval_for_export(
|
|
5168
5262
|
bash_script_lines,
|
|
5169
5263
|
export,
|
|
5170
5264
|
data: export.echo,
|
|
@@ -5172,6 +5266,9 @@ module MarkdownExec
|
|
|
5172
5266
|
printf_expand: true,
|
|
5173
5267
|
silent: silent
|
|
5174
5268
|
)
|
|
5269
|
+
if command_result.success?
|
|
5270
|
+
command_result.exportable = true
|
|
5271
|
+
end
|
|
5175
5272
|
|
|
5176
5273
|
when :edit, UxActSource::EDIT
|
|
5177
5274
|
output = ''
|
|
@@ -5188,7 +5285,6 @@ module MarkdownExec
|
|
|
5188
5285
|
end
|
|
5189
5286
|
rescue Interrupt
|
|
5190
5287
|
exportable = false
|
|
5191
|
-
transformable = false
|
|
5192
5288
|
end
|
|
5193
5289
|
|
|
5194
5290
|
if exportable
|
|
@@ -5197,29 +5293,35 @@ module MarkdownExec
|
|
|
5197
5293
|
text: output }
|
|
5198
5294
|
end
|
|
5199
5295
|
command_result = CommandResult.new(stdout: output)
|
|
5296
|
+
if command_result.success?
|
|
5297
|
+
command_result.exportable = true
|
|
5298
|
+
end
|
|
5200
5299
|
|
|
5201
5300
|
when :exec, UxActSource::EXEC
|
|
5202
|
-
command_result
|
|
5301
|
+
command_result = ux_block_eval_for_export(
|
|
5203
5302
|
bash_script_lines,
|
|
5204
5303
|
export,
|
|
5205
5304
|
data: export.exec,
|
|
5206
5305
|
force: force,
|
|
5207
5306
|
silent: silent
|
|
5208
5307
|
)
|
|
5308
|
+
if command_result.success?
|
|
5309
|
+
command_result.exportable = true
|
|
5310
|
+
end
|
|
5209
5311
|
|
|
5210
5312
|
else
|
|
5211
|
-
transformable = false
|
|
5212
5313
|
command_result = CommandResult.new(stdout: export.default.to_s)
|
|
5314
|
+
if command_result.success?
|
|
5315
|
+
command_result.exportable = true
|
|
5316
|
+
end
|
|
5213
5317
|
end
|
|
5214
5318
|
|
|
5215
5319
|
# add message for required variables
|
|
5216
|
-
if command_result.exit_status == EXIT_STATUS_REQUIRED_EMPTY
|
|
5320
|
+
if command_result.exit_status == CommandResult::EXIT_STATUS_REQUIRED_EMPTY
|
|
5217
5321
|
command_result.warning = warning_required_empty(export)
|
|
5218
5322
|
warn command_result.warning unless silent
|
|
5219
5323
|
end
|
|
5220
5324
|
|
|
5221
|
-
command_result.exportable = exportable
|
|
5222
|
-
command_result.transformable = transformable
|
|
5223
5325
|
command_result.new_lines = new_lines
|
|
5224
5326
|
command_result
|
|
5225
5327
|
rescue StandardError
|
|
@@ -5232,22 +5334,21 @@ module MarkdownExec
|
|
|
5232
5334
|
command_result = nil
|
|
5233
5335
|
exportable = true
|
|
5234
5336
|
force = export.force.nil? ? false : export.force
|
|
5235
|
-
new_lines = []
|
|
5236
5337
|
silent = true
|
|
5237
|
-
transformable = true
|
|
5238
5338
|
|
|
5239
5339
|
case FCB.init_source(export)
|
|
5240
5340
|
when false, UxActSource::FALSE
|
|
5241
5341
|
exportable = false
|
|
5242
|
-
|
|
5243
|
-
|
|
5342
|
+
command_result = CommandResult.new(
|
|
5343
|
+
exportable: false
|
|
5344
|
+
)
|
|
5244
5345
|
|
|
5245
5346
|
when :allow, UxActSource::ALLOW
|
|
5246
5347
|
raise unless export.allow.present?
|
|
5247
5348
|
|
|
5248
5349
|
case export.allow
|
|
5249
5350
|
when :echo, ExportValueSource::ECHO
|
|
5250
|
-
cr_echo
|
|
5351
|
+
cr_echo = ux_block_eval_for_export(
|
|
5251
5352
|
bash_script_lines,
|
|
5252
5353
|
export,
|
|
5253
5354
|
data: export.echo,
|
|
@@ -5258,7 +5359,7 @@ module MarkdownExec
|
|
|
5258
5359
|
)
|
|
5259
5360
|
export_init = cr_echo.stdout.split("\n").first
|
|
5260
5361
|
|
|
5261
|
-
command_result
|
|
5362
|
+
command_result = ux_block_eval_for_export(
|
|
5262
5363
|
[assign_key_value_in_bash(export.name, export_init)],
|
|
5263
5364
|
export,
|
|
5264
5365
|
data: export.echo,
|
|
@@ -5271,7 +5372,7 @@ module MarkdownExec
|
|
|
5271
5372
|
|
|
5272
5373
|
when :exec, ExportValueSource::EXEC
|
|
5273
5374
|
# extract first line from 'exec' output
|
|
5274
|
-
command_result
|
|
5375
|
+
command_result = ux_block_eval_for_export(
|
|
5275
5376
|
bash_script_lines,
|
|
5276
5377
|
export,
|
|
5277
5378
|
data: export.exec,
|
|
@@ -5279,10 +5380,9 @@ module MarkdownExec
|
|
|
5279
5380
|
force: force,
|
|
5280
5381
|
silent: silent
|
|
5281
5382
|
)
|
|
5282
|
-
|
|
5283
5383
|
unless command_result.failure?
|
|
5284
5384
|
export_init = command_result.stdout.split("\n").first
|
|
5285
|
-
command_result
|
|
5385
|
+
command_result = ux_block_eval_for_export(
|
|
5286
5386
|
[assign_key_value_in_bash(export.name, export_init)],
|
|
5287
5387
|
export,
|
|
5288
5388
|
data: export.exec,
|
|
@@ -5296,7 +5396,7 @@ module MarkdownExec
|
|
|
5296
5396
|
else
|
|
5297
5397
|
# first item from 'allow' list
|
|
5298
5398
|
export_init = export.allow.first
|
|
5299
|
-
command_result
|
|
5399
|
+
command_result = ux_block_eval_for_export(
|
|
5300
5400
|
[assign_key_value_in_bash(export.name, export_init)],
|
|
5301
5401
|
export,
|
|
5302
5402
|
data: export.allow,
|
|
@@ -5309,13 +5409,14 @@ module MarkdownExec
|
|
|
5309
5409
|
end
|
|
5310
5410
|
|
|
5311
5411
|
when :default, UxActSource::DEFAULT
|
|
5312
|
-
|
|
5313
|
-
|
|
5412
|
+
command_result = CommandResult.new(
|
|
5413
|
+
stdout: export.default.to_s
|
|
5414
|
+
)
|
|
5314
5415
|
|
|
5315
5416
|
when :echo, UxActSource::ECHO
|
|
5316
5417
|
raise unless export.echo.present?
|
|
5317
5418
|
|
|
5318
|
-
command_result
|
|
5419
|
+
command_result = ux_block_eval_for_export(
|
|
5319
5420
|
bash_script_lines,
|
|
5320
5421
|
export,
|
|
5321
5422
|
data: export.echo,
|
|
@@ -5327,7 +5428,7 @@ module MarkdownExec
|
|
|
5327
5428
|
when :exec, UxActSource::EXEC
|
|
5328
5429
|
raise unless export.exec.present?
|
|
5329
5430
|
|
|
5330
|
-
command_result
|
|
5431
|
+
command_result = ux_block_eval_for_export(
|
|
5331
5432
|
bash_script_lines,
|
|
5332
5433
|
export,
|
|
5333
5434
|
data: export.exec,
|
|
@@ -5337,7 +5438,7 @@ module MarkdownExec
|
|
|
5337
5438
|
|
|
5338
5439
|
else
|
|
5339
5440
|
export_init = export.init.to_s
|
|
5340
|
-
command_result
|
|
5441
|
+
command_result = ux_block_eval_for_export(
|
|
5341
5442
|
[assign_key_value_in_bash(export.name, export_init)],
|
|
5342
5443
|
export,
|
|
5343
5444
|
data: export.exec,
|
|
@@ -5349,17 +5450,15 @@ module MarkdownExec
|
|
|
5349
5450
|
end
|
|
5350
5451
|
|
|
5351
5452
|
# add message for required variables
|
|
5352
|
-
if command_result.exit_status == EXIT_STATUS_REQUIRED_EMPTY
|
|
5453
|
+
if command_result.exit_status == CommandResult::EXIT_STATUS_REQUIRED_EMPTY
|
|
5353
5454
|
command_result.warning = warning_required_empty(export)
|
|
5354
5455
|
warn command_result.warning unless silent
|
|
5355
5456
|
end
|
|
5356
5457
|
|
|
5357
|
-
command_result.exportable = exportable
|
|
5358
|
-
command_result.transformable = transformable
|
|
5359
|
-
command_result.new_lines = new_lines
|
|
5458
|
+
command_result.exportable = command_result.success? && exportable
|
|
5360
5459
|
command_result
|
|
5361
5460
|
rescue StandardError
|
|
5362
|
-
wwe bash_script_lines, export
|
|
5461
|
+
wwe $!, bash_script_lines, export
|
|
5363
5462
|
end
|
|
5364
5463
|
|
|
5365
5464
|
# true if the variable is exported in a series of evaluations
|
|
@@ -5395,10 +5494,10 @@ module MarkdownExec
|
|
|
5395
5494
|
end
|
|
5396
5495
|
|
|
5397
5496
|
def vux_edit_inherited
|
|
5398
|
-
edited = edit_text(@dml_link_state.
|
|
5497
|
+
edited = edit_text(@dml_link_state.context_code_block)
|
|
5399
5498
|
return unless edited
|
|
5400
5499
|
|
|
5401
|
-
@dml_link_state.
|
|
5500
|
+
@dml_link_state.context_code =
|
|
5402
5501
|
annotate_required_lines(
|
|
5403
5502
|
'blk:EDIT', edited.split("\n"), block_name: 'EDIT'
|
|
5404
5503
|
)
|
|
@@ -5491,7 +5590,8 @@ module MarkdownExec
|
|
|
5491
5590
|
|
|
5492
5591
|
elsif block_is_shell(@dml_block_state.block)
|
|
5493
5592
|
debounce_reset
|
|
5494
|
-
vux_input_and_execute_shell_commands(stream: $stderr,
|
|
5593
|
+
vux_input_and_execute_shell_commands(stream: $stderr,
|
|
5594
|
+
shell: @delegate_object[:shell])
|
|
5495
5595
|
return pause_user_exit ? :break : nil
|
|
5496
5596
|
|
|
5497
5597
|
elsif block_is_view(@dml_block_state.block)
|
|
@@ -5617,7 +5717,7 @@ module MarkdownExec
|
|
|
5617
5717
|
def vux_load_code_files_into_state
|
|
5618
5718
|
return unless @menu_base_options[:load_code].present?
|
|
5619
5719
|
|
|
5620
|
-
@dml_link_state.
|
|
5720
|
+
@dml_link_state.context_code =
|
|
5621
5721
|
@menu_base_options[:load_code].split(':').map do |path|
|
|
5622
5722
|
File.readlines(path, chomp: true)
|
|
5623
5723
|
end.flatten(1)
|
|
@@ -5628,7 +5728,7 @@ module MarkdownExec
|
|
|
5628
5728
|
|
|
5629
5729
|
pop_add_current_code_to_head_and_trigger_load(
|
|
5630
5730
|
@dml_link_state, inherited_block_names,
|
|
5631
|
-
|
|
5731
|
+
transient_code, inherited_dependencies, selected
|
|
5632
5732
|
)
|
|
5633
5733
|
end
|
|
5634
5734
|
|
|
@@ -5637,7 +5737,7 @@ module MarkdownExec
|
|
|
5637
5737
|
document_name_in_glob_as_file_name
|
|
5638
5738
|
))
|
|
5639
5739
|
|
|
5640
|
-
@dml_link_state.
|
|
5740
|
+
@dml_link_state.context_code_append(
|
|
5641
5741
|
File.readlines(filespec, chomp: true)
|
|
5642
5742
|
)
|
|
5643
5743
|
end
|
|
@@ -5796,7 +5896,7 @@ module MarkdownExec
|
|
|
5796
5896
|
files = document_glob ? Dir.glob(document_glob) : []
|
|
5797
5897
|
@doc_saved_lines_files = files.count.positive? ? files : []
|
|
5798
5898
|
|
|
5799
|
-
lines_count = @dml_link_state.
|
|
5899
|
+
lines_count = @dml_link_state.context_code_count
|
|
5800
5900
|
|
|
5801
5901
|
# add menu items (glob, load, save) and enable selectively
|
|
5802
5902
|
if files.count.positive? || lines_count.positive?
|
|
@@ -5921,7 +6021,7 @@ module MarkdownExec
|
|
|
5921
6021
|
end
|
|
5922
6022
|
|
|
5923
6023
|
def vux_view_inherited(stream:)
|
|
5924
|
-
stream.puts @dml_link_state.
|
|
6024
|
+
stream.puts @dml_link_state.context_code_block
|
|
5925
6025
|
end
|
|
5926
6026
|
|
|
5927
6027
|
def wait_for_stream_processing
|
|
@@ -5992,6 +6092,10 @@ module MarkdownExec
|
|
|
5992
6092
|
determine_block_state(selected_option)
|
|
5993
6093
|
end
|
|
5994
6094
|
|
|
6095
|
+
def warning_failure(export)
|
|
6096
|
+
"A value must exist for: #{export.required.join(', ')}"
|
|
6097
|
+
end
|
|
6098
|
+
|
|
5995
6099
|
def warning_required_empty(export)
|
|
5996
6100
|
"A value must exist for: #{export.required.join(', ')}"
|
|
5997
6101
|
end
|
|
@@ -6010,7 +6114,7 @@ module MarkdownExec
|
|
|
6010
6114
|
prefix: @delegate_object[:saved_script_filename_prefix],
|
|
6011
6115
|
saved_asset_format:
|
|
6012
6116
|
shell_escape_asset_format(
|
|
6013
|
-
|
|
6117
|
+
transient_code: @dml_link_state.context_code,
|
|
6014
6118
|
shell: shell
|
|
6015
6119
|
),
|
|
6016
6120
|
time: time_now
|
|
@@ -6069,7 +6173,7 @@ module MarkdownExec
|
|
|
6069
6173
|
if save_filespec.present?
|
|
6070
6174
|
File.write(
|
|
6071
6175
|
save_filespec,
|
|
6072
|
-
HashDelegator.join_code_lines(link_state&.
|
|
6176
|
+
HashDelegator.join_code_lines(link_state&.context_code)
|
|
6073
6177
|
)
|
|
6074
6178
|
@delegate_object[:filename]
|
|
6075
6179
|
else
|
|
@@ -6252,7 +6356,7 @@ module MarkdownExec
|
|
|
6252
6356
|
LinkState.new(block_name: 'sample_block',
|
|
6253
6357
|
document_filename: 'sample_file',
|
|
6254
6358
|
inherited_dependencies: {},
|
|
6255
|
-
|
|
6359
|
+
context_code: ['# ', 'KEY="VALUE"'])
|
|
6256
6360
|
)
|
|
6257
6361
|
assert_equal expected_result,
|
|
6258
6362
|
@hd.execute_block_type_link_with_state(
|
|
@@ -6428,12 +6532,43 @@ module MarkdownExec
|
|
|
6428
6532
|
def test_execute_block_type_port_code_lines_with_vars
|
|
6429
6533
|
YAML.stubs(:load).returns({ 'key' => 'value' })
|
|
6430
6534
|
@mdoc.stubs(:collect_recursively_required_code)
|
|
6431
|
-
.returns({
|
|
6535
|
+
.returns({ context_code: [], transient_code: ['code line'] })
|
|
6432
6536
|
result = @hd.execute_block_type_port_code_lines(
|
|
6433
6537
|
mdoc: @mdoc, selected: @selected, block_source: {}
|
|
6434
6538
|
)
|
|
6435
6539
|
|
|
6436
|
-
assert_equal ['
|
|
6540
|
+
assert_equal ['key="value"'], result[:context_code]
|
|
6541
|
+
assert_equal ['code line'], result[:transient_code]
|
|
6542
|
+
end
|
|
6543
|
+
|
|
6544
|
+
def test_transient_code_parameter_usage
|
|
6545
|
+
# Test that transient_code parameter is used correctly in execute_bash_script_lines
|
|
6546
|
+
transient_code = ["echo 'test'", "echo 'transient'"]
|
|
6547
|
+
export = OpenStruct.new(exportable: false, validate: //, transform: ->(x) { x })
|
|
6548
|
+
result = HashDelegator.execute_bash_script_lines(
|
|
6549
|
+
transient_code: transient_code,
|
|
6550
|
+
export: export,
|
|
6551
|
+
export_name: 'TEST',
|
|
6552
|
+
shell: '/bin/bash'
|
|
6553
|
+
)
|
|
6554
|
+
|
|
6555
|
+
assert result.is_a?(CommandResult)
|
|
6556
|
+
assert_equal transient_code, result.script
|
|
6557
|
+
end
|
|
6558
|
+
|
|
6559
|
+
def test_transient_code_vs_context_code_separation
|
|
6560
|
+
# Test that transient_code is separate from context_code
|
|
6561
|
+
context_code = ['CONTEXT_VAR="context_value"']
|
|
6562
|
+
transient_code = ['TRANSIENT_VAR="transient_value"']
|
|
6563
|
+
|
|
6564
|
+
# Simulate combining them
|
|
6565
|
+
all_code = HashDelegator.flatten_and_compact_arrays(
|
|
6566
|
+
context_code, transient_code
|
|
6567
|
+
)
|
|
6568
|
+
|
|
6569
|
+
assert_equal 2, all_code.length
|
|
6570
|
+
assert_includes all_code, 'CONTEXT_VAR="context_value"'
|
|
6571
|
+
assert_includes all_code, 'TRANSIENT_VAR="transient_value"'
|
|
6437
6572
|
end
|
|
6438
6573
|
end
|
|
6439
6574
|
|
|
@@ -7211,12 +7346,16 @@ module MarkdownExec
|
|
|
7211
7346
|
def setup
|
|
7212
7347
|
@hd = HashDelegator.new
|
|
7213
7348
|
@bash_script_lines = ['#!/bin/bash', 'set -e']
|
|
7214
|
-
@export = OpenStruct.new(
|
|
7349
|
+
@export = OpenStruct.new(
|
|
7350
|
+
name: 'TEST_VAR', required: ['TEST_VAR'], init: 'default'
|
|
7351
|
+
)
|
|
7215
7352
|
@mock_result = OpenStruct.new(
|
|
7216
|
-
|
|
7217
|
-
|
|
7218
|
-
|
|
7219
|
-
|
|
7353
|
+
command_result: OpenStruct.new(
|
|
7354
|
+
exit_status: 0,
|
|
7355
|
+
stdout: 'test_output',
|
|
7356
|
+
stderr: '',
|
|
7357
|
+
warning: nil
|
|
7358
|
+
)
|
|
7220
7359
|
)
|
|
7221
7360
|
end
|
|
7222
7361
|
|
|
@@ -7229,29 +7368,27 @@ module MarkdownExec
|
|
|
7229
7368
|
|
|
7230
7369
|
# Test string input - typical case
|
|
7231
7370
|
def test_string_input_success
|
|
7232
|
-
@hd.stubs(:output_from_adhoc_bash_script_file).returns([@mock_result,
|
|
7233
|
-
true])
|
|
7234
7371
|
@hd.stubs(:variable_is_exportable).returns(true)
|
|
7235
7372
|
|
|
7236
|
-
|
|
7237
|
-
@bash_script_lines,
|
|
7373
|
+
command_result = @hd.ux_block_eval_for_export(
|
|
7374
|
+
@bash_script_lines,
|
|
7375
|
+
@export,
|
|
7238
7376
|
data: 'echo "hello"',
|
|
7239
7377
|
force: false,
|
|
7240
7378
|
silent: false
|
|
7241
7379
|
)
|
|
7242
7380
|
|
|
7243
|
-
|
|
7244
|
-
assert_equal
|
|
7245
|
-
assert_equal
|
|
7246
|
-
assert_equal
|
|
7247
|
-
assert_equal 'TEST_VAR', new_lines.first[:name]
|
|
7248
|
-
assert_equal 'test_output', new_lines.first[:text]
|
|
7381
|
+
# assert_equal @mock_result, command_result
|
|
7382
|
+
assert_equal 1, command_result.new_lines.length
|
|
7383
|
+
assert_equal 'TEST_VAR', command_result.new_lines.first[:name]
|
|
7384
|
+
assert_equal "hello\n", command_result.stdout
|
|
7249
7385
|
end
|
|
7250
7386
|
|
|
7251
7387
|
# Test string input with printf_expand
|
|
7252
7388
|
def test_string_input_with_printf_expand
|
|
7253
|
-
|
|
7254
|
-
|
|
7389
|
+
HashDelegator.stubs(:execute_bash_script_lines).returns(
|
|
7390
|
+
@mock_result
|
|
7391
|
+
)
|
|
7255
7392
|
@hd.stubs(:variable_is_exportable).returns(true)
|
|
7256
7393
|
|
|
7257
7394
|
@hd.ux_block_eval_for_export(
|
|
@@ -7268,198 +7405,180 @@ module MarkdownExec
|
|
|
7268
7405
|
|
|
7269
7406
|
# Test integer input
|
|
7270
7407
|
def test_integer_input
|
|
7271
|
-
@
|
|
7272
|
-
|
|
7408
|
+
@mock_result.exportable = true
|
|
7409
|
+
HashDelegator.stubs(:execute_bash_script_lines).returns(
|
|
7410
|
+
@mock_result
|
|
7411
|
+
)
|
|
7273
7412
|
@hd.stubs(:variable_is_exportable).returns(true)
|
|
7274
7413
|
|
|
7275
|
-
|
|
7414
|
+
command_result = @hd.ux_block_eval_for_export(
|
|
7276
7415
|
@bash_script_lines, @export,
|
|
7277
7416
|
data: 42,
|
|
7278
7417
|
force: true,
|
|
7279
7418
|
silent: false
|
|
7280
7419
|
)
|
|
7281
7420
|
|
|
7282
|
-
command_result, exportable, new_lines = result
|
|
7283
7421
|
assert_equal @mock_result, command_result
|
|
7284
|
-
assert_equal
|
|
7285
|
-
assert_equal 1, new_lines.length
|
|
7422
|
+
assert_equal 1, command_result.new_lines.length
|
|
7286
7423
|
end
|
|
7287
7424
|
|
|
7288
7425
|
# Test boolean inputs
|
|
7289
7426
|
def test_boolean_true_input
|
|
7290
|
-
@
|
|
7291
|
-
|
|
7427
|
+
@mock_result.exportable = true
|
|
7428
|
+
HashDelegator.stubs(:execute_bash_script_lines).returns(
|
|
7429
|
+
@mock_result
|
|
7430
|
+
)
|
|
7292
7431
|
@hd.stubs(:variable_is_exportable).returns(true)
|
|
7293
7432
|
|
|
7294
|
-
|
|
7433
|
+
command_result = @hd.ux_block_eval_for_export(
|
|
7295
7434
|
@bash_script_lines, @export,
|
|
7296
7435
|
data: true,
|
|
7297
7436
|
force: false,
|
|
7298
7437
|
silent: false
|
|
7299
7438
|
)
|
|
7300
7439
|
|
|
7301
|
-
command_result, exportable, = result
|
|
7302
7440
|
assert_equal @mock_result, command_result
|
|
7303
|
-
assert_equal true, exportable
|
|
7304
7441
|
end
|
|
7305
7442
|
|
|
7306
7443
|
def test_boolean_false_input
|
|
7307
|
-
@
|
|
7308
|
-
|
|
7444
|
+
@mock_result.exportable = true
|
|
7445
|
+
HashDelegator.stubs(:execute_bash_script_lines).returns(
|
|
7446
|
+
@mock_result
|
|
7447
|
+
)
|
|
7309
7448
|
@hd.stubs(:variable_is_exportable).returns(true)
|
|
7310
7449
|
|
|
7311
|
-
|
|
7450
|
+
command_result = @hd.ux_block_eval_for_export(
|
|
7312
7451
|
@bash_script_lines, @export,
|
|
7313
7452
|
data: false,
|
|
7314
7453
|
force: false,
|
|
7315
7454
|
silent: false
|
|
7316
7455
|
)
|
|
7317
7456
|
|
|
7318
|
-
command_result, exportable, = result
|
|
7319
7457
|
assert_equal @mock_result, command_result
|
|
7320
|
-
assert_equal true, exportable
|
|
7321
7458
|
end
|
|
7322
7459
|
|
|
7323
7460
|
# Test float input
|
|
7324
7461
|
def test_float_input
|
|
7325
|
-
@
|
|
7326
|
-
|
|
7462
|
+
@mock_result.exportable = true
|
|
7463
|
+
HashDelegator.stubs(:execute_bash_script_lines).returns(
|
|
7464
|
+
@mock_result
|
|
7465
|
+
)
|
|
7327
7466
|
@hd.stubs(:variable_is_exportable).returns(true)
|
|
7328
7467
|
|
|
7329
|
-
|
|
7468
|
+
command_result = @hd.ux_block_eval_for_export(
|
|
7330
7469
|
@bash_script_lines, @export,
|
|
7331
7470
|
data: 3.14,
|
|
7332
7471
|
force: false,
|
|
7333
7472
|
silent: false
|
|
7334
7473
|
)
|
|
7335
7474
|
|
|
7336
|
-
command_result, exportable, = result
|
|
7337
7475
|
assert_equal @mock_result, command_result
|
|
7338
|
-
assert_equal true, exportable
|
|
7339
7476
|
end
|
|
7340
7477
|
|
|
7341
7478
|
# Test hash input - typical case
|
|
7342
7479
|
def test_hash_input_success
|
|
7343
7480
|
hash_data = { 'VAR1' => 'value1', 'VAR2' => 'value2' }
|
|
7344
|
-
@
|
|
7345
|
-
|
|
7481
|
+
@mock_result.exportable = true
|
|
7482
|
+
HashDelegator.stubs(:execute_bash_script_lines).returns(
|
|
7483
|
+
@mock_result
|
|
7484
|
+
)
|
|
7346
7485
|
@hd.stubs(:variable_is_exportable).returns(true)
|
|
7347
7486
|
@hd.stubs(:code_line_to_assign_a_variable).returns('VAR1=value1')
|
|
7348
7487
|
|
|
7349
|
-
|
|
7488
|
+
command_result = @hd.ux_block_eval_for_export(
|
|
7350
7489
|
@bash_script_lines, @export,
|
|
7351
7490
|
data: hash_data,
|
|
7352
7491
|
force: false,
|
|
7353
7492
|
silent: false
|
|
7354
7493
|
)
|
|
7355
7494
|
|
|
7356
|
-
command_result, exportable, new_lines = result
|
|
7357
7495
|
assert_equal @mock_result, command_result
|
|
7358
|
-
assert_equal
|
|
7359
|
-
assert_equal
|
|
7360
|
-
assert_equal '
|
|
7361
|
-
assert_equal 'VAR2', new_lines.last[:name]
|
|
7496
|
+
assert_equal 2, command_result.new_lines.length
|
|
7497
|
+
assert_equal 'VAR1', command_result.new_lines.first[:name]
|
|
7498
|
+
assert_equal 'VAR2', command_result.new_lines.last[:name]
|
|
7362
7499
|
end
|
|
7363
7500
|
|
|
7364
7501
|
# Test hash input with first_only flag
|
|
7365
7502
|
def test_hash_input_first_only
|
|
7366
7503
|
hash_data = { 'VAR1' => 'value1', 'VAR2' => 'value2' }
|
|
7367
|
-
@hd.stubs(:output_from_adhoc_bash_script_file).returns([@mock_result,
|
|
7368
|
-
true])
|
|
7369
|
-
@hd.stubs(:variable_is_exportable).returns(true)
|
|
7370
|
-
@hd.stubs(:code_line_to_assign_a_variable).returns('VAR1=value1')
|
|
7371
7504
|
|
|
7372
|
-
|
|
7505
|
+
command_result = @hd.ux_block_eval_for_export(
|
|
7373
7506
|
@bash_script_lines, @export,
|
|
7374
7507
|
data: hash_data,
|
|
7375
7508
|
first_only: true,
|
|
7376
7509
|
force: false,
|
|
7510
|
+
printf_expand: true,
|
|
7377
7511
|
silent: false
|
|
7378
7512
|
)
|
|
7379
7513
|
|
|
7380
|
-
|
|
7381
|
-
assert_equal
|
|
7382
|
-
assert_equal 1, new_lines.length
|
|
7383
|
-
assert_equal 'VAR1', new_lines.first[:name]
|
|
7514
|
+
assert_equal 1, command_result.new_lines.length
|
|
7515
|
+
assert_equal 'VAR1', command_result.new_lines.first[:name]
|
|
7384
7516
|
end
|
|
7385
7517
|
|
|
7386
7518
|
# Test hash with non-exportable variables
|
|
7387
7519
|
def test_hash_input_non_exportable_variables
|
|
7388
7520
|
hash_data = { 'LOCAL_VAR' => 'value1' }
|
|
7389
|
-
@
|
|
7390
|
-
|
|
7521
|
+
@mock_result.exportable = true
|
|
7522
|
+
@mock_result.new_lines = []
|
|
7523
|
+
HashDelegator.stubs(:execute_bash_script_lines).returns(@mock_result)
|
|
7391
7524
|
@hd.stubs(:variable_is_exportable).returns(false)
|
|
7392
7525
|
@hd.stubs(:code_line_to_assign_a_variable).returns('LOCAL_VAR=value1')
|
|
7393
7526
|
|
|
7394
|
-
|
|
7527
|
+
command_result = @hd.ux_block_eval_for_export(
|
|
7395
7528
|
@bash_script_lines, @export,
|
|
7396
7529
|
data: hash_data,
|
|
7397
7530
|
force: false,
|
|
7398
7531
|
silent: false
|
|
7399
7532
|
)
|
|
7400
7533
|
|
|
7401
|
-
command_result, _, new_lines = result
|
|
7402
7534
|
assert_equal @mock_result, command_result
|
|
7403
|
-
assert_equal 0, new_lines.length # No exportable variables
|
|
7535
|
+
assert_equal 0, command_result.new_lines.length # No exportable variables
|
|
7404
7536
|
end
|
|
7405
7537
|
|
|
7406
7538
|
# Test EXIT_STATUS_REQUIRED_EMPTY handling
|
|
7407
7539
|
def test_exit_status_required_empty_with_warning
|
|
7408
|
-
failed_result =
|
|
7409
|
-
exit_status:
|
|
7540
|
+
failed_result = CommandResult.new(
|
|
7541
|
+
exit_status: CommandResult::EXIT_STATUS_REQUIRED_EMPTY,
|
|
7542
|
+
exportable: false,
|
|
7410
7543
|
stdout: '',
|
|
7411
7544
|
stderr: 'Required variable empty',
|
|
7412
7545
|
warning: nil
|
|
7413
7546
|
)
|
|
7414
|
-
|
|
7415
|
-
false])
|
|
7547
|
+
HashDelegator.stubs(:execute_bash_script_lines).returns(failed_result)
|
|
7416
7548
|
@hd.stubs(:warning_required_empty).returns('Warning: required empty')
|
|
7417
7549
|
|
|
7418
|
-
|
|
7550
|
+
command_result = @hd.ux_block_eval_for_export(
|
|
7419
7551
|
@bash_script_lines, @export,
|
|
7420
7552
|
data: 'echo ""',
|
|
7421
7553
|
force: false,
|
|
7422
7554
|
silent: false
|
|
7423
7555
|
)
|
|
7424
7556
|
|
|
7425
|
-
command_result, exportable, new_lines = result
|
|
7426
7557
|
assert_equal failed_result, command_result
|
|
7427
|
-
assert_equal false, exportable
|
|
7428
|
-
assert_equal 0, new_lines.length
|
|
7429
7558
|
assert_equal 'Warning: required empty', command_result.warning
|
|
7430
7559
|
end
|
|
7431
7560
|
|
|
7432
7561
|
# Test EXIT_STATUS_REQUIRED_EMPTY handling with silent flag
|
|
7433
7562
|
def test_exit_status_required_empty_silent
|
|
7434
|
-
|
|
7435
|
-
exit_status: 248,
|
|
7436
|
-
stdout: '',
|
|
7437
|
-
stderr: 'Required variable empty',
|
|
7438
|
-
warning: nil
|
|
7439
|
-
)
|
|
7440
|
-
@hd.stubs(:output_from_adhoc_bash_script_file).returns([failed_result,
|
|
7441
|
-
false])
|
|
7442
|
-
|
|
7443
|
-
result = @hd.ux_block_eval_for_export(
|
|
7563
|
+
command_result = @hd.ux_block_eval_for_export(
|
|
7444
7564
|
@bash_script_lines, @export,
|
|
7445
7565
|
data: 'echo ""',
|
|
7446
7566
|
force: false,
|
|
7447
7567
|
silent: true
|
|
7448
7568
|
)
|
|
7449
7569
|
|
|
7450
|
-
command_result
|
|
7451
|
-
assert_equal failed_result, command_result
|
|
7452
|
-
assert_equal false, exportable
|
|
7453
|
-
assert_nil command_result.warning # No warning when silent
|
|
7570
|
+
assert_empty command_result.warning # No warning when silent
|
|
7454
7571
|
end
|
|
7455
7572
|
|
|
7456
7573
|
# Test string parameter override
|
|
7457
7574
|
def test_string_parameter_override
|
|
7458
|
-
@
|
|
7459
|
-
|
|
7575
|
+
@mock_result.exportable = true
|
|
7576
|
+
HashDelegator.stubs(:execute_bash_script_lines).returns(
|
|
7577
|
+
@mock_result
|
|
7578
|
+
)
|
|
7460
7579
|
@hd.stubs(:variable_is_exportable).returns(true)
|
|
7461
7580
|
|
|
7462
|
-
|
|
7581
|
+
command_result = @hd.ux_block_eval_for_export(
|
|
7463
7582
|
@bash_script_lines, @export,
|
|
7464
7583
|
data: 'original_data',
|
|
7465
7584
|
string: 'override_string',
|
|
@@ -7468,136 +7587,115 @@ module MarkdownExec
|
|
|
7468
7587
|
)
|
|
7469
7588
|
|
|
7470
7589
|
# The function should use string parameter instead of data
|
|
7471
|
-
command_result, exportable, = result
|
|
7472
7590
|
assert_equal @mock_result, command_result
|
|
7473
|
-
assert_equal true, exportable
|
|
7474
7591
|
end
|
|
7475
7592
|
|
|
7476
7593
|
# Edge case: empty string
|
|
7477
7594
|
def test_empty_string_input
|
|
7478
|
-
@
|
|
7479
|
-
|
|
7595
|
+
@mock_result.exportable = true
|
|
7596
|
+
HashDelegator.stubs(:execute_bash_script_lines).returns(
|
|
7597
|
+
@mock_result
|
|
7598
|
+
)
|
|
7480
7599
|
@hd.stubs(:variable_is_exportable).returns(true)
|
|
7481
7600
|
|
|
7482
|
-
|
|
7601
|
+
command_result = @hd.ux_block_eval_for_export(
|
|
7483
7602
|
@bash_script_lines, @export,
|
|
7484
7603
|
data: '',
|
|
7485
7604
|
force: false,
|
|
7486
7605
|
silent: false
|
|
7487
7606
|
)
|
|
7488
7607
|
|
|
7489
|
-
command_result, exportable, = result
|
|
7490
7608
|
assert_equal @mock_result, command_result
|
|
7491
|
-
assert_equal true, exportable
|
|
7492
7609
|
end
|
|
7493
7610
|
|
|
7494
7611
|
# Edge case: nil data (uses string.nil? check)
|
|
7495
7612
|
def test_nil_data_input
|
|
7496
|
-
@
|
|
7497
|
-
|
|
7613
|
+
@mock_result.exportable = true
|
|
7614
|
+
HashDelegator.stubs(:execute_bash_script_lines).returns(
|
|
7615
|
+
@mock_result
|
|
7616
|
+
)
|
|
7498
7617
|
@hd.stubs(:variable_is_exportable).returns(true)
|
|
7499
7618
|
|
|
7500
|
-
|
|
7619
|
+
command_result = @hd.ux_block_eval_for_export(
|
|
7501
7620
|
@bash_script_lines, @export,
|
|
7502
7621
|
data: 'd1',
|
|
7503
7622
|
force: false,
|
|
7504
7623
|
silent: false
|
|
7505
7624
|
)
|
|
7506
7625
|
|
|
7507
|
-
command_result, exportable, = result
|
|
7508
7626
|
assert_equal @mock_result, command_result
|
|
7509
|
-
assert_equal true, exportable
|
|
7510
7627
|
end
|
|
7511
7628
|
|
|
7512
7629
|
# Edge case: empty hash
|
|
7513
7630
|
def test_empty_hash_input
|
|
7514
|
-
|
|
7631
|
+
command_result = @hd.ux_block_eval_for_export(
|
|
7515
7632
|
@bash_script_lines, @export,
|
|
7516
7633
|
data: {},
|
|
7517
7634
|
force: false,
|
|
7518
7635
|
silent: false
|
|
7519
7636
|
)
|
|
7520
7637
|
|
|
7521
|
-
command_result, exportable, new_lines = result
|
|
7522
7638
|
assert_nil command_result # No iterations, so command_result remains nil
|
|
7523
|
-
assert_equal true, exportable # Initial value
|
|
7524
|
-
assert_equal 0, new_lines.length
|
|
7525
7639
|
end
|
|
7526
7640
|
|
|
7527
7641
|
# Edge case: hash with nil values
|
|
7528
7642
|
def test_hash_with_nil_values
|
|
7529
7643
|
hash_data = { 'VAR1' => nil, 'VAR2' => 'value2' }
|
|
7530
|
-
@hd.
|
|
7531
|
-
true])
|
|
7532
|
-
@hd.stubs(:variable_is_exportable).returns(true)
|
|
7533
|
-
@hd.stubs(:code_line_to_assign_a_variable).returns('VAR1=')
|
|
7534
|
-
|
|
7535
|
-
result = @hd.ux_block_eval_for_export(
|
|
7644
|
+
command_result = @hd.ux_block_eval_for_export(
|
|
7536
7645
|
@bash_script_lines, @export,
|
|
7537
7646
|
data: hash_data,
|
|
7538
7647
|
force: false,
|
|
7648
|
+
printf_expand: true,
|
|
7539
7649
|
silent: false
|
|
7540
7650
|
)
|
|
7541
7651
|
|
|
7542
|
-
|
|
7543
|
-
assert_equal @mock_result, command_result
|
|
7544
|
-
assert_equal true, exportable
|
|
7545
|
-
assert_equal 2, new_lines.length
|
|
7652
|
+
assert_equal 2, command_result.new_lines.length
|
|
7546
7653
|
end
|
|
7547
7654
|
|
|
7548
7655
|
# Edge case: unsupported input type (Array)
|
|
7549
7656
|
def test_unsupported_input_type_array
|
|
7550
|
-
|
|
7657
|
+
command_result = @hd.ux_block_eval_for_export(
|
|
7551
7658
|
@bash_script_lines, @export,
|
|
7552
7659
|
data: %w[item1 item2],
|
|
7553
7660
|
force: false,
|
|
7554
7661
|
silent: false
|
|
7555
7662
|
)
|
|
7556
7663
|
|
|
7557
|
-
command_result, exportable, new_lines = result
|
|
7558
7664
|
assert_nil command_result # No processing for unsupported types
|
|
7559
|
-
assert_equal true, exportable # Initial value
|
|
7560
|
-
assert_equal 0, new_lines.length
|
|
7561
7665
|
end
|
|
7562
7666
|
|
|
7563
7667
|
# Edge case: unsupported input type (custom object)
|
|
7564
7668
|
def test_unsupported_input_type_object
|
|
7565
7669
|
custom_object = Object.new
|
|
7566
|
-
|
|
7670
|
+
command_result = @hd.ux_block_eval_for_export(
|
|
7567
7671
|
@bash_script_lines, @export,
|
|
7568
7672
|
data: custom_object,
|
|
7569
7673
|
force: false,
|
|
7570
7674
|
silent: false
|
|
7571
7675
|
)
|
|
7572
7676
|
|
|
7573
|
-
command_result, exportable, new_lines = result
|
|
7574
7677
|
assert_nil command_result # No processing for unsupported types
|
|
7575
|
-
assert_equal true, exportable # Initial value
|
|
7576
|
-
assert_equal 0, new_lines.length
|
|
7577
7678
|
end
|
|
7578
7679
|
|
|
7579
7680
|
# Test error handling - StandardError rescue
|
|
7580
7681
|
def test_standard_error_rescue
|
|
7581
7682
|
# Should not raise, but return nil due to rescue block
|
|
7582
|
-
|
|
7683
|
+
command_result = @hd.ux_block_eval_for_export(
|
|
7583
7684
|
@bash_script_lines, @export,
|
|
7584
7685
|
data: 'test_data',
|
|
7585
7686
|
force: false,
|
|
7586
7687
|
silent: false
|
|
7587
7688
|
)
|
|
7588
7689
|
|
|
7589
|
-
|
|
7590
|
-
assert_equal 127, command_result.exit_status
|
|
7690
|
+
assert_equal CommandResult::EXIT_STATUS_FAIL, command_result.exit_status
|
|
7591
7691
|
end
|
|
7592
7692
|
|
|
7593
7693
|
# Test environment variable setting
|
|
7594
7694
|
def test_environment_variable_setting
|
|
7595
|
-
@hd.stubs(:output_from_adhoc_bash_script_file).returns([@mock_result,
|
|
7596
|
-
true])
|
|
7597
7695
|
@hd.stubs(:variable_is_exportable).returns(true)
|
|
7598
7696
|
|
|
7599
7697
|
# Mock EnvInterface.set to verify it's called
|
|
7600
|
-
EnvInterface.expects(:set).with('TEST_VAR',
|
|
7698
|
+
EnvInterface.expects(:set).with('TEST_VAR', "test\n")
|
|
7601
7699
|
|
|
7602
7700
|
@hd.ux_block_eval_for_export(
|
|
7603
7701
|
@bash_script_lines, @export,
|
|
@@ -7609,10 +7707,6 @@ module MarkdownExec
|
|
|
7609
7707
|
|
|
7610
7708
|
# Test join_array_of_arrays is called correctly
|
|
7611
7709
|
def test_join_array_of_arrays_called
|
|
7612
|
-
@hd.stubs(:output_from_adhoc_bash_script_file).returns([@mock_result,
|
|
7613
|
-
true])
|
|
7614
|
-
@hd.stubs(:variable_is_exportable).returns(true)
|
|
7615
|
-
|
|
7616
7710
|
# Mock join_array_of_arrays to verify it's called with correct parameters
|
|
7617
7711
|
@hd.expects(:join_array_of_arrays).with(
|
|
7618
7712
|
@bash_script_lines,
|