markdown_exec 2.7.1 → 2.7.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2777165b185482931d9fe8e519921490e8e252dcb93d141abf52fc6e53b95ba7
4
- data.tar.gz: c5925bd62f6853ad701946a2ecca3bf57c8b967b7f65c9990f72c17748591398
3
+ metadata.gz: bf1cce75f6ae919ebb237862e74ade141e6300426e514331b4410cf7cfa0b27e
4
+ data.tar.gz: 2ea6f8f6fa47f01b324b6663c6c1dcd0f69a0c2a164d7591f5c714d9618b90a4
5
5
  SHA512:
6
- metadata.gz: 0f534d77704be9418666e804a2bf1ecfd6c41ae4cee8b0c7f3c7753f2967b88b257e1962f3f8dc9565af09a697f75fb823054f062bffea9a7aabef9d9bae885e
7
- data.tar.gz: 18bcdb411c4655bb3f99c8e7557adf7d872c0562fcfeef18700134578dcc9c8e8ecf9992c43c82521eb773aad6d97a95e7f6859d90a36ded25a2ac88e3a2babc
6
+ metadata.gz: 87b6c3f35b0fd85b06dc1d94afc6c145fd27989def6972dcaf66e85a8c899e3550376efa9b0e70efe2327e403a46615b6c51a5210653bf5bdd0e1c6946d477f7
7
+ data.tar.gz: 78fd6cb33feabb7a94c0df274528cf2ffd0d4b60e1bf37328304a125b71edc44c6fd884c003af7088b0953923cee3e3a2b3f39b139b1559bf0b2b4337792ecc9
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- markdown_exec (2.7.1)
4
+ markdown_exec (2.7.2)
5
5
  clipboard (~> 1.3.6)
6
6
  open3 (~> 0.1.1)
7
7
  optparse (~> 0.1.1)
data/bats/border.bats ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bats
2
+
3
+ load 'test_helper'
4
+
5
+ @test 'Border - ' {
6
+ spec_mde_xansi_dname_doc_blocks_expect docs/dev/border.md \
7
+ 'A: 1_ B: 2_'
8
+ }
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env bats
2
+
3
+ load 'test_helper'
4
+
5
+ @test 'document_shell - required' {
6
+ spec_mde_xansi_dname_doc_blocks_expect docs/dev/document-shell.md \
7
+ --dump-inherited-lines t '* Exit' \
8
+ ' inherited_lines_ - : : from required_ - : : from document_shell'
9
+ }
@@ -13,7 +13,7 @@ __filedirs_all()
13
13
  }
14
14
 
15
15
  _mde_echo_version() {
16
- echo "2.7.1"
16
+ echo "2.7.2"
17
17
  }
18
18
 
19
19
  _mde() {
@@ -5,6 +5,10 @@ VAULT: 1
5
5
  echo "Species: $Species"
6
6
  echo "VAULT: $VAULT"
7
7
  ```
8
+ | Variable| Value
9
+ | -| -
10
+ | Species| ${Species}
11
+ | VAULT| ${VAULT}
8
12
  @import bats-document-configuration.md
9
13
  ```vars :(document_vars)
10
14
  Species: Not specified
@@ -0,0 +1,7 @@
1
+ ```vars
2
+ A: 1
3
+ B: 2
4
+ ```
5
+ @import bats-document-configuration.md
6
+ ```opts :(document_opts)
7
+ ```
@@ -11,6 +11,7 @@ echo "current base name is now $(basename `pwd`)"
11
11
  ```link
12
12
  load: file_$(basename `pwd`).sh
13
13
  ```
14
+ / This should not be evaluated $(err). It errs with "Error: HashDelegator.blocks_from_nested_files -- Shell script execution failed: /bin/bash: line 2: err: command not found"
14
15
  @import bats-document-configuration.md
15
16
  ```opts :(document_opts)
16
17
  heading1_center: false
@@ -0,0 +1,6 @@
1
+ ```bash :(required)
2
+ : from required
3
+ ```
4
+ ```bash :(document_shell) +(required)
5
+ : from document_shell
6
+ ```
data/lib/fcb.rb CHANGED
@@ -35,6 +35,14 @@ module MarkdownExec
35
35
  }.merge(options)
36
36
  end
37
37
 
38
+ def code_name_included?(*names)
39
+ names.include?(@attrs[:oname])
40
+ end
41
+
42
+ def code_name_exp?(regexp)
43
+ Regexp.new(regexp) =~ @attrs[:oname]
44
+ end
45
+
38
46
  # Derives a title from the body of an FCB object.
39
47
  # @param fcb [Object] The FCB object whose title is to be derived.
40
48
  # @return [String] The derived title.
@@ -152,23 +160,27 @@ module MarkdownExec
152
160
  @attrs.to_yaml
153
161
  end
154
162
 
155
- # Expand variables in `dname` and `body` attributes
163
+ # Expand variables in attributes
164
+ ####
156
165
  def expand_variables_in_attributes!(pattern, replacements)
157
- ### update name, nickname, title, label ???
158
-
159
- # Replace variables in `dname` using the replacements dictionary
166
+ @attrs[:raw_dname] ||= @attrs[:dname]
160
167
  @attrs[:dname] = @attrs[:dname]&.gsub(pattern) do |match|
161
168
  replacements[match]
162
169
  end
170
+
171
+ @attrs[:raw_s0printable] ||= @attrs[:s0printable]
163
172
  @attrs[:s0printable] = @attrs[:s0printable]&.gsub(pattern) do |match|
164
173
  replacements[match]
165
174
  end
175
+
176
+ @attrs[:raw_s1decorated] ||= @attrs[:s1decorated]
166
177
  @attrs[:s1decorated] = @attrs[:s1decorated]&.gsub(pattern) do |match|
167
178
  replacements[match]
168
179
  end
169
180
 
170
181
  # Replace variables in each line of `body` if `body` is present
171
182
  if @attrs[:body]
183
+ @attrs[:raw_body] ||= @attrs[:body]
172
184
  @attrs[:body] = @attrs[:body]&.map do |line|
173
185
  if line.empty?
174
186
  line
data/lib/filter.rb CHANGED
@@ -136,14 +136,14 @@ module MarkdownExec
136
136
  if options[:hide_blocks_by_name]
137
137
  filters[:hidden_name] =
138
138
  !!(options[:block_name_hidden_match].present? &&
139
- name =~ Regexp.new(options[:block_name_hidden_match]))
139
+ fcb.code_name_exp?(options[:block_name_hidden_match]))
140
140
  end
141
141
  filters[:include_name] =
142
142
  !!(options[:block_name_include_match].present? &&
143
- name =~ Regexp.new(options[:block_name_include_match]))
143
+ fcb.code_name_exp?(options[:block_name_include_match]))
144
144
  filters[:wrap_name] =
145
145
  !!(options[:block_name_wrapper_match].present? &&
146
- name =~ Regexp.new(options[:block_name_wrapper_match]))
146
+ fcb.code_name_exp?(options[:block_name_wrapper_match]))
147
147
  end
148
148
 
149
149
  # Evaluates the filter settings to make a final decision on
@@ -227,27 +227,6 @@ if $PROGRAM_NAME == __FILE__
227
227
  require_relative 'constants'
228
228
 
229
229
  module MarkdownExec
230
- # Define a mock fenced code block class for testing purposes
231
- class FCB
232
- attr_accessor :chrome, :disabled, :oname, :shell, :start_line, :type
233
-
234
- def initialize(
235
- chrome: false, dname: nil, oname: nil,
236
- shell: '', start_line: nil, type: nil
237
- )
238
- @chrome = chrome
239
- @dname = dname
240
- @oname = oname
241
- @shell = shell
242
- @type = type
243
- @start_line = start_line
244
- end
245
-
246
- def fetch(key, default)
247
- instance_variable_get("@#{key}") || default
248
- end
249
- end
250
-
251
230
  class FilterTest < Minitest::Test
252
231
  def setup
253
232
  @options = {}
@@ -361,10 +361,10 @@ module HashDelegatorSelf
361
361
  # @param [String] line The line to be processed.
362
362
  # @param [Array<Symbol>] selected_types A list of message types to check.
363
363
  # @param [Proc] block The block to be called with the line data.
364
- def yield_line_if_selected(line, selected_types, id: '', &block)
364
+ def yield_line_if_selected(line, selected_types, source_id: '', &block)
365
365
  return unless block && block_type_selected?(selected_types, :line)
366
366
 
367
- block.call(:line, MarkdownExec::FCB.new(body: [line], id: id))
367
+ block.call(:line, MarkdownExec::FCB.new(body: [line], id: source_id))
368
368
  end
369
369
  end
370
370
 
@@ -600,52 +600,72 @@ module MarkdownExec
600
600
  end
601
601
  end
602
602
 
603
- def add_back_option(id: '', menu_blocks:)
604
- append_chrome_block(id: id, menu_blocks: menu_blocks,
605
- menu_state: MenuState::BACK)
603
+ def add_back_option(menu_blocks:, source_id: '')
604
+ append_chrome_block(
605
+ menu_blocks: menu_blocks,
606
+ menu_state: MenuState::BACK,
607
+ source_id: source_id
608
+ )
606
609
  end
607
610
 
608
- def add_exit_option(id: '', menu_blocks:)
609
- append_chrome_block(id: id, menu_blocks: menu_blocks,
610
- menu_state: MenuState::EXIT)
611
+ def add_exit_option(menu_blocks:, source_id: '')
612
+ append_chrome_block(
613
+ menu_blocks: menu_blocks,
614
+ menu_state: MenuState::EXIT,
615
+ source_id: source_id
616
+ )
611
617
  end
612
618
 
613
- def add_inherited_lines(menu_blocks:, link_state:)
614
- append_inherited_lines(menu_blocks: menu_blocks, link_state: link_state)
619
+ def add_inherited_lines(link_state:, menu_blocks:)
620
+ append_inherited_lines(
621
+ link_state: link_state,
622
+ menu_blocks: menu_blocks
623
+ )
615
624
  end
616
625
 
617
626
  # Modifies the provided menu blocks array by adding 'Back' and 'Exit' options,
618
627
  # along with initial and final dividers, based on the delegate object's configuration.
619
628
  #
620
629
  # @param menu_blocks [Array] The array of menu block elements to be modified.
621
- def add_menu_chrome_blocks!(id: '', menu_blocks:, link_state:)
630
+ def add_menu_chrome_blocks!(link_state:, menu_blocks:, source_id: '')
622
631
  return unless @delegate_object[:menu_link_format].present?
623
632
 
624
- if @delegate_object[:menu_with_inherited_lines]
625
- add_inherited_lines(menu_blocks: menu_blocks,
626
- link_state: link_state)
627
- end
633
+ add_inherited_lines(
634
+ link_state: link_state,
635
+ menu_blocks: menu_blocks
636
+ ) if @delegate_object[:menu_with_inherited_lines]
628
637
 
629
638
  # back before exit
630
- add_back_option(id: "#{id}.back",
631
- menu_blocks: menu_blocks) if should_add_back_option?
639
+ add_back_option(
640
+ menu_blocks: menu_blocks,
641
+ source_id: "#{source_id}.back"
642
+ ) if should_add_back_option?
632
643
 
633
644
  # exit after other options
634
- if @delegate_object[:menu_with_exit]
635
- add_exit_option(id: "#{id}.exit", menu_blocks: menu_blocks)
636
- end
637
645
 
638
- append_divider(id: "#{id}.init", menu_blocks: menu_blocks,
639
- position: :initial)
640
- append_divider(id: "#{id}.final", menu_blocks: menu_blocks,
641
- position: :final)
646
+ add_exit_option(
647
+ menu_blocks: menu_blocks,
648
+ source_id: "#{source_id}.exit"
649
+ ) if @delegate_object[:menu_with_exit]
650
+
651
+ append_divider(
652
+ menu_blocks: menu_blocks,
653
+ position: :initial,
654
+ source_id: "#{source_id}.init"
655
+ )
656
+
657
+ append_divider(
658
+ menu_blocks: menu_blocks,
659
+ position: :final,
660
+ source_id: "#{source_id}.final"
661
+ )
642
662
  end
643
663
 
644
664
  # Appends a chrome block, which is a menu option for Back or Exit
645
665
  #
646
666
  # @param all_blocks [Array] The current blocks in the menu
647
667
  # @param type [Symbol] The type of chrome block to add (:back or :exit)
648
- def append_chrome_block(menu_blocks:, menu_state:, id: '')
668
+ def append_chrome_block(menu_blocks:, menu_state:, source_id: '')
649
669
  case menu_state
650
670
  when MenuState::BACK
651
671
  history_state_partition
@@ -683,7 +703,7 @@ module MarkdownExec
683
703
  dname: HashDelegator.new(@delegate_object).string_send_color(
684
704
  formatted_name, :menu_chrome_color
685
705
  ),
686
- id: id,
706
+ id: source_id.to_s,
687
707
  type: BlockType::CHROME,
688
708
  nickname: formatted_name,
689
709
  oname: formatted_name
@@ -703,10 +723,10 @@ module MarkdownExec
703
723
  #
704
724
  # @param menu_blocks [Array] The array of menu block elements.
705
725
  # @param position [Symbol] The position to insert the divider (:initial or :final).
706
- def append_divider(id: '', menu_blocks:, position:)
726
+ def append_divider(menu_blocks:, position:, source_id: '')
707
727
  return unless divider_formatting_present?(position)
708
728
 
709
- divider = create_divider(position, id: id)
729
+ divider = create_divider(position, source_id: source_id)
710
730
  position == :initial ? menu_blocks.unshift(divider) : menu_blocks.push(divider)
711
731
  end
712
732
 
@@ -715,7 +735,7 @@ module MarkdownExec
715
735
  #
716
736
  # @param menu_blocks [Array] The array of menu block elements.
717
737
  # @param position [Symbol] The position to insert the divider (:initial or :final).
718
- def append_inherited_lines(menu_blocks:, link_state:, position: top)
738
+ def append_inherited_lines(link_state:, menu_blocks:, position: top)
719
739
  return unless link_state.inherited_lines_present?
720
740
 
721
741
  insert_at_top = @delegate_object[:menu_inherited_lines_at_top]
@@ -783,13 +803,31 @@ module MarkdownExec
783
803
 
784
804
  # private
785
805
 
806
+ def expand_references!(fcb, link_state)
807
+ expand_variable_references!(
808
+ blocks: [fcb],
809
+ initial_code_required: false,
810
+ link_state: link_state
811
+ )
812
+ expand_variable_references!(
813
+ blocks: [fcb],
814
+ echo_format: '%s',
815
+ group_name: :command,
816
+ initial_code_required: false,
817
+ key_format: '$(%s)',
818
+ link_state: link_state,
819
+ pattern: options_command_substitution_regexp
820
+ )
821
+ end
822
+
786
823
  # Iterates through nested files to collect various types
787
824
  # of blocks, including dividers, tasks, and others.
788
825
  # The method categorizes blocks based on their type and processes them accordingly.
789
826
  #
790
827
  # @return [Array<FCB>] An array of FCB objects representing the blocks.
791
828
  def blocks_from_nested_files(
792
- link_state: @dml_link_state || LinkState.new
829
+ link_state: @dml_link_state || LinkState.new,
830
+ source_id: nil
793
831
  )
794
832
  register_console_attributes(@delegate_object)
795
833
  @decor_patterns_from_delegate_object_for_block_create = collect_line_decor_patterns(@delegate_object)
@@ -799,22 +837,6 @@ module MarkdownExec
799
837
  iter_blocks_from_nested_files do |btype, fcb|
800
838
  count += 1
801
839
 
802
- # text substitution in menu
803
- #
804
- expand_references = lambda do |fcb|
805
- expand_variable_references!(blocks: [fcb], link_state: link_state,
806
- initial_code_required: false)
807
- expand_variable_references!(
808
- blocks: [fcb],
809
- echo_format: '%s',
810
- initial_code_required: false,
811
- key_format: '$(%s)',
812
- link_state: link_state,
813
- group_name: :command,
814
- pattern: options_command_substitution_regexp
815
- )
816
- end
817
-
818
840
  case btype
819
841
  when :blocks
820
842
  if @delegate_object[:bash]
@@ -822,20 +844,25 @@ module MarkdownExec
822
844
  block_calls_scan: @delegate_object[:block_calls_scan],
823
845
  block_name_match: @delegate_object[:block_name_match],
824
846
  block_name_nick_match: @delegate_object[:block_name_nick_match],
825
- id: "*#{count}"
847
+ id: "#{source_id}_bfnf_b_#{count}"
826
848
  ) do |oname, color|
827
849
  apply_block_type_color_option(oname, color)
828
850
  end
851
+ else
852
+ expand_references!(fcb, link_state)
829
853
  end
830
- expand_references.call(fcb)
831
854
  blocks << fcb
832
855
  when :filter # types accepted
833
856
  %i[blocks line]
834
857
  when :line
835
858
  unless @delegate_object[:no_chrome]
836
- expand_references.call(fcb)
837
- create_and_add_chrome_blocks(blocks, fcb, id: "*#{count}",
838
- init_ids: init_ids)
859
+ # expand references only if block is recognized (not a comment)
860
+ create_and_add_chrome_blocks(
861
+ blocks, fcb, id: "#{source_id}_bfnf_l_#{count}", init_ids: init_ids
862
+ ) do
863
+ # expand references only if block is recognized (not a comment)
864
+ expand_references!(fcb, link_state)
865
+ end
839
866
  end
840
867
  end
841
868
  end
@@ -1134,8 +1161,10 @@ module MarkdownExec
1134
1161
  end
1135
1162
 
1136
1163
  # Check if the expression contains wildcard characters
1137
- def contains_wildcards?(expr)
1138
- expr.match(%r{\*|\?|\[})
1164
+ def contains_glob?(str)
1165
+ return false if str.nil?
1166
+
1167
+ str.match?(/[\*\?\[\{\}]/)
1139
1168
  end
1140
1169
 
1141
1170
  def copy_to_clipboard(required_lines)
@@ -1200,7 +1229,8 @@ module MarkdownExec
1200
1229
  collapse: nil, color_method:, decor_patterns: [],
1201
1230
  disabled: true, format_option:, id: '',
1202
1231
  level: 0, match_data:, type: '',
1203
- wrap: nil
1232
+ wrap: nil,
1233
+ fcb: nil
1204
1234
  )
1205
1235
  line_cap = NamedCaptureExtractor.extract_named_group2(match_data)
1206
1236
  # replace tabs in indent
@@ -1256,23 +1286,44 @@ module MarkdownExec
1256
1286
  )
1257
1287
 
1258
1288
  line_obj[:line] = line_obj[:indent] + line_obj[:text]
1259
- blocks.push FCB.new(
1260
- center: center,
1261
- chrome: true,
1262
- collapse: collapse.nil? ? (line_obj[:collapse] == COLLAPSIBLE_TOKEN_COLLAPSE) : collapse,
1263
- token: line_obj[:collapse],
1264
- disabled: disabled ? TtyMenu::DISABLE : nil,
1265
- id: "#{id}.#{index}",
1266
- level: level,
1267
- s0indent: indent,
1268
- s0printable: line_obj[:text],
1269
- s1decorated: decorated,
1270
- dname: line_obj[:indent] + decorated,
1271
- indent: line_obj[:indent],
1272
- oname: line_obj[:text],
1273
- text: line_obj[:text],
1274
- type: type
1275
- )
1289
+
1290
+ if fcb.nil?
1291
+ fcb = FCB.new(
1292
+ center: center,
1293
+ chrome: true,
1294
+ collapse: collapse.nil? ? (line_obj[:collapse] == COLLAPSIBLE_TOKEN_COLLAPSE) : collapse,
1295
+ token: line_obj[:collapse],
1296
+ disabled: disabled ? TtyMenu::DISABLE : nil,
1297
+ id: "#{id}.#{index}",
1298
+ level: level,
1299
+ s0indent: indent,
1300
+ s0printable: line_obj[:text],
1301
+ s1decorated: decorated,
1302
+ dname: line_obj[:indent] + decorated,
1303
+ indent: line_obj[:indent],
1304
+ oname: line_obj[:text],
1305
+ text: line_obj[:text],
1306
+ type: type
1307
+ )
1308
+ else
1309
+ fcb.center = center
1310
+ fcb.chrome = true
1311
+ fcb.collapse = collapse.nil? ? (line_obj[:collapse] == COLLAPSIBLE_TOKEN_COLLAPSE) : collapse
1312
+ fcb.token = line_obj[:collapse]
1313
+ fcb.disabled = disabled ? TtyMenu::DISABLE : nil
1314
+ fcb.id = "#{id}.#{index}"
1315
+ fcb.level = level
1316
+ fcb.s0indent = indent
1317
+ fcb.s0printable = line_obj[:text]
1318
+ fcb.s1decorated = decorated
1319
+ fcb.dname = line_obj[:indent] + decorated
1320
+ fcb.indent = line_obj[:indent]
1321
+ fcb.oname = line_obj[:text]
1322
+ fcb.text = line_obj[:text]
1323
+ fcb.type = type
1324
+ end
1325
+
1326
+ blocks.push fcb
1276
1327
  end
1277
1328
  line_caps.count
1278
1329
  end
@@ -1292,6 +1343,12 @@ module MarkdownExec
1292
1343
  next
1293
1344
  end
1294
1345
 
1346
+ if block_given?
1347
+ # expand references only if block is recognized (not a comment)
1348
+ yield if block_given?
1349
+ mbody = fcb.body[0].match @delegate_object[criteria[:match]]
1350
+ end
1351
+
1295
1352
  create_and_add_chrome_block(
1296
1353
  blocks: blocks,
1297
1354
  case_conversion: criteria[:case_conversion],
@@ -1312,6 +1369,7 @@ module MarkdownExec
1312
1369
  decor_patterns:
1313
1370
  @decor_patterns_from_delegate_object_for_block_create,
1314
1371
  disabled: !(criteria[:collapsible] && @delegate_object[criteria[:collapsible]]),
1372
+ fcb: fcb,
1315
1373
  id: "#{id}.#{index}",
1316
1374
  format_option: criteria[:format] &&
1317
1375
  @delegate_object[criteria[:format]],
@@ -1324,7 +1382,7 @@ module MarkdownExec
1324
1382
  end
1325
1383
  end
1326
1384
 
1327
- def create_divider(position, id: '')
1385
+ def create_divider(position, source_id: '')
1328
1386
  divider_key = if position == :initial
1329
1387
  :menu_initial_divider
1330
1388
  else
@@ -1337,7 +1395,7 @@ module MarkdownExec
1337
1395
  chrome: true,
1338
1396
  disabled: TtyMenu::DISABLE,
1339
1397
  dname: string_send_color(oname, :menu_divider_color),
1340
- id: id,
1398
+ id: source_id,
1341
1399
  oname: oname
1342
1400
  )
1343
1401
  end
@@ -1420,9 +1478,10 @@ module MarkdownExec
1420
1478
 
1421
1479
  def dml_menu_append_chrome_item(
1422
1480
  name, count, type,
1423
- id: '',
1481
+ always_create: true,
1482
+ always_enable: true,
1424
1483
  menu_state: MenuState::LOAD,
1425
- always_create: true, always_enable: true
1484
+ source_id: ''
1426
1485
  )
1427
1486
  raise unless name.present?
1428
1487
  raise if @dml_menu_blocks.nil?
@@ -1432,7 +1491,7 @@ module MarkdownExec
1432
1491
  # create menu item when it is needed (count > 0)
1433
1492
  #
1434
1493
  if item.nil? && (always_create || count.positive?)
1435
- item = append_chrome_block(id: id,
1494
+ item = append_chrome_block(source_id: source_id,
1436
1495
  menu_blocks: @dml_menu_blocks,
1437
1496
  menu_state: menu_state)
1438
1497
  end
@@ -1688,11 +1747,7 @@ module MarkdownExec
1688
1747
 
1689
1748
  elsif COLLAPSIBLE_TYPES.include?(selected.type)
1690
1749
  debounce_reset
1691
- if @compressed_ids.keys.include?(selected.id)
1692
- @compressed_ids.delete(selected.id)
1693
- else
1694
- @compressed_ids.merge!(selected.id => selected.level)
1695
- end
1750
+ menu_toggle_collapsible_block(selected)
1696
1751
  LoadFileLinkState.new(LoadFile::REUSE, link_state)
1697
1752
 
1698
1753
  elsif debounce_allows
@@ -1880,15 +1935,25 @@ module MarkdownExec
1880
1935
  view: @delegate_object[:vars_block_filename_view]
1881
1936
  )
1882
1937
  block_data = HashDelegator.parse_yaml_data_from_body(selected.body)
1883
- if selected_option = select_option_with_metadata(
1938
+
1939
+ dirs = Dir.glob(
1940
+ File.join(
1941
+ Dir.pwd,
1942
+ block_data['directory'] || directory,
1943
+ block_data['glob'] || glob
1944
+ )
1945
+ )
1946
+
1947
+ if !contains_glob?(block_data['directory']) &&
1948
+ !contains_glob?(block_data['glob'])
1949
+ if dirs[0]
1950
+ File.readlines(dirs[0], chomp: true)
1951
+ else
1952
+ warn 'No matching file found.'
1953
+ end
1954
+ elsif selected_option = select_option_with_metadata(
1884
1955
  prompt_title,
1885
- [exit_prompt] + Dir.glob(
1886
- File.join(
1887
- Dir.pwd,
1888
- block_data['directory'] || directory,
1889
- block_data['glob'] || glob
1890
- )
1891
- ).sort.map do |file|
1956
+ [exit_prompt] + dirs.sort.map do |file|
1892
1957
  { name: format(
1893
1958
  block_data['view'] || view,
1894
1959
  NamedCaptureExtractor.extract_named_group2(
@@ -1908,7 +1973,7 @@ module MarkdownExec
1908
1973
  File.readlines(selected_option.oname, chomp: true)
1909
1974
  end
1910
1975
  else
1911
- warn 'No matching files found'
1976
+ warn 'No matching files found.'
1912
1977
  end
1913
1978
  end
1914
1979
 
@@ -2175,6 +2240,7 @@ module MarkdownExec
2175
2240
  key_format: '${%s}',
2176
2241
  pattern: nil
2177
2242
  )
2243
+ # defined($x) ? '' : ($x = 1; pp [__LINE__, caller.deref])
2178
2244
  pattern ||= options_variable_expression_regexp
2179
2245
  return if pattern.nil?
2180
2246
 
@@ -2397,7 +2463,7 @@ module MarkdownExec
2397
2463
  Regexp.new(@delegate_object.fetch(
2398
2464
  :fenced_start_and_end_regex, '^(?<indent> *)`{3,}'
2399
2465
  )),
2400
- fcb: MarkdownExec::FCB.new,
2466
+ fcb: MarkdownExec::FCB.new(id: 'INIT'),
2401
2467
  in_fenced_block: false,
2402
2468
  headings: []
2403
2469
  }
@@ -2419,16 +2485,16 @@ module MarkdownExec
2419
2485
 
2420
2486
  update_line_and_block_state(
2421
2487
  nested_line, state, selected_types,
2422
- id: "#{@delegate_object[:filename]}:#{index}",
2488
+ source_id: "#{@delegate_object[:filename]}_ibfnf_#{index}",
2423
2489
  &block
2424
2490
  )
2425
2491
  end
2426
2492
  end
2427
2493
 
2428
- def iter_source_blocks(source, &block)
2494
+ def iter_source_blocks(source, source_id: nil, &block)
2429
2495
  case source
2430
2496
  when 1
2431
- blocks_from_nested_files.each(&block)
2497
+ blocks_from_nested_files(source_id: source_id).each(&block)
2432
2498
  when 2
2433
2499
  @dml_blocks_in_file.each(&block)
2434
2500
  when 3
@@ -2548,12 +2614,14 @@ module MarkdownExec
2548
2614
  }
2549
2615
  end
2550
2616
 
2551
- def list_blocks
2617
+ def list_blocks(source_id: nil)
2552
2618
  message = @delegate_object[:list_blocks_message]
2553
2619
  block_eval = @delegate_object[:list_blocks_eval]
2554
2620
 
2555
2621
  list = []
2556
- iter_source_blocks(@delegate_object[:list_blocks_type]) do |block|
2622
+ iter_source_blocks(
2623
+ @delegate_object[:list_blocks_type], source_id: source_id
2624
+ ) do |block|
2557
2625
  list << (block_eval.present? ? eval(block_eval) : block.send(message))
2558
2626
  end
2559
2627
  list.compact!
@@ -2566,7 +2634,7 @@ module MarkdownExec
2566
2634
  # Executes a specified block once per filename.
2567
2635
  # @param all_blocks [Array] Array of all block elements.
2568
2636
  # @return [Boolean, nil] True if values were modified, nil otherwise.
2569
- def load_auto_opts_block(all_blocks, id: '', mdoc:)
2637
+ def load_auto_opts_block(all_blocks, mdoc:)
2570
2638
  block_name = @delegate_object[:document_load_opts_block_name]
2571
2639
  unless block_name.present? &&
2572
2640
  @opts_most_recent_filename != @delegate_object[:filename]
@@ -2586,6 +2654,30 @@ module MarkdownExec
2586
2654
  true
2587
2655
  end
2588
2656
 
2657
+ def load_document_shell_block(all_blocks, mdoc: nil)
2658
+ block_name = @delegate_object[:document_load_shell_block_name]
2659
+ unless block_name.present? &&
2660
+ @shell_most_recent_filename != @delegate_object[:filename]
2661
+ return
2662
+ end
2663
+
2664
+ fcb = HashDelegator.block_find(all_blocks, :oname, block_name)
2665
+ return unless fcb
2666
+
2667
+ @shell_most_recent_filename = @delegate_object[:filename]
2668
+
2669
+ if mdoc
2670
+ mdoc.collect_recursively_required_code(
2671
+ anyname: fcb.pub_name,
2672
+ label_format_above: @delegate_object[:shell_code_label_format_above],
2673
+ label_format_below: @delegate_object[:shell_code_label_format_below],
2674
+ block_source: block_source
2675
+ )[:code]
2676
+ else
2677
+ fcb.body
2678
+ end
2679
+ end
2680
+
2589
2681
  def load_auto_vars_block(all_blocks,
2590
2682
  block_name: @delegate_object[:document_load_vars_block_name])
2591
2683
  unless block_name.present? &&
@@ -2628,7 +2720,7 @@ module MarkdownExec
2628
2720
  expanded_expression = formatted_expression(expression)
2629
2721
 
2630
2722
  # Handle wildcards or direct file specification
2631
- if contains_wildcards?(expanded_expression)
2723
+ if contains_glob?(expanded_expression)
2632
2724
  load_filespec_wildcard_expansion(expanded_expression)
2633
2725
  else
2634
2726
  expanded_expression
@@ -2676,8 +2768,8 @@ module MarkdownExec
2676
2768
  [block_name_from_cli, now_using_cli]
2677
2769
  end
2678
2770
 
2679
- def mdoc_and_blocks_from_nested_files
2680
- menu_blocks = blocks_from_nested_files
2771
+ def mdoc_and_blocks_from_nested_files(source_id: nil)
2772
+ menu_blocks = blocks_from_nested_files(source_id: source_id)
2681
2773
  mdoc = MDoc.new(menu_blocks) do |nopts|
2682
2774
  @delegate_object.merge!(nopts)
2683
2775
  end
@@ -2687,12 +2779,19 @@ module MarkdownExec
2687
2779
  ## Handles the file loading and returns the blocks
2688
2780
  # in the file and MDoc instance
2689
2781
  #
2690
- def mdoc_menu_and_blocks_from_nested_files(link_state, id: '')
2782
+ def mdoc_menu_and_blocks_from_nested_files(link_state, source_id: '')
2691
2783
  # read blocks, load document opts block, and re-process blocks
2692
2784
  #
2693
- all_blocks, mdoc = mdoc_and_blocks_from_nested_files
2694
- if load_auto_opts_block(all_blocks, id: id, mdoc: mdoc)
2695
- all_blocks, mdoc = mdoc_and_blocks_from_nested_files
2785
+ all_blocks, mdoc = mdoc_and_blocks_from_nested_files(source_id: source_id)
2786
+ if load_auto_opts_block(all_blocks, mdoc: mdoc)
2787
+ all_blocks, mdoc = mdoc_and_blocks_from_nested_files(source_id: source_id)
2788
+ end
2789
+
2790
+ # load document shell block
2791
+ #
2792
+ if code_lines = load_document_shell_block(all_blocks, mdoc: mdoc)
2793
+ next_state_set_code(nil, link_state, code_lines)
2794
+ link_state.inherited_lines = code_lines
2696
2795
  end
2697
2796
 
2698
2797
  # load document vars block
@@ -2700,11 +2799,7 @@ module MarkdownExec
2700
2799
  if code_lines = load_auto_vars_block(all_blocks)
2701
2800
  new_code = HashDelegator.code_merge(link_state.inherited_lines,
2702
2801
  code_lines)
2703
- next_state_set_code(
2704
- nil,
2705
- link_state,
2706
- new_code
2707
- )
2802
+ next_state_set_code(nil, link_state, new_code)
2708
2803
  link_state.inherited_lines = new_code
2709
2804
  end
2710
2805
 
@@ -2714,10 +2809,22 @@ module MarkdownExec
2714
2809
  @delegate_object.merge!(compressed_ids: @compressed_ids)
2715
2810
  )
2716
2811
 
2812
+ # re-expand blocks
2813
+ menu_blocks.each do |fcb|
2814
+ fcb.body = fcb.raw_body || fcb.body || []
2815
+ fcb.dname = fcb.raw_dname || fcb.dname
2816
+ fcb.s0printable = fcb.raw_s0printable || fcb.s0printable
2817
+ fcb.s1decorated = fcb.raw_s1decorated || fcb.s1decorated
2818
+ expand_references!(fcb, link_state)
2819
+ end
2820
+
2717
2821
  # chrome for menu
2718
2822
  #
2719
- add_menu_chrome_blocks!(id: id, menu_blocks: menu_blocks,
2720
- link_state: link_state)
2823
+ add_menu_chrome_blocks!(
2824
+ link_state: link_state,
2825
+ menu_blocks: menu_blocks,
2826
+ source_id: source_id
2827
+ )
2721
2828
 
2722
2829
  ### compress empty lines
2723
2830
  HashDelegator.delete_consecutive_blank_lines!(menu_blocks)
@@ -2743,6 +2850,7 @@ module MarkdownExec
2743
2850
  dname: HashDelegator.new(@delegate_object).string_send_color(
2744
2851
  document_glob, :menu_inherited_lines_color
2745
2852
  ),
2853
+ # 2025-01-03 menu item is disabled ∴ does not need a recall id
2746
2854
  oname: formatted_name
2747
2855
  )
2748
2856
 
@@ -2783,6 +2891,22 @@ module MarkdownExec
2783
2891
  end
2784
2892
  end
2785
2893
 
2894
+ def menu_compress_collapsible_block(selected)
2895
+ @compressed_ids.merge!(selected.id => selected.level)
2896
+ end
2897
+
2898
+ def menu_expand_collapsible_block(selected)
2899
+ @compressed_ids.delete(selected.id)
2900
+ end
2901
+
2902
+ def menu_toggle_collapsible_block(selected)
2903
+ if @compressed_ids.keys.include?(selected.id)
2904
+ menu_expand_collapsible_block(selected)
2905
+ else
2906
+ menu_compress_collapsible_block(selected)
2907
+ end
2908
+ end
2909
+
2786
2910
  # If a method is missing, treat it as a key for the @delegate_object.
2787
2911
  def method_missing(method_name, *args, &block)
2788
2912
  if @delegate_object.respond_to?(method_name)
@@ -3435,7 +3559,7 @@ module MarkdownExec
3435
3559
  formatted = formatted_expression(expression)
3436
3560
 
3437
3561
  # Handle wildcards or direct file specification
3438
- if contains_wildcards?(formatted)
3562
+ if contains_glob?(formatted)
3439
3563
  save_filespec_wildcard_expansion(formatted)
3440
3564
  else
3441
3565
  formatted
@@ -3579,11 +3703,14 @@ module MarkdownExec
3579
3703
  item == selection
3580
3704
  end
3581
3705
  end
3706
+
3707
+ # new FCB if selected is not an object
3582
3708
  if selected.instance_of?(String)
3583
3709
  selected = FCB.new(dname: selected)
3584
3710
  elsif selected.instance_of?(Hash)
3585
3711
  selected = FCB.new(selected)
3586
3712
  end
3713
+
3587
3714
  unless selected
3588
3715
  HashDelegator.error_handler('select_option_with_metadata',
3589
3716
  error: 'menu item not found')
@@ -3651,7 +3778,9 @@ module MarkdownExec
3651
3778
  # @param fenced_start_extended_regex [Regexp]
3652
3779
  # Regular expression to identify fenced block start.
3653
3780
  # @return [MarkdownExec::FCB] A new FCB instance with the parsed attributes.
3654
- def start_fenced_block(line, headings, fenced_start_extended_regex)
3781
+ def start_fenced_block(
3782
+ line, headings, fenced_start_extended_regex, source_id: nil
3783
+ )
3655
3784
  fcb_title_groups = NamedCaptureExtractor.extract_named_groups(
3656
3785
  line, fenced_start_extended_regex
3657
3786
  )
@@ -3702,6 +3831,7 @@ module MarkdownExec
3702
3831
  disabled: disabled,
3703
3832
  dname: dname,
3704
3833
  headings: headings,
3834
+ id: source_id.to_s,
3705
3835
  indent: fcb_title_groups.fetch(:indent, ''),
3706
3836
  nickname: nickname,
3707
3837
  oname: oname,
@@ -3764,7 +3894,7 @@ module MarkdownExec
3764
3894
  ##
3765
3895
  def update_line_and_block_state(
3766
3896
  nested_line, state, selected_types,
3767
- id:,
3897
+ source_id:,
3768
3898
  &block
3769
3899
  )
3770
3900
  line = nested_line.to_s
@@ -3784,7 +3914,8 @@ module MarkdownExec
3784
3914
  #
3785
3915
  state[:fcb] = start_fenced_block(
3786
3916
  line, state[:headings],
3787
- @delegate_object[:fenced_start_extended_regex]
3917
+ @delegate_object[:fenced_start_extended_regex],
3918
+ source_id: source_id
3788
3919
  )
3789
3920
  state[:fcb][:depth] = nested_line[:depth]
3790
3921
  state[:fcb][:indention] = nested_line[:indention]
@@ -3801,8 +3932,9 @@ module MarkdownExec
3801
3932
  @delegate_object[:menu_include_imported_notes]
3802
3933
  # add line if it is depth 0 or option allows it
3803
3934
  #
3804
- HashDelegator.yield_line_if_selected(line, selected_types, id: id,
3805
- &block)
3935
+ HashDelegator.yield_line_if_selected(
3936
+ line, selected_types, source_id: source_id, &block
3937
+ )
3806
3938
  end
3807
3939
  end
3808
3940
 
@@ -4078,15 +4210,20 @@ module MarkdownExec
4078
4210
  end
4079
4211
  end
4080
4212
 
4213
+ count = 0
4081
4214
  InputSequencer.new(
4082
4215
  @delegate_object[:filename],
4083
4216
  block_list
4084
4217
  ).run do |msg, data|
4218
+ count += 1
4085
4219
  case msg
4086
4220
  when :parse_document # once for each menu
4087
- vux_parse_document(id: 'vux_parse_document')
4088
- vux_menu_append_history_files(formatted_choice_ostructs,
4089
- id: 'vux_menu_append_history_files')
4221
+ count = 0
4222
+ vux_parse_document(source_id: "#{@delegate_object[:filename]}_vmlpd")
4223
+ vux_menu_append_history_files(
4224
+ formatted_choice_ostructs,
4225
+ source_id: "#{@delegate_object[:filename]}_vmlhf"
4226
+ )
4090
4227
  vux_publish_document_file_name_for_external_automation
4091
4228
 
4092
4229
  when :display_menu
@@ -4097,7 +4234,7 @@ module MarkdownExec
4097
4234
  # yield :end_of_cli, @delegate_object
4098
4235
 
4099
4236
  if @delegate_object[:list_blocks]
4100
- list_blocks
4237
+ list_blocks(source_id: "#{@delegate_object[:filename]}_vmleoc")
4101
4238
  :exit
4102
4239
  end
4103
4240
 
@@ -4132,8 +4269,9 @@ module MarkdownExec
4132
4269
  end
4133
4270
  end
4134
4271
 
4135
- def vux_menu_append_history_files(formatted_choice_ostructs,
4136
- id: '')
4272
+ def vux_menu_append_history_files(
4273
+ formatted_choice_ostructs, source_id: ''
4274
+ )
4137
4275
  if @delegate_object[:menu_for_history]
4138
4276
  history_files(
4139
4277
  @dml_link_state,
@@ -4145,8 +4283,8 @@ module MarkdownExec
4145
4283
  dml_menu_append_chrome_item(
4146
4284
  formatted_choice_ostructs[:history].oname, files.count,
4147
4285
  'files',
4148
- id: id,
4149
- menu_state: MenuState::HISTORY
4286
+ menu_state: MenuState::HISTORY,
4287
+ source_id: source_id
4150
4288
  )
4151
4289
  end
4152
4290
  end
@@ -4168,38 +4306,38 @@ module MarkdownExec
4168
4306
  if files.count.positive?
4169
4307
  dml_menu_append_chrome_item(
4170
4308
  formatted_choice_ostructs[:load].dname, files.count, 'files',
4171
- id: "#{id}.load",
4172
- menu_state: MenuState::LOAD
4309
+ menu_state: MenuState::LOAD,
4310
+ source_id: "#{source_id}_vmahf_load"
4173
4311
  )
4174
4312
  end
4175
4313
  if @delegate_object[:menu_inherited_lines_edit_always] ||
4176
4314
  lines_count.positive?
4177
4315
  dml_menu_append_chrome_item(
4178
4316
  formatted_choice_ostructs[:edit].dname, lines_count, 'lines',
4179
- id: "#{id}.edit",
4180
- menu_state: MenuState::EDIT
4317
+ menu_state: MenuState::EDIT,
4318
+ source_id: "#{source_id}_vmahf_edit"
4181
4319
  )
4182
4320
  end
4183
4321
  if lines_count.positive?
4184
4322
  dml_menu_append_chrome_item(
4185
4323
  formatted_choice_ostructs[:save].dname, 1, '',
4186
- id: "#{id}.save",
4187
- menu_state: MenuState::SAVE
4324
+ menu_state: MenuState::SAVE,
4325
+ source_id: "#{source_id}_vmahf_save"
4188
4326
  )
4189
4327
  end
4190
4328
  if lines_count.positive?
4191
4329
  dml_menu_append_chrome_item(
4192
4330
  formatted_choice_ostructs[:view].dname, 1, '',
4193
- id: "#{id}.view",
4194
- menu_state: MenuState::VIEW
4331
+ menu_state: MenuState::VIEW,
4332
+ source_id: "#{source_id}_vmahf_view"
4195
4333
  )
4196
4334
  end
4197
4335
  # rubocop:disable Style/GuardClause
4198
4336
  if @delegate_object[:menu_with_shell]
4199
4337
  dml_menu_append_chrome_item(
4200
4338
  formatted_choice_ostructs[:shell].dname, 1, '',
4201
- id: "#{id}.shell",
4202
- menu_state: MenuState::SHELL
4339
+ menu_state: MenuState::SHELL,
4340
+ source_id: "#{source_id}_vmahf_shell"
4203
4341
  )
4204
4342
  end
4205
4343
  # rubocop:enable Style/GuardClause
@@ -4217,7 +4355,7 @@ module MarkdownExec
4217
4355
  )
4218
4356
  end
4219
4357
 
4220
- def vux_parse_document(id: '')
4358
+ def vux_parse_document(source_id: '')
4221
4359
  @run_state.batch_index += 1
4222
4360
  @run_state.in_own_window = false
4223
4361
 
@@ -4239,7 +4377,9 @@ module MarkdownExec
4239
4377
  # update @delegate_object and @menu_base_options in auto_load
4240
4378
  #
4241
4379
  @dml_blocks_in_file, @dml_menu_blocks, @dml_mdoc =
4242
- mdoc_menu_and_blocks_from_nested_files(@dml_link_state, id: id)
4380
+ mdoc_menu_and_blocks_from_nested_files(
4381
+ @dml_link_state, source_id: source_id
4382
+ )
4243
4383
  dump_delobj(@dml_blocks_in_file, @dml_menu_blocks, @dml_link_state)
4244
4384
  end
4245
4385
 
@@ -94,13 +94,18 @@ class InputSequencer
94
94
  break if exit_when_bq_empty && bq_is_empty? && !now_menu.prior_block_was_link
95
95
 
96
96
  if now_menu.display_menu
97
+ # !!b
97
98
  break if run_yield(:end_of_cli, &block) == :exit
99
+ # !!b
98
100
 
99
101
  exit_when_bq_empty = false
100
102
  run_yield :display_menu, &block
103
+ # !!b
101
104
 
102
105
  choice = run_yield :user_choice, &block
106
+ # !!b
103
107
  break if choice == :break
108
+ # !!b
104
109
 
105
110
  raise BlockMissing, 'Block not recognized.' if choice.nil?
106
111
  # Exit loop and method to terminate the app
@@ -115,7 +120,9 @@ class InputSequencer
115
120
  if now_menu.block_name && !now_menu.block_name.empty?
116
121
  block_name = now_menu.block_name
117
122
  else
123
+ # break if bq_is_empty? # Exit loop if no more blocks to process
118
124
  if bq_is_empty? # Exit loop if no more blocks to process
125
+ # !!b
119
126
  run_yield :end_of_cli, &block
120
127
  break
121
128
  end
@@ -7,5 +7,5 @@ module MarkdownExec
7
7
  BIN_NAME = 'mde'
8
8
  GEM_NAME = 'markdown_exec'
9
9
  TAP_DEBUG = 'MDE_DEBUG'
10
- VERSION = '2.7.1'
10
+ VERSION = '2.7.2'
11
11
  end
data/lib/mdoc.rb CHANGED
@@ -177,12 +177,12 @@ module MarkdownExec
177
177
  blocks.map do |block|
178
178
  (block[:wraps] || []).map do |wrap|
179
179
  wrap_before = wrap.sub('}', '-before}') ### hardcoded wrap name
180
- @table.select { |fcb| [wrap_before, wrap].include? fcb.oname }
180
+ @table.select { |fcb| fcb.code_name_included?(wrap_before, wrap) }
181
181
  end.flatten(1) +
182
182
  [block] +
183
183
  (block[:wraps] || []).reverse.map do |wrap|
184
184
  wrap_after = wrap.sub('}', '-after}') ### hardcoded wrap name
185
- @table.select { |fcb| fcb.oname == wrap_after }
185
+ @table.select { |fcb| fcb.code_name_included?(wrap_after) }
186
186
  end.flatten(1)
187
187
  end.flatten(1).compact
188
188
  end
@@ -623,25 +623,22 @@ if $PROGRAM_NAME == __FILE__
623
623
  # Mocking the @table object for testing
624
624
  def setup
625
625
  @table = [
626
- OpenStruct.new(oname: '{wrap1}'),
627
- OpenStruct.new(oname: '{wrap2-before}'),
628
- OpenStruct.new(oname: '{wrap2}'),
629
- OpenStruct.new(oname: '{wrap2-after}'),
630
- OpenStruct.new(oname: '{wrap3-before}'),
631
- OpenStruct.new(oname: '{wrap3}'),
632
- OpenStruct.new(oname: '{wrap3-after}')
626
+ FCB.new(oname: '{wrap1}'),
627
+ FCB.new(oname: '{wrap2-before}'),
628
+ FCB.new(oname: '{wrap2}'),
629
+ FCB.new(oname: '{wrap2-after}'),
630
+ FCB.new(oname: '{wrap3-before}'),
631
+ FCB.new(oname: '{wrap3}'),
632
+ FCB.new(oname: '{wrap3-after}')
633
633
  ]
634
634
  @mdoc = MDoc.new(@table)
635
635
  end
636
636
 
637
637
  def test_collect_wrapped_blocks
638
638
  # Test case 1: blocks with wraps
639
- OpenStruct.new(oname: 'block1')
640
-
641
639
  assert_equal(%w[{wrap2-before} {wrap2} b {wrap2-after}],
642
640
  @mdoc.collect_wrapped_blocks(
643
- [OpenStruct.new(oname: 'b',
644
- wraps: ['{wrap2}'])]
641
+ [FCB.new(oname: 'b', wraps: ['{wrap2}'])]
645
642
  ).map(&:oname))
646
643
 
647
644
  assert_equal(%w[{wrap2-before} {wrap2} {wrap3-before} {wrap3} c {wrap3-after} {wrap2-after}],
data/lib/menu.src.yml CHANGED
@@ -200,6 +200,12 @@
200
200
  :default: "(document_opts)"
201
201
  :procname: val_as_str
202
202
 
203
+ - :opt_name: document_load_shell_block_name
204
+ :env_var: MDE_DOCUMENT_LOAD_SHELL_BLOCK_NAME
205
+ :description: Name of shell block to load with the document
206
+ :default: "(document_shell)"
207
+ :procname: val_as_str
208
+
203
209
  - :opt_name: document_load_vars_block_name
204
210
  :env_var: MDE_DOCUMENT_LOAD_VARS_BLOCK_NAME
205
211
  :description: Name of Vars block to load with the document
@@ -676,8 +682,7 @@
676
682
  :env_var: MDE_MENU_ACTIVE_COLOR_PASTEL_MESSAGES
677
683
  :description: menu_active_color_pastel_messages
678
684
  :default:
679
- - bright_magenta
680
- - on_black
685
+ - inverse
681
686
 
682
687
  - :opt_name: menu_back_at_top
683
688
  :env_var: MDE_MENU_BACK_AT_TOP
data/lib/menu.yml CHANGED
@@ -166,6 +166,11 @@
166
166
  :description: Name of Opts block to load with the document
167
167
  :default: "(document_opts)"
168
168
  :procname: val_as_str
169
+ - :opt_name: document_load_shell_block_name
170
+ :env_var: MDE_DOCUMENT_LOAD_SHELL_BLOCK_NAME
171
+ :description: Name of shell block to load with the document
172
+ :default: "(document_shell)"
173
+ :procname: val_as_str
169
174
  - :opt_name: document_load_vars_block_name
170
175
  :env_var: MDE_DOCUMENT_LOAD_VARS_BLOCK_NAME
171
176
  :description: Name of Vars block to load with the document
@@ -572,8 +577,7 @@
572
577
  :env_var: MDE_MENU_ACTIVE_COLOR_PASTEL_MESSAGES
573
578
  :description: menu_active_color_pastel_messages
574
579
  :default:
575
- - bright_magenta
576
- - on_black
580
+ - inverse
577
581
  - :opt_name: menu_back_at_top
578
582
  :env_var: MDE_MENU_BACK_AT_TOP
579
583
  :description: Display Back option at top of menu (vs bottom)
data/lib/ww.rb CHANGED
@@ -24,7 +24,7 @@ def ww0(*objs,
24
24
  category: nil,
25
25
  full_backtrace: false,
26
26
  level: :debug,
27
- locations: caller_locations,
27
+ locations: caller_locations[1..-1],
28
28
  log_file: nil,
29
29
  output: $stderr,
30
30
  single_line: false,
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: markdown_exec
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.7.1
4
+ version: 2.7.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Fareed Stevenson
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-12-10 00:00:00.000000000 Z
11
+ date: 2025-01-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: clipboard
@@ -108,8 +108,10 @@ files:
108
108
  - assets/select_a_file.png
109
109
  - bats/bats.bats
110
110
  - bats/block-types.bats
111
+ - bats/border.bats
111
112
  - bats/cli.bats
112
113
  - bats/command-substitution.bats
114
+ - bats/document-shell.bats
113
115
  - bats/fail.bats
114
116
  - bats/history.bats
115
117
  - bats/import.bats
@@ -134,9 +136,11 @@ files:
134
136
  - docs/dev/block-type-opts.md
135
137
  - docs/dev/block-type-port.md
136
138
  - docs/dev/block-type-vars.md
139
+ - docs/dev/border.md
137
140
  - docs/dev/command-substitution.md
138
141
  - docs/dev/data-blocks.md
139
142
  - docs/dev/disable.md
143
+ - docs/dev/document-shell.md
140
144
  - docs/dev/import-missing.md
141
145
  - docs/dev/import.md
142
146
  - docs/dev/linked-file.md