markdown_exec 3.1.0 → 3.2.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 401f0583b9951f0cfd6259313d7120d2f5f7fbbb3c596110eeafe449f63b9ca7
4
- data.tar.gz: 8c411e5c1f3ae394d76a2e0fbbc92aae009e31ba0e17b9fa29d30dabfd8b8e5a
3
+ metadata.gz: 8c39aff829d6b7a3d4eb05134922cdb6fed1d54192fab72ba244d7d7ff73183e
4
+ data.tar.gz: f2bbfa6b9be857c718ba23c1bbc071b91ffe7ba027626c9a27b1d06c8bfce5a9
5
5
  SHA512:
6
- metadata.gz: 896ac3441e10cac18bbccbe02913612f8a926a7108dd86a9b01d0dc8354d1da4f8ca58dcb8413f460072277802639be2bd4421efc83abced9e18ea9212505010
7
- data.tar.gz: 4804a98ff4a6ff6a5d7ba7dc0739e6ec2d6b7a115dd7f6198955261bf1d07ed62e93c9d1180570e14f3d1e43e6a59a6ae587c21fbbd13d02491b79ad7ac92e1e
6
+ metadata.gz: 1b97c91ff7b91da388ff9d3aed19ee5e15fd25bd4d6e8f3591a8997614736e27e1c12fb3682a3395bae5853131578b924cbf55284ffda2beb9b89843c8b7c2b7
7
+ data.tar.gz: 3056e41d512fa097204cae511a057b193c5ad3c70e406dee3da1df369bb0bed4f517137cf55e86ac6fcdc1308b70d604c75e9c2c2ee8c9b30edf0d5f574c006e
data/CHANGELOG.md CHANGED
@@ -1,5 +1,31 @@
1
1
  # Changelog
2
2
 
3
+ ## [3.2.0] - 2025-07-24
4
+
5
+ ### Added
6
+
7
+ - Option for number of inactive lines requiring a scroll point.
8
+ - Option for variables to not export from a series.
9
+ Some intermediate results are not to be exported.
10
+ Names matching the regular expression are available for
11
+ calculation within the block but not after.
12
+
13
+ ### Changed
14
+
15
+ - Intermediate results are available.
16
+ Fix the evaluation of sequences of expressions by providing
17
+ script lines for intermediate results.
18
+ - Complete backtrace is available for exceptions.
19
+ - Prevent abort when executing a block.
20
+ Often raised by YAML parsing.
21
+
22
+ ## [3.1.1] - 2025-06-28
23
+
24
+ ### Changed
25
+
26
+ - Fix inherited lines for chained blocks.
27
+ - Optimize import text replacement.
28
+
3
29
  ## [3.1.0] - 2025-06-23
4
30
 
5
31
  ### Added
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- markdown_exec (3.1.0)
4
+ markdown_exec (3.2.0)
5
5
  clipboard (~> 1.3.6)
6
6
  open3 (~> 0.1.1)
7
7
  optparse (~> 0.1.1)
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env bats
2
+
3
+ load 'test_helper'
4
+
5
+ @test 'initial value, inherited lines' {
6
+ spec_mde_xansi_dname_doc_blocks_expect docs/dev/block-type-ux-require-chained.md \
7
+ '[SPECIES]' \
8
+ 'ENTITY = Pongo tapanuliensis,Pongo_ENTITY="Pongo tapanuliensis,Pongo"_SPECIES=Pongo\ tapanuliensis_GENUS=Pongo_NAME=Pongo\ tapanuliensis\ -\ Pongo_NAME2=Pongo\ tapanuliensis\ -\ Pongo_SPECIES=Pongo tapanuliensis_GENUS=Pongo_NAME=Pongo tapanuliensis - Pongo_NAME2=Pongo tapanuliensis - Pongo'
9
+ }
@@ -6,3 +6,9 @@ load 'test_helper'
6
6
  spec_mde_xansi_dname_doc_blocks_expect docs/dev/block-type-ux-require.md \
7
7
  'SPECIES=Pongo tapanuliensis_GENUS=Pongo_NAME=Pongo tapanuliensis - Pongo_NAME2=Pongo tapanuliensis - Pongo'
8
8
  }
9
+
10
+ @test 'inherited lines' {
11
+ spec_mde_xansi_dname_doc_blocks_expect docs/dev/block-type-ux-require.md \
12
+ '(menu_with_inherited_lines)' \
13
+ 'SPECIES=Pongo\ tapanuliensis_GENUS=Pongo_NAME=Pongo\ tapanuliensis\ -\ Pongo_NAME2=Pongo\ tapanuliensis\ -\ Pongo_SPECIES=Pongo tapanuliensis_GENUS=Pongo_NAME=Pongo tapanuliensis - Pongo_NAME2=Pongo tapanuliensis - Pongo'
14
+ }
@@ -4,23 +4,23 @@ load 'test_helper'
4
4
 
5
5
  @test 'document initial state' {
6
6
  spec_mde_xansi_dname_doc_blocks_expect docs/dev/load-vars-state-demo.md \
7
- 'var1 = line1_var3 = line6_ inherited_lines_ - : var1="line1"_ - : var3="line6"_ LOAD BLOCK STATE MODIFICATION DEMO__This document demonstrates how a LOAD block can modify the inherited state that was initially set_by VARS blocks.__First, establish baseline variables using a VARS block:__Use a LOAD block to modify the initial state:__load-mode-default_load-mode-append_load-mode-replace'
7
+ 'var1 = line1_var3 = line6_ inherited_lines_ - : var1="line1"_ - : var3="line6"_ LOAD BLOCK STATE MODIFICATION DEMO__This document demonstrates how a LOAD block can modify_the inherited state that was initially set by VARS_blocks.__First, establish baseline variables using a VARS block:__Use a LOAD block to modify the initial state:__load-mode-default_load-mode-append_load-mode-replace'
8
8
  }
9
9
 
10
10
  @test 'load-mode-default' {
11
11
  spec_mde_xansi_dname_doc_blocks_expect docs/dev/load-vars-state-demo.md \
12
12
  load-mode-default \
13
- 'var1 = line1_var3 = line6_ inherited_lines_ - : var1="line1"_ - : var3="line6"_ inherited_lines_ - : var1="line1"_ - : var3="line6"_ - : # line 1_ - : var1=line2_ - : # line 3_ - : var2=line4_ - : # line 5_ LOAD BLOCK STATE MODIFICATION DEMO__This document demonstrates how a LOAD block can modify the inherited state that was initially set_by VARS blocks.__First, establish baseline variables using a VARS block:__Use a LOAD block to modify the initial state:__load-mode-default_load-mode-append_load-mode-replace'
13
+ 'var1 = line1_var3 = line6_ inherited_lines_ - : var1="line1"_ - : var3="line6"_ inherited_lines_ - : var1="line1"_ - : var3="line6"_ - : # line 1_ - : var1=line2_ - : # line 3_ - : var2=line4_ - : # line 5_ LOAD BLOCK STATE MODIFICATION DEMO__This document demonstrates how a LOAD block can modify_the inherited state that was initially set by VARS_blocks.__First, establish baseline variables using a VARS block:__Use a LOAD block to modify the initial state:__load-mode-default_load-mode-append_load-mode-replace'
14
14
  }
15
15
 
16
16
  @test 'load-mode-append' {
17
17
  spec_mde_xansi_dname_doc_blocks_expect docs/dev/load-vars-state-demo.md \
18
18
  load-mode-append \
19
- 'var1 = line1_var3 = line6_ inherited_lines_ - : var1="line1"_ - : var3="line6"_ inherited_lines_ - : var1="line1"_ - : var3="line6"_ - : # line 1_ - : var1=line2_ - : # line 3_ - : var2=line4_ - : # line 5_ LOAD BLOCK STATE MODIFICATION DEMO__This document demonstrates how a LOAD block can modify the inherited state that was initially set_by VARS blocks.__First, establish baseline variables using a VARS block:__Use a LOAD block to modify the initial state:__load-mode-default_load-mode-append_load-mode-replace'
19
+ 'var1 = line1_var3 = line6_ inherited_lines_ - : var1="line1"_ - : var3="line6"_ inherited_lines_ - : var1="line1"_ - : var3="line6"_ - : # line 1_ - : var1=line2_ - : # line 3_ - : var2=line4_ - : # line 5_ LOAD BLOCK STATE MODIFICATION DEMO__This document demonstrates how a LOAD block can modify_the inherited state that was initially set by VARS_blocks.__First, establish baseline variables using a VARS block:__Use a LOAD block to modify the initial state:__load-mode-default_load-mode-append_load-mode-replace'
20
20
  }
21
21
 
22
22
  @test 'load-mode-replace' {
23
23
  spec_mde_xansi_dname_doc_blocks_expect docs/dev/load-vars-state-demo.md \
24
24
  load-mode-replace \
25
- 'var1 = line1_var3 = line6_ inherited_lines_ - : var1="line1"_ - : var3="line6"_ inherited_lines_ - : # line 1_ - : var1=line2_ - : # line 3_ - : var2=line4_ - : # line 5_ LOAD BLOCK STATE MODIFICATION DEMO__This document demonstrates how a LOAD block can modify the inherited state that was initially set_by VARS blocks.__First, establish baseline variables using a VARS block:__Use a LOAD block to modify the initial state:__load-mode-default_load-mode-append_load-mode-replace'
25
+ 'var1 = line1_var3 = line6_ inherited_lines_ - : var1="line1"_ - : var3="line6"_ inherited_lines_ - : # line 1_ - : var1=line2_ - : # line 3_ - : var2=line4_ - : # line 5_ LOAD BLOCK STATE MODIFICATION DEMO__This document demonstrates how a LOAD block can modify_the inherited state that was initially set by VARS_blocks.__First, establish baseline variables using a VARS block:__Use a LOAD block to modify the initial state:__load-mode-default_load-mode-append_load-mode-replace'
26
26
  }
@@ -0,0 +1,33 @@
1
+ / UX blocks may requiring other UX blocks
2
+ ```vars :(document_vars)
3
+ ENTITY: Pongo tapanuliensis,Pongo
4
+ ```
5
+ ```ux :[SPECIES] +[GENUS] +[NAME]
6
+ act: :echo
7
+ echo: "${ENTITY%%,*}"
8
+ force: true
9
+ init: false
10
+ name: SPECIES
11
+ ```
12
+ ```ux :[GENUS]
13
+ echo: "${ENTITY##*,}"
14
+ force: true
15
+ init: false
16
+ name: GENUS
17
+ ```
18
+ ```ux :[NAME] +[NAME2]
19
+ echo: "$SPECIES - $GENUS"
20
+ force: true
21
+ init: false
22
+ name: NAME
23
+ ```
24
+ ```ux :[NAME2]
25
+ echo: "$NAME"
26
+ force: true
27
+ init: false
28
+ name: NAME2
29
+ ```
30
+ ```opts :(document_opts)
31
+ menu_with_inherited_lines: true
32
+ ```
33
+ @import bats-document-configuration.md
@@ -4,20 +4,28 @@ ENTITY='Pongo tapanuliensis,Pongo'
4
4
  ```
5
5
  ```ux +(shell)
6
6
  echo: "${ENTITY%%,*}"
7
+ force: true
7
8
  name: SPECIES
8
9
  ```
9
10
  ```ux +(shell)
10
11
  echo: "${ENTITY##*,}"
12
+ force: true
11
13
  name: GENUS
12
14
  ```
13
15
  / executed in context of prior ux blocks, uses their initial values
14
16
  ```ux
15
17
  echo: "$SPECIES - $GENUS"
18
+ force: true
16
19
  name: NAME
17
20
  ```
18
21
  / executed after other ux blocks, uses their initial values
19
22
  ```ux
20
23
  echo: "$NAME"
24
+ force: true
21
25
  name: NAME2
22
26
  ```
27
+ / This block is not visible. Execute to display the inherited lines for testing.
28
+ ```opts :(menu_with_inherited_lines)
29
+ menu_with_inherited_lines: true
30
+ ```
23
31
  @import bats-document-configuration.md
@@ -61,19 +61,20 @@ transform: '%{major}.%{minor}.%{patch}'
61
61
  name: BRANCH_NAME
62
62
  init: ":exec"
63
63
  exec: "git branch --format='%(refname:short)'"
64
- validate: "^(?<type>feature|bugfix|hotfix)/(?<ticket>[A-Z]+-\d+)-(?<desc>.+)$"
64
+ validate: '^(?<type>feature|bugfix|hotfix)/(?<ticket>[A-Z]+-\d+)-(?<desc>.+)$'
65
65
  transform: "${type}/${ticket}-${desc}"
66
66
  prompt: "Select or enter branch name"
67
67
  ```
68
68
 
69
69
  ### Environment Configuration with Dependencies
70
- ```ux
70
+ ```ux @attrs[:body]
71
71
  name: DATABASE_URL
72
72
  require:
73
73
  - ENVIRONMENT
74
74
  - DB_HOST
75
75
  - DB_PORT
76
- format: "postgresql://${DB_USER}:${DB_PASS}@${DB_HOST}:${DB_PORT}/${DB_NAME}"
76
+ format: "postgresql://${DB_USER}:${DB_PASS}@${DATABASE_URL}:${DB_PORT}/${DB_NAME}"
77
+ #format: "postgresql://${DB_USER}:${DB_PASS}@${DB_HOST}:${DB_PORT}/${DB_NAME}"
77
78
  ```
78
79
 
79
80
  ### Multi-step Configuration
@@ -104,7 +105,7 @@ require:
104
105
  ```ux
105
106
  name: PHONE_NUMBER
106
107
  prompt: "Enter phone number"
107
- validate: "(?<country>\d{1,3})(?<area>\d{3})(?<number>\d{7})"
108
+ validate: '(?<country>\d{1,3})(?<area>\d{3})(?<number>\d{7})'
108
109
  transform: "+${country} (${area}) ${number}"
109
110
  format: "Phone: ${PHONE_NUMBER}"
110
111
  ```
@@ -114,7 +115,7 @@ format: "Phone: ${PHONE_NUMBER}"
114
115
  name: GIT_STATUS
115
116
  init: ":exec"
116
117
  exec: "git status --porcelain"
117
- validate: "(?<status>[AMDR])\s+(?<file>.+)"
118
+ validate: '(?<status>[AMDR])\s+(?<file>.+)'
118
119
  transform: "${status}: ${file}"
119
120
  format: "Changes: ${GIT_STATUS}"
120
121
  ```
@@ -123,7 +123,9 @@ class CachedNestedFileReader
123
123
  /([A-Za-z_]\w*)=(?:"([^"]*)"|'([^']*)'|(\S+))/
124
124
  ) do |key, quoted_double, quoted_single, unquoted|
125
125
  value = quoted_double || quoted_single || unquoted
126
- params[key] = value
126
+ # skip replacement of equal values
127
+ # otherwise, the text is not available for other substitutions
128
+ params[key] = value if key != value
127
129
  end
128
130
  params
129
131
  end
data/lib/env_interface.rb CHANGED
@@ -10,7 +10,7 @@ class EnvInterface
10
10
  # @param transform [Proc] Optional transformation to apply to the value
11
11
  # @return [Object] The environment variable value
12
12
  def get(key, default: nil, transform: nil)
13
- ww key, \
13
+ wwt :env, key, \
14
14
  value = ENV[key]
15
15
  return default if value.nil?
16
16
 
@@ -23,7 +23,7 @@ ww key, \
23
23
  # @param transform [Proc] Optional transformation to apply before setting
24
24
  # @return [String] The set value
25
25
  def set(key, value, transform: nil)
26
- ww key, caller.deref[0..3], value
26
+ wwt :env, key, caller.deref[0..3], value
27
27
  transformed_value = transform ? transform.call(value) : value
28
28
  ENV[key] = transformed_value.to_s
29
29
  end
data/lib/fcb.rb CHANGED
@@ -75,6 +75,14 @@ module MarkdownExec
75
75
  full&.to_s&.pub_name(**kwargs)
76
76
  end
77
77
 
78
+ def body
79
+ @attrs[:body]
80
+ end
81
+
82
+ def body=(value)
83
+ @attrs[:body] = value
84
+ end
85
+
78
86
  def code_name_included?(*names)
79
87
  names.include?(@attrs[:oname])
80
88
  end
@@ -93,7 +101,9 @@ module MarkdownExec
93
101
  # 2024-08-04 match nickname
94
102
  # may not exist if block name is duplicated
95
103
  def delete_matching_name!(dependencies)
96
- dependencies.delete(@attrs[:dname]) ||
104
+ ####
105
+ dependencies.delete(@attrs[:id]) ||
106
+ dependencies.delete(@attrs[:dname]) ||
97
107
  dependencies.delete(@attrs[:nickname]) ||
98
108
  dependencies.delete(@attrs[:oname]) ||
99
109
  dependencies.delete(@attrs.pub_name) ||
@@ -271,7 +281,8 @@ module MarkdownExec
271
281
  end
272
282
 
273
283
  def is_named?(name)
274
- @attrs[:dname] == name ||
284
+ @attrs[:id] == name ||
285
+ @attrs[:dname] == name ||
275
286
  @attrs[:nickname] == name ||
276
287
  @attrs[:oname] == name ||
277
288
  @attrs.pub_name == name ||
@@ -361,6 +372,7 @@ module MarkdownExec
361
372
  end
362
373
 
363
374
  # Expand variables in attributes
375
+ # @return [void]
364
376
  def expand_variables_in_attributes!(pattern, replacements)
365
377
  @attrs[:raw_dname] ||= @attrs[:dname]
366
378
  @attrs[:dname] = @attrs[:dname]&.gsub(pattern) do |match|
@@ -1110,7 +1110,7 @@ module MarkdownExec
1110
1110
  selected, mdoc, inherited_code: nil, force: true, only_default: false,
1111
1111
  silent:
1112
1112
  )
1113
- wwt :fcb, 'ux block with code', selected
1113
+ wwt :fcb, 'selected:', selected
1114
1114
  ret_command_result = nil
1115
1115
  exit_prompt = @delegate_object[:prompt_filespec_back]
1116
1116
 
@@ -1169,10 +1169,12 @@ module MarkdownExec
1169
1169
  end
1170
1170
  return command_result_w_e_t_nl if command_result_w_e_t_nl.failure?
1171
1171
 
1172
+ # update the required lines for this and subsequent blocks
1172
1173
  command_result_w_e_t_nl.new_lines =
1173
1174
  process_command_result_lines(command_result_w_e_t_nl, export,
1174
1175
  required_lines)
1175
1176
  required_lines.concat(command_result_w_e_t_nl.new_lines)
1177
+ command_result_w_e_t_nl.new_lines = required_lines
1176
1178
  ret_command_result = command_result_w_e_t_nl
1177
1179
  else
1178
1180
  raise "Invalid data type: #{data.inspect}"
@@ -1440,12 +1442,17 @@ module MarkdownExec
1440
1442
  # Skip processing for shell-type blocks
1441
1443
  next if exclude_types.include?(block.type)
1442
1444
 
1443
- # Scan each block name for matches of the pattern
1444
- count_named_group_occurrences_block_body_fix_indent(block).scan(pattern) do |(_, _variable_name)|
1445
- pattern.match($LAST_MATCH_INFO.to_s) # Reapply match for named groups
1446
- id = $LAST_MATCH_INFO[group_name]
1447
- occurrence_count[id] += 1
1448
- occurrence_expressions[id] = $LAST_MATCH_INFO['expression']
1445
+ begin
1446
+
1447
+ # Scan each block name for matches of the pattern
1448
+ count_named_group_occurrences_block_body_fix_indent(block).scan(pattern) do |(_, _variable_name)|
1449
+ pattern.match($LAST_MATCH_INFO.to_s) # Reapply match for named groups
1450
+ id = $LAST_MATCH_INFO[group_name]
1451
+ occurrence_count[id] += 1
1452
+ occurrence_expressions[id] = $LAST_MATCH_INFO['expression']
1453
+ end
1454
+ rescue Interrupt
1455
+ binding.irb
1449
1456
  end
1450
1457
  end
1451
1458
 
@@ -2586,6 +2593,8 @@ module MarkdownExec
2586
2593
  pattern: options_command_substitution_regexp
2587
2594
  )
2588
2595
  # no return
2596
+ rescue StandardError
2597
+ wwe 'fcb:', fcb, 'link_state:', link_state
2589
2598
  end
2590
2599
 
2591
2600
  def expand_variable_references!(
@@ -2643,17 +2652,23 @@ module MarkdownExec
2643
2652
  exportable = false
2644
2653
  command_result.warning = warning_required_empty(export) unless silent
2645
2654
  else
2655
+ ### TBD validate/transform?
2656
+ # store the transformed value in ENV
2646
2657
  EnvInterface.set(export.name, command_result.stdout.to_s)
2658
+
2647
2659
  new_lines << { name: export.name, force: force,
2648
2660
  text: command_result.stdout }
2649
2661
  end
2650
2662
 
2651
2663
  when Hash
2664
+ required_lines = []
2665
+
2652
2666
  # each item in the hash is a variable name and value
2653
2667
  export_string.each do |name, expression|
2654
2668
  command_result, = output_from_adhoc_bash_script_file(
2655
2669
  join_array_of_arrays(
2656
2670
  bash_script_lines,
2671
+ required_lines,
2657
2672
  %(printf '%s' "#{expression}")
2658
2673
  ),
2659
2674
  export,
@@ -2662,9 +2677,22 @@ module MarkdownExec
2662
2677
  if command_result.exit_status == EXIT_STATUS_REQUIRED_EMPTY
2663
2678
  command_result.warning = warning_required_empty(export) unless silent
2664
2679
  else
2665
- EnvInterface.set(name, command_result.stdout.to_s)
2666
- new_lines << { name: name, force: force,
2667
- text: command_result.stdout }
2680
+ transformed = command_result.stdout.to_s
2681
+ ### TBD validate/transform?
2682
+ # transformed = if command_result_w_e_t_nl.transformable transform_export_value(name_force[:text], export) else name_force[:text] end
2683
+
2684
+ # code for subsequent expression evaluations
2685
+ required_lines << code_line_to_assign_a_variable(
2686
+ name, transformed, force: force
2687
+ )
2688
+
2689
+ if variable_is_exportable(name)
2690
+ # store the transformed value in ENV
2691
+ EnvInterface.set(name, transformed)
2692
+
2693
+ new_lines << { name: name, force: force,
2694
+ text: command_result.stdout }
2695
+ end
2668
2696
  end
2669
2697
  end
2670
2698
  end
@@ -3264,7 +3292,7 @@ module MarkdownExec
3264
3292
 
3265
3293
  if mdoc
3266
3294
  mdoc.collect_recursively_required_code(
3267
- anyname: fcb.pub_name,
3295
+ anyname: fcb.id,####
3268
3296
  label_format_above: @delegate_object[:shell_code_label_format_above],
3269
3297
  label_format_below: @delegate_object[:shell_code_label_format_below],
3270
3298
  block_source: block_source
@@ -3446,6 +3474,7 @@ module MarkdownExec
3446
3474
  [all_blocks, menu_blocks, mdoc]
3447
3475
  end
3448
3476
 
3477
+ # enable scroll targets in long sequences of inactive lines
3449
3478
  def handle_consecutive_inactive_items!(menu_blocks)
3450
3479
  consecutive_inactive_count = 0
3451
3480
  menu_blocks.each do |fcb|
@@ -3453,7 +3482,10 @@ module MarkdownExec
3453
3482
  consecutive_inactive_count = 0
3454
3483
  else
3455
3484
  consecutive_inactive_count += 1
3456
- if (consecutive_inactive_count % (@delegate_object[:select_page_height] / 3)).zero?
3485
+ if (consecutive_inactive_count %
3486
+ (@delegate_object[:select_page_height] /
3487
+ @delegate_object[:select_page_ratio])
3488
+ ).zero?
3457
3489
  fcb.disabled = TtyMenu::ENABLE
3458
3490
  fcb.is_enabled_but_inactive = true
3459
3491
  end
@@ -4079,14 +4111,14 @@ module MarkdownExec
4079
4111
  end
4080
4112
  end
4081
4113
 
4082
- # Handle expression with wildcard characters
4083
- # allow user to select or enter
4084
- def puts_gets_oprompt_(filespec)
4085
- puts format(@delegate_object[:prompt_show_expr_format],
4086
- { expr: filespec })
4087
- puts @delegate_object[:prompt_enter_filespec]
4088
- gets.chomp
4089
- end
4114
+ # # Handle expression with wildcard characters
4115
+ # # allow user to select or enter
4116
+ # def puts_gets_oprompt_(filespec)
4117
+ # puts format(@delegate_object[:prompt_show_expr_format],
4118
+ # { expr: filespec })
4119
+ # puts @delegate_object[:prompt_enter_filespec]
4120
+ # gets.chomp
4121
+ # end
4090
4122
 
4091
4123
  def read_saved_assets_for_history_table(
4092
4124
  asset: nil,
@@ -4443,12 +4475,14 @@ module MarkdownExec
4443
4475
  # no enabled options in page
4444
4476
  return
4445
4477
  end
4478
+ ww 'selection', selection
4446
4479
 
4447
4480
  menu_list = opts.fetch(:match_dml, true) ? @dml_menu_blocks : menu_items
4448
4481
  menu_list ||= tty_menu_items
4449
4482
  selected = menu_list.find do |item|
4450
4483
  if item.instance_of?(Hash)
4451
- [item[:id], item[:name], item[:dname]].include?(selection)
4484
+ ### [item[:id], item[:name], item[:dname]].include?(selection)
4485
+ item[:id] == selection
4452
4486
  elsif item.instance_of?(MarkdownExec::FCB)
4453
4487
  item.id == selection
4454
4488
  else
@@ -4959,8 +4993,15 @@ module MarkdownExec
4959
4993
  command_result
4960
4994
  end
4961
4995
 
4962
- def warning_required_empty(export)
4963
- "A value must exist for: #{export.required.join(', ')}"
4996
+ # true if the variable is exported in a series of evaluations
4997
+ def variable_is_exportable(name)
4998
+ local_name_pattern = @delegate_object.fetch(:local_name_pattern, '')
4999
+
5000
+ # export all if rule is empty
5001
+ return true if local_name_pattern.empty?
5002
+
5003
+ # export if it its name does not match the rule
5004
+ !(name =~ Regexp.new(local_name_pattern))
4964
5005
  end
4965
5006
 
4966
5007
  def vux_await_user_selection(prior_answer: @dml_block_selection)
@@ -5261,9 +5302,14 @@ module MarkdownExec
5261
5302
  vux_user_selected_block_name
5262
5303
 
5263
5304
  when :execute_block
5264
- ret = vux_execute_block_per_type(data, formatted_choice_ostructs)
5265
- vux_publish_block_name_for_external_automation(data)
5266
- ret
5305
+ begin
5306
+ ret = vux_execute_block_per_type(data, formatted_choice_ostructs)
5307
+ vux_publish_block_name_for_external_automation(data)
5308
+ ret
5309
+ rescue StandardError
5310
+ # error executing block, do not abort
5311
+ InputSequencer.next_link_state(prior_block_was_link: false)
5312
+ end
5267
5313
 
5268
5314
  when :close_ux
5269
5315
  if @vux_pipe_open.present? && File.exist?(@vux_pipe_open)
@@ -5517,6 +5563,10 @@ module MarkdownExec
5517
5563
  determine_block_state(selected_option)
5518
5564
  end
5519
5565
 
5566
+ def warning_required_empty(export)
5567
+ "A value must exist for: #{export.required.join(', ')}"
5568
+ end
5569
+
5520
5570
  # Handles the core logic for generating the command
5521
5571
  # file's metadata and content.
5522
5572
  def write_command_file(required_lines:, blockname:, shell: nil)
@@ -1,3 +1,4 @@
1
+
1
2
  # frozen_string_literal: true
2
3
 
3
4
  # :reek:TooManyConstants
@@ -7,5 +8,5 @@ module MarkdownExec
7
8
  BIN_NAME = 'mde'
8
9
  GEM_NAME = 'markdown_exec'
9
10
  TAP_DEBUG = 'MDE_DEBUG'
10
- VERSION = '3.1.0'
11
+ VERSION = '3.2.0'
11
12
  end
data/lib/mdoc.rb CHANGED
@@ -119,7 +119,9 @@ module MarkdownExec
119
119
  raise "Named code block `#{anyname}` not found. (@#{__LINE__})"
120
120
  end
121
121
 
122
- nickname = name_block.pub_name
122
+ # nickname = name_block.pub_name
123
+ ####
124
+ nickname = name_block.id
123
125
 
124
126
  dependencies = collect_dependencies(pubname: nickname)
125
127
  # !!t dependencies.count
@@ -164,6 +166,8 @@ module MarkdownExec
164
166
  anyname:, block_source:,
165
167
  label_body: true, label_format_above: nil, label_format_below: nil
166
168
  )
169
+ ww 'anyname:', anyname
170
+ ww 'block_source:', block_source
167
171
  block_search = collect_block_dependencies(anyname: anyname)
168
172
  if block_search[:blocks]
169
173
  blocks = collect_wrapped_blocks(block_search[:blocks])
data/lib/menu.src.yml CHANGED
@@ -688,6 +688,12 @@
688
688
  :default: ''
689
689
  :procname: val_as_str
690
690
 
691
+ - :opt_name: local_name_pattern
692
+ :env_var: MDE_LOCAL_NAME_PATTERN
693
+ :description: Pattern for variables not exported in a series of evaluations
694
+ :default: '^.{1,3}$'
695
+ :procname: val_as_str
696
+
691
697
  - :opt_name: logged_stdout_filename_prefix
692
698
  :env_var: MDE_LOGGED_STDOUT_FILENAME_PREFIX
693
699
  :description: Name prefix for stdout files
@@ -1594,6 +1600,12 @@
1594
1600
  :default: 0
1595
1601
  :procname: val_as_int
1596
1602
 
1603
+ - :opt_name: select_page_ratio
1604
+ :env_var: MDE_SELECT_PAGE_RATIO
1605
+ :description: Number of lines of inactive text that require a scroll point, as a ratio of the page height.
1606
+ :default: 2
1607
+ :procname: val_as_int
1608
+
1597
1609
  - :opt_name: shebang
1598
1610
  :env_var: MDE_SHEBANG
1599
1611
  :description: Shebang for saved scripts
data/lib/menu.yml CHANGED
@@ -582,6 +582,11 @@
582
582
  :arg_name: PATH
583
583
  :default: ''
584
584
  :procname: val_as_str
585
+ - :opt_name: local_name_pattern
586
+ :env_var: MDE_LOCAL_NAME_PATTERN
587
+ :description: Pattern for variables not exported in a series of evaluations
588
+ :default: "^.{1,3}$"
589
+ :procname: val_as_str
585
590
  - :opt_name: logged_stdout_filename_prefix
586
591
  :env_var: MDE_LOGGED_STDOUT_FILENAME_PREFIX
587
592
  :description: Name prefix for stdout files
@@ -1362,6 +1367,12 @@
1362
1367
  :description: 'Maximum # of rows in select list. Detects current limit if not specified.'
1363
1368
  :default: 0
1364
1369
  :procname: val_as_int
1370
+ - :opt_name: select_page_ratio
1371
+ :env_var: MDE_SELECT_PAGE_RATIO
1372
+ :description: Number of lines of inactive text that require a scroll point, as a
1373
+ ratio of the page height.
1374
+ :default: 2
1375
+ :procname: val_as_int
1365
1376
  - :opt_name: shebang
1366
1377
  :env_var: MDE_SHEBANG
1367
1378
  :description: Shebang for saved scripts
data/lib/ww.rb CHANGED
@@ -19,13 +19,16 @@ def ww(*objs, **kwargs)
19
19
  # return the last item in the list, as the label is usually first
20
20
  return objs.last unless $debug
21
21
 
22
- ww0(*objs, **kwargs.merge(locations: caller_locations))
22
+ locations = kwargs[:locations] || caller_locations
23
+ ww0(*objs, **kwargs.merge(locations: locations))
23
24
  end
24
25
 
25
26
  # select enabled, for exceptions
26
27
  # print a data object for the error, and the failing line
27
28
  def wwe(*objs, **kwargs)
28
- ww0(*objs, **kwargs.merge(locations: caller_locations[0..0]))
29
+ ww0(*objs,
30
+ **kwargs.merge(full_backtrace: true,
31
+ locations: caller_locations))
29
32
 
30
33
  raise StandardError, objs.first[:error]
31
34
  end
@@ -33,6 +36,8 @@ end
33
36
  # selectively enabled, for process tracking
34
37
  # print the failing line
35
38
  def wwp(*objs, **kwargs)
39
+ return objs.last unless $debug
40
+
36
41
  ww(*objs, **kwargs.merge(locations: caller_locations[0..0]))
37
42
  end
38
43
 
@@ -40,7 +45,7 @@ end
40
45
  # print the failing line
41
46
  # eg wwt :line, 'data:', data
42
47
  def wwt(*objs, **kwargs)
43
- # return if [:line].include? objs.first
48
+ return objs.last if !$debug || %i[env].include?(objs.first)
44
49
 
45
50
  formatted = ['Tagged', objs.first] + objs[1..]
46
51
  ww(*formatted, **kwargs.merge(locations: caller_locations[0..0]))
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: 3.1.0
4
+ version: 3.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Fareed Stevenson
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-06-23 00:00:00.000000000 Z
11
+ date: 2025-07-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: clipboard
@@ -124,6 +124,7 @@ files:
124
124
  - bats/block-type-ux-hidden.bats
125
125
  - bats/block-type-ux-invalid.bats
126
126
  - bats/block-type-ux-readonly.bats
127
+ - bats/block-type-ux-require-chained.bats
127
128
  - bats/block-type-ux-require.bats
128
129
  - bats/block-type-ux-required-variables.bats
129
130
  - bats/block-type-ux-row-format.bats
@@ -182,6 +183,7 @@ files:
182
183
  - docs/dev/block-type-ux-hidden.md
183
184
  - docs/dev/block-type-ux-invalid.md
184
185
  - docs/dev/block-type-ux-readonly.md
186
+ - docs/dev/block-type-ux-require-chained.md
185
187
  - docs/dev/block-type-ux-require.md
186
188
  - docs/dev/block-type-ux-required-variables.md
187
189
  - docs/dev/block-type-ux-row-format.md