markdown_exec 1.8.1 → 1.8.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +16 -0
- data/Gemfile.lock +1 -1
- data/bin/tab_completion.sh +15 -3
- data/examples/colors.md +37 -20
- data/examples/linked1.md +1 -1
- data/examples/linked2.md +4 -0
- data/lib/ansi_formatter.rb +0 -3
- data/lib/constants.rb +1 -1
- data/lib/hash_delegator.rb +448 -649
- data/lib/link_history.rb +131 -0
- data/lib/markdown_exec/version.rb +1 -1
- data/lib/markdown_exec.rb +22 -51
- data/lib/mdoc.rb +40 -34
- data/lib/menu.src.yml +24 -21
- data/lib/menu.yml +25 -22
- metadata +3 -2
data/lib/hash_delegator.rb
CHANGED
@@ -24,6 +24,7 @@ require_relative 'fcb'
|
|
24
24
|
require_relative 'filter'
|
25
25
|
require_relative 'fout'
|
26
26
|
require_relative 'hash'
|
27
|
+
require_relative 'link_history'
|
27
28
|
require_relative 'mdoc'
|
28
29
|
require_relative 'string_util'
|
29
30
|
|
@@ -115,6 +116,7 @@ module MarkdownExec
|
|
115
116
|
@run_state = OpenStruct.new(
|
116
117
|
link_history: []
|
117
118
|
)
|
119
|
+
@link_history = LinkHistory.new
|
118
120
|
@fout = FOut.new(@delegate_object) ### slice only relevant keys
|
119
121
|
|
120
122
|
@process_mutex = Mutex.new
|
@@ -145,10 +147,6 @@ module MarkdownExec
|
|
145
147
|
|
146
148
|
private
|
147
149
|
|
148
|
-
def should_add_back_option?
|
149
|
-
@delegate_object[:menu_with_back] && history_env_state_exist?
|
150
|
-
end
|
151
|
-
|
152
150
|
def add_back_option(menu_blocks)
|
153
151
|
append_chrome_block(menu_blocks, MenuState::BACK)
|
154
152
|
end
|
@@ -171,9 +169,7 @@ module MarkdownExec
|
|
171
169
|
def append_chrome_block(menu_blocks, type)
|
172
170
|
case type
|
173
171
|
when MenuState::BACK
|
174
|
-
|
175
|
-
@hs_curr = state[:unit]
|
176
|
-
@hs_rest = state[:rest]
|
172
|
+
history_state_partition
|
177
173
|
option_name = @delegate_object[:menu_option_back_name]
|
178
174
|
insert_at_top = @delegate_object[:menu_back_at_top]
|
179
175
|
when MenuState::EXIT
|
@@ -185,13 +181,9 @@ module MarkdownExec
|
|
185
181
|
safeval(option_name))
|
186
182
|
chrome_block = FCB.new(
|
187
183
|
chrome: true,
|
188
|
-
|
189
|
-
# dname: formatted_name.send(@delegate_object[:menu_link_color].to_sym),
|
190
184
|
dname: HashDelegator.new(@delegate_object).string_send_color(
|
191
185
|
formatted_name, :menu_link_color
|
192
186
|
),
|
193
|
-
#dname: @delegate_object.string_send_color(formatted_name, :menu_link_color),
|
194
|
-
|
195
187
|
oname: formatted_name
|
196
188
|
)
|
197
189
|
|
@@ -216,42 +208,16 @@ module MarkdownExec
|
|
216
208
|
|
217
209
|
# private
|
218
210
|
|
219
|
-
|
220
|
-
divider_key = position == :initial ? :menu_initial_divider : :menu_final_divider
|
221
|
-
@delegate_object[:menu_divider_format].present? && @delegate_object[divider_key].present?
|
222
|
-
end
|
223
|
-
|
224
|
-
def create_divider(position)
|
225
|
-
divider_key = position == :initial ? :menu_initial_divider : :menu_final_divider
|
226
|
-
oname = format(@delegate_object[:menu_divider_format],
|
227
|
-
safeval(@delegate_object[divider_key]))
|
228
|
-
|
229
|
-
FCB.new(
|
230
|
-
chrome: true,
|
231
|
-
disabled: '',
|
232
|
-
dname: string_send_color(oname, :menu_divider_color),
|
233
|
-
oname: oname
|
234
|
-
)
|
235
|
-
end
|
236
|
-
|
237
|
-
# Execute a code block after approval and provide user interaction options.
|
238
|
-
#
|
239
|
-
# This method displays required code blocks, asks for user approval, and
|
240
|
-
# executes the code block if approved. It also allows users to copy the
|
241
|
-
# code to the clipboard or save it to a file.
|
242
|
-
#
|
243
|
-
# @param opts [Hash] Options hash containing configuration settings.
|
244
|
-
# @param mdoc [YourMDocClass] An instance of the MDoc class.
|
211
|
+
# Applies shell color options to the given string if applicable.
|
245
212
|
#
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
handle_opts_block(selected, @menu_base_options)
|
213
|
+
# @param name [String] The name to potentially colorize.
|
214
|
+
# @param shell_color_option [Symbol, nil] The shell color option to apply.
|
215
|
+
# @return [String] The colorized or original name string.
|
216
|
+
def apply_shell_color_option(name, shell_color_option)
|
217
|
+
if shell_color_option && @delegate_object[shell_color_option].present?
|
218
|
+
string_send_color(name, shell_color_option)
|
253
219
|
else
|
254
|
-
|
220
|
+
name
|
255
221
|
end
|
256
222
|
end
|
257
223
|
|
@@ -286,22 +252,6 @@ module MarkdownExec
|
|
286
252
|
|
287
253
|
# private
|
288
254
|
|
289
|
-
def process_block_based_on_type(blocks, btype, fcb)
|
290
|
-
case btype
|
291
|
-
when :blocks
|
292
|
-
blocks.push(get_block_summary(fcb))
|
293
|
-
when :filter
|
294
|
-
%i[blocks line]
|
295
|
-
when :line
|
296
|
-
unless @delegate_object[:no_chrome]
|
297
|
-
create_and_add_chrome_blocks(blocks,
|
298
|
-
fcb)
|
299
|
-
end
|
300
|
-
end
|
301
|
-
end
|
302
|
-
|
303
|
-
# private
|
304
|
-
|
305
255
|
def cfile
|
306
256
|
@cfile ||= CachedNestedFileReader.new(
|
307
257
|
import_pattern: @delegate_object.fetch(:import_pattern) #, "^ *@import +(?<name>.+?) *$")
|
@@ -322,23 +272,13 @@ module MarkdownExec
|
|
322
272
|
true
|
323
273
|
end
|
324
274
|
|
325
|
-
def
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
format(
|
330
|
-
@delegate_object.fetch(:exception_format_name, "\n%{name}"),
|
331
|
-
data
|
332
|
-
).send(@delegate_object.fetch(:exception_color_name, :red)) +
|
333
|
-
format(
|
334
|
-
@delegate_object.fetch(:exception_format_detail, " - %{detail}\n"),
|
335
|
-
data
|
336
|
-
).send(@delegate_object.fetch(:exception_color_detail, :yellow))
|
337
|
-
)
|
338
|
-
end
|
339
|
-
return unless (@delegate_object[exception_sym]).positive?
|
275
|
+
def code_join(*bodies)
|
276
|
+
bc = bodies&.compact
|
277
|
+
bc.count.positive? ? bc.join("\n") : nil
|
278
|
+
end
|
340
279
|
|
341
|
-
|
280
|
+
def code_merge(*bodies)
|
281
|
+
merge_lists(*bodies)
|
342
282
|
end
|
343
283
|
|
344
284
|
# Collects required code lines based on the selected block and the delegate object's configuration.
|
@@ -347,15 +287,20 @@ module MarkdownExec
|
|
347
287
|
# @param mdoc [YourMDocClass] An instance of the MDoc class.
|
348
288
|
# @param selected [Hash] The selected block.
|
349
289
|
# @return [Array<String>] Required code blocks as an array of lines.
|
350
|
-
def collect_required_code_lines(mdoc, selected)
|
351
|
-
|
290
|
+
def collect_required_code_lines(mdoc, selected, link_state = LinkState.new, block_source:)
|
291
|
+
set_environment_variables_for_block(selected) if selected[:shell] == BlockType::VARS
|
352
292
|
|
353
293
|
required = mdoc.collect_recursively_required_code(
|
354
294
|
@delegate_object[:block_name],
|
355
295
|
label_format_above: @delegate_object[:shell_code_label_format_above],
|
356
|
-
label_format_below: @delegate_object[:shell_code_label_format_below]
|
296
|
+
label_format_below: @delegate_object[:shell_code_label_format_below],
|
297
|
+
block_source: block_source
|
357
298
|
)
|
299
|
+
required[:unmet_dependencies] =
|
300
|
+
(required[:unmet_dependencies] || []) - (link_state&.inherited_block_names || [])
|
358
301
|
if required[:unmet_dependencies].present?
|
302
|
+
### filter against link_state.inherited_block_names
|
303
|
+
|
359
304
|
warn format_and_highlight_dependencies(required[:dependencies],
|
360
305
|
highlight: required[:unmet_dependencies])
|
361
306
|
runtime_exception(:runtime_exception_error_level,
|
@@ -364,27 +309,14 @@ module MarkdownExec
|
|
364
309
|
warn format_and_highlight_dependencies(required[:dependencies],
|
365
310
|
highlight: [@delegate_object[:block_name]])
|
366
311
|
end
|
367
|
-
read_required_blocks_from_temp_file + required[:code]
|
368
|
-
end
|
369
|
-
|
370
|
-
# private
|
371
|
-
|
372
|
-
def set_environment_variables(selected)
|
373
|
-
YAML.load(selected[:body].join("\n")).each do |key, value|
|
374
|
-
ENV[key] = value.to_s
|
375
|
-
next unless @delegate_object[:menu_vars_set_format].present?
|
376
312
|
|
377
|
-
|
378
|
-
{ key: key, value: value })
|
379
|
-
print string_send_color(formatted_string, :menu_vars_set_color)
|
380
|
-
end
|
313
|
+
code_merge link_state&.inherited_lines, required[:code]
|
381
314
|
end
|
382
315
|
|
383
316
|
def command_execute(command, args: [])
|
384
317
|
@run_state.files = Hash.new([])
|
385
318
|
@run_state.options = @delegate_object
|
386
319
|
@run_state.started_at = Time.now.utc
|
387
|
-
# rbp
|
388
320
|
|
389
321
|
Open3.popen3(@delegate_object[:shell],
|
390
322
|
'-c', command,
|
@@ -442,6 +374,26 @@ module MarkdownExec
|
|
442
374
|
error_handler('command_or_user_selected_block')
|
443
375
|
end
|
444
376
|
|
377
|
+
# This method is responsible for handling the execution of generic blocks in a markdown document.
|
378
|
+
# It collects the required code lines from the document and, depending on the configuration,
|
379
|
+
# may display the code for user approval before execution. It then executes the approved block.
|
380
|
+
#
|
381
|
+
# @param mdoc [Object] The markdown document object containing code blocks.
|
382
|
+
# @param selected [Hash] The selected item from the menu to be executed.
|
383
|
+
# @return [LoadFileLinkState] An object indicating whether to load the next block or reuse the current one.
|
384
|
+
def compile_execute_bash_and_special_blocks_and_trigger_reuse(mdoc, selected,
|
385
|
+
link_state = nil, block_source:)
|
386
|
+
required_lines = collect_required_code_lines(mdoc, selected, link_state,
|
387
|
+
block_source: block_source)
|
388
|
+
output_or_approval = @delegate_object[:output_script] || @delegate_object[:user_must_approve]
|
389
|
+
display_required_code(required_lines) if output_or_approval
|
390
|
+
allow_execution = @delegate_object[:user_must_approve] ? prompt_for_user_approval(required_lines) : true
|
391
|
+
execute_required_lines(required_lines) if allow_execution
|
392
|
+
|
393
|
+
link_state.block_name = nil
|
394
|
+
LoadFileLinkState.new(LoadFile::Reuse, link_state)
|
395
|
+
end
|
396
|
+
|
445
397
|
def copy_to_clipboard(required_lines)
|
446
398
|
text = required_lines.flatten.join($INPUT_RECORD_SEPARATOR)
|
447
399
|
Clipboard.copy(text)
|
@@ -520,13 +472,13 @@ module MarkdownExec
|
|
520
472
|
# @param file_path [String] The path where the file will be created.
|
521
473
|
# @param content [String] The content to write into the file.
|
522
474
|
# @param chmod_value [Integer] The file permission value to set; skips if zero.
|
523
|
-
def
|
524
|
-
|
475
|
+
def create_file_and_write_string_with_permissions(file_path, content,
|
476
|
+
chmod_value)
|
525
477
|
create_directory_for_file(file_path)
|
526
|
-
|
478
|
+
File.write(file_path, content)
|
527
479
|
set_file_permissions(file_path, chmod_value) unless chmod_value.zero?
|
528
480
|
rescue StandardError
|
529
|
-
error_handler('
|
481
|
+
error_handler('create_file_and_write_string_with_permissions')
|
530
482
|
end
|
531
483
|
|
532
484
|
# private
|
@@ -535,21 +487,17 @@ module MarkdownExec
|
|
535
487
|
FileUtils.mkdir_p(File.dirname(file_path))
|
536
488
|
end
|
537
489
|
|
538
|
-
def
|
539
|
-
|
540
|
-
|
541
|
-
|
542
|
-
def set_file_permissions(file_path, chmod_value)
|
543
|
-
File.chmod(chmod_value, file_path)
|
544
|
-
end
|
490
|
+
def create_divider(position)
|
491
|
+
divider_key = position == :initial ? :menu_initial_divider : :menu_final_divider
|
492
|
+
oname = format(@delegate_object[:menu_divider_format],
|
493
|
+
safeval(@delegate_object[divider_key]))
|
545
494
|
|
546
|
-
|
547
|
-
|
548
|
-
|
549
|
-
|
550
|
-
|
551
|
-
|
552
|
-
set_environment_variable(temp_file_path)
|
495
|
+
FCB.new(
|
496
|
+
chrome: true,
|
497
|
+
disabled: '',
|
498
|
+
dname: string_send_color(oname, :menu_divider_color),
|
499
|
+
oname: oname
|
500
|
+
)
|
553
501
|
end
|
554
502
|
|
555
503
|
# private
|
@@ -558,14 +506,6 @@ module MarkdownExec
|
|
558
506
|
Dir::Tmpname.create(self.class.to_s) { |path| path }
|
559
507
|
end
|
560
508
|
|
561
|
-
def write_to_file(path, content)
|
562
|
-
File.write(path, content)
|
563
|
-
end
|
564
|
-
|
565
|
-
def set_environment_variable(path)
|
566
|
-
ENV['MDE_LINK_REQUIRED_FILE'] = path
|
567
|
-
end
|
568
|
-
|
569
509
|
# Updates the title of an FCB object from its body content if the title is nil or empty.
|
570
510
|
def default_block_title_from_body(fcb)
|
571
511
|
return unless fcb.title.nil? || fcb.title.empty?
|
@@ -584,27 +524,14 @@ module MarkdownExec
|
|
584
524
|
# Deletes a temporary file specified by an environment variable.
|
585
525
|
# Checks if the file exists before attempting to delete it and clears the environment variable afterward.
|
586
526
|
# Any errors encountered during deletion are handled gracefully.
|
587
|
-
def delete_required_temp_file
|
588
|
-
temp_blocks_file_path = fetch_temp_blocks_file_path
|
589
|
-
|
527
|
+
def delete_required_temp_file(temp_blocks_file_path)
|
590
528
|
return if temp_blocks_file_path.nil? || temp_blocks_file_path.empty?
|
591
529
|
|
592
530
|
safely_remove_file(temp_blocks_file_path)
|
593
|
-
clear_required_file
|
594
531
|
rescue StandardError
|
595
532
|
error_handler('delete_required_temp_file')
|
596
533
|
end
|
597
534
|
|
598
|
-
# private
|
599
|
-
|
600
|
-
def fetch_temp_blocks_file_path
|
601
|
-
ENV.fetch('MDE_LINK_REQUIRED_FILE', nil)
|
602
|
-
end
|
603
|
-
|
604
|
-
def safely_remove_file(path)
|
605
|
-
FileUtils.rm_f(path)
|
606
|
-
end
|
607
|
-
|
608
535
|
# Determines the state of a selected block in the menu based on the selected option.
|
609
536
|
# It categorizes the selected option into either EXIT, BACK, or CONTINUE state.
|
610
537
|
#
|
@@ -636,12 +563,9 @@ module MarkdownExec
|
|
636
563
|
:script_preview_frame_color)
|
637
564
|
end
|
638
565
|
|
639
|
-
|
640
|
-
|
641
|
-
|
642
|
-
formatted_string = string_send_color(@delegate_object[data_sym],
|
643
|
-
color_sym)
|
644
|
-
@fout.fout formatted_string
|
566
|
+
def divider_formatting_present?(position)
|
567
|
+
divider_key = position == :initial ? :menu_initial_divider : :menu_final_divider
|
568
|
+
@delegate_object[:menu_divider_format].present? && @delegate_object[divider_key].present?
|
645
569
|
end
|
646
570
|
|
647
571
|
def error_handler(name = '', opts = {})
|
@@ -659,36 +583,38 @@ module MarkdownExec
|
|
659
583
|
#
|
660
584
|
# @param required_lines [Array<String>] The lines of code to be executed.
|
661
585
|
# @param selected [FCB] The selected functional code block object.
|
662
|
-
def
|
586
|
+
def execute_required_lines(required_lines = [])
|
663
587
|
# set_script_block_name(selected)
|
664
|
-
|
588
|
+
save_executed_script_if_specified(required_lines)
|
665
589
|
format_and_execute_command(required_lines)
|
666
590
|
post_execution_process
|
667
591
|
end
|
668
592
|
|
669
|
-
#
|
670
|
-
|
671
|
-
|
672
|
-
|
673
|
-
|
593
|
+
# Execute a code block after approval and provide user interaction options.
|
594
|
+
#
|
595
|
+
# This method displays required code blocks, asks for user approval, and
|
596
|
+
# executes the code block if approved. It also allows users to copy the
|
597
|
+
# code to the clipboard or save it to a file.
|
598
|
+
#
|
599
|
+
# @param opts [Hash] Options hash containing configuration settings.
|
600
|
+
# @param mdoc [YourMDocClass] An instance of the MDoc class.
|
601
|
+
#
|
602
|
+
def execute_bash_and_special_blocks(selected, mdoc, link_state = LinkState.new,
|
603
|
+
block_source:)
|
604
|
+
if selected.fetch(:shell, '') == BlockType::LINK
|
605
|
+
push_link_history_and_trigger_load(selected.fetch(:body, ''), mdoc, selected,
|
606
|
+
link_state)
|
674
607
|
|
675
|
-
|
676
|
-
|
677
|
-
end
|
608
|
+
elsif @menu_user_clicked_back_link
|
609
|
+
pop_link_history_and_trigger_load
|
678
610
|
|
679
|
-
|
680
|
-
|
681
|
-
@fout.fout fetch_color(data_sym: :script_execution_head,
|
682
|
-
color_sym: :script_execution_frame_color)
|
683
|
-
command_execute(formatted_command, args: @pass_args)
|
684
|
-
@fout.fout fetch_color(data_sym: :script_execution_tail,
|
685
|
-
color_sym: :script_execution_frame_color)
|
686
|
-
end
|
611
|
+
elsif selected[:shell] == BlockType::OPTS
|
612
|
+
update_options_and_trigger_reuse(selected, @menu_base_options, link_state)
|
687
613
|
|
688
|
-
|
689
|
-
|
690
|
-
|
691
|
-
|
614
|
+
else
|
615
|
+
compile_execute_bash_and_special_blocks_and_trigger_reuse(mdoc, selected, link_state,
|
616
|
+
block_source: block_source)
|
617
|
+
end
|
692
618
|
end
|
693
619
|
|
694
620
|
# Retrieves a specific data symbol from the delegate object, converts it to a string,
|
@@ -705,6 +631,26 @@ module MarkdownExec
|
|
705
631
|
string_send_color(data_string, color_sym)
|
706
632
|
end
|
707
633
|
|
634
|
+
# DebugHelper.d ["HDmm method_name: #{method_name}", "#{first_n_caller_items 1}"]
|
635
|
+
def first_n_caller_items(n)
|
636
|
+
call_stack = caller
|
637
|
+
base_path = File.realpath('.')
|
638
|
+
|
639
|
+
# Modify the call stack to remove the base path and keep only the first n items
|
640
|
+
call_stack.take(n + 1)[1..].map do |line|
|
641
|
+
" . #{line.sub(/^#{Regexp.escape(base_path)}\//, '')}"
|
642
|
+
end.join("\n")
|
643
|
+
end
|
644
|
+
|
645
|
+
def format_and_execute_command(lines)
|
646
|
+
formatted_command = lines.flatten.join("\n")
|
647
|
+
@fout.fout fetch_color(data_sym: :script_execution_head,
|
648
|
+
color_sym: :script_execution_frame_color)
|
649
|
+
command_execute(formatted_command, args: @pass_args)
|
650
|
+
@fout.fout fetch_color(data_sym: :script_execution_tail,
|
651
|
+
color_sym: :script_execution_frame_color)
|
652
|
+
end
|
653
|
+
|
708
654
|
# Formats a string based on a given context and applies color styling to it.
|
709
655
|
# It retrieves format and color information from the delegate object and processes accordingly.
|
710
656
|
#
|
@@ -756,124 +702,21 @@ module MarkdownExec
|
|
756
702
|
fcb
|
757
703
|
end
|
758
704
|
|
759
|
-
# private
|
760
|
-
|
761
|
-
# Applies shell color options to the given string if applicable.
|
762
|
-
#
|
763
|
-
# @param name [String] The name to potentially colorize.
|
764
|
-
# @param shell_color_option [Symbol, nil] The shell color option to apply.
|
765
|
-
# @return [String] The colorized or original name string.
|
766
|
-
def apply_shell_color_option(name, shell_color_option)
|
767
|
-
if shell_color_option && @delegate_object[shell_color_option].present?
|
768
|
-
string_send_color(name, shell_color_option)
|
769
|
-
else
|
770
|
-
name
|
771
|
-
end
|
772
|
-
end
|
773
|
-
|
774
|
-
# This method handles the back-link operation in the Markdown execution context.
|
775
|
-
# It updates the history state and prepares to load the next block.
|
776
|
-
#
|
777
|
-
# @return [LoadFileNextBlock] An object indicating the action to load the next block.
|
778
|
-
def handle_back_link
|
779
|
-
history_state_pop
|
780
|
-
LoadFileNextBlock.new(LoadFile::Load, '')
|
781
|
-
end
|
782
|
-
|
783
|
-
# private
|
784
705
|
# Updates the delegate object's state based on the provided block state.
|
785
706
|
# It sets the block name and determines if the user clicked the back link in the menu.
|
786
707
|
#
|
787
708
|
# @param block_state [Object] An object representing the state of a block in the menu.
|
788
709
|
def handle_block_state(block_state)
|
710
|
+
return if block_state.nil?
|
789
711
|
unless [MenuState::BACK,
|
790
712
|
MenuState::CONTINUE].include?(block_state.state)
|
791
713
|
return
|
792
714
|
end
|
793
715
|
|
794
716
|
@delegate_object[:block_name] = block_state.block[:oname]
|
795
|
-
# rbp
|
796
717
|
@menu_user_clicked_back_link = block_state.state == MenuState::BACK
|
797
718
|
end
|
798
719
|
|
799
|
-
# This method is responsible for handling the execution of generic blocks in a markdown document.
|
800
|
-
# It collects the required code lines from the document and, depending on the configuration,
|
801
|
-
# may display the code for user approval before execution. It then executes the approved block.
|
802
|
-
#
|
803
|
-
# @param mdoc [Object] The markdown document object containing code blocks.
|
804
|
-
# @param selected [Hash] The selected item from the menu to be executed.
|
805
|
-
# @return [LoadFileNextBlock] An object indicating whether to load the next block or reuse the current one.
|
806
|
-
def handle_generic_block(mdoc, selected)
|
807
|
-
# rbp
|
808
|
-
required_lines = collect_required_code_lines(mdoc, selected)
|
809
|
-
output_or_approval = @delegate_object[:output_script] || @delegate_object[:user_must_approve]
|
810
|
-
display_required_code(required_lines) if output_or_approval
|
811
|
-
allow_execution = @delegate_object[:user_must_approve] ? prompt_for_user_approval(required_lines) : true
|
812
|
-
execute_approved_block(required_lines, selected) if allow_execution
|
813
|
-
|
814
|
-
LoadFileNextBlock.new(LoadFile::Reuse, '')
|
815
|
-
end
|
816
|
-
|
817
|
-
# Handles the processing of a link block in Markdown Execution.
|
818
|
-
# It loads YAML data from the body content, pushes the state to history,
|
819
|
-
# sets environment variables, and decides on the next block to load.
|
820
|
-
#
|
821
|
-
# @param body [Array<String>] The body content as an array of strings.
|
822
|
-
# @param mdoc [Object] Markdown document object.
|
823
|
-
# @param selected [Boolean] Selected state.
|
824
|
-
# @return [LoadFileNextBlock] Object indicating the next action for file loading.
|
825
|
-
def handle_link_block(body, mdoc, selected)
|
826
|
-
data = parse_yaml_data_from_body(body)
|
827
|
-
data_file = data['file']
|
828
|
-
return LoadFileNextBlock.new(LoadFile::Reuse, '') unless data_file
|
829
|
-
|
830
|
-
history_state_push(mdoc, data_file, selected)
|
831
|
-
set_environment_variables(data['vars'])
|
832
|
-
|
833
|
-
LoadFileNextBlock.new(LoadFile::Load, data['block'] || '')
|
834
|
-
end
|
835
|
-
|
836
|
-
# private
|
837
|
-
|
838
|
-
def parse_yaml_data_from_body(body)
|
839
|
-
body.any? ? YAML.load(body.join("\n")) : {}
|
840
|
-
end
|
841
|
-
|
842
|
-
def set_environment_variables(vars)
|
843
|
-
vars ||= []
|
844
|
-
vars.each { |key, value| ENV[key] = value.to_s }
|
845
|
-
end
|
846
|
-
|
847
|
-
# Processes YAML data from the selected menu item, updating delegate objects and optionally printing formatted output.
|
848
|
-
# @param selected [Hash] Selected item from the menu containing a YAML body.
|
849
|
-
# @param tgt2 [Hash, nil] An optional target hash to update with YAML data.
|
850
|
-
# @return [LoadFileNextBlock] An instance indicating the next action for loading files.
|
851
|
-
def handle_opts_block(selected, tgt2 = nil)
|
852
|
-
data = YAML.load(selected[:body].join("\n"))
|
853
|
-
(data || []).each do |key, value|
|
854
|
-
update_delegate_and_target(key, value, tgt2)
|
855
|
-
if @delegate_object[:menu_opts_set_format].present?
|
856
|
-
print_formatted_option(key,
|
857
|
-
value)
|
858
|
-
end
|
859
|
-
end
|
860
|
-
LoadFileNextBlock.new(LoadFile::Reuse, '')
|
861
|
-
end
|
862
|
-
|
863
|
-
# private
|
864
|
-
|
865
|
-
def update_delegate_and_target(key, value, tgt2)
|
866
|
-
sym_key = key.to_sym
|
867
|
-
@delegate_object[sym_key] = value
|
868
|
-
tgt2[sym_key] = value if tgt2
|
869
|
-
end
|
870
|
-
|
871
|
-
def print_formatted_option(key, value)
|
872
|
-
formatted_str = format(@delegate_object[:menu_opts_set_format],
|
873
|
-
{ key: key, value: value })
|
874
|
-
print string_send_color(formatted_str, :menu_opts_set_color)
|
875
|
-
end
|
876
|
-
|
877
720
|
def handle_stream(stream, file_type, swap: false)
|
878
721
|
@process_mutex.synchronize do
|
879
722
|
Thread.new do
|
@@ -896,52 +739,6 @@ module MarkdownExec
|
|
896
739
|
end
|
897
740
|
end
|
898
741
|
|
899
|
-
def wait_for_stream_processing
|
900
|
-
@process_mutex.synchronize do
|
901
|
-
@process_cv.wait(@process_mutex)
|
902
|
-
end
|
903
|
-
end
|
904
|
-
|
905
|
-
# Partitions the history state from the environment variable based on the document separator.
|
906
|
-
# @return [Hash] A hash containing two parts: :unit (first part) and :rest (remaining part).
|
907
|
-
def history_state_partition
|
908
|
-
history_env_value = ENV.fetch(MDE_HISTORY_ENV_NAME, '')
|
909
|
-
separator = @delegate_object[:history_document_separator]
|
910
|
-
|
911
|
-
unit, rest = StringUtil.partition_at_first(history_env_value, separator)
|
912
|
-
{ unit: unit, rest: rest }
|
913
|
-
end
|
914
|
-
|
915
|
-
# Pops the last entry from the history state, updating the delegate object and environment variable.
|
916
|
-
# It also deletes the required temporary file and updates the run state link history.
|
917
|
-
def history_state_pop
|
918
|
-
state = history_state_partition
|
919
|
-
@delegate_object[:filename] = state[:unit]
|
920
|
-
ENV[MDE_HISTORY_ENV_NAME] = state[:rest]
|
921
|
-
delete_required_temp_file
|
922
|
-
@run_state.link_history.pop
|
923
|
-
end
|
924
|
-
|
925
|
-
# Updates the history state by pushing a new entry and managing environment variables.
|
926
|
-
# @param mdoc [Object] The Markdown document object.
|
927
|
-
# @param data_file [String] The data file to be processed.
|
928
|
-
# @param selected [Hash] Hash containing the selected block's name.
|
929
|
-
def history_state_push(mdoc, data_file, selected)
|
930
|
-
# Construct new history string
|
931
|
-
new_history = [@delegate_object[:filename],
|
932
|
-
@delegate_object[:history_document_separator],
|
933
|
-
ENV.fetch(MDE_HISTORY_ENV_NAME, '')].join
|
934
|
-
|
935
|
-
# Update delegate object and environment variable
|
936
|
-
@delegate_object[:filename] = data_file
|
937
|
-
ENV[MDE_HISTORY_ENV_NAME] = new_history
|
938
|
-
|
939
|
-
# Write required blocks to temp file and update run state
|
940
|
-
write_required_blocks_to_temp_file(mdoc, @delegate_object[:block_name])
|
941
|
-
@run_state.link_history.push(block_name: selected[:oname],
|
942
|
-
filename: data_file)
|
943
|
-
end
|
944
|
-
|
945
742
|
# Indents all lines in a given string with a specified indentation string.
|
946
743
|
# @param body [String] A multi-line string to be indented.
|
947
744
|
# @param indent [String] The string used for indentation (default is an empty string).
|
@@ -952,10 +749,6 @@ module MarkdownExec
|
|
952
749
|
body.lines.map { |line| indent + line.chomp }.join("\n")
|
953
750
|
end
|
954
751
|
|
955
|
-
def initialize_fcb_names(fcb)
|
956
|
-
fcb.oname = fcb.dname = fcb.title || ''
|
957
|
-
end
|
958
|
-
|
959
752
|
# Initializes variables for regex and other states
|
960
753
|
def initial_state
|
961
754
|
{
|
@@ -989,6 +782,10 @@ module MarkdownExec
|
|
989
782
|
write_execution_output_to_file
|
990
783
|
end
|
991
784
|
|
785
|
+
def initialize_fcb_names(fcb)
|
786
|
+
fcb.oname = fcb.dname = fcb.title || ''
|
787
|
+
end
|
788
|
+
|
992
789
|
# Iterates through blocks in a file, applying the provided block to each line.
|
993
790
|
# The iteration only occurs if the file exists.
|
994
791
|
# @yield [Symbol] :filter Yields to obtain selected messages for processing.
|
@@ -1006,6 +803,31 @@ module MarkdownExec
|
|
1006
803
|
end
|
1007
804
|
end
|
1008
805
|
|
806
|
+
def link_history_push_and_next(
|
807
|
+
curr_block_name:, curr_document_filename:,
|
808
|
+
inherited_block_names:, inherited_lines:,
|
809
|
+
next_block_name:, next_document_filename:,
|
810
|
+
next_load_file:
|
811
|
+
)
|
812
|
+
@link_history.push(
|
813
|
+
LinkState.new(
|
814
|
+
block_name: curr_block_name,
|
815
|
+
document_filename: curr_document_filename,
|
816
|
+
inherited_block_names: inherited_block_names,
|
817
|
+
inherited_lines: inherited_lines
|
818
|
+
)
|
819
|
+
)
|
820
|
+
LoadFileLinkState.new(
|
821
|
+
next_load_file,
|
822
|
+
LinkState.new(
|
823
|
+
block_name: next_block_name,
|
824
|
+
document_filename: next_document_filename,
|
825
|
+
inherited_block_names: inherited_block_names,
|
826
|
+
inherited_lines: inherited_lines
|
827
|
+
)
|
828
|
+
)
|
829
|
+
end
|
830
|
+
|
1009
831
|
# Loads auto blocks based on delegate object settings and updates if new filename is detected.
|
1010
832
|
# Executes a specified block once per filename.
|
1011
833
|
# @param all_blocks [Array] Array of all block elements.
|
@@ -1019,46 +841,11 @@ module MarkdownExec
|
|
1019
841
|
block = block_find(all_blocks, :oname, block_name)
|
1020
842
|
return unless block
|
1021
843
|
|
1022
|
-
|
844
|
+
update_options_and_trigger_reuse(block, @delegate_object)
|
1023
845
|
@most_recent_loaded_filename = @delegate_object[:filename]
|
1024
846
|
true
|
1025
847
|
end
|
1026
848
|
|
1027
|
-
# DebugHelper.d ["HDmm method_name: #{method_name}", "#{first_n_caller_items 1}"]
|
1028
|
-
def first_n_caller_items(n)
|
1029
|
-
# Get the call stack
|
1030
|
-
call_stack = caller
|
1031
|
-
base_path = File.realpath('.')
|
1032
|
-
|
1033
|
-
# Modify the call stack to remove the base path and keep only the first n items
|
1034
|
-
call_stack.take(n + 1)[1..].map do |line|
|
1035
|
-
" . #{line.sub(/^#{Regexp.escape(base_path)}\//, '')}"
|
1036
|
-
end.join("\n")
|
1037
|
-
end
|
1038
|
-
|
1039
|
-
# Checks if a history environment variable is set and returns its value if present.
|
1040
|
-
# @return [String, nil] The value of the history environment variable or nil if not present.
|
1041
|
-
def history_env_state_exist?
|
1042
|
-
ENV.fetch(MDE_HISTORY_ENV_NAME, '').present?
|
1043
|
-
end
|
1044
|
-
|
1045
|
-
# def history_env_state_exist?
|
1046
|
-
# history = ENV.fetch(MDE_HISTORY_ENV_NAME, '')
|
1047
|
-
# history.present? ? history : nil
|
1048
|
-
# end
|
1049
|
-
|
1050
|
-
# If a method is missing, treat it as a key for the @delegate_object.
|
1051
|
-
def method_missing(method_name, *args, &block)
|
1052
|
-
if @delegate_object.respond_to?(method_name)
|
1053
|
-
@delegate_object.send(method_name, *args, &block)
|
1054
|
-
elsif method_name.to_s.end_with?('=') && args.size == 1
|
1055
|
-
@delegate_object[method_name.to_s.chop.to_sym] = args.first
|
1056
|
-
else
|
1057
|
-
@delegate_object[method_name]
|
1058
|
-
# super
|
1059
|
-
end
|
1060
|
-
end
|
1061
|
-
|
1062
849
|
def mdoc_and_blocks_from_nested_files
|
1063
850
|
menu_blocks = blocks_from_nested_files
|
1064
851
|
mdoc = MDoc.new(menu_blocks) do |nopts|
|
@@ -1074,9 +861,7 @@ module MarkdownExec
|
|
1074
861
|
|
1075
862
|
# recreate menu with new options
|
1076
863
|
#
|
1077
|
-
if load_auto_blocks(all_blocks)
|
1078
|
-
all_blocks, mdoc = mdoc_and_blocks_from_nested_files
|
1079
|
-
end
|
864
|
+
all_blocks, mdoc = mdoc_and_blocks_from_nested_files if load_auto_blocks(all_blocks)
|
1080
865
|
|
1081
866
|
menu_blocks = mdoc.fcbs_per_options(@delegate_object)
|
1082
867
|
add_menu_chrome_blocks!(menu_blocks)
|
@@ -1104,16 +889,41 @@ module MarkdownExec
|
|
1104
889
|
if @delegate_object[:menu_chrome_format]
|
1105
890
|
format(@delegate_object[:menu_chrome_format], option_value)
|
1106
891
|
else
|
1107
|
-
option_value
|
892
|
+
option_value
|
893
|
+
end
|
894
|
+
end
|
895
|
+
|
896
|
+
def merge_lists(*args)
|
897
|
+
# Filters out nil values, flattens the arrays, and ensures an empty list is returned if no valid lists are provided
|
898
|
+
merged = args.compact.flatten
|
899
|
+
merged.empty? ? [] : merged
|
900
|
+
end
|
901
|
+
|
902
|
+
# If a method is missing, treat it as a key for the @delegate_object.
|
903
|
+
def method_missing(method_name, *args, &block)
|
904
|
+
if @delegate_object.respond_to?(method_name)
|
905
|
+
@delegate_object.send(method_name, *args, &block)
|
906
|
+
elsif method_name.to_s.end_with?('=') && args.size == 1
|
907
|
+
@delegate_object[method_name.to_s.chop.to_sym] = args.first
|
908
|
+
else
|
909
|
+
@delegate_object[method_name]
|
910
|
+
# super
|
1108
911
|
end
|
1109
912
|
end
|
1110
913
|
|
1111
|
-
def
|
1112
|
-
return
|
914
|
+
def pop_cli_argument!
|
915
|
+
return false unless @delegate_object[:input_cli_rest].present?
|
916
|
+
|
917
|
+
@cli_block_name = @delegate_object[:input_cli_rest].pop
|
918
|
+
true
|
919
|
+
end
|
920
|
+
|
921
|
+
# private
|
1113
922
|
|
1114
|
-
|
1115
|
-
|
1116
|
-
|
923
|
+
def output_color_formatted(data_sym, color_sym)
|
924
|
+
formatted_string = string_send_color(@delegate_object[data_sym],
|
925
|
+
color_sym)
|
926
|
+
@fout.fout formatted_string
|
1117
927
|
end
|
1118
928
|
|
1119
929
|
def output_execution_result
|
@@ -1162,13 +972,38 @@ module MarkdownExec
|
|
1162
972
|
), level: level
|
1163
973
|
end
|
1164
974
|
|
975
|
+
# private
|
976
|
+
|
977
|
+
def parse_yaml_data_from_body(body)
|
978
|
+
body.any? ? YAML.load(body.join("\n")) : {}
|
979
|
+
end
|
980
|
+
|
981
|
+
# This method handles the back-link operation in the Markdown execution context.
|
982
|
+
# It updates the history state and prepares to load the next block.
|
983
|
+
#
|
984
|
+
# @return [LoadFileLinkState] An object indicating the action to load the next block.
|
985
|
+
def pop_link_history_and_trigger_load
|
986
|
+
pop = @link_history.pop
|
987
|
+
peek = @link_history.peek
|
988
|
+
LoadFileLinkState.new(LoadFile::Load, LinkState.new(
|
989
|
+
document_filename: pop.document_filename,
|
990
|
+
inherited_block_names: peek.inherited_block_names,
|
991
|
+
inherited_lines: peek.inherited_lines
|
992
|
+
))
|
993
|
+
end
|
994
|
+
|
995
|
+
def post_execution_process
|
996
|
+
initialize_and_save_execution_output
|
997
|
+
output_execution_summary
|
998
|
+
output_execution_result
|
999
|
+
end
|
1000
|
+
|
1165
1001
|
# Prepare the blocks menu by adding labels and other necessary details.
|
1166
1002
|
#
|
1167
1003
|
# @param all_blocks [Array<Hash>] The list of blocks from the file.
|
1168
1004
|
# @param opts [Hash] The options hash.
|
1169
1005
|
# @return [Array<Hash>] The updated blocks menu.
|
1170
1006
|
def prepare_blocks_menu(menu_blocks)
|
1171
|
-
### replace_consecutive_blanks(menu_blocks).map do |fcb|
|
1172
1007
|
menu_blocks.map do |fcb|
|
1173
1008
|
next if Filter.prepared_not_in_menu?(@delegate_object, fcb,
|
1174
1009
|
%i[block_name_include_match block_name_wrapper_match])
|
@@ -1189,6 +1024,28 @@ module MarkdownExec
|
|
1189
1024
|
end.compact
|
1190
1025
|
end
|
1191
1026
|
|
1027
|
+
def print_formatted_option(key, value)
|
1028
|
+
formatted_str = format(@delegate_object[:menu_opts_set_format],
|
1029
|
+
{ key: key, value: value })
|
1030
|
+
print string_send_color(formatted_str, :menu_opts_set_color)
|
1031
|
+
end
|
1032
|
+
|
1033
|
+
# private
|
1034
|
+
|
1035
|
+
def process_block_based_on_type(blocks, btype, fcb)
|
1036
|
+
case btype
|
1037
|
+
when :blocks
|
1038
|
+
blocks.push(get_block_summary(fcb))
|
1039
|
+
when :filter
|
1040
|
+
%i[blocks line]
|
1041
|
+
when :line
|
1042
|
+
unless @delegate_object[:no_chrome]
|
1043
|
+
create_and_add_chrome_blocks(blocks,
|
1044
|
+
fcb)
|
1045
|
+
end
|
1046
|
+
end
|
1047
|
+
end
|
1048
|
+
|
1192
1049
|
##
|
1193
1050
|
# Presents a menu to the user for approving an action and performs additional tasks based on the selection.
|
1194
1051
|
# The function provides options for approval, rejection, copying data to clipboard, or saving data to a file.
|
@@ -1247,17 +1104,57 @@ module MarkdownExec
|
|
1247
1104
|
exit 1
|
1248
1105
|
end
|
1249
1106
|
|
1250
|
-
def save_to_file(required_lines)
|
1251
|
-
write_command_file(required_lines)
|
1252
|
-
@fout.fout "File saved: #{@run_state.saved_filespec}"
|
1253
|
-
end
|
1254
|
-
|
1255
1107
|
# public
|
1256
1108
|
|
1109
|
+
# Handles the processing of a link block in Markdown Execution.
|
1110
|
+
# It loads YAML data from the link_block_body content, pushes the state to history,
|
1111
|
+
# sets environment variables, and decides on the next block to load.
|
1112
|
+
#
|
1113
|
+
# @param link_block_body [Array<String>] The body content as an array of strings.
|
1114
|
+
# @param mdoc [Object] Markdown document object.
|
1115
|
+
# @param selected [FCB] Selected code block.
|
1116
|
+
# @return [LoadFileLinkState] Object indicating the next action for file loading.
|
1117
|
+
def push_link_history_and_trigger_load(link_block_body, mdoc, selected,
|
1118
|
+
link_state = LinkState.new)
|
1119
|
+
link_block_data = parse_yaml_data_from_body(link_block_body)
|
1120
|
+
|
1121
|
+
# load key and values from link block into current environment
|
1122
|
+
#
|
1123
|
+
(link_block_data['vars'] || []).each do |(key, value)|
|
1124
|
+
ENV[key] = value.to_s
|
1125
|
+
end
|
1126
|
+
|
1127
|
+
## collect blocks specified by block
|
1128
|
+
#
|
1129
|
+
if mdoc
|
1130
|
+
code_info = mdoc.collect_recursively_required_code(
|
1131
|
+
selected[:oname],
|
1132
|
+
label_format_above: @delegate_object[:shell_code_label_format_above],
|
1133
|
+
label_format_below: @delegate_object[:shell_code_label_format_below],
|
1134
|
+
block_source: { document_filename: link_state.document_filename }
|
1135
|
+
)
|
1136
|
+
code_lines = code_info[:code]
|
1137
|
+
block_names = code_info[:block_names]
|
1138
|
+
else
|
1139
|
+
block_names = []
|
1140
|
+
code_lines = []
|
1141
|
+
end
|
1142
|
+
|
1143
|
+
next_document_filename = link_block_data['file'] || @delegate_object[:filename]
|
1144
|
+
link_history_push_and_next(
|
1145
|
+
curr_block_name: selected[:oname],
|
1146
|
+
curr_document_filename: @delegate_object[:filename],
|
1147
|
+
inherited_block_names: ((link_state&.inherited_block_names || []) + block_names).sort.uniq,
|
1148
|
+
inherited_lines: code_merge(link_state&.inherited_lines, code_lines),
|
1149
|
+
next_block_name: link_block_data['block'] || '',
|
1150
|
+
next_document_filename: next_document_filename,
|
1151
|
+
next_load_file: next_document_filename == @delegate_object[:filename] ? LoadFile::Reuse : LoadFile::Load
|
1152
|
+
)
|
1153
|
+
end
|
1154
|
+
|
1257
1155
|
# Reads required code blocks from a temporary file specified by an environment variable.
|
1258
1156
|
# @return [Array<String>] Lines read from the temporary file, or an empty array if file is not found or path is empty.
|
1259
|
-
def read_required_blocks_from_temp_file
|
1260
|
-
temp_blocks_file_path = ENV.fetch('MDE_LINK_REQUIRED_FILE', nil)
|
1157
|
+
def read_required_blocks_from_temp_file(temp_blocks_file_path)
|
1261
1158
|
return [] if temp_blocks_file_path.to_s.empty?
|
1262
1159
|
|
1263
1160
|
if File.exist?(temp_blocks_file_path)
|
@@ -1269,6 +1166,29 @@ module MarkdownExec
|
|
1269
1166
|
end
|
1270
1167
|
end
|
1271
1168
|
|
1169
|
+
def runtime_exception(exception_sym, name, items)
|
1170
|
+
if @delegate_object[exception_sym] != 0
|
1171
|
+
data = { name: name, detail: items.join(', ') }
|
1172
|
+
warn(
|
1173
|
+
format(
|
1174
|
+
@delegate_object.fetch(:exception_format_name, "\n%{name}"),
|
1175
|
+
data
|
1176
|
+
).send(@delegate_object.fetch(:exception_color_name, :red)) +
|
1177
|
+
format(
|
1178
|
+
@delegate_object.fetch(:exception_format_detail, " - %{detail}\n"),
|
1179
|
+
data
|
1180
|
+
).send(@delegate_object.fetch(:exception_color_detail, :yellow))
|
1181
|
+
)
|
1182
|
+
end
|
1183
|
+
return unless (@delegate_object[exception_sym]).positive?
|
1184
|
+
|
1185
|
+
exit @delegate_object[exception_sym]
|
1186
|
+
end
|
1187
|
+
|
1188
|
+
def safely_remove_file(path)
|
1189
|
+
FileUtils.rm_f(path)
|
1190
|
+
end
|
1191
|
+
|
1272
1192
|
# Evaluates the given string as Ruby code and rescues any StandardErrors.
|
1273
1193
|
# If an error occurs, it calls the error_handler method with 'safeval'.
|
1274
1194
|
# @param str [String] The string to be evaluated.
|
@@ -1279,11 +1199,10 @@ module MarkdownExec
|
|
1279
1199
|
error_handler('safeval')
|
1280
1200
|
end
|
1281
1201
|
|
1282
|
-
|
1283
|
-
|
1284
|
-
|
1285
|
-
|
1286
|
-
# end
|
1202
|
+
def save_to_file(required_lines)
|
1203
|
+
write_command_file(required_lines)
|
1204
|
+
@fout.fout "File saved: #{@run_state.saved_filespec}"
|
1205
|
+
end
|
1287
1206
|
|
1288
1207
|
# Select and execute a code block from a Markdown document.
|
1289
1208
|
#
|
@@ -1291,26 +1210,27 @@ module MarkdownExec
|
|
1291
1210
|
# Markdown document, obtain approval, and execute the chosen block of code.
|
1292
1211
|
#
|
1293
1212
|
# @return [Nil] Returns nil if no code block is selected or an error occurs.
|
1294
|
-
def
|
1213
|
+
def select_execute_bash_and_special_blocks(_execute: true)
|
1295
1214
|
@menu_base_options = @delegate_object
|
1296
|
-
|
1297
|
-
|
1298
|
-
|
1299
|
-
|
1300
|
-
|
1301
|
-
@
|
1215
|
+
link_state = LinkState.new(
|
1216
|
+
block_name: @delegate_object[:block_name],
|
1217
|
+
document_filename: @delegate_object[:filename]
|
1218
|
+
)
|
1219
|
+
block_name_from_cli = link_state.block_name.present?
|
1220
|
+
@cli_block_name = link_state.block_name
|
1221
|
+
load_file = nil
|
1222
|
+
menu_default_dname = nil
|
1302
1223
|
|
1303
1224
|
loop do
|
1304
1225
|
loop do
|
1305
1226
|
@delegate_object = @menu_base_options.dup
|
1306
|
-
@menu_base_options[:filename] = @menu_state_filename
|
1307
|
-
# rbp
|
1308
|
-
@menu_base_options[:block_name] = @menu_state_block_name
|
1309
|
-
@menu_state_filename = nil
|
1310
|
-
@menu_state_block_name = nil
|
1311
1227
|
@menu_user_clicked_back_link = false
|
1228
|
+
@delegate_object[:filename] = link_state.document_filename
|
1229
|
+
link_state.block_name = @delegate_object[:block_name] =
|
1230
|
+
block_name_from_cli ? @cli_block_name : link_state.block_name
|
1312
1231
|
|
1313
1232
|
blocks_in_file, menu_blocks, mdoc = mdoc_menu_and_blocks_from_nested_files
|
1233
|
+
|
1314
1234
|
if @delegate_object[:dump_blocks_in_file]
|
1315
1235
|
warn format_and_highlight_dependencies(
|
1316
1236
|
compact_and_index_hash(blocks_in_file),
|
@@ -1323,12 +1243,13 @@ module MarkdownExec
|
|
1323
1243
|
label: 'menu_blocks'
|
1324
1244
|
)
|
1325
1245
|
end
|
1246
|
+
|
1326
1247
|
block_state = command_or_user_selected_block(blocks_in_file,
|
1327
|
-
menu_blocks,
|
1248
|
+
menu_blocks, menu_default_dname)
|
1328
1249
|
return if block_state.state == MenuState::EXIT
|
1329
1250
|
|
1330
1251
|
if block_state.block.nil?
|
1331
|
-
warn_format('
|
1252
|
+
warn_format('select_execute_bash_and_special_blocks', "Block not found -- #{@delegate_object[:block_name]}",
|
1332
1253
|
{ abort: true })
|
1333
1254
|
# error_handler("Block not found -- #{opts[:block_name]}", { abort: true })
|
1334
1255
|
end
|
@@ -1337,18 +1258,20 @@ module MarkdownExec
|
|
1337
1258
|
warn block_state.block.to_yaml.sub(/^(?:---\n)?/, "Block:\n")
|
1338
1259
|
end
|
1339
1260
|
|
1340
|
-
|
1341
|
-
|
1342
|
-
|
1343
|
-
|
1344
|
-
|
1345
|
-
|
1346
|
-
|
1347
|
-
|
1261
|
+
load_file_link_state = execute_bash_and_special_blocks(
|
1262
|
+
block_state.block,
|
1263
|
+
mdoc,
|
1264
|
+
link_state,
|
1265
|
+
block_source: { document_filename: @delegate_object[:filename] }
|
1266
|
+
)
|
1267
|
+
load_file = load_file_link_state.load_file
|
1268
|
+
link_state = load_file_link_state.link_state
|
1269
|
+
# if the same menu is being displayed, collect the display name of the selected menu item for use as the default item
|
1270
|
+
menu_default_dname = load_file == LoadFile::Load ? nil : block_state.block[:dname]
|
1348
1271
|
|
1349
1272
|
# user prompt to exit if the menu will be displayed again
|
1350
1273
|
#
|
1351
|
-
if
|
1274
|
+
if !block_name_from_cli &&
|
1352
1275
|
block_state.block[:shell] == BlockType::BASH &&
|
1353
1276
|
@delegate_object[:pause_after_script_execution] &&
|
1354
1277
|
prompt_select_continue == MenuState::EXIT
|
@@ -1357,19 +1280,15 @@ module MarkdownExec
|
|
1357
1280
|
|
1358
1281
|
# exit current document/menu if loading next document or single block_name was specified
|
1359
1282
|
#
|
1360
|
-
if block_state.state == MenuState::CONTINUE &&
|
1361
|
-
|
1362
|
-
end
|
1363
|
-
break if repeat_menu == MenuControl::Fresh
|
1283
|
+
break if block_state.state == MenuState::CONTINUE && load_file == LoadFile::Load
|
1284
|
+
break if block_name_from_cli
|
1364
1285
|
end
|
1365
|
-
break if
|
1286
|
+
break if load_file == LoadFile::Reuse
|
1366
1287
|
|
1367
|
-
|
1368
|
-
@menu_state_filename = @menu_base_options[:filename]
|
1369
|
-
@menu_state_block_name = @menu_base_options[:block_name]
|
1288
|
+
block_name_from_cli = pop_cli_argument!
|
1370
1289
|
end
|
1371
1290
|
rescue StandardError
|
1372
|
-
error_handler('
|
1291
|
+
error_handler('select_execute_bash_and_special_blocks',
|
1373
1292
|
{ abort: true })
|
1374
1293
|
end
|
1375
1294
|
|
@@ -1386,8 +1305,7 @@ module MarkdownExec
|
|
1386
1305
|
|
1387
1306
|
item.merge(
|
1388
1307
|
if selection == menu_chrome_colored_option(:menu_option_back_name)
|
1389
|
-
{ option: selection,
|
1390
|
-
shell: BlockType::LINK }
|
1308
|
+
{ option: selection, shell: BlockType::LINK }
|
1391
1309
|
elsif selection == menu_chrome_colored_option(:menu_option_exit_name)
|
1392
1310
|
{ option: selection }
|
1393
1311
|
else
|
@@ -1400,6 +1318,35 @@ module MarkdownExec
|
|
1400
1318
|
error_handler('select_option_with_metadata')
|
1401
1319
|
end
|
1402
1320
|
|
1321
|
+
def set_environment_variables_for_block(selected)
|
1322
|
+
YAML.load(selected[:body].join("\n")).each do |key, value|
|
1323
|
+
ENV[key] = value.to_s
|
1324
|
+
next unless @delegate_object[:menu_vars_set_format].present?
|
1325
|
+
|
1326
|
+
formatted_string = format(@delegate_object[:menu_vars_set_format],
|
1327
|
+
{ key: key, value: value })
|
1328
|
+
print string_send_color(formatted_string, :menu_vars_set_color)
|
1329
|
+
end
|
1330
|
+
end
|
1331
|
+
|
1332
|
+
def set_environment_variables_per_array(vars)
|
1333
|
+
vars ||= []
|
1334
|
+
vars.each { |key, value| ENV[key] = value.to_s }
|
1335
|
+
end
|
1336
|
+
|
1337
|
+
def set_file_permissions(file_path, chmod_value)
|
1338
|
+
File.chmod(chmod_value, file_path)
|
1339
|
+
end
|
1340
|
+
|
1341
|
+
def set_script_block_name(selected)
|
1342
|
+
@run_state.script_block_name = selected[:oname]
|
1343
|
+
end
|
1344
|
+
|
1345
|
+
def should_add_back_option?
|
1346
|
+
@delegate_object[:menu_with_back] && @link_history.prior_state_exist?
|
1347
|
+
# @delegate_object[:menu_with_back] && link_history_prior_state_exist?
|
1348
|
+
end
|
1349
|
+
|
1403
1350
|
# Initializes a new fenced code block (FCB) object based on the provided line and heading information.
|
1404
1351
|
# @param line [String] The line initiating the fenced block.
|
1405
1352
|
# @param headings [Array<String>] Current headings hierarchy.
|
@@ -1459,6 +1406,12 @@ module MarkdownExec
|
|
1459
1406
|
)
|
1460
1407
|
end
|
1461
1408
|
|
1409
|
+
def update_delegate_and_target(key, value, tgt2)
|
1410
|
+
sym_key = key.to_sym
|
1411
|
+
@delegate_object[sym_key] = value
|
1412
|
+
tgt2[sym_key] = value if tgt2
|
1413
|
+
end
|
1414
|
+
|
1462
1415
|
# Updates the hierarchy of document headings based on the given line.
|
1463
1416
|
# Utilizes regular expressions to identify heading levels.
|
1464
1417
|
# @param line [String] The line of text to check for headings.
|
@@ -1527,12 +1480,9 @@ module MarkdownExec
|
|
1527
1480
|
## add line to fenced code block
|
1528
1481
|
# remove fcb indent if possible
|
1529
1482
|
#
|
1530
|
-
# if nested_line[:depth].zero? || opts[:menu_include_imported_blocks]
|
1531
|
-
# if add_import_block?(nested_line)
|
1532
1483
|
state[:fcb].body += [
|
1533
1484
|
line.chomp.sub(/^#{state[:fcb].indent}/, '')
|
1534
1485
|
]
|
1535
|
-
# end
|
1536
1486
|
elsif nested_line[:depth].zero? || @delegate_object[:menu_include_imported_notes]
|
1537
1487
|
# add line if it is depth 0 or option allows it
|
1538
1488
|
#
|
@@ -1555,10 +1505,29 @@ module MarkdownExec
|
|
1555
1505
|
yield_to_block_if_applicable(fcb, selected_messages, &block)
|
1556
1506
|
end
|
1557
1507
|
|
1508
|
+
# Processes YAML data from the selected menu item, updating delegate objects and optionally printing formatted output.
|
1509
|
+
# @param selected [Hash] Selected item from the menu containing a YAML body.
|
1510
|
+
# @param tgt2 [Hash, nil] An optional target hash to update with YAML data.
|
1511
|
+
# @return [LoadFileLinkState] An instance indicating the next action for loading files.
|
1512
|
+
def update_options_and_trigger_reuse(selected, tgt2 = nil, link_state = LinkState.new)
|
1513
|
+
data = YAML.load(selected[:body].join("\n"))
|
1514
|
+
(data || []).each do |key, value|
|
1515
|
+
update_delegate_and_target(key, value, tgt2)
|
1516
|
+
print_formatted_option(key, value) if @delegate_object[:menu_opts_set_format].present?
|
1517
|
+
end
|
1518
|
+
link_state.block_name = nil
|
1519
|
+
LoadFileLinkState.new(LoadFile::Reuse, link_state)
|
1520
|
+
end
|
1521
|
+
|
1522
|
+
def wait_for_stream_processing
|
1523
|
+
@process_mutex.synchronize do
|
1524
|
+
@process_cv.wait(@process_mutex)
|
1525
|
+
end
|
1526
|
+
end
|
1527
|
+
|
1558
1528
|
def wait_for_user_selected_block(all_blocks, menu_blocks, default)
|
1559
1529
|
block_state = wait_for_user_selection(all_blocks, menu_blocks, default)
|
1560
1530
|
handle_block_state(block_state)
|
1561
|
-
|
1562
1531
|
block_state
|
1563
1532
|
rescue StandardError
|
1564
1533
|
error_handler('wait_for_user_selected_block')
|
@@ -1590,7 +1559,6 @@ module MarkdownExec
|
|
1590
1559
|
def write_command_file(required_lines)
|
1591
1560
|
return unless @delegate_object[:save_executed_script]
|
1592
1561
|
|
1593
|
-
# rbp
|
1594
1562
|
time_now = Time.now.utc
|
1595
1563
|
@run_state.saved_script_filename =
|
1596
1564
|
SavedAsset.script_name(blockname: @delegate_object[:block_name],
|
@@ -1613,7 +1581,7 @@ module MarkdownExec
|
|
1613
1581
|
"# time: #{time_now}\n" \
|
1614
1582
|
"#{required_lines.flatten.join("\n")}\n"
|
1615
1583
|
|
1616
|
-
|
1584
|
+
create_file_and_write_string_with_permissions(
|
1617
1585
|
@run_state.saved_filespec,
|
1618
1586
|
content,
|
1619
1587
|
@delegate_object[:saved_script_chmod]
|
@@ -1622,6 +1590,10 @@ module MarkdownExec
|
|
1622
1590
|
error_handler('write_command_file')
|
1623
1591
|
end
|
1624
1592
|
|
1593
|
+
def save_executed_script_if_specified(lines)
|
1594
|
+
write_command_file(lines) if @delegate_object[:save_executed_script]
|
1595
|
+
end
|
1596
|
+
|
1625
1597
|
def write_execution_output_to_file
|
1626
1598
|
FileUtils.mkdir_p File.dirname(@delegate_object[:logged_stdout_filespec])
|
1627
1599
|
|
@@ -1641,7 +1613,7 @@ module MarkdownExec
|
|
1641
1613
|
#
|
1642
1614
|
# @param mdoc [Object] The Markdown document object.
|
1643
1615
|
# @param block_name [String] The name of the block to collect code for.
|
1644
|
-
def
|
1616
|
+
def write_required_blocks_to_file(mdoc, block_name, temp_file_path, import_filename: nil)
|
1645
1617
|
c1 = if mdoc
|
1646
1618
|
mdoc.collect_recursively_required_code(
|
1647
1619
|
block_name,
|
@@ -1652,10 +1624,16 @@ module MarkdownExec
|
|
1652
1624
|
[]
|
1653
1625
|
end
|
1654
1626
|
|
1655
|
-
code_blocks = (read_required_blocks_from_temp_file +
|
1627
|
+
code_blocks = (read_required_blocks_from_temp_file(import_filename) +
|
1656
1628
|
c1).join("\n")
|
1657
1629
|
|
1658
|
-
|
1630
|
+
write_code_to_file(code_blocks, temp_file_path)
|
1631
|
+
end
|
1632
|
+
|
1633
|
+
# Writes the provided code blocks to a file.
|
1634
|
+
# @param code_blocks [String] Code blocks to write into the file.
|
1635
|
+
def write_code_to_file(content, path)
|
1636
|
+
File.write(path, content)
|
1659
1637
|
end
|
1660
1638
|
|
1661
1639
|
# Yields a line as a new block if the selected message type includes :line.
|
@@ -1698,7 +1676,7 @@ if $PROGRAM_NAME == __FILE__
|
|
1698
1676
|
@mdoc = mock('MarkdownDocument')
|
1699
1677
|
end
|
1700
1678
|
|
1701
|
-
def
|
1679
|
+
def test_calling_execute_required_lines_calls_command_execute_with_argument_args_value
|
1702
1680
|
pigeon = 'E'
|
1703
1681
|
obj = {
|
1704
1682
|
output_execution_label_format: '',
|
@@ -1715,46 +1693,33 @@ if $PROGRAM_NAME == __FILE__
|
|
1715
1693
|
args: pigeon
|
1716
1694
|
)
|
1717
1695
|
|
1718
|
-
# Call method
|
1719
|
-
c.
|
1696
|
+
# Call method opts_execute_required_lines
|
1697
|
+
c.execute_required_lines([])
|
1720
1698
|
end
|
1721
1699
|
|
1722
1700
|
# Test case for empty body
|
1723
|
-
def
|
1724
|
-
assert_equal
|
1725
|
-
@hd.
|
1701
|
+
def test_push_link_history_and_trigger_load_with_empty_body
|
1702
|
+
assert_equal LoadFile::Reuse,
|
1703
|
+
@hd.push_link_history_and_trigger_load([], nil, FCB.new).load_file
|
1726
1704
|
end
|
1727
1705
|
|
1728
1706
|
# Test case for non-empty body without 'file' key
|
1729
|
-
def
|
1707
|
+
def test_push_link_history_and_trigger_load_without_file_key
|
1730
1708
|
body = ["vars:\n KEY: VALUE"]
|
1731
|
-
assert_equal
|
1732
|
-
@hd.
|
1709
|
+
assert_equal LoadFile::Reuse,
|
1710
|
+
@hd.push_link_history_and_trigger_load(body, nil, FCB.new).load_file
|
1733
1711
|
end
|
1734
1712
|
|
1735
1713
|
# Test case for non-empty body with 'file' key
|
1736
|
-
def
|
1714
|
+
def test_push_link_history_and_trigger_load_with_file_key
|
1737
1715
|
body = ["file: sample_file\nblock: sample_block\nvars:\n KEY: VALUE"]
|
1738
|
-
expected_result =
|
1739
|
-
'sample_block'
|
1740
|
-
|
1716
|
+
expected_result = LoadFileLinkState.new(LoadFile::Load,
|
1717
|
+
LinkState.new(block_name: 'sample_block',
|
1718
|
+
document_filename: 'sample_file',
|
1719
|
+
inherited_lines: []))
|
1741
1720
|
assert_equal expected_result,
|
1742
|
-
@hd.
|
1743
|
-
|
1744
|
-
|
1745
|
-
def test_history_env_state_exist_with_value
|
1746
|
-
ENV[MDE_HISTORY_ENV_NAME] = 'history_value'
|
1747
|
-
assert @hd.history_env_state_exist?
|
1748
|
-
end
|
1749
|
-
|
1750
|
-
def test_history_env_state_exist_without_value
|
1751
|
-
ENV[MDE_HISTORY_ENV_NAME] = ''
|
1752
|
-
refute @hd.history_env_state_exist?
|
1753
|
-
end
|
1754
|
-
|
1755
|
-
def test_history_env_state_exist_not_set
|
1756
|
-
ENV.delete(MDE_HISTORY_ENV_NAME)
|
1757
|
-
refute @hd.history_env_state_exist?
|
1721
|
+
@hd.push_link_history_and_trigger_load(body, nil, FCB.new(block_name: 'sample_block',
|
1722
|
+
filename: 'sample_file'))
|
1758
1723
|
end
|
1759
1724
|
|
1760
1725
|
def test_indent_all_lines_with_indent
|
@@ -1778,22 +1743,6 @@ if $PROGRAM_NAME == __FILE__
|
|
1778
1743
|
assert_equal body, @hd.indent_all_lines(body, indent)
|
1779
1744
|
end
|
1780
1745
|
|
1781
|
-
def test_read_required_blocks_from_temp_file
|
1782
|
-
Tempfile.create do |file|
|
1783
|
-
file.write("Line 1\nLine 2")
|
1784
|
-
file.rewind
|
1785
|
-
ENV['MDE_LINK_REQUIRED_FILE'] = file.path
|
1786
|
-
|
1787
|
-
result = @hd.read_required_blocks_from_temp_file
|
1788
|
-
assert_equal ['Line 1', 'Line 2'], result
|
1789
|
-
end
|
1790
|
-
end
|
1791
|
-
|
1792
|
-
def test_read_required_blocks_from_temp_file_no_file
|
1793
|
-
ENV['MDE_LINK_REQUIRED_FILE'] = nil
|
1794
|
-
assert_empty @hd.read_required_blocks_from_temp_file
|
1795
|
-
end
|
1796
|
-
|
1797
1746
|
def test_safeval_successful_evaluation
|
1798
1747
|
assert_equal 4, @hd.safeval('2 + 2')
|
1799
1748
|
end
|
@@ -1823,8 +1772,6 @@ if $PROGRAM_NAME == __FILE__
|
|
1823
1772
|
}
|
1824
1773
|
]
|
1825
1774
|
|
1826
|
-
# hd = HashDelegator.new
|
1827
|
-
|
1828
1775
|
# iterate over the input and output data and
|
1829
1776
|
# assert that the method sets the title as expected
|
1830
1777
|
input_output_data.each do |data|
|
@@ -1871,7 +1818,7 @@ if $PROGRAM_NAME == __FILE__
|
|
1871
1818
|
|
1872
1819
|
assert_empty menu_blocks
|
1873
1820
|
end
|
1874
|
-
end
|
1821
|
+
end
|
1875
1822
|
|
1876
1823
|
class TestHashDelegatorBlockFind < Minitest::Test
|
1877
1824
|
def setup
|
@@ -1895,7 +1842,7 @@ if $PROGRAM_NAME == __FILE__
|
|
1895
1842
|
result = @hd.block_find(blocks, :key, 'value3', 'default')
|
1896
1843
|
assert_equal 'default', result
|
1897
1844
|
end
|
1898
|
-
end
|
1845
|
+
end
|
1899
1846
|
|
1900
1847
|
class TestHashDelegatorBlocksFromNestedFiles < Minitest::Test
|
1901
1848
|
def setup
|
@@ -1922,7 +1869,7 @@ if $PROGRAM_NAME == __FILE__
|
|
1922
1869
|
|
1923
1870
|
assert_kind_of Array, result
|
1924
1871
|
end
|
1925
|
-
end
|
1872
|
+
end
|
1926
1873
|
|
1927
1874
|
class TestHashDelegatorCollectRequiredCodeLines < Minitest::Test
|
1928
1875
|
def setup
|
@@ -1938,13 +1885,11 @@ if $PROGRAM_NAME == __FILE__
|
|
1938
1885
|
def test_collect_required_code_lines_with_vars
|
1939
1886
|
YAML.stubs(:load).returns({ 'key' => 'value' })
|
1940
1887
|
@mdoc.stubs(:collect_recursively_required_code).returns({ code: ['code line'] })
|
1941
|
-
|
1942
|
-
|
1943
|
-
result = @hd.collect_required_code_lines(@mdoc, @selected)
|
1888
|
+
result = @hd.collect_required_code_lines(@mdoc, @selected, block_source: {})
|
1944
1889
|
|
1945
1890
|
assert_equal ['code line'], result
|
1946
1891
|
end
|
1947
|
-
end
|
1892
|
+
end
|
1948
1893
|
|
1949
1894
|
class TestHashDelegatorCommandOrUserSelectedBlock < Minitest::Test
|
1950
1895
|
def setup
|
@@ -1975,7 +1920,7 @@ if $PROGRAM_NAME == __FILE__
|
|
1975
1920
|
assert_equal block_state.block, result.block
|
1976
1921
|
assert_equal :some_state, result.state
|
1977
1922
|
end
|
1978
|
-
end
|
1923
|
+
end
|
1979
1924
|
|
1980
1925
|
class TestHashDelegatorCountBlockInFilename < Minitest::Test
|
1981
1926
|
def setup
|
@@ -2004,7 +1949,7 @@ if $PROGRAM_NAME == __FILE__
|
|
2004
1949
|
|
2005
1950
|
assert_equal 0, count
|
2006
1951
|
end
|
2007
|
-
end
|
1952
|
+
end
|
2008
1953
|
|
2009
1954
|
class TestHashDelegatorCreateAndWriteFile < Minitest::Test
|
2010
1955
|
def setup
|
@@ -2015,7 +1960,7 @@ if $PROGRAM_NAME == __FILE__
|
|
2015
1960
|
File.stubs(:chmod)
|
2016
1961
|
end
|
2017
1962
|
|
2018
|
-
def
|
1963
|
+
def test_create_file_and_write_string_with_permissions
|
2019
1964
|
file_path = '/path/to/file'
|
2020
1965
|
content = 'sample content'
|
2021
1966
|
chmod_value = 0o644
|
@@ -2024,8 +1969,8 @@ if $PROGRAM_NAME == __FILE__
|
|
2024
1969
|
File.expects(:write).with(file_path, content).once
|
2025
1970
|
File.expects(:chmod).with(chmod_value, file_path).once
|
2026
1971
|
|
2027
|
-
@hd.
|
2028
|
-
|
1972
|
+
@hd.create_file_and_write_string_with_permissions(file_path, content,
|
1973
|
+
chmod_value)
|
2029
1974
|
|
2030
1975
|
assert true # Placeholder for actual test assertions
|
2031
1976
|
end
|
@@ -2039,70 +1984,12 @@ if $PROGRAM_NAME == __FILE__
|
|
2039
1984
|
File.expects(:write).with(file_path, content).once
|
2040
1985
|
File.expects(:chmod).never
|
2041
1986
|
|
2042
|
-
@hd.
|
2043
|
-
|
2044
|
-
|
2045
|
-
assert true # Placeholder for actual test assertions
|
2046
|
-
end
|
2047
|
-
end # class TestHashDelegator
|
2048
|
-
|
2049
|
-
class TestHashDelegatorCreateTempFile < Minitest::Test
|
2050
|
-
def setup
|
2051
|
-
@hd = HashDelegator.new
|
2052
|
-
@temp_file_path = '/tmp/tempfile'
|
2053
|
-
end
|
2054
|
-
|
2055
|
-
def test_create_temp_file_with_code
|
2056
|
-
Dir::Tmpname.stubs(:create).returns(@temp_file_path)
|
2057
|
-
File.stubs(:write).with(@temp_file_path, 'code_blocks')
|
2058
|
-
# ENV.expects(:[]=).with('MDE_LINK_REQUIRED_FILE', @temp_file_path)
|
2059
|
-
|
2060
|
-
@hd.create_temp_file_with_code('code_blocks')
|
2061
|
-
|
2062
|
-
assert true # Placeholder for actual test assertions
|
2063
|
-
end
|
2064
|
-
end # class TestHashDelegator
|
2065
|
-
|
2066
|
-
class TestHashDelegatorDeleteRequiredTempFile < Minitest::Test
|
2067
|
-
def setup
|
2068
|
-
@hd = HashDelegator.new
|
2069
|
-
@hd.stubs(:error_handler)
|
2070
|
-
@hd.stubs(:clear_required_file)
|
2071
|
-
FileUtils.stubs(:rm_f)
|
2072
|
-
end
|
2073
|
-
|
2074
|
-
def test_delete_required_temp_file_with_existing_file
|
2075
|
-
ENV.stubs(:fetch).with('MDE_LINK_REQUIRED_FILE',
|
2076
|
-
nil).returns('/path/to/temp_file')
|
2077
|
-
FileUtils.expects(:rm_f).with('/path/to/temp_file').once
|
2078
|
-
@hd.expects(:clear_required_file).once
|
2079
|
-
|
2080
|
-
@hd.delete_required_temp_file
|
2081
|
-
|
2082
|
-
assert true # Placeholder for actual test assertions
|
2083
|
-
end
|
2084
|
-
|
2085
|
-
def test_delete_required_temp_file_with_no_file
|
2086
|
-
ENV.stubs(:fetch).with('MDE_LINK_REQUIRED_FILE', nil).returns(nil)
|
2087
|
-
FileUtils.expects(:rm_f).never
|
2088
|
-
@hd.expects(:clear_required_file).never
|
2089
|
-
|
2090
|
-
@hd.delete_required_temp_file
|
2091
|
-
|
2092
|
-
assert true # Placeholder for actual test assertions
|
2093
|
-
end
|
2094
|
-
|
2095
|
-
def test_delete_required_temp_file_with_error
|
2096
|
-
ENV.stubs(:fetch).with('MDE_LINK_REQUIRED_FILE',
|
2097
|
-
nil).returns('/path/to/temp_file')
|
2098
|
-
FileUtils.stubs(:rm_f).raises(StandardError)
|
2099
|
-
@hd.expects(:error_handler).with('delete_required_temp_file').once
|
2100
|
-
|
2101
|
-
@hd.delete_required_temp_file
|
1987
|
+
@hd.create_file_and_write_string_with_permissions(file_path, content,
|
1988
|
+
chmod_value)
|
2102
1989
|
|
2103
1990
|
assert true # Placeholder for actual test assertions
|
2104
1991
|
end
|
2105
|
-
end
|
1992
|
+
end
|
2106
1993
|
|
2107
1994
|
class TestHashDelegatorDetermineBlockState < Minitest::Test
|
2108
1995
|
def setup
|
@@ -2137,7 +2024,7 @@ if $PROGRAM_NAME == __FILE__
|
|
2137
2024
|
assert_equal MenuState::CONTINUE, result.state
|
2138
2025
|
assert_equal selected_option, result.block
|
2139
2026
|
end
|
2140
|
-
end
|
2027
|
+
end
|
2141
2028
|
|
2142
2029
|
class TestHashDelegatorDisplayRequiredCode < Minitest::Test
|
2143
2030
|
def setup
|
@@ -2158,7 +2045,7 @@ if $PROGRAM_NAME == __FILE__
|
|
2158
2045
|
# Verifying that fout is called for each line and for header & footer
|
2159
2046
|
assert true # Placeholder for actual test assertions
|
2160
2047
|
end
|
2161
|
-
end
|
2048
|
+
end
|
2162
2049
|
|
2163
2050
|
class TestHashDelegatorFetchColor < Minitest::Test
|
2164
2051
|
def setup
|
@@ -2189,7 +2076,7 @@ if $PROGRAM_NAME == __FILE__
|
|
2189
2076
|
|
2190
2077
|
assert_equal 'Default Colored String', result
|
2191
2078
|
end
|
2192
|
-
end
|
2079
|
+
end
|
2193
2080
|
|
2194
2081
|
class TestHashDelegatorFormatReferencesSendColor < Minitest::Test
|
2195
2082
|
def setup
|
@@ -2220,7 +2107,7 @@ if $PROGRAM_NAME == __FILE__
|
|
2220
2107
|
|
2221
2108
|
assert_equal 'Default Colored String', result
|
2222
2109
|
end
|
2223
|
-
end
|
2110
|
+
end
|
2224
2111
|
|
2225
2112
|
class TestHashDelegatorFormatExecutionStreams < Minitest::Test
|
2226
2113
|
def setup
|
@@ -2253,7 +2140,7 @@ if $PROGRAM_NAME == __FILE__
|
|
2253
2140
|
|
2254
2141
|
assert_equal '', result
|
2255
2142
|
end
|
2256
|
-
end
|
2143
|
+
end
|
2257
2144
|
|
2258
2145
|
class TestHashDelegatorHandleBackLink < Minitest::Test
|
2259
2146
|
def setup
|
@@ -2261,18 +2148,18 @@ if $PROGRAM_NAME == __FILE__
|
|
2261
2148
|
@hd.stubs(:history_state_pop)
|
2262
2149
|
end
|
2263
2150
|
|
2264
|
-
def
|
2151
|
+
def test_pop_link_history_and_trigger_load
|
2265
2152
|
# Verifying that history_state_pop is called
|
2266
|
-
@hd.expects(:history_state_pop).once
|
2153
|
+
# @hd.expects(:history_state_pop).once
|
2267
2154
|
|
2268
|
-
result = @hd.
|
2155
|
+
result = @hd.pop_link_history_and_trigger_load
|
2269
2156
|
|
2270
|
-
# Asserting the result is an instance of
|
2271
|
-
assert_instance_of
|
2157
|
+
# Asserting the result is an instance of LoadFileLinkState
|
2158
|
+
assert_instance_of LoadFileLinkState, result
|
2272
2159
|
assert_equal LoadFile::Load, result.load_file
|
2273
|
-
|
2160
|
+
assert_nil result.link_state.block_name
|
2274
2161
|
end
|
2275
|
-
end
|
2162
|
+
end
|
2276
2163
|
|
2277
2164
|
class TestHashDelegatorHandleBlockState < Minitest::Test
|
2278
2165
|
def setup
|
@@ -2311,7 +2198,7 @@ if $PROGRAM_NAME == __FILE__
|
|
2311
2198
|
assert_nil @hd.instance_variable_get(:@delegate_object)[:block_name]
|
2312
2199
|
assert_nil @hd.instance_variable_get(:@menu_user_clicked_back_link)
|
2313
2200
|
end
|
2314
|
-
end
|
2201
|
+
end
|
2315
2202
|
|
2316
2203
|
class TestHashDelegatorHandleGenericBlock < Minitest::Test
|
2317
2204
|
def setup
|
@@ -2320,7 +2207,7 @@ if $PROGRAM_NAME == __FILE__
|
|
2320
2207
|
@selected_item = mock('FCB')
|
2321
2208
|
end
|
2322
2209
|
|
2323
|
-
def
|
2210
|
+
def test_compile_execute_bash_and_special_blocks_and_trigger_reuse_without_user_approval
|
2324
2211
|
# Mock the delegate object configuration
|
2325
2212
|
@hd.instance_variable_set(:@delegate_object,
|
2326
2213
|
{ output_script: false,
|
@@ -2330,7 +2217,7 @@ if $PROGRAM_NAME == __FILE__
|
|
2330
2217
|
# Expectations and assertions go here
|
2331
2218
|
end
|
2332
2219
|
|
2333
|
-
def
|
2220
|
+
def test_compile_execute_bash_and_special_blocks_and_trigger_reuse_with_user_approval
|
2334
2221
|
# Mock the delegate object configuration
|
2335
2222
|
@hd.instance_variable_set(:@delegate_object,
|
2336
2223
|
{ output_script: false,
|
@@ -2340,7 +2227,7 @@ if $PROGRAM_NAME == __FILE__
|
|
2340
2227
|
# Expectations and assertions go here
|
2341
2228
|
end
|
2342
2229
|
|
2343
|
-
def
|
2230
|
+
def test_compile_execute_bash_and_special_blocks_and_trigger_reuse_with_output_script
|
2344
2231
|
# Mock the delegate object configuration
|
2345
2232
|
@hd.instance_variable_set(:@delegate_object,
|
2346
2233
|
{ output_script: true,
|
@@ -2361,25 +2248,25 @@ if $PROGRAM_NAME == __FILE__
|
|
2361
2248
|
@hd.stubs(:print)
|
2362
2249
|
end
|
2363
2250
|
|
2364
|
-
def
|
2251
|
+
def test_update_options_and_trigger_reuse
|
2365
2252
|
selected = { body: ['option1: value1'] }
|
2366
2253
|
tgt2 = {}
|
2367
2254
|
|
2368
|
-
result = @hd.
|
2255
|
+
result = @hd.update_options_and_trigger_reuse(selected, tgt2)
|
2369
2256
|
|
2370
|
-
assert_instance_of
|
2257
|
+
assert_instance_of LoadFileLinkState, result
|
2371
2258
|
assert_equal 'value1',
|
2372
2259
|
@hd.instance_variable_get(:@delegate_object)[:option1]
|
2373
2260
|
assert_equal 'value1', tgt2[:option1]
|
2374
2261
|
end
|
2375
2262
|
|
2376
|
-
def
|
2263
|
+
def test_update_options_and_trigger_reuse_without_format
|
2377
2264
|
selected = { body: ['option2: value2'] }
|
2378
2265
|
@hd.instance_variable_set(:@delegate_object, {})
|
2379
2266
|
|
2380
|
-
result = @hd.
|
2267
|
+
result = @hd.update_options_and_trigger_reuse(selected)
|
2381
2268
|
|
2382
|
-
assert_instance_of
|
2269
|
+
assert_instance_of LoadFileLinkState, result
|
2383
2270
|
assert_equal 'value2',
|
2384
2271
|
@hd.instance_variable_get(:@delegate_object)[:option2]
|
2385
2272
|
end
|
@@ -2422,94 +2309,6 @@ if $PROGRAM_NAME == __FILE__
|
|
2422
2309
|
end
|
2423
2310
|
end
|
2424
2311
|
|
2425
|
-
class TestHashDelegatorHistoryStatePartition < Minitest::Test
|
2426
|
-
def setup
|
2427
|
-
@hd = HashDelegator.new
|
2428
|
-
@hd.instance_variable_set(:@delegate_object, {
|
2429
|
-
history_document_separator: '|'
|
2430
|
-
})
|
2431
|
-
end
|
2432
|
-
|
2433
|
-
def test_history_state_partition_with_value
|
2434
|
-
ENV[MDE_HISTORY_ENV_NAME] = 'part1|part2'
|
2435
|
-
|
2436
|
-
result = @hd.history_state_partition
|
2437
|
-
assert_equal({ unit: 'part1', rest: 'part2' }, result)
|
2438
|
-
end
|
2439
|
-
|
2440
|
-
def test_history_state_partition_with_no_separator
|
2441
|
-
ENV[MDE_HISTORY_ENV_NAME] = 'onlypart'
|
2442
|
-
|
2443
|
-
result = @hd.history_state_partition
|
2444
|
-
assert_equal({ unit: 'onlypart', rest: '' }, result)
|
2445
|
-
end
|
2446
|
-
|
2447
|
-
def test_history_state_partition_with_empty_env
|
2448
|
-
ENV[MDE_HISTORY_ENV_NAME] = ''
|
2449
|
-
|
2450
|
-
result = @hd.history_state_partition
|
2451
|
-
assert_equal({ unit: '', rest: '' }, result)
|
2452
|
-
end
|
2453
|
-
end
|
2454
|
-
|
2455
|
-
class TestHashDelegatorHistoryStatePop < Minitest::Test
|
2456
|
-
def setup
|
2457
|
-
@hd = HashDelegator.new
|
2458
|
-
@hd.instance_variable_set(:@delegate_object,
|
2459
|
-
{ filename: 'initial.md' })
|
2460
|
-
@hd.instance_variable_set(:@run_state,
|
2461
|
-
OpenStruct.new(link_history: [{ block_name: 'block1',
|
2462
|
-
filename: 'file1.md' }]))
|
2463
|
-
@hd.stubs(:history_state_partition).returns({ unit: 'file2.md',
|
2464
|
-
rest: 'history_data' })
|
2465
|
-
@hd.stubs(:delete_required_temp_file)
|
2466
|
-
end
|
2467
|
-
|
2468
|
-
def test_history_state_pop
|
2469
|
-
ENV[MDE_HISTORY_ENV_NAME] = 'some_history'
|
2470
|
-
|
2471
|
-
@hd.history_state_pop
|
2472
|
-
|
2473
|
-
assert_equal 'file2.md',
|
2474
|
-
@hd.instance_variable_get(:@delegate_object)[:filename]
|
2475
|
-
assert_equal 'history_data',
|
2476
|
-
ENV.fetch(MDE_HISTORY_ENV_NAME, nil)
|
2477
|
-
assert_empty @hd.instance_variable_get(:@run_state).link_history
|
2478
|
-
end
|
2479
|
-
end
|
2480
|
-
|
2481
|
-
class TestHashDelegatorHistoryStatePush < Minitest::Test
|
2482
|
-
def setup
|
2483
|
-
@hd = HashDelegator.new
|
2484
|
-
@hd.instance_variable_set(:@delegate_object, {
|
2485
|
-
filename: 'test.md',
|
2486
|
-
block_name: 'test_block',
|
2487
|
-
history_document_separator: '||'
|
2488
|
-
})
|
2489
|
-
@hd.instance_variable_set(:@run_state,
|
2490
|
-
OpenStruct.new(link_history: []))
|
2491
|
-
@hd.stubs(:write_required_blocks_to_temp_file)
|
2492
|
-
end
|
2493
|
-
|
2494
|
-
def test_history_state_push
|
2495
|
-
mdoc = 'markdown content'
|
2496
|
-
data_file = 'data.md'
|
2497
|
-
selected = { oname: 'selected_block' }
|
2498
|
-
|
2499
|
-
ENV[MDE_HISTORY_ENV_NAME] = 'existing_history'
|
2500
|
-
|
2501
|
-
@hd.history_state_push(mdoc, data_file, selected)
|
2502
|
-
|
2503
|
-
assert_equal 'data.md',
|
2504
|
-
@hd.instance_variable_get(:@delegate_object)[:filename]
|
2505
|
-
assert_equal 'test.md||existing_history',
|
2506
|
-
ENV.fetch(MDE_HISTORY_ENV_NAME, nil)
|
2507
|
-
assert_includes @hd.instance_variable_get(:@run_state).link_history,
|
2508
|
-
{ block_name: 'selected_block',
|
2509
|
-
filename: 'data.md' }
|
2510
|
-
end
|
2511
|
-
end
|
2512
|
-
|
2513
2312
|
class TestHashDelegatorIterBlocksFromNestedFiles < Minitest::Test
|
2514
2313
|
def setup
|
2515
2314
|
@hd = HashDelegator.new
|
@@ -2544,7 +2343,7 @@ if $PROGRAM_NAME == __FILE__
|
|
2544
2343
|
def setup
|
2545
2344
|
@hd = HashDelegator.new
|
2546
2345
|
@hd.stubs(:block_find).returns({})
|
2547
|
-
@hd.stubs(:
|
2346
|
+
@hd.stubs(:update_options_and_trigger_reuse)
|
2548
2347
|
end
|
2549
2348
|
|
2550
2349
|
def test_load_auto_blocks_with_new_filename
|
@@ -2681,7 +2480,7 @@ if $PROGRAM_NAME == __FILE__
|
|
2681
2480
|
result = @hd.yield_line_if_selected('Test line', [:line])
|
2682
2481
|
assert_nil result
|
2683
2482
|
end
|
2684
|
-
end
|
2483
|
+
end
|
2685
2484
|
|
2686
2485
|
class TestHashDelegator < Minitest::Test
|
2687
2486
|
def setup
|