markdown_exec 2.5.0 → 2.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +15 -0
- data/Gemfile.lock +2 -2
- data/Rakefile +3 -3
- data/bats/block-types.bats +13 -7
- data/bats/import.bats +6 -0
- data/bats/markup.bats +6 -15
- data/bats/options-collapse.bats +26 -0
- data/bats/options.bats +1 -1
- data/bats/table.bats +8 -0
- data/bats/test_helper.bash +74 -49
- data/bats/variable-expansion.bats +46 -0
- data/bin/tab_completion.sh +1 -1
- data/docs/dev/bats-document-configuration.md +8 -1
- data/docs/dev/block-type-bash.md +1 -1
- data/docs/dev/block-type-opts.md +1 -5
- data/docs/dev/block-type-vars.md +4 -0
- data/docs/dev/import-missing.md +2 -0
- data/docs/dev/menu-cli.md +1 -1
- data/docs/dev/options-collapse.md +47 -0
- data/docs/dev/requiring-blocks.md +3 -0
- data/docs/dev/specs.md +2 -1
- data/docs/dev/table-crash.md +39 -0
- data/docs/dev/table-indent.md +26 -0
- data/docs/dev/text-decoration.md +2 -5
- data/docs/dev/variable-expansion.md +2 -4
- data/examples/bash-blocks.md +1 -1
- data/examples/block-names.md +1 -1
- data/examples/block-types.md +1 -1
- data/examples/data-files.md +1 -1
- data/examples/document_options.md +2 -2
- data/examples/indent.md +1 -1
- data/examples/interrupt.md +1 -1
- data/examples/link-blocks-vars.md +1 -1
- data/examples/linked.md +1 -1
- data/examples/linked1.md +1 -1
- data/examples/nickname.md +1 -1
- data/examples/opts-blocks-require.md +1 -1
- data/examples/opts-blocks.md +1 -1
- data/examples/opts_output_execution.md +1 -1
- data/examples/pass-through-arguments.md +1 -1
- data/examples/pause-after-execution.md +1 -1
- data/examples/port-blocks.md +1 -1
- data/examples/save.md +1 -1
- data/examples/text-markup.md +1 -1
- data/examples/variable-expansion.md +6 -2
- data/examples/vars-blocks.md +1 -1
- data/examples/wrap.md +1 -1
- data/lib/block_types.rb +4 -0
- data/lib/cached_nested_file_reader.rb +7 -4
- data/lib/collapser.rb +302 -0
- data/lib/constants.rb +10 -0
- data/lib/evaluate_shell_expressions.rb +0 -3
- data/lib/fcb.rb +13 -17
- data/lib/format_table.rb +11 -7
- data/lib/hash_delegator.rb +461 -272
- data/lib/hierarchy_string.rb +5 -1
- data/lib/markdown_exec/version.rb +1 -1
- data/lib/markdown_exec.rb +16 -32
- data/lib/mdoc.rb +100 -35
- data/lib/menu.src.yml +124 -17
- data/lib/menu.yml +102 -16
- data/lib/ww.rb +75 -22
- metadata +12 -9
- data/lib/append_to_bash_history.rb +0 -303
- data/lib/ce_get_cost_and_usage.rb +0 -23
- data/lib/doh.rb +0 -190
- data/lib/layered_hash.rb +0 -143
- data/lib/poly.rb +0 -171
data/lib/hash_delegator.rb
CHANGED
@@ -20,7 +20,6 @@ require 'yaml'
|
|
20
20
|
require_relative 'ansi_string'
|
21
21
|
require_relative 'array'
|
22
22
|
require_relative 'array_util'
|
23
|
-
# require_relative 'block_label'
|
24
23
|
require_relative 'block_types'
|
25
24
|
require_relative 'cached_nested_file_reader'
|
26
25
|
require_relative 'constants'
|
@@ -165,6 +164,7 @@ module HashDelegatorSelf
|
|
165
164
|
|
166
165
|
def initialize_fcb_names(fcb)
|
167
166
|
fcb.oname = fcb.dname = fcb.title || ''
|
167
|
+
fcb.s2title = fcb.oname
|
168
168
|
end
|
169
169
|
|
170
170
|
def join_code_lines(lines)
|
@@ -267,6 +267,7 @@ module HashDelegatorSelf
|
|
267
267
|
def tables_into_columns!(blocks_menu, delegate_object)
|
268
268
|
return unless delegate_object[:tables_into_columns]
|
269
269
|
|
270
|
+
screenwidth = delegate_object[:console_width]
|
270
271
|
lines = blocks_menu.map(&:oname)
|
271
272
|
text_tables = TableExtractor.extract_tables(
|
272
273
|
lines,
|
@@ -279,7 +280,7 @@ module HashDelegatorSelf
|
|
279
280
|
|
280
281
|
range = table[:start_index]..(table[:start_index] + table[:rows] - 1)
|
281
282
|
lines = blocks_menu[range].map(&:dname)
|
282
|
-
|
283
|
+
table__hs = MarkdownTableFormatter.format_table__hs(
|
283
284
|
column_count: table[:columns],
|
284
285
|
decorate: {
|
285
286
|
border: delegate_object[:table_border_color],
|
@@ -290,8 +291,7 @@ module HashDelegatorSelf
|
|
290
291
|
lines: lines
|
291
292
|
)
|
292
293
|
|
293
|
-
unless
|
294
|
-
# warn [__LINE__, range, lines, formatted].inspect
|
294
|
+
unless table__hs.count == range.size
|
295
295
|
raise 'Invalid result from MarkdownTableFormatter.format_table()'
|
296
296
|
end
|
297
297
|
|
@@ -300,11 +300,28 @@ module HashDelegatorSelf
|
|
300
300
|
|
301
301
|
# replace text in each block
|
302
302
|
range.each.with_index do |block_ind, ind|
|
303
|
-
|
304
|
-
|
303
|
+
fcb = blocks_menu[block_ind]
|
304
|
+
fcb.s3formatted_table_row = fcb.padded = table__hs[ind] ####
|
305
|
+
fcb.padded_width = table__hs[ind].padded_width
|
306
|
+
if fcb.center
|
307
|
+
cw = (screenwidth - table__hs[ind].padded_width) / 2
|
308
|
+
if cw.positive?
|
309
|
+
indent = ' ' * cw
|
310
|
+
fcb.s3indent = fcb.indent = indent
|
311
|
+
end
|
312
|
+
else
|
313
|
+
fcb.s3indent = fcb.indent
|
314
|
+
end
|
315
|
+
fcb.s3indent ||= ''
|
316
|
+
fcb.dname = fcb.indented_decorated = fcb.s3indent + fcb.s3formatted_table_row.decorate
|
305
317
|
end
|
306
318
|
end
|
307
319
|
end
|
320
|
+
# s0indent: indent,
|
321
|
+
# s0printable: line_obj[:text],
|
322
|
+
# s1decorated: decorated,
|
323
|
+
# s2title = fcb.oname
|
324
|
+
# s3formatted_table_row = fcb.padded = table__hs[ind]####
|
308
325
|
|
309
326
|
# Creates a TTY prompt with custom settings. Specifically,
|
310
327
|
# it disables the default 'cross' symbol and
|
@@ -345,10 +362,10 @@ module HashDelegatorSelf
|
|
345
362
|
# @param [String] line The line to be processed.
|
346
363
|
# @param [Array<Symbol>] selected_types A list of message types to check.
|
347
364
|
# @param [Proc] block The block to be called with the line data.
|
348
|
-
def yield_line_if_selected(line, selected_types, &block)
|
365
|
+
def yield_line_if_selected(line, selected_types, id: '', &block)
|
349
366
|
return unless block && block_type_selected?(selected_types, :line)
|
350
367
|
|
351
|
-
block.call(:line, MarkdownExec::FCB.new(body: [line]))
|
368
|
+
block.call(:line, MarkdownExec::FCB.new(body: [line], id: id))
|
352
369
|
end
|
353
370
|
end
|
354
371
|
|
@@ -532,7 +549,7 @@ module MarkdownExec
|
|
532
549
|
end
|
533
550
|
|
534
551
|
class HashDelegatorParent
|
535
|
-
attr_accessor :
|
552
|
+
attr_accessor :pass_args, :run_state,
|
536
553
|
:p_all_arguments, :p_options_parsed, :p_params, :p_rest
|
537
554
|
|
538
555
|
extend HashDelegatorSelf
|
@@ -543,7 +560,8 @@ module MarkdownExec
|
|
543
560
|
@delegate_object = delegate_object
|
544
561
|
@prompt = HashDelegator.tty_prompt_without_disabled_symbol
|
545
562
|
|
546
|
-
@
|
563
|
+
@opts_most_recent_filename = nil
|
564
|
+
@vars_most_recent_filename = nil
|
547
565
|
@pass_args = []
|
548
566
|
@run_state = OpenStruct.new(
|
549
567
|
link_history: [],
|
@@ -559,17 +577,9 @@ module MarkdownExec
|
|
559
577
|
@p_options_parsed = []
|
560
578
|
@p_params = {}
|
561
579
|
@p_rest = []
|
562
|
-
end
|
563
580
|
|
564
|
-
|
565
|
-
|
566
|
-
# def [](key)
|
567
|
-
# @delegate_object[key]
|
568
|
-
# end
|
569
|
-
|
570
|
-
# def []=(key, value)
|
571
|
-
# @delegate_object[key] = value
|
572
|
-
# end
|
581
|
+
@compressed_ids = nil
|
582
|
+
end
|
573
583
|
|
574
584
|
##
|
575
585
|
# Returns the absolute path of the given file path.
|
@@ -591,11 +601,25 @@ module MarkdownExec
|
|
591
601
|
end
|
592
602
|
end
|
593
603
|
|
604
|
+
def add_back_option(id: '', menu_blocks:)
|
605
|
+
append_chrome_block(id: id, menu_blocks: menu_blocks,
|
606
|
+
menu_state: MenuState::BACK)
|
607
|
+
end
|
608
|
+
|
609
|
+
def add_exit_option(id: '', menu_blocks:)
|
610
|
+
append_chrome_block(id: id, menu_blocks: menu_blocks,
|
611
|
+
menu_state: MenuState::EXIT)
|
612
|
+
end
|
613
|
+
|
614
|
+
def add_inherited_lines(menu_blocks:, link_state:)
|
615
|
+
append_inherited_lines(menu_blocks: menu_blocks, link_state: link_state)
|
616
|
+
end
|
617
|
+
|
594
618
|
# Modifies the provided menu blocks array by adding 'Back' and 'Exit' options,
|
595
619
|
# along with initial and final dividers, based on the delegate object's configuration.
|
596
620
|
#
|
597
621
|
# @param menu_blocks [Array] The array of menu block elements to be modified.
|
598
|
-
def add_menu_chrome_blocks!(menu_blocks:, link_state:)
|
622
|
+
def add_menu_chrome_blocks!(id: '', menu_blocks:, link_state:)
|
599
623
|
return unless @delegate_object[:menu_link_format].present?
|
600
624
|
|
601
625
|
if @delegate_object[:menu_with_inherited_lines]
|
@@ -604,89 +628,18 @@ module MarkdownExec
|
|
604
628
|
end
|
605
629
|
|
606
630
|
# back before exit
|
607
|
-
add_back_option(
|
631
|
+
add_back_option(id: "#{id}.back",
|
632
|
+
menu_blocks: menu_blocks) if should_add_back_option?
|
608
633
|
|
609
634
|
# exit after other options
|
610
635
|
if @delegate_object[:menu_with_exit]
|
611
|
-
add_exit_option(menu_blocks: menu_blocks)
|
636
|
+
add_exit_option(id: "#{id}.exit", menu_blocks: menu_blocks)
|
612
637
|
end
|
613
638
|
|
614
|
-
append_divider(
|
615
|
-
|
616
|
-
|
617
|
-
|
618
|
-
def variable_expansions!(
|
619
|
-
echo_command_form: 'echo "$%s"',
|
620
|
-
link_state:,
|
621
|
-
menu_blocks:,
|
622
|
-
regexp: Regexp.new(@delegate_object[:variable_expression_regexp])
|
623
|
-
)
|
624
|
-
# !!v link_state.inherited_lines_block
|
625
|
-
# collect variables in menu_blocks
|
626
|
-
#
|
627
|
-
variables_count = Hash.new(0)
|
628
|
-
menu_blocks.each do |fcb|
|
629
|
-
next if fcb.type == BlockType::SHELL
|
630
|
-
|
631
|
-
fcb.oname.scan(regexp) do |(expression, variable)|
|
632
|
-
expression.match(regexp)
|
633
|
-
variables_count[$LAST_MATCH_INFO[:variable]] += 1
|
634
|
-
end
|
635
|
-
end
|
636
|
-
# !!v variables_count
|
637
|
-
|
638
|
-
# commands to echo variables
|
639
|
-
#
|
640
|
-
commands = {}
|
641
|
-
variables_count.each do |variable, count|
|
642
|
-
command = format(echo_command_form, variable)
|
643
|
-
commands[variable] = command
|
644
|
-
end
|
645
|
-
# !!v commands
|
646
|
-
|
647
|
-
# replacement dictionary from evaluated commands
|
648
|
-
#
|
649
|
-
replacement_dictionary = evaluate_shell_expressions(
|
650
|
-
link_state.inherited_lines_block, commands,
|
651
|
-
key_format: "${%s}" # no need to escape variable name for regexp
|
652
|
-
) # !!t
|
653
|
-
return if replacement_dictionary.nil?
|
654
|
-
|
655
|
-
# update blocks
|
656
|
-
#
|
657
|
-
Regexp.union(replacement_dictionary.keys).tap do |pattern|
|
658
|
-
menu_blocks.each do |fcb|
|
659
|
-
next if fcb.type == BlockType::SHELL
|
660
|
-
|
661
|
-
fcb.variable_expansion!(pattern, replacement_dictionary)
|
662
|
-
end
|
663
|
-
end
|
664
|
-
end
|
665
|
-
|
666
|
-
private
|
667
|
-
|
668
|
-
def replace_keys_in_lines(replacement_dictionary, lines)
|
669
|
-
# Create a regex pattern that matches any key in the replacement dictionary
|
670
|
-
pattern = Regexp.union(replacement_dictionary.keys.map { |key|
|
671
|
-
"%<#{key}>"
|
672
|
-
})
|
673
|
-
|
674
|
-
# Iterate over each line and apply gsub with the replacement hash
|
675
|
-
lines.map do |line|
|
676
|
-
line.gsub(pattern) { |match| replacement_dictionary[match] }
|
677
|
-
end
|
678
|
-
end
|
679
|
-
|
680
|
-
def add_back_option(menu_blocks:)
|
681
|
-
append_chrome_block(menu_blocks: menu_blocks, menu_state: MenuState::BACK)
|
682
|
-
end
|
683
|
-
|
684
|
-
def add_exit_option(menu_blocks:)
|
685
|
-
append_chrome_block(menu_blocks: menu_blocks, menu_state: MenuState::EXIT)
|
686
|
-
end
|
687
|
-
|
688
|
-
def add_inherited_lines(menu_blocks:, link_state:)
|
689
|
-
append_inherited_lines(menu_blocks: menu_blocks, link_state: link_state)
|
639
|
+
append_divider(id: "#{id}.init", menu_blocks: menu_blocks,
|
640
|
+
position: :initial)
|
641
|
+
append_divider(id: "#{id}.final", menu_blocks: menu_blocks,
|
642
|
+
position: :final)
|
690
643
|
end
|
691
644
|
|
692
645
|
public
|
@@ -695,7 +648,7 @@ module MarkdownExec
|
|
695
648
|
#
|
696
649
|
# @param all_blocks [Array] The current blocks in the menu
|
697
650
|
# @param type [Symbol] The type of chrome block to add (:back or :exit)
|
698
|
-
def append_chrome_block(menu_blocks:, menu_state:)
|
651
|
+
def append_chrome_block(menu_blocks:, menu_state:, id: '')
|
699
652
|
case menu_state
|
700
653
|
when MenuState::BACK
|
701
654
|
history_state_partition
|
@@ -733,6 +686,8 @@ module MarkdownExec
|
|
733
686
|
dname: HashDelegator.new(@delegate_object).string_send_color(
|
734
687
|
formatted_name, :menu_chrome_color
|
735
688
|
),
|
689
|
+
id: id,
|
690
|
+
type: BlockType::CHROME,
|
736
691
|
nickname: formatted_name,
|
737
692
|
oname: formatted_name
|
738
693
|
)
|
@@ -751,10 +706,10 @@ module MarkdownExec
|
|
751
706
|
#
|
752
707
|
# @param menu_blocks [Array] The array of menu block elements.
|
753
708
|
# @param position [Symbol] The position to insert the divider (:initial or :final).
|
754
|
-
def append_divider(menu_blocks:, position:)
|
709
|
+
def append_divider(id: '', menu_blocks:, position:)
|
755
710
|
return unless divider_formatting_present?(position)
|
756
711
|
|
757
|
-
divider = create_divider(position)
|
712
|
+
divider = create_divider(position, id: id)
|
758
713
|
position == :initial ? menu_blocks.unshift(divider) : menu_blocks.push(divider)
|
759
714
|
end
|
760
715
|
|
@@ -772,7 +727,7 @@ module MarkdownExec
|
|
772
727
|
{ line: line })
|
773
728
|
FCB.new(
|
774
729
|
chrome: true,
|
775
|
-
disabled:
|
730
|
+
disabled: TtyMenu::DISABLE,
|
776
731
|
dname: HashDelegator.new(@delegate_object).string_send_color(
|
777
732
|
formatted, :menu_inherited_lines_color
|
778
733
|
),
|
@@ -840,8 +795,10 @@ module MarkdownExec
|
|
840
795
|
register_console_attributes(@delegate_object)
|
841
796
|
@decor_patterns_from_delegate_object_for_block_create = collect_line_decor_patterns(@delegate_object)
|
842
797
|
|
798
|
+
count = 0
|
843
799
|
blocks = []
|
844
800
|
iter_blocks_from_nested_files do |btype, fcb|
|
801
|
+
count += 1
|
845
802
|
case btype
|
846
803
|
when :blocks
|
847
804
|
if @delegate_object[:bash]
|
@@ -849,6 +806,7 @@ module MarkdownExec
|
|
849
806
|
block_calls_scan: @delegate_object[:block_calls_scan],
|
850
807
|
block_name_match: @delegate_object[:block_name_match],
|
851
808
|
block_name_nick_match: @delegate_object[:block_name_nick_match],
|
809
|
+
id: "*#{count}",
|
852
810
|
) do |oname, color|
|
853
811
|
apply_block_type_color_option(oname, color)
|
854
812
|
end
|
@@ -858,7 +816,8 @@ module MarkdownExec
|
|
858
816
|
%i[blocks line]
|
859
817
|
when :line
|
860
818
|
unless @delegate_object[:no_chrome]
|
861
|
-
create_and_add_chrome_blocks(blocks, fcb
|
819
|
+
create_and_add_chrome_blocks(blocks, fcb, id: "*#{count}",
|
820
|
+
init_ids: init_ids)
|
862
821
|
end
|
863
822
|
end
|
864
823
|
end
|
@@ -894,6 +853,13 @@ module MarkdownExec
|
|
894
853
|
|
895
854
|
# private
|
896
855
|
|
856
|
+
def build_replacement_dictionary(commands, link_state)
|
857
|
+
evaluate_shell_expressions(
|
858
|
+
link_state.inherited_lines_block, commands,
|
859
|
+
key_format: "${%s}" # no need to escape variable name for regexp
|
860
|
+
) # !!t
|
861
|
+
end
|
862
|
+
|
897
863
|
def calc_logged_stdout_filename(block_name:)
|
898
864
|
return unless @delegate_object[:saved_stdout_folder]
|
899
865
|
|
@@ -937,13 +903,39 @@ module MarkdownExec
|
|
937
903
|
true
|
938
904
|
end
|
939
905
|
|
906
|
+
def chrome_block_criteria
|
907
|
+
[
|
908
|
+
{ center: :table_center, format: :menu_note_format,
|
909
|
+
match: :menu_table_rows_match, type: BlockType::TEXT },
|
910
|
+
{ case_conversion: :upcase, center: :heading1_center,
|
911
|
+
collapse: :heading1_collapse, collapsible: :heading1_collapsible,
|
912
|
+
color: :menu_heading1_color, format: :menu_heading1_format, level: 1,
|
913
|
+
match: :heading1_match, type: BlockType::HEADING, wrap: true },
|
914
|
+
{ center: :heading2_center,
|
915
|
+
collapse: :heading2_collapse, collapsible: :heading2_collapsible,
|
916
|
+
color: :menu_heading2_color, format: :menu_heading2_format, level: 2,
|
917
|
+
match: :heading2_match, type: BlockType::HEADING, wrap: true },
|
918
|
+
{ case_conversion: :downcase, center: :heading3_center,
|
919
|
+
collapse: :heading3_collapse, collapsible: :heading3_collapsible,
|
920
|
+
color: :menu_heading3_color, format: :menu_heading3_format, level: 3,
|
921
|
+
match: :heading3_match, type: BlockType::HEADING, wrap: true },
|
922
|
+
{ center: :divider4_center,
|
923
|
+
collapse: :divider4_collapse, collapsible: :divider4_collapsible,
|
924
|
+
color: :menu_divider_color, format: :menu_divider_format, level: 4,
|
925
|
+
match: :divider_match, type: BlockType::DIVIDER },
|
926
|
+
{ color: :menu_note_color, format: :menu_note_format,
|
927
|
+
match: :menu_note_match, type: BlockType::TEXT, wrap: true },
|
928
|
+
{ color: :menu_task_color, format: :menu_task_format,
|
929
|
+
match: :menu_task_match, type: BlockType::TEXT, wrap: true }
|
930
|
+
]
|
931
|
+
end
|
932
|
+
|
933
|
+
# sets ENV
|
940
934
|
def code_from_vars_block_to_set_environment_variables(selected)
|
941
935
|
code_lines = []
|
942
936
|
YAML.load(selected.body.join("\n"))&.each do |key, value|
|
943
937
|
ENV[key] = value.to_s
|
944
|
-
|
945
|
-
require 'shellwords'
|
946
|
-
code_lines.push "#{key}=\"#{Shellwords.escape(value)}\""
|
938
|
+
code_lines.push "#{key}=#{Shellwords.escape(value)}"
|
947
939
|
|
948
940
|
next unless @delegate_object[:menu_vars_set_format].present?
|
949
941
|
|
@@ -971,7 +963,11 @@ module MarkdownExec
|
|
971
963
|
end
|
972
964
|
end
|
973
965
|
|
974
|
-
def command_execute(
|
966
|
+
def command_execute(
|
967
|
+
command,
|
968
|
+
erls:,
|
969
|
+
shell:, args: []
|
970
|
+
)
|
975
971
|
@run_state.files = StreamsOut.new
|
976
972
|
@run_state.options = @delegate_object
|
977
973
|
@run_state.started_at = Time.now.utc
|
@@ -983,6 +979,7 @@ module MarkdownExec
|
|
983
979
|
@run_state.in_own_window = true
|
984
980
|
command_execute_in_own_window(
|
985
981
|
args: args,
|
982
|
+
erls: erls,
|
986
983
|
script: @delegate_object[:execute_command_format]
|
987
984
|
)
|
988
985
|
|
@@ -990,6 +987,7 @@ module MarkdownExec
|
|
990
987
|
@run_state.in_own_window = false
|
991
988
|
command_execute_in_process(
|
992
989
|
args: args, command: command,
|
990
|
+
erls: erls,
|
993
991
|
filename: @delegate_object[:filename], shell: shell
|
994
992
|
)
|
995
993
|
end
|
@@ -1007,18 +1005,27 @@ module MarkdownExec
|
|
1007
1005
|
@fout.fout "Error ENOENT: #{err.inspect}"
|
1008
1006
|
end
|
1009
1007
|
|
1010
|
-
def command_execute_in_own_window(
|
1008
|
+
def command_execute_in_own_window(
|
1009
|
+
args:,
|
1010
|
+
erls:,
|
1011
|
+
script:
|
1012
|
+
)
|
1011
1013
|
system(
|
1012
1014
|
format(
|
1013
1015
|
script,
|
1014
1016
|
command_execute_in_own_window_format_arguments(
|
1017
|
+
erls: erls,
|
1015
1018
|
rest: args ? args.join(' ') : ''
|
1016
1019
|
)
|
1017
1020
|
)
|
1018
1021
|
)
|
1019
1022
|
end
|
1020
1023
|
|
1021
|
-
def command_execute_in_own_window_format_arguments(
|
1024
|
+
def command_execute_in_own_window_format_arguments(
|
1025
|
+
home: Dir.pwd,
|
1026
|
+
erls:,
|
1027
|
+
rest: ''
|
1028
|
+
)
|
1022
1029
|
{
|
1023
1030
|
batch_index: @run_state.batch_index,
|
1024
1031
|
batch_random: @run_state.batch_random,
|
@@ -1030,6 +1037,7 @@ module MarkdownExec
|
|
1030
1037
|
@delegate_object[:logged_stdout_filespec]
|
1031
1038
|
),
|
1032
1039
|
output_filespec: @delegate_object[:logged_stdout_filespec],
|
1040
|
+
play_command: erls[:play_bin],
|
1033
1041
|
rest: rest,
|
1034
1042
|
script_filename: @run_state.saved_filespec,
|
1035
1043
|
script_filespec: File.join(home, @run_state.saved_filespec),
|
@@ -1039,7 +1047,11 @@ module MarkdownExec
|
|
1039
1047
|
}
|
1040
1048
|
end
|
1041
1049
|
|
1042
|
-
def command_execute_in_process(
|
1050
|
+
def command_execute_in_process(
|
1051
|
+
args:, command:,
|
1052
|
+
erls:,
|
1053
|
+
filename:, shell:
|
1054
|
+
)
|
1043
1055
|
execute_command_with_streams(
|
1044
1056
|
[shell, '-c', command,
|
1045
1057
|
@delegate_object[:filename], *args]
|
@@ -1061,6 +1073,19 @@ module MarkdownExec
|
|
1061
1073
|
def compile_execute_and_trigger_reuse(
|
1062
1074
|
mdoc:, selected:, block_source:, link_state:
|
1063
1075
|
)
|
1076
|
+
# play_bin matches the name in mde.applescript, called by .mde.macos.yml
|
1077
|
+
bim = @delegate_object[:block_interactive_match]
|
1078
|
+
play_bin = if bim.present? && selected.start_line =~ Regexp.new(bim)
|
1079
|
+
@delegate_object[:play_bin_interactive]
|
1080
|
+
else
|
1081
|
+
bbm = @delegate_object[:block_batch_match]
|
1082
|
+
if bbm.present? && selected.start_line =~ Regexp.new(bbm)
|
1083
|
+
@delegate_object[:play_bin_batch]
|
1084
|
+
else
|
1085
|
+
@delegate_object[:document_play_bin]
|
1086
|
+
end
|
1087
|
+
end
|
1088
|
+
|
1064
1089
|
required_lines = execute_block_type_port_code_lines(
|
1065
1090
|
mdoc: mdoc, selected: selected,
|
1066
1091
|
link_state: link_state, block_source: block_source
|
@@ -1080,8 +1105,10 @@ module MarkdownExec
|
|
1080
1105
|
end
|
1081
1106
|
|
1082
1107
|
if allow_execution
|
1083
|
-
execute_required_lines(
|
1084
|
-
|
1108
|
+
execute_required_lines(blockname: selected.pub_name,
|
1109
|
+
erls: { play_bin: play_bin,
|
1110
|
+
shell: selected.shell },
|
1111
|
+
required_lines: required_lines,
|
1085
1112
|
shell: selected.shell)
|
1086
1113
|
end
|
1087
1114
|
|
@@ -1117,6 +1144,26 @@ module MarkdownExec
|
|
1117
1144
|
HashDelegator.count_matches_in_lines(lines, regex) / 2
|
1118
1145
|
end
|
1119
1146
|
|
1147
|
+
def count_named_group_occurrences(
|
1148
|
+
blocks, pattern, exclude_types: [BlockType::SHELL]
|
1149
|
+
)
|
1150
|
+
# Initialize a counter for named group occurrences
|
1151
|
+
occurrence_count = Hash.new(0)
|
1152
|
+
|
1153
|
+
blocks.each do |block|
|
1154
|
+
# Skip processing for shell-type blocks
|
1155
|
+
next if exclude_types.include?(block.type)
|
1156
|
+
|
1157
|
+
# Scan each block name for matches of the pattern
|
1158
|
+
block.oname.scan(pattern) do |(_, variable_name)|
|
1159
|
+
pattern.match($LAST_MATCH_INFO.to_s) # Reapply match for named groups
|
1160
|
+
occurrence_count[$LAST_MATCH_INFO[:variable]] += 1
|
1161
|
+
end
|
1162
|
+
end
|
1163
|
+
|
1164
|
+
occurrence_count
|
1165
|
+
end
|
1166
|
+
|
1120
1167
|
##
|
1121
1168
|
# Creates and adds a formatted block to the blocks array
|
1122
1169
|
# based on the provided match and format options.
|
@@ -1129,13 +1176,17 @@ module MarkdownExec
|
|
1129
1176
|
# to the block's display name.
|
1130
1177
|
# return number of lines added
|
1131
1178
|
def create_and_add_chrome_block(blocks:, match_data:,
|
1179
|
+
collapse: nil,
|
1132
1180
|
format_option:, color_method:,
|
1133
1181
|
case_conversion: nil,
|
1134
1182
|
center: nil,
|
1135
1183
|
decor_patterns: [],
|
1184
|
+
disabled: true,
|
1185
|
+
id: '',
|
1186
|
+
level: 0,
|
1187
|
+
type: '',
|
1136
1188
|
wrap: nil)
|
1137
1189
|
line_cap = NamedCaptureExtractor::extract_named_group2(match_data)
|
1138
|
-
|
1139
1190
|
# replace tabs in indent
|
1140
1191
|
line_cap[:indent] ||= ''
|
1141
1192
|
line_cap[:indent] = line_cap[:indent].dup if line_cap[:indent].frozen?
|
@@ -1145,23 +1196,19 @@ module MarkdownExec
|
|
1145
1196
|
line_cap[:text] = line_cap[:text].dup if line_cap[:text].frozen?
|
1146
1197
|
line_cap[:text].gsub!("\t", ' ')
|
1147
1198
|
# missing capture
|
1199
|
+
line_cap[:collapse] ||= ''
|
1148
1200
|
line_cap[:line] ||= ''
|
1149
1201
|
|
1150
1202
|
accepted_width = @delegate_object[:console_width] - 2
|
1151
|
-
|
1152
|
-
|
1153
|
-
|
1154
|
-
|
1155
|
-
|
1156
|
-
|
1157
|
-
|
1158
|
-
|
1159
|
-
|
1160
|
-
[line_cap]
|
1161
|
-
end
|
1162
|
-
else
|
1163
|
-
[line_cap]
|
1164
|
-
end
|
1203
|
+
|
1204
|
+
line_caps = [line_cap]
|
1205
|
+
if wrap && line_cap[:text].length > accepted_width
|
1206
|
+
wrapper = StringWrapper.new(width: accepted_width - line_cap[:indent].length)
|
1207
|
+
line_caps = wrapper.wrap(line_cap[:text]).map do |wrapped_line|
|
1208
|
+
line_cap.dup.merge(text: wrapped_line)
|
1209
|
+
end
|
1210
|
+
end
|
1211
|
+
|
1165
1212
|
if center
|
1166
1213
|
line_caps.each do |line_obj|
|
1167
1214
|
line_obj[:indent] =
|
@@ -1173,7 +1220,7 @@ module MarkdownExec
|
|
1173
1220
|
end
|
1174
1221
|
end
|
1175
1222
|
|
1176
|
-
line_caps.
|
1223
|
+
line_caps.each_with_index do |line_obj, index|
|
1177
1224
|
next if line_obj[:text].nil?
|
1178
1225
|
|
1179
1226
|
case case_conversion
|
@@ -1196,10 +1243,23 @@ module MarkdownExec
|
|
1196
1243
|
|
1197
1244
|
line_obj[:line] = line_obj[:indent] + line_obj[:text]
|
1198
1245
|
blocks.push FCB.new(
|
1246
|
+
center: center,
|
1199
1247
|
chrome: true,
|
1200
|
-
|
1248
|
+
collapse: collapse.nil? ? (line_obj[:collapse] == COLLAPSIBLE_TOKEN_COLLAPSE) : collapse,
|
1249
|
+
token: line_obj[:collapse],
|
1250
|
+
disabled: disabled ? TtyMenu::DISABLE : nil,
|
1251
|
+
####
|
1252
|
+
# id: "#{@delegate_object[:filename]}:#{index}",
|
1253
|
+
id: "#{id}.#{index}",
|
1254
|
+
level: level,
|
1255
|
+
s0indent: indent,
|
1256
|
+
s0printable: line_obj[:text],
|
1257
|
+
s1decorated: decorated,
|
1201
1258
|
dname: line_obj[:indent] + decorated,
|
1202
|
-
|
1259
|
+
indent: line_obj[:indent],
|
1260
|
+
oname: line_obj[:text],
|
1261
|
+
text: line_obj[:text],
|
1262
|
+
type: type
|
1203
1263
|
)
|
1204
1264
|
end
|
1205
1265
|
line_caps.count
|
@@ -1213,20 +1273,8 @@ module MarkdownExec
|
|
1213
1273
|
# @param opts [Hash] Options containing configuration for line processing.
|
1214
1274
|
# @param use_chrome [Boolean] Indicates if the chrome styling should
|
1215
1275
|
# be applied.
|
1216
|
-
def create_and_add_chrome_blocks(blocks, fcb)
|
1217
|
-
|
1218
|
-
match_criteria = [
|
1219
|
-
{ format: :menu_note_format, match: :menu_table_rows_match },
|
1220
|
-
{ color: :menu_heading1_color, format: :menu_heading1_format, match: :heading1_match, wrap: true, center: :heading1_center, case_conversion: :upcase },
|
1221
|
-
{ color: :menu_heading2_color, format: :menu_heading2_format, match: :heading2_match, wrap: true, center: :heading2_center },
|
1222
|
-
{ color: :menu_heading3_color, format: :menu_heading3_format, match: :heading3_match, wrap: true, center: :heading3_center, case_conversion: :downcase },
|
1223
|
-
{ color: :menu_divider_color, format: :menu_divider_format, match: :menu_divider_match },
|
1224
|
-
{ color: :menu_note_color, format: :menu_note_format, match: :menu_note_match, wrap: true },
|
1225
|
-
{ color: :menu_task_color, format: :menu_task_format, match: :menu_task_match, wrap: true }
|
1226
|
-
]
|
1227
|
-
# rubocop:enable Layout/LineLength
|
1228
|
-
# rubocop:enable Style/UnlessElse
|
1229
|
-
match_criteria.each do |criteria|
|
1276
|
+
def create_and_add_chrome_blocks(blocks, fcb, id: '', init_ids: false)
|
1277
|
+
chrome_block_criteria.each_with_index do |criteria, index|
|
1230
1278
|
unless @delegate_object[criteria[:match]].present? &&
|
1231
1279
|
(mbody = fcb.body[0].match @delegate_object[criteria[:match]])
|
1232
1280
|
next
|
@@ -1237,20 +1285,34 @@ module MarkdownExec
|
|
1237
1285
|
case_conversion: criteria[:case_conversion],
|
1238
1286
|
center: criteria[:center] &&
|
1239
1287
|
@delegate_object[criteria[:center]],
|
1288
|
+
|
1289
|
+
collapse: case fcb.collapse_token
|
1290
|
+
when COLLAPSIBLE_TOKEN_COLLAPSE
|
1291
|
+
true
|
1292
|
+
when COLLAPSIBLE_TOKEN_EXPAND
|
1293
|
+
false
|
1294
|
+
else
|
1295
|
+
false####
|
1296
|
+
end,
|
1297
|
+
|
1240
1298
|
color_method: criteria[:color] &&
|
1241
1299
|
@delegate_object[criteria[:color]].to_sym,
|
1242
1300
|
decor_patterns:
|
1243
1301
|
@decor_patterns_from_delegate_object_for_block_create,
|
1302
|
+
disabled: !(criteria[:collapsible] && @delegate_object[criteria[:collapsible]]),
|
1303
|
+
id: "#{id}.#{index}",
|
1244
1304
|
format_option: criteria[:format] &&
|
1245
1305
|
@delegate_object[criteria[:format]],
|
1306
|
+
level: criteria[:level],
|
1246
1307
|
match_data: mbody,
|
1308
|
+
type: criteria[:type],
|
1247
1309
|
wrap: criteria[:wrap]
|
1248
1310
|
)
|
1249
1311
|
break
|
1250
1312
|
end
|
1251
1313
|
end
|
1252
1314
|
|
1253
|
-
def create_divider(position)
|
1315
|
+
def create_divider(position, id: '')
|
1254
1316
|
divider_key = if position == :initial
|
1255
1317
|
:menu_initial_divider
|
1256
1318
|
else
|
@@ -1261,8 +1323,9 @@ module MarkdownExec
|
|
1261
1323
|
|
1262
1324
|
FCB.new(
|
1263
1325
|
chrome: true,
|
1264
|
-
disabled:
|
1326
|
+
disabled: TtyMenu::DISABLE,
|
1265
1327
|
dname: string_send_color(oname, :menu_divider_color),
|
1328
|
+
id: id,
|
1266
1329
|
oname: oname
|
1267
1330
|
)
|
1268
1331
|
end
|
@@ -1344,7 +1407,9 @@ module MarkdownExec
|
|
1344
1407
|
end
|
1345
1408
|
|
1346
1409
|
def dml_menu_append_chrome_item(
|
1347
|
-
name, count, type,
|
1410
|
+
name, count, type,
|
1411
|
+
id: '',
|
1412
|
+
menu_state: MenuState::LOAD,
|
1348
1413
|
always_create: true, always_enable: true
|
1349
1414
|
)
|
1350
1415
|
raise unless name.present?
|
@@ -1355,7 +1420,8 @@ module MarkdownExec
|
|
1355
1420
|
# create menu item when it is needed (count > 0)
|
1356
1421
|
#
|
1357
1422
|
if item.nil? && (always_create || count.positive?)
|
1358
|
-
item = append_chrome_block(
|
1423
|
+
item = append_chrome_block(id: id,
|
1424
|
+
menu_blocks: @dml_menu_blocks,
|
1359
1425
|
menu_state: menu_state)
|
1360
1426
|
end
|
1361
1427
|
|
@@ -1367,7 +1433,7 @@ module MarkdownExec
|
|
1367
1433
|
if always_enable || count.positive?
|
1368
1434
|
item.delete(:disabled)
|
1369
1435
|
else
|
1370
|
-
item[:disabled] =
|
1436
|
+
item[:disabled] = TtyMenu::DISABLE
|
1371
1437
|
end
|
1372
1438
|
end
|
1373
1439
|
|
@@ -1521,18 +1587,15 @@ module MarkdownExec
|
|
1521
1587
|
def execute_block_by_type_for_lfls(
|
1522
1588
|
selected:, mdoc:, block_source:, link_state: LinkState.new
|
1523
1589
|
)
|
1524
|
-
# !!v selected
|
1525
1590
|
# order should not be important other than else clause
|
1526
1591
|
if selected.type == BlockType::EDIT
|
1527
1592
|
debounce_reset
|
1528
|
-
# !!v link_state.inherited_lines_block
|
1529
1593
|
vux_edit_inherited
|
1530
1594
|
return :break if pause_user_exit
|
1531
1595
|
|
1532
1596
|
next_state_append_code(selected, link_state, [])
|
1533
1597
|
|
1534
1598
|
elsif selected.type == BlockType::HISTORY
|
1535
|
-
# !!b
|
1536
1599
|
debounce_reset
|
1537
1600
|
return :break if execute_block_type_history_ux(
|
1538
1601
|
selected: selected,
|
@@ -1544,10 +1607,10 @@ module MarkdownExec
|
|
1544
1607
|
elsif selected.type == BlockType::LINK
|
1545
1608
|
debounce_reset
|
1546
1609
|
execute_block_type_link_with_state(link_block_body: selected.body,
|
1547
|
-
|
1548
|
-
|
1549
|
-
|
1550
|
-
|
1610
|
+
mdoc: mdoc,
|
1611
|
+
selected: selected,
|
1612
|
+
link_state: link_state,
|
1613
|
+
block_source: block_source)
|
1551
1614
|
|
1552
1615
|
elsif selected.type == BlockType::LOAD
|
1553
1616
|
debounce_reset
|
@@ -1611,6 +1674,15 @@ module MarkdownExec
|
|
1611
1674
|
next_state_append_code(selected, link_state,
|
1612
1675
|
code_from_vars_block_to_set_environment_variables(selected))
|
1613
1676
|
|
1677
|
+
elsif COLLAPSIBLE_TYPES.include?(selected.type)
|
1678
|
+
debounce_reset
|
1679
|
+
if @compressed_ids.keys.include?(selected.id)
|
1680
|
+
@compressed_ids.delete(selected.id)
|
1681
|
+
else
|
1682
|
+
@compressed_ids.merge!(selected.id => selected.level)
|
1683
|
+
end
|
1684
|
+
LoadFileLinkState.new(LoadFile::REUSE, link_state)
|
1685
|
+
|
1614
1686
|
elsif debounce_allows
|
1615
1687
|
compile_execute_and_trigger_reuse(mdoc: mdoc,
|
1616
1688
|
selected: selected,
|
@@ -1695,9 +1767,7 @@ module MarkdownExec
|
|
1695
1767
|
link_block_body: [], mdoc: nil, selected: FCB.new,
|
1696
1768
|
link_state: LinkState.new, block_source: {}
|
1697
1769
|
)
|
1698
|
-
# !!p link_block_body selected
|
1699
1770
|
link_block_data = HashDelegator.parse_yaml_data_from_body(link_block_body)
|
1700
|
-
# !!v link_block_data
|
1701
1771
|
## collect blocks specified by block
|
1702
1772
|
#
|
1703
1773
|
if mdoc
|
@@ -1791,16 +1861,15 @@ module MarkdownExec
|
|
1791
1861
|
def execute_block_type_load_code_lines(
|
1792
1862
|
selected,
|
1793
1863
|
directory: @delegate_object[:document_configurations_directory],
|
1864
|
+
exit_prompt: @delegate_object[:prompt_filespec_back],
|
1794
1865
|
filename_pattern: @delegate_object[:vars_block_filename_pattern],
|
1795
1866
|
glob: @delegate_object[:document_configurations_glob],
|
1796
1867
|
view: @delegate_object[:vars_block_filename_view]
|
1797
1868
|
)
|
1798
|
-
# !!p selected
|
1799
1869
|
block_data = HashDelegator.parse_yaml_data_from_body(selected.body)
|
1800
|
-
# !!v block_data
|
1801
1870
|
if selected_option = select_option_with_metadata(
|
1802
1871
|
prompt_title,
|
1803
|
-
Dir.glob(
|
1872
|
+
[exit_prompt] + Dir.glob(
|
1804
1873
|
File.join(
|
1805
1874
|
Dir.pwd,
|
1806
1875
|
block_data['directory'] || directory,
|
@@ -1808,19 +1877,21 @@ module MarkdownExec
|
|
1808
1877
|
)
|
1809
1878
|
).sort.map do |file|
|
1810
1879
|
{ name: format(
|
1811
|
-
|
1812
|
-
|
1813
|
-
|
1814
|
-
|
1815
|
-
|
1816
|
-
)
|
1880
|
+
block_data['view'] || view,
|
1881
|
+
NamedCaptureExtractor::extract_named_group2(
|
1882
|
+
file.match(
|
1883
|
+
Regexp.new(block_data['filename_pattern'] ||
|
1884
|
+
filename_pattern)
|
1817
1885
|
)
|
1818
|
-
)
|
1886
|
+
)
|
1887
|
+
),
|
1819
1888
|
oname: file }
|
1820
1889
|
end,
|
1821
1890
|
simple_menu_options
|
1822
1891
|
)
|
1823
|
-
|
1892
|
+
if selected_option.dname != exit_prompt
|
1893
|
+
File.readlines(selected_option.oname, chomp: true)
|
1894
|
+
end
|
1824
1895
|
else
|
1825
1896
|
warn "No matching files found" ###
|
1826
1897
|
end
|
@@ -1835,7 +1906,7 @@ module MarkdownExec
|
|
1835
1906
|
# @param selected [Hash] The selected block.
|
1836
1907
|
# @return [Array<String>] Required code blocks as an array of lines.
|
1837
1908
|
def execute_block_type_port_code_lines(mdoc:, selected:, block_source:,
|
1838
|
-
|
1909
|
+
link_state: LinkState.new)
|
1839
1910
|
required = mdoc.collect_recursively_required_code(
|
1840
1911
|
anyname: selected.pub_name,
|
1841
1912
|
label_format_above: @delegate_object[:shell_code_label_format_above],
|
@@ -1881,24 +1952,19 @@ module MarkdownExec
|
|
1881
1952
|
end
|
1882
1953
|
|
1883
1954
|
def execute_block_type_save(code_lines:, selected:)
|
1884
|
-
# !!p code_lines, selected
|
1885
1955
|
block_data = HashDelegator.parse_yaml_data_from_body(selected.body)
|
1886
|
-
# !!v block_data
|
1887
1956
|
directory_glob = if block_data['directory']
|
1888
|
-
# !!b
|
1889
1957
|
File.join(
|
1890
1958
|
block_data['directory'],
|
1891
1959
|
block_data['glob'] ||
|
1892
1960
|
@delegate_object[:document_saved_lines_glob].split('/').last
|
1893
1961
|
)
|
1894
1962
|
else
|
1895
|
-
# !!b
|
1896
1963
|
@delegate_object[:document_saved_lines_glob]
|
1897
1964
|
end
|
1898
|
-
# !!v directory_glob
|
1899
1965
|
|
1900
1966
|
save_filespec_from_expression(directory_glob).tap do |save_filespec|
|
1901
|
-
if save_filespec
|
1967
|
+
if save_filespec && save != exit_prompt
|
1902
1968
|
begin
|
1903
1969
|
File.write(save_filespec,
|
1904
1970
|
HashDelegator.join_code_lines(code_lines))
|
@@ -2049,20 +2115,63 @@ module MarkdownExec
|
|
2049
2115
|
# @param required_lines [Array<String>] The lines of code to be executed.
|
2050
2116
|
# @param selected [FCB] The selected functional code block object.
|
2051
2117
|
def execute_required_lines(
|
2052
|
-
|
2118
|
+
blockname: '',
|
2119
|
+
erls: {},
|
2120
|
+
required_lines: [], shell:
|
2053
2121
|
)
|
2054
2122
|
if @delegate_object[:save_executed_script]
|
2055
|
-
write_command_file(
|
2056
|
-
|
2123
|
+
write_command_file(blockname: blockname,
|
2124
|
+
required_lines: required_lines,
|
2057
2125
|
shell: shell)
|
2058
2126
|
end
|
2059
2127
|
if @dml_block_state
|
2060
2128
|
calc_logged_stdout_filename(block_name: @dml_block_state.block.oname)
|
2061
2129
|
end
|
2062
|
-
format_and_execute_command(
|
2130
|
+
format_and_execute_command(
|
2131
|
+
code_lines: required_lines,
|
2132
|
+
erls: erls,
|
2133
|
+
shell: shell
|
2134
|
+
)
|
2063
2135
|
post_execution_process
|
2064
2136
|
end
|
2065
2137
|
|
2138
|
+
def expand_blocks_with_replacements(
|
2139
|
+
menu_blocks, replacements, exclude_types: [BlockType::SHELL]
|
2140
|
+
)
|
2141
|
+
# update blocks
|
2142
|
+
#
|
2143
|
+
Regexp.union(replacements.keys).tap do |pattern|
|
2144
|
+
menu_blocks.each do |block|
|
2145
|
+
next if exclude_types.include?(block.type)
|
2146
|
+
|
2147
|
+
block.expand_variables_in_attributes!(pattern, replacements)
|
2148
|
+
end
|
2149
|
+
end
|
2150
|
+
end
|
2151
|
+
|
2152
|
+
def expand_variable_references!(
|
2153
|
+
# echo_format: 'echo "$%s"',
|
2154
|
+
echo_format: 'echo $%s',
|
2155
|
+
link_state:,
|
2156
|
+
blocks:,
|
2157
|
+
pattern: Regexp.new(@delegate_object[:variable_expression_regexp])
|
2158
|
+
)
|
2159
|
+
# Count occurrences of named groups in each block
|
2160
|
+
variable_counts = count_named_group_occurrences(blocks, pattern)
|
2161
|
+
|
2162
|
+
# Generate echo commands for each variable based on its count
|
2163
|
+
echo_commands = generate_echo_commands(variable_counts, echo_format)
|
2164
|
+
|
2165
|
+
# Build a dictionary to replace variables with the corresponding commands
|
2166
|
+
replacements = build_replacement_dictionary(echo_commands, link_state)
|
2167
|
+
|
2168
|
+
# Exit early if no replacements are needed
|
2169
|
+
return if replacements.nil?
|
2170
|
+
|
2171
|
+
# Expand each block with replacements from the dictionary
|
2172
|
+
expand_blocks_with_replacements(blocks, replacements)
|
2173
|
+
end
|
2174
|
+
|
2066
2175
|
# Retrieves a specific data symbol from the delegate object,
|
2067
2176
|
# converts it to a string, and applies a color style
|
2068
2177
|
# based on the specified color symbol.
|
@@ -2096,11 +2205,20 @@ module MarkdownExec
|
|
2096
2205
|
{ size: file_size, lines: line_count }
|
2097
2206
|
end
|
2098
2207
|
|
2099
|
-
def format_and_execute_command(
|
2208
|
+
def format_and_execute_command(
|
2209
|
+
code_lines:,
|
2210
|
+
erls:,
|
2211
|
+
shell:
|
2212
|
+
)
|
2100
2213
|
formatted_command = code_lines.flatten.join("\n")
|
2101
2214
|
@fout.fout fetch_color(data_sym: :script_execution_head,
|
2102
2215
|
color_sym: :script_execution_frame_color)
|
2103
|
-
command_execute(
|
2216
|
+
command_execute(
|
2217
|
+
formatted_command,
|
2218
|
+
args: @pass_args,
|
2219
|
+
erls: erls,
|
2220
|
+
shell: shell
|
2221
|
+
)
|
2104
2222
|
@fout.fout fetch_color(data_sym: :script_execution_tail,
|
2105
2223
|
color_sym: :script_execution_frame_color)
|
2106
2224
|
end
|
@@ -2162,6 +2280,17 @@ module MarkdownExec
|
|
2162
2280
|
color_sym: :execution_report_preview_frame_color)
|
2163
2281
|
end
|
2164
2282
|
|
2283
|
+
def generate_echo_commands(variable_counts, echo_format)
|
2284
|
+
# commands to echo variables
|
2285
|
+
#
|
2286
|
+
commands = {}
|
2287
|
+
variable_counts.each do |variable, count|
|
2288
|
+
command = format(echo_format, variable)
|
2289
|
+
commands[variable] = command
|
2290
|
+
end
|
2291
|
+
commands
|
2292
|
+
end
|
2293
|
+
|
2165
2294
|
def generate_temp_filename(ext = '.sh')
|
2166
2295
|
filename = begin
|
2167
2296
|
Dir::Tmpname.make_tmpname(['x', ext], nil)
|
@@ -2219,12 +2348,9 @@ module MarkdownExec
|
|
2219
2348
|
order: :chronological,
|
2220
2349
|
path: ''
|
2221
2350
|
)
|
2222
|
-
# !!v filename, 'path', path
|
2223
|
-
# !!v File.join(home, path, filename)
|
2224
2351
|
files = Dir.glob(
|
2225
2352
|
File.join(home, path, filename)
|
2226
2353
|
)
|
2227
|
-
# !!v files
|
2228
2354
|
sorted_files = case order
|
2229
2355
|
when :alphabetical
|
2230
2356
|
files.sort
|
@@ -2267,16 +2393,18 @@ module MarkdownExec
|
|
2267
2393
|
cfile.readlines(
|
2268
2394
|
@delegate_object[:filename],
|
2269
2395
|
import_paths: @delegate_object[:import_paths]&.split(':')
|
2270
|
-
).
|
2396
|
+
).each_with_index do |nested_line, index|
|
2271
2397
|
if nested_line
|
2272
|
-
update_line_and_block_state(
|
2273
|
-
|
2398
|
+
update_line_and_block_state(
|
2399
|
+
nested_line, state, selected_types,
|
2400
|
+
id: "#{@delegate_object[:filename]}:#{index}",
|
2401
|
+
&block
|
2402
|
+
)
|
2274
2403
|
end
|
2275
2404
|
end
|
2276
2405
|
end
|
2277
2406
|
|
2278
2407
|
def iter_source_blocks(source, &block)
|
2279
|
-
# !!v source
|
2280
2408
|
case source
|
2281
2409
|
when 1
|
2282
2410
|
blocks_from_nested_files.each(&block)
|
@@ -2400,18 +2528,14 @@ module MarkdownExec
|
|
2400
2528
|
end
|
2401
2529
|
|
2402
2530
|
def list_blocks
|
2403
|
-
# !!b
|
2404
2531
|
message = @delegate_object[:list_blocks_message]
|
2405
2532
|
block_eval = @delegate_object[:list_blocks_eval]
|
2406
|
-
# !!v message block_eval
|
2407
2533
|
|
2408
2534
|
list = []
|
2409
2535
|
iter_source_blocks(@delegate_object[:list_blocks_type]) do |block|
|
2410
|
-
# !!v block
|
2411
2536
|
list << (block_eval.present? ? eval(block_eval) : block.send(message))
|
2412
2537
|
end
|
2413
2538
|
list.compact!
|
2414
|
-
# !!v list
|
2415
2539
|
|
2416
2540
|
@fout.fout_list(list)
|
2417
2541
|
end
|
@@ -2421,10 +2545,10 @@ module MarkdownExec
|
|
2421
2545
|
# Executes a specified block once per filename.
|
2422
2546
|
# @param all_blocks [Array] Array of all block elements.
|
2423
2547
|
# @return [Boolean, nil] True if values were modified, nil otherwise.
|
2424
|
-
def load_auto_opts_block(all_blocks, mdoc:)
|
2548
|
+
def load_auto_opts_block(all_blocks, id: '', mdoc:)
|
2425
2549
|
block_name = @delegate_object[:document_load_opts_block_name]
|
2426
2550
|
unless block_name.present? &&
|
2427
|
-
@
|
2551
|
+
@opts_most_recent_filename != @delegate_object[:filename]
|
2428
2552
|
return
|
2429
2553
|
end
|
2430
2554
|
|
@@ -2437,13 +2561,26 @@ module MarkdownExec
|
|
2437
2561
|
)
|
2438
2562
|
update_menu_base(options_state.options)
|
2439
2563
|
|
2440
|
-
@
|
2564
|
+
@opts_most_recent_filename = @delegate_object[:filename]
|
2441
2565
|
true
|
2442
2566
|
end
|
2443
2567
|
|
2568
|
+
def load_auto_vars_block(all_blocks,
|
2569
|
+
block_name: @delegate_object[:document_load_vars_block_name])
|
2570
|
+
unless block_name.present? &&
|
2571
|
+
@vars_most_recent_filename != @delegate_object[:filename]
|
2572
|
+
return
|
2573
|
+
end
|
2574
|
+
|
2575
|
+
block = HashDelegator.block_find(all_blocks, :oname, block_name)
|
2576
|
+
return unless block
|
2577
|
+
|
2578
|
+
@vars_most_recent_filename = @delegate_object[:filename]
|
2579
|
+
code_from_vars_block_to_set_environment_variables(block)
|
2580
|
+
end
|
2581
|
+
|
2444
2582
|
def load_cli_or_user_selected_block(all_blocks: [], menu_blocks: [],
|
2445
2583
|
default: nil)
|
2446
|
-
# !!b
|
2447
2584
|
if @delegate_object[:block_name].present?
|
2448
2585
|
block = all_blocks.find do |item|
|
2449
2586
|
item.pub_name == @delegate_object[:block_name]
|
@@ -2505,7 +2642,6 @@ module MarkdownExec
|
|
2505
2642
|
link_state:)
|
2506
2643
|
if block_name_from_cli &&
|
2507
2644
|
@cli_block_name == @menu_base_options[:menu_persist_block_name]
|
2508
|
-
# !!b 'pause cli control, allow user to select block'
|
2509
2645
|
block_name_from_cli = false
|
2510
2646
|
now_using_cli = false
|
2511
2647
|
@menu_base_options[:block_name] =
|
@@ -2530,24 +2666,48 @@ module MarkdownExec
|
|
2530
2666
|
## Handles the file loading and returns the blocks
|
2531
2667
|
# in the file and MDoc instance
|
2532
2668
|
#
|
2533
|
-
def mdoc_menu_and_blocks_from_nested_files(link_state)
|
2669
|
+
def mdoc_menu_and_blocks_from_nested_files(link_state, id: '')
|
2670
|
+
# read blocks, load document opts block, and re-process blocks
|
2671
|
+
#
|
2534
2672
|
all_blocks, mdoc = mdoc_and_blocks_from_nested_files
|
2673
|
+
if load_auto_opts_block(all_blocks, id: id, mdoc: mdoc)
|
2674
|
+
all_blocks, mdoc = mdoc_and_blocks_from_nested_files
|
2675
|
+
end
|
2535
2676
|
|
2536
|
-
#
|
2677
|
+
# load document vars block
|
2537
2678
|
#
|
2538
|
-
if
|
2539
|
-
|
2679
|
+
if code_lines = load_auto_vars_block(all_blocks)
|
2680
|
+
new_code = HashDelegator.code_merge(link_state.inherited_lines,
|
2681
|
+
code_lines)
|
2682
|
+
next_state_set_code(
|
2683
|
+
nil,
|
2684
|
+
link_state,
|
2685
|
+
new_code
|
2686
|
+
)
|
2687
|
+
link_state.inherited_lines = new_code
|
2540
2688
|
end
|
2541
2689
|
|
2542
|
-
|
2690
|
+
# filter by name, collapsed
|
2691
|
+
#
|
2692
|
+
menu_blocks, @compressed_ids = mdoc.fcbs_per_options(
|
2693
|
+
@delegate_object.merge!(compressed_ids: @compressed_ids)
|
2694
|
+
)
|
2695
|
+
|
2696
|
+
# text substitution in menu
|
2697
|
+
#
|
2698
|
+
expand_variable_references!(blocks: menu_blocks, link_state: link_state)
|
2699
|
+
# expand_command_substition!(blocks: menu_blocks, link_state: link_state)
|
2543
2700
|
|
2544
|
-
|
2545
|
-
|
2701
|
+
# chrome for menu
|
2702
|
+
#
|
2703
|
+
add_menu_chrome_blocks!(id: id, menu_blocks: menu_blocks,
|
2704
|
+
link_state: link_state)
|
2546
2705
|
|
2547
2706
|
### compress empty lines
|
2548
2707
|
HashDelegator.delete_consecutive_blank_lines!(menu_blocks)
|
2549
|
-
HashDelegator.tables_into_columns!(menu_blocks, @delegate_object)
|
2550
|
-
|
2708
|
+
HashDelegator.tables_into_columns!(menu_blocks, @delegate_object) ####
|
2709
|
+
|
2710
|
+
[all_blocks, menu_blocks, mdoc]
|
2551
2711
|
end
|
2552
2712
|
|
2553
2713
|
def menu_add_disabled_option(document_glob)
|
@@ -2562,7 +2722,7 @@ module MarkdownExec
|
|
2562
2722
|
|
2563
2723
|
chrome_block = FCB.new(
|
2564
2724
|
chrome: true,
|
2565
|
-
disabled:
|
2725
|
+
disabled: TtyMenu::DISABLE,
|
2566
2726
|
dname: HashDelegator.new(@delegate_object).string_send_color(
|
2567
2727
|
document_glob, :menu_inherited_lines_color
|
2568
2728
|
),
|
@@ -2630,7 +2790,7 @@ module MarkdownExec
|
|
2630
2790
|
block_names = []
|
2631
2791
|
dependencies = {}
|
2632
2792
|
link_history_push_and_next(
|
2633
|
-
curr_block_name: selected
|
2793
|
+
curr_block_name: selected&.pub_name,
|
2634
2794
|
curr_document_filename: @delegate_object[:filename],
|
2635
2795
|
inherited_block_names:
|
2636
2796
|
((link_state&.inherited_block_names || []) + block_names).sort.uniq,
|
@@ -2747,32 +2907,31 @@ module MarkdownExec
|
|
2747
2907
|
fout_execution_report if @delegate_object[:output_execution_report]
|
2748
2908
|
end
|
2749
2909
|
|
2750
|
-
#
|
2751
|
-
# Remove filtered blocks.
|
2910
|
+
# Filter blocks per block_name_include_match, block_name_wrapper_match.
|
2752
2911
|
#
|
2753
2912
|
# @param all_blocks [Array<Hash>] The list of blocks from the file.
|
2754
|
-
|
2755
|
-
|
2756
|
-
|
2757
|
-
menu_blocks.map do |fcb|
|
2758
|
-
next if Filter.prepared_not_in_menu?(
|
2913
|
+
def select_blocks(menu_blocks)
|
2914
|
+
menu_blocks.select do |fcb|
|
2915
|
+
!Filter.prepared_not_in_menu?(
|
2759
2916
|
@delegate_object,
|
2760
2917
|
fcb,
|
2761
2918
|
%i[block_name_include_match block_name_wrapper_match]
|
2762
2919
|
)
|
2920
|
+
end
|
2921
|
+
end
|
2763
2922
|
|
2764
|
-
|
2765
|
-
|
2766
|
-
|
2767
|
-
|
2768
|
-
|
2769
|
-
|
2770
|
-
|
2771
|
-
|
2772
|
-
|
2773
|
-
|
2923
|
+
# Filter blocks per block_name_include_match, block_name_wrapper_match.
|
2924
|
+
# Set name displayed by tty-prompt.
|
2925
|
+
#
|
2926
|
+
# @param all_blocks [Array<Hash>] The list of blocks from the file.
|
2927
|
+
# @param opts [Hash] The options hash.
|
2928
|
+
# @return [Array<Hash>] The updated blocks menu.
|
2929
|
+
def blocks_as_menu_items(menu_blocks)
|
2930
|
+
select_blocks(menu_blocks).map do |fcb|
|
2931
|
+
fcb.name = fcb.indented_decorated || (fcb.indent + (fcb.s1decorated || fcb.dname))
|
2932
|
+
fcb.value = fcb.id || fcb.name
|
2774
2933
|
fcb.to_h
|
2775
|
-
end
|
2934
|
+
end
|
2776
2935
|
end
|
2777
2936
|
|
2778
2937
|
def print_formatted_option(key, value)
|
@@ -3142,6 +3301,20 @@ module MarkdownExec
|
|
3142
3301
|
{ abort: true })
|
3143
3302
|
end
|
3144
3303
|
|
3304
|
+
# private
|
3305
|
+
|
3306
|
+
def replace_keys_in_lines(replacement_dictionary, lines)
|
3307
|
+
# Create a regex pattern that matches any key in the replacement dictionary
|
3308
|
+
pattern = Regexp.union(replacement_dictionary.keys.map { |key|
|
3309
|
+
"%<#{key}>"
|
3310
|
+
})
|
3311
|
+
|
3312
|
+
# Iterate over each line and apply gsub with the replacement hash
|
3313
|
+
lines.map do |line|
|
3314
|
+
line.gsub(pattern) { |match| replacement_dictionary[match] }
|
3315
|
+
end
|
3316
|
+
end
|
3317
|
+
|
3145
3318
|
def report_error(err)
|
3146
3319
|
# Handle ENOENT error
|
3147
3320
|
@run_state.aborted_at = Time.now.utc
|
@@ -3235,9 +3408,12 @@ module MarkdownExec
|
|
3235
3408
|
end
|
3236
3409
|
end
|
3237
3410
|
|
3238
|
-
def save_to_file(
|
3411
|
+
def save_to_file(
|
3412
|
+
erls:,
|
3413
|
+
required_lines:, selected:, shell:
|
3414
|
+
)
|
3239
3415
|
write_command_file(
|
3240
|
-
required_lines: required_lines,
|
3416
|
+
required_lines: required_lines, blockname: selected.pub_name, shell: shell
|
3241
3417
|
)
|
3242
3418
|
@fout.fout "File saved: #{@run_state.saved_filespec}"
|
3243
3419
|
end
|
@@ -3254,7 +3430,6 @@ module MarkdownExec
|
|
3254
3430
|
end
|
3255
3431
|
|
3256
3432
|
def select_document_if_multiple(options, files, prompt:)
|
3257
|
-
# binding.irb
|
3258
3433
|
return files if files.class == String ###
|
3259
3434
|
return files[0] if (count = files.count) == 1
|
3260
3435
|
|
@@ -3274,17 +3449,34 @@ module MarkdownExec
|
|
3274
3449
|
# Presents a TTY prompt to select an option or exit,
|
3275
3450
|
# returns metadata including option and selected
|
3276
3451
|
def select_option_with_metadata(prompt_text, menu_items, opts = {})
|
3277
|
-
# !!v prompt_text menu_items
|
3278
3452
|
## configure to environment
|
3279
3453
|
#
|
3280
3454
|
register_console_attributes(opts)
|
3281
3455
|
|
3282
|
-
|
3456
|
+
active_color_pastel = Pastel.new
|
3457
|
+
active_color_pastel = opts[:menu_active_color_pastel_messages]
|
3458
|
+
.inject(active_color_pastel) do |p, message|
|
3459
|
+
p.send(message)
|
3460
|
+
end
|
3461
|
+
|
3283
3462
|
begin
|
3463
|
+
props = {
|
3464
|
+
active_color: active_color_pastel.detach,
|
3465
|
+
# activate dynamic list searching on letter/number key presses
|
3466
|
+
filter: true,
|
3467
|
+
}.freeze
|
3468
|
+
|
3469
|
+
# crashes if all menu options are disabled
|
3470
|
+
# crashes if default is not an existing item
|
3471
|
+
#
|
3284
3472
|
selection = @prompt.select(prompt_text,
|
3285
3473
|
menu_items,
|
3286
|
-
opts.merge(
|
3287
|
-
|
3474
|
+
opts.merge(props))
|
3475
|
+
rescue TTY::Prompt::ConfigurationError
|
3476
|
+
# prompt fails when collapsible block name has changed; clear default
|
3477
|
+
selection = @prompt.select(prompt_text,
|
3478
|
+
menu_items,
|
3479
|
+
opts.merge(props).merge(default: nil))
|
3288
3480
|
rescue NoMethodError
|
3289
3481
|
# no enabled options in page
|
3290
3482
|
return
|
@@ -3292,9 +3484,10 @@ module MarkdownExec
|
|
3292
3484
|
|
3293
3485
|
selected = menu_items.find do |item|
|
3294
3486
|
if item.instance_of?(Hash)
|
3295
|
-
(item[:name] || item[:dname]) == selection
|
3487
|
+
# (item[:id] || item[:name] || item[:dname]) == selection
|
3488
|
+
[item[:id], item[:name], item[:dname]].include?(selection)
|
3296
3489
|
elsif item.instance_of?(MarkdownExec::FCB)
|
3297
|
-
item.dname == selection
|
3490
|
+
item.dname == selection || item.id == selection
|
3298
3491
|
else
|
3299
3492
|
item == selection
|
3300
3493
|
end
|
@@ -3353,7 +3546,7 @@ module MarkdownExec
|
|
3353
3546
|
|
3354
3547
|
out = `#{cmd}`.sub(/.*?#{marker}/m, '')
|
3355
3548
|
File.delete filespec
|
3356
|
-
out
|
3549
|
+
out
|
3357
3550
|
end
|
3358
3551
|
|
3359
3552
|
def should_add_back_option?(
|
@@ -3487,8 +3680,11 @@ module MarkdownExec
|
|
3487
3680
|
# @return [Void] The function modifies the `state`
|
3488
3681
|
# and `selected_types` arguments in place.
|
3489
3682
|
##
|
3490
|
-
def update_line_and_block_state(
|
3491
|
-
|
3683
|
+
def update_line_and_block_state(
|
3684
|
+
nested_line, state, selected_types,
|
3685
|
+
id:,
|
3686
|
+
&block
|
3687
|
+
)
|
3492
3688
|
line = nested_line.to_s
|
3493
3689
|
if line.match(@delegate_object[:fenced_start_and_end_regex])
|
3494
3690
|
if state[:in_fenced_block]
|
@@ -3523,11 +3719,8 @@ module MarkdownExec
|
|
3523
3719
|
@delegate_object[:menu_include_imported_notes]
|
3524
3720
|
# add line if it is depth 0 or option allows it
|
3525
3721
|
#
|
3526
|
-
HashDelegator.yield_line_if_selected(line, selected_types,
|
3527
|
-
|
3528
|
-
else
|
3529
|
-
# !!b 'line is not recognized for block state'
|
3530
|
-
|
3722
|
+
HashDelegator.yield_line_if_selected(line, selected_types, id: id,
|
3723
|
+
&block)
|
3531
3724
|
end
|
3532
3725
|
end
|
3533
3726
|
|
@@ -3545,13 +3738,11 @@ module MarkdownExec
|
|
3545
3738
|
menu_blocks: @dml_menu_blocks,
|
3546
3739
|
default: @dml_menu_default_dname
|
3547
3740
|
)
|
3548
|
-
# !!b '@run_state.source.block_name_from_cli:',@run_state.source.block_name_from_cli
|
3549
3741
|
if !@dml_block_state
|
3550
3742
|
# HashDelegator.error_handler('block_state missing', { abort: true })
|
3551
3743
|
# document has no enabled items
|
3552
3744
|
:break
|
3553
3745
|
elsif @dml_block_state.state == MenuState::EXIT
|
3554
|
-
# !!b 'load_cli_or_user_selected_block -> break'
|
3555
3746
|
:break
|
3556
3747
|
end
|
3557
3748
|
end
|
@@ -3604,7 +3795,6 @@ module MarkdownExec
|
|
3604
3795
|
was_using_cli: @dml_now_using_cli
|
3605
3796
|
)
|
3606
3797
|
|
3607
|
-
# !!b '!block_name_from_ui + cli_break -> break'
|
3608
3798
|
!@dml_block_state.source.block_name_from_ui && cli_break && :break
|
3609
3799
|
end
|
3610
3800
|
|
@@ -3810,23 +4000,21 @@ module MarkdownExec
|
|
3810
4000
|
@delegate_object[:filename],
|
3811
4001
|
block_list
|
3812
4002
|
).run do |msg, data|
|
3813
|
-
# !!v msg data
|
3814
|
-
# !!t msg
|
3815
4003
|
case msg
|
3816
4004
|
when :parse_document # once for each menu
|
3817
|
-
vux_parse_document
|
3818
|
-
vux_menu_append_history_files(formatted_choice_ostructs
|
4005
|
+
vux_parse_document(id: 'vux_parse_document')
|
4006
|
+
vux_menu_append_history_files(formatted_choice_ostructs,
|
4007
|
+
id: "vux_menu_append_history_files",)
|
3819
4008
|
vux_publish_document_file_name_for_external_automation
|
3820
4009
|
|
3821
4010
|
when :display_menu
|
4011
|
+
# does not display
|
3822
4012
|
vux_clear_menu_state
|
3823
4013
|
|
3824
4014
|
when :end_of_cli
|
3825
|
-
# !!b
|
3826
4015
|
# yield :end_of_cli, @delegate_object
|
3827
4016
|
|
3828
4017
|
if @delegate_object[:list_blocks]
|
3829
|
-
# !!b
|
3830
4018
|
list_blocks
|
3831
4019
|
:exit
|
3832
4020
|
end
|
@@ -3862,7 +4050,8 @@ module MarkdownExec
|
|
3862
4050
|
end
|
3863
4051
|
end
|
3864
4052
|
|
3865
|
-
def vux_menu_append_history_files(formatted_choice_ostructs
|
4053
|
+
def vux_menu_append_history_files(formatted_choice_ostructs,
|
4054
|
+
id: '')
|
3866
4055
|
if @delegate_object[:menu_for_history]
|
3867
4056
|
history_files(
|
3868
4057
|
@dml_link_state,
|
@@ -3873,7 +4062,9 @@ module MarkdownExec
|
|
3873
4062
|
if files.count.positive?
|
3874
4063
|
dml_menu_append_chrome_item(
|
3875
4064
|
formatted_choice_ostructs[:history].oname, files.count,
|
3876
|
-
'files',
|
4065
|
+
'files',
|
4066
|
+
id: id,
|
4067
|
+
menu_state: MenuState::HISTORY
|
3877
4068
|
)
|
3878
4069
|
end
|
3879
4070
|
end
|
@@ -3895,6 +4086,7 @@ module MarkdownExec
|
|
3895
4086
|
if files.count.positive?
|
3896
4087
|
dml_menu_append_chrome_item(
|
3897
4088
|
formatted_choice_ostructs[:load].dname, files.count, 'files',
|
4089
|
+
id: "#{id}.load",
|
3898
4090
|
menu_state: MenuState::LOAD
|
3899
4091
|
)
|
3900
4092
|
end
|
@@ -3902,18 +4094,21 @@ module MarkdownExec
|
|
3902
4094
|
lines_count.positive?
|
3903
4095
|
dml_menu_append_chrome_item(
|
3904
4096
|
formatted_choice_ostructs[:edit].dname, lines_count, 'lines',
|
4097
|
+
id: "#{id}.edit",
|
3905
4098
|
menu_state: MenuState::EDIT
|
3906
4099
|
)
|
3907
4100
|
end
|
3908
4101
|
if lines_count.positive?
|
3909
4102
|
dml_menu_append_chrome_item(
|
3910
4103
|
formatted_choice_ostructs[:save].dname, 1, '',
|
4104
|
+
id: "#{id}.save",
|
3911
4105
|
menu_state: MenuState::SAVE
|
3912
4106
|
)
|
3913
4107
|
end
|
3914
4108
|
if lines_count.positive?
|
3915
4109
|
dml_menu_append_chrome_item(
|
3916
4110
|
formatted_choice_ostructs[:view].dname, 1, '',
|
4111
|
+
id: "#{id}.view",
|
3917
4112
|
menu_state: MenuState::VIEW
|
3918
4113
|
)
|
3919
4114
|
end
|
@@ -3921,6 +4116,7 @@ module MarkdownExec
|
|
3921
4116
|
if @delegate_object[:menu_with_shell]
|
3922
4117
|
dml_menu_append_chrome_item(
|
3923
4118
|
formatted_choice_ostructs[:shell].dname, 1, '',
|
4119
|
+
id: "#{id}.shell",
|
3924
4120
|
menu_state: MenuState::SHELL
|
3925
4121
|
)
|
3926
4122
|
end
|
@@ -3939,7 +4135,7 @@ module MarkdownExec
|
|
3939
4135
|
)
|
3940
4136
|
end
|
3941
4137
|
|
3942
|
-
def vux_parse_document
|
4138
|
+
def vux_parse_document(id: '')
|
3943
4139
|
@run_state.batch_index += 1
|
3944
4140
|
@run_state.in_own_window = false
|
3945
4141
|
|
@@ -3960,10 +4156,10 @@ module MarkdownExec
|
|
3960
4156
|
|
3961
4157
|
# update @delegate_object and @menu_base_options in auto_load
|
3962
4158
|
#
|
4159
|
+
# @dml_blocks_in_file, @dml_menu_blocks, @dml_mdoc, @dml_link_state =
|
3963
4160
|
@dml_blocks_in_file, @dml_menu_blocks, @dml_mdoc =
|
3964
|
-
mdoc_menu_and_blocks_from_nested_files(@dml_link_state)
|
4161
|
+
mdoc_menu_and_blocks_from_nested_files(@dml_link_state, id: id)
|
3965
4162
|
dump_delobj(@dml_blocks_in_file, @dml_menu_blocks, @dml_link_state)
|
3966
|
-
# !!b 'loop', @run_state.source.block_name_from_cli, @cli_block_name
|
3967
4163
|
end
|
3968
4164
|
|
3969
4165
|
def vux_publish_block_name_for_external_automation(block_name)
|
@@ -3995,7 +4191,6 @@ module MarkdownExec
|
|
3995
4191
|
|
3996
4192
|
# return :break to break from loop
|
3997
4193
|
def vux_user_selected_block_name
|
3998
|
-
# !!b
|
3999
4194
|
if @dml_link_state.block_name.present?
|
4000
4195
|
# @prior_block_was_link = true
|
4001
4196
|
@dml_block_state.block = blocks_find_by_block_name(
|
@@ -4026,32 +4221,27 @@ module MarkdownExec
|
|
4026
4221
|
end
|
4027
4222
|
|
4028
4223
|
def wait_for_user_selected_block(all_blocks, menu_blocks, default)
|
4029
|
-
# !!b
|
4030
4224
|
block_state = wait_for_user_selection(all_blocks, menu_blocks, default)
|
4031
4225
|
handle_back_or_continue(block_state)
|
4032
4226
|
block_state
|
4033
4227
|
end
|
4034
4228
|
|
4035
4229
|
def wait_for_user_selection(_all_blocks, menu_blocks, default)
|
4036
|
-
# !!b
|
4037
4230
|
if @delegate_object[:clear_screen_for_select_block]
|
4038
4231
|
printf("\e[1;1H\e[2J")
|
4039
4232
|
end
|
4040
4233
|
|
4041
|
-
# !!b
|
4042
4234
|
prompt_title = string_send_color(
|
4043
4235
|
@delegate_object[:prompt_select_block].to_s,
|
4044
4236
|
:prompt_color_after_script_execution
|
4045
4237
|
)
|
4046
4238
|
|
4047
|
-
|
4048
|
-
menu_items = prepare_blocks_menu(menu_blocks)
|
4239
|
+
menu_items = blocks_as_menu_items(menu_blocks)
|
4049
4240
|
if menu_items.empty?
|
4050
4241
|
return SelectedBlockMenuState.new(nil, OpenStruct.new,
|
4051
4242
|
MenuState::EXIT)
|
4052
4243
|
end
|
4053
4244
|
|
4054
|
-
# !!b
|
4055
4245
|
# default value may not match if color is different from
|
4056
4246
|
# originating menu (opts changed while processing)
|
4057
4247
|
selection_opts = if default && menu_blocks.map(&:dname).include?(default)
|
@@ -4060,26 +4250,24 @@ module MarkdownExec
|
|
4060
4250
|
@delegate_object
|
4061
4251
|
end
|
4062
4252
|
|
4063
|
-
# !!b
|
4064
4253
|
selection_opts.merge!(
|
4065
4254
|
{ cycle: @delegate_object[:select_page_cycle],
|
4066
4255
|
per_page: @delegate_object[:select_page_height] }
|
4067
4256
|
)
|
4068
4257
|
selected_option = select_option_with_metadata(prompt_title, menu_items,
|
4069
4258
|
selection_opts)
|
4070
|
-
# !!b
|
4071
4259
|
determine_block_state(selected_option)
|
4072
4260
|
end
|
4073
4261
|
|
4074
4262
|
# Handles the core logic for generating the command
|
4075
4263
|
# file's metadata and content.
|
4076
|
-
def write_command_file(required_lines:,
|
4264
|
+
def write_command_file(required_lines:, blockname:, shell: nil)
|
4077
4265
|
return unless @delegate_object[:save_executed_script]
|
4078
4266
|
|
4079
4267
|
time_now = Time.now.utc
|
4080
4268
|
@run_state.saved_script_filename =
|
4081
4269
|
SavedAsset.new(
|
4082
|
-
blockname:
|
4270
|
+
blockname: blockname,
|
4083
4271
|
exts: '.sh',
|
4084
4272
|
filename: @delegate_object[:filename],
|
4085
4273
|
prefix: @delegate_object[:saved_script_filename_prefix],
|
@@ -4273,6 +4461,7 @@ module MarkdownExec
|
|
4273
4461
|
c.expects(:command_execute).with(
|
4274
4462
|
'',
|
4275
4463
|
args: pigeon,
|
4464
|
+
erls: {},
|
4276
4465
|
shell: ShellType::BASH
|
4277
4466
|
)
|
4278
4467
|
|
@@ -4487,7 +4676,7 @@ module MarkdownExec
|
|
4487
4676
|
mdoc: @mdoc, selected: @selected, block_source: {}
|
4488
4677
|
)
|
4489
4678
|
|
4490
|
-
assert_equal ['code line', 'key=
|
4679
|
+
assert_equal ['code line', 'key=value'], result
|
4491
4680
|
end
|
4492
4681
|
end
|
4493
4682
|
|
@@ -4814,7 +5003,7 @@ module MarkdownExec
|
|
4814
5003
|
def test_call
|
4815
5004
|
@hd.expects(:history_files).with(nil, filename: '*', path: nil).once
|
4816
5005
|
@hd.execute_block_type_history_ux(filename: '*', link_state: LinkState.new,
|
4817
|
-
|
5006
|
+
selected: FCB.new(body: []))
|
4818
5007
|
end
|
4819
5008
|
end
|
4820
5009
|
|