markdown_exec 2.5.0 → 2.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/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
|
|