markdown_exec 2.8.1 → 2.8.2

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: d752af0db5e1c1a770b64f9341c3d08e1e9bc8612230a9cb44ddc7fddc4c3051
4
- data.tar.gz: 5ba8524b3323bd8333b82a5d0607fbb9db59a5157a1c7ae0564b3f624f26addd
3
+ metadata.gz: 066c72f2f85462a89163b7834669dee6526e516ee3ebfe4be2e8b269cb4ece36
4
+ data.tar.gz: 48c2bce9ac82cda2cbecca5bea4564b28013cdbab7005e249e8a856d0280afa0
5
5
  SHA512:
6
- metadata.gz: 29b210e56b46a1edf099c02267e2b3c7cdae6701f7ee99d5a946d06eea7272da3534765110ec36a6de017a10d0f4833c9075c27dacb0cec8b050192d3892d748
7
- data.tar.gz: e73cd906ce9035c8c78d2e301866af4a76bc7a730c5109fc8cc59ecf64679cb578fb04b324e700df064886d250c394c441f77850b9e21230d346d08bd92a9a5f
6
+ metadata.gz: fe1270b8cf11efc8ad9e81cb43052bc75cfc217e362c7d6e30acb6981a6d0be749f290b9b15ce1a2655d6a7e157177c4cd975aa61de22a6f6bafe2a835285228
7
+ data.tar.gz: 9445285db86af55fe5ba0b784a24d30dd418ac3d1dc551183a5a1b3b865df27a6b314ddc08b4a013de5e926e023439753fe08cd4ea8d6c6da0c0d9547e4a9546
data/.rubocop.yml CHANGED
@@ -76,6 +76,9 @@ Security/YAMLLoad:
76
76
  Style/ClassVars:
77
77
  Enabled: false
78
78
 
79
+ Style/CombinableLoops:
80
+ Enabled: false
81
+
79
82
  Style/CommentedKeyword:
80
83
  Enabled: false
81
84
 
data/CHANGELOG.md CHANGED
@@ -1,5 +1,32 @@
1
1
  # Changelog
2
2
 
3
+ ## [2.8.2] - 2025-02-19
4
+
5
+ ### Added
6
+
7
+ - UX blocks can add preconditions. Preconditions are variable names that must be set before the UX block is executed. If any preconditions are not set, a warning is displayed, and the sequence is aborted.
8
+ - UX blocks can require shell an other UX blocks.
9
+ - UX blocks are evaluated in order and calculation can depend on prior variables in the same sequence.
10
+
11
+ ### Changed
12
+
13
+ - Hide all blocks per their initial title instead of `oname`.
14
+ - Make menu blocks for list of files found to fix crash.
15
+ - Use a block ID to recall the selected block.
16
+ - UX blocks are hidden similar to the rest.
17
+
18
+ ## [2.8.1] - 2025-02-13
19
+
20
+ ### Added
21
+
22
+ - BATS tests for UX block type.
23
+
24
+ ### Changed
25
+
26
+ - Improve persistence of position in menu on reload
27
+ - Update block-type-ux-exec BATS test.
28
+ - Refactor menu for selecting items with facets.
29
+
3
30
  ## [2.8.0] - 2025-02-10
4
31
 
5
32
  ### Added
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- markdown_exec (2.8.1)
4
+ markdown_exec (2.8.2)
5
5
  clipboard (~> 1.3.6)
6
6
  open3 (~> 0.1.1)
7
7
  optparse (~> 0.1.1)
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bats
2
+
3
+ load 'test_helper'
4
+
5
+ @test 'hide blocks' {
6
+ spec_mde_xansi_dname_doc_blocks_expect docs/dev/block-hide.md \
7
+ 'visible'
8
+ }
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bats
2
+
3
+ load 'test_helper'
4
+
5
+ @test 'Output of executed commands as initial value' {
6
+ spec_mde_xansi_dname_doc_blocks_expect docs/dev/block-type-ux-require.md \
7
+ 'SPECIES=Pongo tapanuliensis_GENUS=Pongo_NAME=Pongo tapanuliensis - Pongo_NAME2=Pongo tapanuliensis - Pongo'
8
+ }
@@ -13,7 +13,7 @@ __filedirs_all()
13
13
  }
14
14
 
15
15
  _mde_echo_version() {
16
- echo "2.8.1"
16
+ echo "2.8.2"
17
17
  }
18
18
 
19
19
  _mde() {
@@ -0,0 +1,18 @@
1
+ ``` :(hidden)
2
+ ```
3
+ ``` :visible
4
+ ```
5
+ / ux block is displayed differently than other types
6
+ ```ux :()
7
+ name: name
8
+ ```
9
+ @import bats-document-configuration.md
10
+ ```opts :(document_opts)
11
+ # Pattern for blocks to hide from user-selection
12
+ block_name_include_match:
13
+ ^\(.*\)$
14
+
15
+ # Pattern for the block name in the line defining the block
16
+ block_name_match: |
17
+ :(?<title>\S+)( |$)
18
+ ```
@@ -0,0 +1,28 @@
1
+ / an automatic UX block requires a shell block and another UX block
2
+ ``` :(shell)
3
+ ENTITY='Pongo tapanuliensis,Pongo'
4
+ ```
5
+ ```ux :[document_ux_SPECIES] +(shell) +[ux_GENUS]
6
+ default: :exec
7
+ exec: printf "${ENTITY%%,*}"
8
+ name: SPECIES
9
+ ```
10
+ / required ux block requires another
11
+ ```ux :[ux_GENUS] +[ux_NAME]
12
+ default: :exec
13
+ exec: printf "${ENTITY##*,}"
14
+ name: GENUS
15
+ ```
16
+ / executed in context of prior ux blocks, uses their initial values
17
+ ```ux :[ux_NAME]
18
+ default: :exec
19
+ exec: printf "$SPECIES - $GENUS"
20
+ name: NAME
21
+ ```
22
+ / executed after other ux blocks, uses their initial values
23
+ ```ux :[document_ux_NAME2]
24
+ default: :exec
25
+ exec: printf "$NAME"
26
+ name: NAME2
27
+ ```
28
+ @import bats-document-configuration.md
data/lib/fcb.rb CHANGED
@@ -14,7 +14,8 @@ def parse_yaml_of_ux_block(
14
14
  export = data['export']
15
15
  export = data if export.nil?
16
16
  name = export['name']
17
- raise "Invalid data: #{data.inspect}" unless name.present?
17
+
18
+ raise "Name is missing in UX block: #{data.inspect}" unless name.present?
18
19
 
19
20
  OpenStruct.new(
20
21
  allowed: export['allowed'],
@@ -22,6 +23,7 @@ def parse_yaml_of_ux_block(
22
23
  exec: export['exec'],
23
24
  menu_format: export['menu_format'] || menu_format,
24
25
  name: name,
26
+ preconditions: export['preconditions'],
25
27
  prompt: export['prompt'] || prompt,
26
28
  transform: export['transform'],
27
29
  validate: export['validate'] || validate
@@ -136,6 +138,7 @@ module MarkdownExec
136
138
  @attrs[:center] = table_center
137
139
  oname = @attrs[:oname] = format(export.menu_format, export.to_h)
138
140
  else
141
+ # triggered by an empty block
139
142
  raise "Invalid data type: #{data.inspect}"
140
143
  end
141
144
  end
@@ -306,7 +306,7 @@ module HashDelegatorSelf
306
306
  table__hs.each do |table_hs|
307
307
  table_hs.substrings.each do |substrings|
308
308
  substrings.each do |node|
309
- next unless node[:text].class == TrackedString
309
+ next unless node[:text].instance_of?(TrackedString)
310
310
 
311
311
  exceeded_table_cell ||= node[:text].exceeded
312
312
  truncated_table_cell = node[:text].truncated
@@ -606,6 +606,9 @@ module MarkdownExec
606
606
 
607
607
  @process_mutex = Mutex.new
608
608
  @process_cv = ConditionVariable.new
609
+ @dml_link_state = Struct.new(:document_filename, :inherited_lines)
610
+ .new(@delegate_object[:filename], [])
611
+ @dml_menu_blocks = []
609
612
 
610
613
  @p_all_arguments = []
611
614
  @p_options_parsed = []
@@ -1022,25 +1025,11 @@ module MarkdownExec
1022
1025
  ]
1023
1026
  end
1024
1027
 
1025
- def neval(export_exec, inherited_code)
1026
- # ww0 export_exec
1027
- # ww0 inherited_code
1028
- code = (inherited_code || []) + [export_exec]
1029
- filespec = generate_temp_filename
1030
- File.write filespec, HashDelegator.join_code_lines(code)
1031
- File.chmod 0o755, filespec
1032
- # ww0 File.read(filespec)
1033
- ret = `#{filespec}`
1034
- File.delete filespec
1035
- ret
1036
- end
1037
-
1038
- # sets ENV
1028
+ # parse YAML body defining the UX for a single variable
1029
+ # set ENV value for the variable and return code lines for the same
1039
1030
  def code_from_ux_block_to_set_environment_variables(
1040
1031
  selected, mdoc, inherited_code: nil, force: true, only_default: false
1041
1032
  )
1042
- # ww0 inherited_code
1043
- # ww0 mdoc
1044
1033
  exit_prompt = @delegate_object[:prompt_filespec_back]
1045
1034
 
1046
1035
  required = mdoc.collect_recursively_required_code(
@@ -1050,105 +1039,106 @@ module MarkdownExec
1050
1039
  block_source: block_source
1051
1040
  )
1052
1041
 
1042
+ # process each ux block in sequence, setting ENV and collecting lines
1053
1043
  code_lines = []
1054
- case data = YAML.load(selected.body.join("\n"))
1055
- when Hash
1056
- export = parse_yaml_of_ux_block(
1057
- data,
1058
- prompt: @delegate_object[:prompt_ux_enter_a_value],
1059
- validate: '^(?<name>[^ ].*)$'
1060
- )
1061
-
1062
- exportable = true
1063
- if only_default
1064
- value = case export.default
1065
- # exec > default
1066
- when :exec
1067
- raise unless export.exec.present?
1044
+ required[:blocks].each do |block|
1045
+ next unless block.type == BlockType::UX
1046
+
1047
+ case data = YAML.load(block.body.join("\n"))
1048
+ when Hash
1049
+ export = parse_yaml_of_ux_block(
1050
+ data,
1051
+ prompt: @delegate_object[:prompt_ux_enter_a_value],
1052
+ validate: '^(?<name>[^ ].*)$'
1053
+ )
1068
1054
 
1069
- n1 = neval(export.exec,
1070
- (inherited_code || []) + required[:code])
1055
+ # preconditions are variable names that must be set before the UX block is executed.
1056
+ # if any precondition is not set, the sequence is aborted.
1057
+ export.preconditions&.each do |precondition|
1058
+ code_lines.push "[[ -z $#{precondition} ]] && exit 1"
1059
+ end
1071
1060
 
1072
- if export.transform.present?
1073
- if export.transform.is_a? Symbol
1074
- n1.send(export.transform)
1075
- else
1076
- format(
1077
- export.transform,
1078
- NamedCaptureExtractor.extract_named_groups(
1079
- n1, export.validate
1080
- )
1081
- )
1061
+ exportable = true
1062
+ if only_default
1063
+ value = case export.default
1064
+ # exec > default
1065
+ when :exec
1066
+ raise unless export.exec.present?
1067
+
1068
+ output = export_exec_with_code(
1069
+ export, inherited_code, code_lines, required
1070
+ )
1071
+ if output == :invalidated
1072
+ return :ux_exec_prohibited
1082
1073
  end
1074
+
1075
+ transform_export_value(output, export)
1076
+ # default
1083
1077
  else
1084
- n1
1078
+ export.default.to_s
1085
1079
  end
1080
+ else
1081
+ value = nil
1086
1082
 
1087
- # default
1088
- else
1089
- export.default.to_s
1090
- end
1091
- else
1092
- caps = nil
1093
- value = nil
1094
-
1095
- # exec > allowed
1096
- if export.exec
1097
- value = neval(export.exec, (inherited_code || []) + required[:code])
1098
- caps = NamedCaptureExtractor.extract_named_groups(value,
1099
- export.validate)
1100
-
1101
- # allowed > prompt
1102
- elsif export.allowed && export.allowed.count.positive?
1103
- case (choice = prompt_select_code_filename(
1104
- [exit_prompt] + export.allowed,
1105
- string: export.prompt,
1106
- color_sym: :prompt_color_after_script_execution
1107
- ))
1108
- when exit_prompt
1109
- exportable = false
1110
- else
1111
- value = choice
1112
- caps = NamedCaptureExtractor.extract_named_groups(value,
1113
- export.validate)
1114
- end
1115
-
1116
- # prompt > default
1117
- elsif export.prompt.present?
1118
- begin
1119
- while true
1120
- print "#{export.prompt} [#{export.default}]: "
1121
- value = gets.chomp
1122
- value = export.default.to_s if value.empty?
1123
- caps = NamedCaptureExtractor.extract_named_groups(value,
1124
- export.validate)
1125
- break if caps
1083
+ # exec > allowed
1084
+ if export.exec
1085
+ value = export_exec_with_code(
1086
+ export, inherited_code, code_lines, required
1087
+ )
1088
+ if value == :invalidated
1089
+ return :ux_exec_prohibited
1090
+ end
1126
1091
 
1127
- # invalid input, retry
1092
+ # allowed > prompt
1093
+ elsif export.allowed && export.allowed.count.positive?
1094
+ case (choice = prompt_select_code_filename(
1095
+ [exit_prompt] + export.allowed,
1096
+ string: export.prompt,
1097
+ color_sym: :prompt_color_after_script_execution
1098
+ ))
1099
+ when exit_prompt
1100
+ exportable = false
1101
+ else
1102
+ value = choice
1103
+ end
1128
1104
 
1105
+ # prompt > default
1106
+ elsif export.prompt.present?
1107
+ begin
1108
+ loop do
1109
+ print "#{export.prompt} [#{export.default}]: "
1110
+ value = gets.chomp
1111
+ value = export.default.to_s if value.empty?
1112
+ caps = NamedCaptureExtractor.extract_named_groups(value,
1113
+ export.validate)
1114
+ break if caps
1115
+
1116
+ # invalid input, retry
1117
+ end
1118
+ rescue Interrupt
1119
+ exportable = false
1129
1120
  end
1130
- rescue Interrupt
1131
- exportable = false
1121
+
1122
+ # default
1123
+ else
1124
+ value = export.default
1132
1125
  end
1133
1126
 
1134
- # default
1135
- else
1136
- value = export.default
1127
+ if exportable
1128
+ value = transform_export_value(value, export)
1129
+ end
1137
1130
  end
1138
1131
 
1139
- if exportable && export.transform.present?
1140
- value = format(export.transform, caps)
1132
+ if exportable
1133
+ ENV[export.name] = value.to_s
1134
+ code_lines.push code_line_safe_assign(export.name, value,
1135
+ force: force)
1141
1136
  end
1137
+ else
1138
+ raise "Invalid data type: #{data.inspect}"
1142
1139
  end
1143
-
1144
- if exportable
1145
- ENV[export.name] = value.to_s
1146
- code_lines.push code_line_safe_assign(export.name, value,
1147
- force: force)
1148
- end
1149
- else
1150
- raise "Invalid data type: #{data.inspect}"
1151
1140
  end
1141
+
1152
1142
  code_lines
1153
1143
  end
1154
1144
 
@@ -1221,7 +1211,8 @@ module MarkdownExec
1221
1211
  command_execute_in_process(
1222
1212
  args: args, command: command,
1223
1213
  erls: erls,
1224
- filename: @delegate_object[:filename], shell: shell
1214
+ filename: @delegate_object[:filename],
1215
+ shell: shell
1225
1216
  )
1226
1217
  end
1227
1218
 
@@ -1285,7 +1276,8 @@ module MarkdownExec
1285
1276
  )
1286
1277
  execute_command_with_streams(
1287
1278
  [shell, '-c', command,
1288
- @delegate_object[:filename], *args]
1279
+ @delegate_object[:filename],
1280
+ *args]
1289
1281
  )
1290
1282
  end
1291
1283
 
@@ -1987,9 +1979,7 @@ module MarkdownExec
1987
1979
  )
1988
1980
 
1989
1981
  # dname is not fixed for some block types, use block id
1990
- if lfls.load_file != LoadFile::LOAD &&
1991
- [BlockType::HEADING, BlockType::TEXT,
1992
- BlockType::UX].include?(selected.type)
1982
+ if lfls.load_file != LoadFile::LOAD
1993
1983
  block_selection = BlockSelection.new(selected.id)
1994
1984
  end
1995
1985
 
@@ -2173,24 +2163,24 @@ module MarkdownExec
2173
2163
  else
2174
2164
  warn 'No matching file found.'
2175
2165
  end
2176
- elsif selected_option = select_option_with_metadata(
2166
+ elsif (selected_option = select_option_with_metadata(
2177
2167
  prompt_title,
2178
2168
  [exit_prompt] + dirs.map do |file|
2179
- { name: format(
2180
- block_data['view'] || view,
2181
- NamedCaptureExtractor.extract_named_group_match_data(
2182
- file.match(
2183
- Regexp.new(block_data['filename_pattern'] ||
2184
- filename_pattern)
2185
- )
2186
- )
2187
- ),
2169
+ { name:
2170
+ format(
2171
+ block_data['view'] || view,
2172
+ NamedCaptureExtractor.extract_named_group_match_data(
2173
+ file.match(
2174
+ Regexp.new(block_data['filename_pattern'] || filename_pattern)
2175
+ )
2176
+ )
2177
+ ),
2188
2178
  oname: file }
2189
2179
  end,
2190
2180
  menu_options.merge(
2191
2181
  cycle: true
2192
2182
  )
2193
- )
2183
+ ))
2194
2184
  if selected_option.dname != exit_prompt
2195
2185
  File.readlines(selected_option.oname, chomp: true)
2196
2186
  end
@@ -2341,7 +2331,7 @@ module MarkdownExec
2341
2331
 
2342
2332
  interactive_menu_with_display_modes(
2343
2333
  files_table_rows,
2344
- display_formats: [:row, :file],
2334
+ display_formats: %i[row file],
2345
2335
  display_mode_option: @delegate_object[:prompt_filespec_facet],
2346
2336
  exit_option: exit_prompt,
2347
2337
  menu_title: @delegate_object[:prompt_select_history_file],
@@ -2364,9 +2354,9 @@ module MarkdownExec
2364
2354
  def execute_inherited_save(
2365
2355
  code_lines: @dml_link_state.inherited_lines
2366
2356
  )
2367
- return unless save_filespec = save_filespec_from_expression(
2368
- document_name_in_glob_as_file_name
2369
- )
2357
+ return unless (save_filespec = save_filespec_from_expression)
2358
+
2359
+ document_name_in_glob_as_file_name
2370
2360
 
2371
2361
  unless write_file_with_directory_creation(
2372
2362
  content: HashDelegator.join_code_lines(code_lines),
@@ -2422,6 +2412,27 @@ module MarkdownExec
2422
2412
  post_execution_process
2423
2413
  end
2424
2414
 
2415
+ def execute_temporary_script(script_code, additional_code = [])
2416
+ full_code = (additional_code || []) + [script_code]
2417
+
2418
+ Tempfile.create('script_exec') do |temp_file|
2419
+ temp_file.write(HashDelegator.join_code_lines(full_code))
2420
+ temp_file.flush
2421
+ File.chmod(0o755, temp_file.path)
2422
+
2423
+ output = `#{temp_file.path}`
2424
+
2425
+ if $?.exitstatus != 0
2426
+ return :invalidated
2427
+ end
2428
+
2429
+ output
2430
+ end
2431
+ rescue StandardError => err
2432
+ warn "Error executing script: #{err.message}"
2433
+ nil
2434
+ end
2435
+
2425
2436
  def expand_blocks_with_replacements(
2426
2437
  menu_blocks, replacements, exclude_types: [BlockType::SHELL]
2427
2438
  )
@@ -2468,6 +2479,18 @@ module MarkdownExec
2468
2479
  expand_blocks_with_replacements(blocks, replacements)
2469
2480
  end
2470
2481
 
2482
+ def export_exec_with_code(export, inherited_code, code_lines, required)
2483
+ value = execute_temporary_script(
2484
+ export.exec,
2485
+ (inherited_code || []) +
2486
+ code_lines + required[:code]
2487
+ )
2488
+ if value == :invalidated
2489
+ warn "A value must exist for: #{export.preconditions.join(', ')}"
2490
+ end
2491
+ value
2492
+ end
2493
+
2471
2494
  # Retrieves a specific data symbol from the delegate object,
2472
2495
  # converts it to a string, and applies a color style
2473
2496
  # based on the specified color symbol.
@@ -2580,7 +2603,7 @@ module MarkdownExec
2580
2603
  # commands to echo variables
2581
2604
  #
2582
2605
  commands = {}
2583
- variable_counts.each do |variable, _count|
2606
+ variable_counts.each_key do |variable|
2584
2607
  command = format(echo_format, variable)
2585
2608
  commands[variable] = command
2586
2609
  end
@@ -2637,7 +2660,6 @@ module MarkdownExec
2637
2660
  end
2638
2661
 
2639
2662
  def history_files(
2640
- link_state,
2641
2663
  direction: :reverse,
2642
2664
  filename: nil,
2643
2665
  home: Dir.pwd,
@@ -2950,19 +2972,24 @@ module MarkdownExec
2950
2972
  @ux_most_recent_filename = @delegate_object[:filename]
2951
2973
 
2952
2974
  (blocks.each.with_object([]) do |block, merged_options|
2953
- merged_options.push(
2954
- code_from_ux_block_to_set_environment_variables(
2955
- block,
2956
- mdoc,
2957
- force: @delegate_object[:ux_auto_load_force_default],
2958
- only_default: true
2959
- )
2975
+ code = code_from_ux_block_to_set_environment_variables(
2976
+ block,
2977
+ mdoc,
2978
+ force: @delegate_object[:ux_auto_load_force_default],
2979
+ only_default: true
2960
2980
  )
2981
+ if code == :ux_exec_prohibited
2982
+ merged_options
2983
+ else
2984
+ merged_options.push(code)
2985
+ end
2961
2986
  end).to_a
2962
2987
  end
2963
2988
 
2964
- def load_auto_vars_block(all_blocks,
2965
- block_name: @delegate_object[:document_load_vars_block_name])
2989
+ def load_auto_vars_block(
2990
+ all_blocks,
2991
+ block_name: @delegate_object[:document_load_vars_block_name]
2992
+ )
2966
2993
  unless block_name.present? &&
2967
2994
  @vars_most_recent_filename != @delegate_object[:filename]
2968
2995
  return
@@ -3103,7 +3130,7 @@ module MarkdownExec
3103
3130
 
3104
3131
  # load document shell block
3105
3132
  #
3106
- if code_lines = load_document_shell_block(all_blocks, mdoc: mdoc)
3133
+ if (code_lines = load_document_shell_block(all_blocks, mdoc: mdoc))
3107
3134
  next_state_set_code(nil, link_state, code_lines)
3108
3135
  link_state.inherited_lines = code_lines
3109
3136
  reload_blocks = true
@@ -3111,7 +3138,7 @@ module MarkdownExec
3111
3138
 
3112
3139
  # load document ux block
3113
3140
  #
3114
- if code_lines = load_auto_ux_block(all_blocks, mdoc)
3141
+ if (code_lines = load_auto_ux_block(all_blocks, mdoc))
3115
3142
  new_code = HashDelegator.code_merge(link_state.inherited_lines,
3116
3143
  code_lines)
3117
3144
  next_state_set_code(nil, link_state, new_code)
@@ -3121,7 +3148,7 @@ module MarkdownExec
3121
3148
 
3122
3149
  # load document vars block
3123
3150
  #
3124
- if code_lines = load_auto_vars_block(all_blocks)
3151
+ if (code_lines = load_auto_vars_block(all_blocks))
3125
3152
  new_code = HashDelegator.code_merge(link_state.inherited_lines,
3126
3153
  code_lines)
3127
3154
  next_state_set_code(nil, link_state, new_code)
@@ -3267,7 +3294,10 @@ module MarkdownExec
3267
3294
  next_state_set_code(
3268
3295
  selected,
3269
3296
  link_state,
3270
- HashDelegator.code_merge(link_state&.inherited_lines, code_lines)
3297
+ HashDelegator.code_merge(
3298
+ link_state&.inherited_lines,
3299
+ code_lines.is_a?(Array) ? code_lines : [] # no code for :ux_exec_prohibited
3300
+ )
3271
3301
  )
3272
3302
  end
3273
3303
 
@@ -3409,8 +3439,8 @@ module MarkdownExec
3409
3439
  #
3410
3440
  # @param all_blocks [Array<Hash>] The list of blocks from the file.
3411
3441
  def select_blocks(menu_blocks)
3412
- menu_blocks.select do |fcb|
3413
- !Filter.prepared_not_in_menu?(
3442
+ menu_blocks.reject do |fcb|
3443
+ Filter.prepared_not_in_menu?(
3414
3444
  @delegate_object,
3415
3445
  fcb,
3416
3446
  %i[block_name_include_match block_name_wrapper_match]
@@ -3659,16 +3689,16 @@ module MarkdownExec
3659
3689
 
3660
3690
  case @delegate_object[:publish_document_file_mode]
3661
3691
  when 'append'
3662
- File.write(pipe_path, message + "\n", mode: 'a')
3692
+ File.write(pipe_path, "#{message}\n", mode: 'a')
3663
3693
  when 'fifo'
3664
3694
  unless @vux_pipe_open
3665
3695
  unless File.exist?(pipe_path)
3666
- FileUtils.mkfifo(pipe_path)
3696
+ File.mkfifo(pipe_path)
3667
3697
  @vux_pipe_created = pipe_path
3668
3698
  end
3669
3699
  @vux_pipe_open = File.open(pipe_path, 'w')
3670
3700
  end
3671
- @vux_pipe_open.puts(message + "\n")
3701
+ @vux_pipe_open.puts("#{message}\n")
3672
3702
  @vux_pipe_open.flush
3673
3703
  when 'write'
3674
3704
  File.write(pipe_path, message)
@@ -3695,7 +3725,6 @@ module MarkdownExec
3695
3725
  regexp: @delegate_object[:saved_asset_match]
3696
3726
  )
3697
3727
  history_files(
3698
- @dml_link_state,
3699
3728
  filename:
3700
3729
  if asset.present?
3701
3730
  saved_asset_filename(asset, @dml_link_state)
@@ -3710,7 +3739,8 @@ module MarkdownExec
3710
3739
  end
3711
3740
 
3712
3741
  saved_asset = saved_asset_for_history(
3713
- file: file, form: form,
3742
+ file: file,
3743
+ form: form,
3714
3744
  match_info: $LAST_MATCH_INFO
3715
3745
  )
3716
3746
  saved_asset == :break ? nil : saved_asset
@@ -3959,7 +3989,7 @@ module MarkdownExec
3959
3989
 
3960
3990
  def screen_width
3961
3991
  width = @delegate_object[:screen_width]
3962
- if width && width.positive?
3992
+ if width&.positive?
3963
3993
  width
3964
3994
  else
3965
3995
  @delegate_object[:console_width]
@@ -3976,7 +4006,7 @@ module MarkdownExec
3976
4006
  end
3977
4007
 
3978
4008
  def select_document_if_multiple(options, files, prompt:)
3979
- return files if files.class == String
4009
+ return files if files.instance_of?(String)
3980
4010
  return files[0] if (count = files.count) == 1
3981
4011
 
3982
4012
  return unless count >= 2
@@ -3994,7 +4024,11 @@ module MarkdownExec
3994
4024
 
3995
4025
  # Presents a TTY prompt to select an option or exit,
3996
4026
  # returns metadata including option and selected
3997
- def select_option_with_metadata(prompt_text, menu_items, opts = {})
4027
+ def select_option_with_metadata(
4028
+ prompt_text, menu_items, opts = {}, menu_blocks: nil
4029
+ )
4030
+ @dml_menu_blocks = menu_blocks if menu_blocks
4031
+
3998
4032
  ## configure to environment
3999
4033
  #
4000
4034
  register_console_attributes(opts)
@@ -4039,23 +4073,16 @@ module MarkdownExec
4039
4073
  return
4040
4074
  end
4041
4075
 
4042
- selected = menu_items.find do |item|
4076
+ selected = @dml_menu_blocks.find do |item|
4043
4077
  if item.instance_of?(Hash)
4044
4078
  [item[:id], item[:name], item[:dname]].include?(selection)
4045
4079
  elsif item.instance_of?(MarkdownExec::FCB)
4046
- item.dname == selection || item.id == selection
4080
+ item.id == selection
4047
4081
  else
4048
4082
  item == selection
4049
4083
  end
4050
4084
  end
4051
4085
 
4052
- # new FCB if selected is not an object
4053
- if selected.instance_of?(String)
4054
- selected = FCB.new(dname: selected)
4055
- elsif selected.instance_of?(Hash)
4056
- selected = FCB.new(selected)
4057
- end
4058
-
4059
4086
  unless selected
4060
4087
  HashDelegator.error_handler('select_option_with_metadata',
4061
4088
  error: 'menu item not found')
@@ -4206,6 +4233,21 @@ module MarkdownExec
4206
4233
  HashDelegator.apply_color_from_hash(string, @delegate_object, color_sym)
4207
4234
  end
4208
4235
 
4236
+ def transform_export_value(value, export)
4237
+ return value unless export.transform.present?
4238
+
4239
+ if export.transform.is_a? Symbol
4240
+ value.send(export.transform)
4241
+ else
4242
+ format(
4243
+ export.transform,
4244
+ NamedCaptureExtractor.extract_named_groups(
4245
+ value, export.validate
4246
+ )
4247
+ )
4248
+ end
4249
+ end
4250
+
4209
4251
  ##
4210
4252
  # Processes an individual line within a loop, updating headings
4211
4253
  # and handling fenced code blocks.
@@ -4372,7 +4414,7 @@ module MarkdownExec
4372
4414
 
4373
4415
  when formatted_choice_ostructs[:history].pub_name
4374
4416
  debounce_reset
4375
- return :break unless files_table_rows = vux_history_files_table_rows
4417
+ return :break unless (files_table_rows = vux_history_files_table_rows)
4376
4418
 
4377
4419
  execute_history_select(files_table_rows, stream: $stderr)
4378
4420
  return :break if pause_user_exit
@@ -4498,9 +4540,9 @@ module MarkdownExec
4498
4540
  end
4499
4541
 
4500
4542
  def vux_load_inherited
4501
- return unless filespec = load_filespec_from_expression(
4543
+ return unless (filespec = load_filespec_from_expression(
4502
4544
  document_name_in_glob_as_file_name
4503
- )
4545
+ ))
4504
4546
 
4505
4547
  @dml_link_state.inherited_lines_append(
4506
4548
  File.readlines(filespec, chomp: true)
@@ -4619,7 +4661,6 @@ module MarkdownExec
4619
4661
  )
4620
4662
  if @delegate_object[:menu_for_history]
4621
4663
  history_files(
4622
- @dml_link_state,
4623
4664
  filename: saved_asset_filename(@delegate_object[:filename],
4624
4665
  @dml_link_state),
4625
4666
  path: @delegate_object[:saved_script_folder]
@@ -4818,15 +4859,17 @@ module MarkdownExec
4818
4859
  menu_blocks.find do |block|
4819
4860
  block.dname.include?(prior_answer)
4820
4861
  end&.name
4821
- when Struct
4862
+ when Struct, MarkdownExec::FCB
4822
4863
  if prior_answer.id
4823
- menu_items.find_index do |block|
4864
+ # when switching documents, the prior answer will not be found
4865
+ (menu_blocks.find_index do |block|
4824
4866
  block[:id] == prior_answer.id
4825
- end + 1
4867
+ end || 0) + 1
4826
4868
  else
4827
4869
  prior_answer.index || prior_answer.name
4828
4870
  end
4829
4871
  end
4872
+
4830
4873
  # prior_answer value may not match if color is different from
4831
4874
  # originating menu (opts changed while processing)
4832
4875
  selection_opts = if selected_answer
@@ -5157,13 +5200,12 @@ module MarkdownExec
5157
5200
 
5158
5201
  class TestHashDelegatorAppendDivider < Minitest::Test
5159
5202
  def setup
5160
- @hd = HashDelegator.new
5161
- @hd.instance_variable_set(:@delegate_object, {
5162
- menu_divider_format: 'Format',
5163
- menu_initial_divider: 'Initial Divider',
5164
- menu_final_divider: 'Final Divider',
5165
- menu_divider_color: :color
5166
- })
5203
+ @hd = HashDelegator.new(
5204
+ menu_divider_color: :color,
5205
+ menu_divider_format: 'Format',
5206
+ menu_final_divider: 'Final Divider',
5207
+ menu_initial_divider: 'Initial Divider'
5208
+ )
5167
5209
  @hd.stubs(:string_send_color).returns('Formatted Divider')
5168
5210
  HashDelegator.stubs(:safeval).returns('Safe Value')
5169
5211
  end
@@ -5185,7 +5227,7 @@ module MarkdownExec
5185
5227
  end
5186
5228
 
5187
5229
  def test_append_divider_without_format
5188
- @hd.instance_variable_set(:@delegate_object, {})
5230
+ @hd = HashDelegator.new
5189
5231
  menu_blocks = []
5190
5232
  @hd.append_divider(menu_blocks: menu_blocks, position: :initial)
5191
5233
 
@@ -5223,7 +5265,6 @@ module MarkdownExec
5223
5265
  @hd = HashDelegator.new
5224
5266
  @hd.stubs(:iter_blocks_from_nested_files).yields(:blocks, FCB.new)
5225
5267
  @hd.stubs(:create_and_add_chrome_blocks)
5226
- @hd.instance_variable_set(:@delegate_object, {})
5227
5268
  HashDelegator.stubs(:error_handler)
5228
5269
  end
5229
5270
 
@@ -5234,7 +5275,7 @@ module MarkdownExec
5234
5275
  end
5235
5276
 
5236
5277
  def test_blocks_from_nested_files_with_no_chrome
5237
- @hd.instance_variable_set(:@delegate_object, { no_chrome: true })
5278
+ @hd = HashDelegator.new(no_chrome: true)
5238
5279
  @hd.expects(:create_and_add_chrome_blocks).never
5239
5280
 
5240
5281
  result = @hd.blocks_from_nested_files
@@ -5246,7 +5287,6 @@ module MarkdownExec
5246
5287
  class TestHashDelegatorCollectRequiredCodeLines < Minitest::Test
5247
5288
  def setup
5248
5289
  @hd = HashDelegator.new
5249
- @hd.instance_variable_set(:@delegate_object, {})
5250
5290
  @mdoc = mock('YourMDocClass')
5251
5291
  @selected = FCB.new(
5252
5292
  body: ['key: value'],
@@ -5272,15 +5312,13 @@ module MarkdownExec
5272
5312
  class TestHashDelegatorCommandOrUserSelectedBlock < Minitest::Test
5273
5313
  def setup
5274
5314
  @hd = HashDelegator.new
5275
- @hd.instance_variable_set(:@delegate_object, {})
5276
5315
  HashDelegator.stubs(:error_handler)
5277
5316
  @hd.stubs(:wait_for_user_selected_block)
5278
5317
  end
5279
5318
 
5280
5319
  def test_command_selected_block
5281
5320
  all_blocks = [{ oname: 'block1' }, { oname: 'block2' }]
5282
- @hd.instance_variable_set(:@delegate_object,
5283
- { block_name: 'block1' })
5321
+ @hd = HashDelegator.new(block_name: 'block1')
5284
5322
 
5285
5323
  result = @hd.load_cli_or_user_selected_block(all_blocks: all_blocks)
5286
5324
 
@@ -5309,10 +5347,10 @@ module MarkdownExec
5309
5347
 
5310
5348
  class TestHashDelegatorCountBlockInFilename < Minitest::Test
5311
5349
  def setup
5312
- @hd = HashDelegator.new
5313
- @hd.instance_variable_set(:@delegate_object,
5314
- { fenced_start_and_end_regex: '^```',
5315
- filename: '/path/to/file' })
5350
+ @hd = HashDelegator.new(
5351
+ fenced_start_and_end_regex: '^```',
5352
+ filename: '/path/to/file'
5353
+ )
5316
5354
  @hd.stubs(:cfile).returns(mock('cfile'))
5317
5355
  end
5318
5356
 
@@ -5421,7 +5459,6 @@ module MarkdownExec
5421
5459
  def setup
5422
5460
  @hd = HashDelegator.new
5423
5461
  @hd.instance_variable_set(:@fout, mock('fout'))
5424
- @hd.instance_variable_set(:@delegate_object, {})
5425
5462
  @hd.stubs(:string_send_color)
5426
5463
  end
5427
5464
 
@@ -5443,7 +5480,6 @@ module MarkdownExec
5443
5480
  class TestHashDelegatorFetchColor < Minitest::Test
5444
5481
  def setup
5445
5482
  @hd = HashDelegator.new
5446
- @hd.instance_variable_set(:@delegate_object, {})
5447
5483
  end
5448
5484
 
5449
5485
  def test_fetch_color_with_valid_data
@@ -5476,7 +5512,6 @@ module MarkdownExec
5476
5512
  class TestHashDelegatorFormatReferencesSendColor < Minitest::Test
5477
5513
  def setup
5478
5514
  @hd = HashDelegator.new
5479
- @hd.instance_variable_set(:@delegate_object, {})
5480
5515
  end
5481
5516
 
5482
5517
  def test_format_references_send_color_with_valid_data
@@ -5581,7 +5616,6 @@ module MarkdownExec
5581
5616
  # )
5582
5617
 
5583
5618
  # def history_files(
5584
- # link_state,
5585
5619
  # direction: :reverse,
5586
5620
  # filename: nil,
5587
5621
  # home: Dir.pwd,
@@ -5590,9 +5624,10 @@ module MarkdownExec
5590
5624
  # )
5591
5625
 
5592
5626
  def test_call
5593
- @hd.expects(:history_files).with(nil, filename: '*', path: nil).once
5594
- @hd.execute_block_type_history_ux(filename: '*', link_state: LinkState.new,
5595
- selected: FCB.new(body: []))
5627
+ @hd.expects(:history_files).with(filename: '*', path: nil).once
5628
+ @hd.execute_block_type_history_ux(
5629
+ filename: '*', link_state: LinkState.new, selected: FCB.new(body: [])
5630
+ )
5596
5631
  end
5597
5632
  end
5598
5633
 
@@ -5677,11 +5712,9 @@ module MarkdownExec
5677
5712
 
5678
5713
  class TestHashDelegatorHandleStream < Minitest::Test
5679
5714
  def setup
5680
- @hd = HashDelegator.new
5715
+ @hd = HashDelegator.new(output_stdout: true)
5681
5716
  @hd.instance_variable_set(:@run_state,
5682
5717
  OpenStruct.new(files: StreamsOut.new))
5683
- @hd.instance_variable_set(:@delegate_object,
5684
- { output_stdout: true })
5685
5718
  end
5686
5719
 
5687
5720
  def test_handle_stream
@@ -5713,9 +5746,7 @@ module MarkdownExec
5713
5746
 
5714
5747
  class TestHashDelegatorIterBlocksFromNestedFiles < Minitest::Test
5715
5748
  def setup
5716
- @hd = HashDelegator.new
5717
- @hd.instance_variable_set(:@delegate_object,
5718
- { filename: 'test.md' })
5749
+ @hd = HashDelegator.new(filename: 'test.md')
5719
5750
  @hd.stubs(:check_file_existence).with('test.md').returns(true)
5720
5751
  @hd.stubs(:initial_state).returns({})
5721
5752
  @hd.stubs(:cfile).returns(Minitest::Mock.new)
@@ -5744,12 +5775,11 @@ module MarkdownExec
5744
5775
 
5745
5776
  class TestHashDelegatorMenuChromeColoredOption < Minitest::Test
5746
5777
  def setup
5747
- @hd = HashDelegator.new
5748
- @hd.instance_variable_set(:@delegate_object, {
5749
- menu_option_back_name: 'Back',
5750
- menu_chrome_color: :red,
5751
- menu_chrome_format: '-- %s --'
5752
- })
5778
+ @hd = HashDelegator.new(
5779
+ menu_chrome_color: :red,
5780
+ menu_chrome_format: '-- %s --',
5781
+ menu_option_back_name: 'Back'
5782
+ )
5753
5783
  @hd.stubs(:menu_chrome_formatted_option)
5754
5784
  .with(:menu_option_back_name).returns('-- Back --')
5755
5785
  @hd.stubs(:string_send_color)
@@ -5763,8 +5793,9 @@ module MarkdownExec
5763
5793
  end
5764
5794
 
5765
5795
  def test_menu_chrome_colored_option_without_color
5766
- @hd.instance_variable_set(:@delegate_object,
5767
- { menu_option_back_name: 'Back' })
5796
+ @hd = HashDelegator.new(menu_option_back_name: 'Back')
5797
+ @hd.stubs(:menu_chrome_formatted_option)
5798
+ .with(:menu_option_back_name).returns('-- Back --')
5768
5799
  assert_equal '-- Back --',
5769
5800
  @hd.menu_chrome_colored_option(:menu_option_back_name)
5770
5801
  end
@@ -5772,11 +5803,10 @@ module MarkdownExec
5772
5803
 
5773
5804
  class TestHashDelegatorMenuChromeOption < Minitest::Test
5774
5805
  def setup
5775
- @hd = HashDelegator.new
5776
- @hd.instance_variable_set(:@delegate_object, {
5777
- menu_option_back_name: "'Back'",
5778
- menu_chrome_format: '-- %s --'
5779
- })
5806
+ @hd = HashDelegator.new(
5807
+ menu_chrome_format: '-- %s --',
5808
+ menu_option_back_name: "'Back'"
5809
+ )
5780
5810
  HashDelegator.stubs(:safeval).with("'Back'").returns('Back')
5781
5811
  end
5782
5812
 
@@ -5786,8 +5816,7 @@ module MarkdownExec
5786
5816
  end
5787
5817
 
5788
5818
  def test_menu_chrome_formatted_option_without_format
5789
- @hd.instance_variable_set(:@delegate_object,
5790
- { menu_option_back_name: "'Back'" })
5819
+ @hd = HashDelegator.new(menu_option_back_name: "'Back'")
5791
5820
  assert_equal 'Back',
5792
5821
  @hd.menu_chrome_formatted_option(:menu_option_back_name)
5793
5822
  end
@@ -5795,10 +5824,12 @@ module MarkdownExec
5795
5824
 
5796
5825
  class TestHashDelegatorStartFencedBlock < Minitest::Test
5797
5826
  def setup
5798
- @hd = HashDelegator.new({
5799
- block_name_wrapper_match: 'WRAPPER_REGEX',
5800
- block_calls_scan: 'CALLS_REGEX'
5801
- })
5827
+ @hd = HashDelegator.new(
5828
+ {
5829
+ block_calls_scan: 'CALLS_REGEX',
5830
+ block_name_wrapper_match: 'WRAPPER_REGEX'
5831
+ }
5832
+ )
5802
5833
  end
5803
5834
 
5804
5835
  def test_start_fenced_block
@@ -5816,9 +5847,7 @@ module MarkdownExec
5816
5847
 
5817
5848
  class TestHashDelegatorStringSendColor < Minitest::Test
5818
5849
  def setup
5819
- @hd = HashDelegator.new
5820
- @hd.instance_variable_set(:@delegate_object,
5821
- { red: 'red', green: 'green' })
5850
+ @hd = HashDelegator.new(red: 'red', green: 'green')
5822
5851
  end
5823
5852
 
5824
5853
  def test_string_send_color
@@ -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.8.1'
10
+ VERSION = '2.8.2'
11
11
  end
data/lib/markdown_exec.rb CHANGED
@@ -656,32 +656,6 @@ module MarkdownExec
656
656
  @options.merge(@options.run_state.to_h)
657
657
  end
658
658
 
659
- def iter_source_blocks(source, &block)
660
- case source
661
- when 1
662
- HashDelegator.new(@options).blocks_from_nested_files.each(&block)
663
- when 2
664
- blocks_in_file, menu_blocks, mdoc =
665
- HashDelegator.new(@options)
666
- .mdoc_menu_and_blocks_from_nested_files(LinkState.new)
667
- blocks_in_file.each(&block)
668
- when 3
669
- blocks_in_file, menu_blocks, mdoc =
670
- HashDelegator.new(@options)
671
- .mdoc_menu_and_blocks_from_nested_files(LinkState.new)
672
- menu_blocks.each(&block)
673
- else
674
- @options.iter_blocks_from_nested_files do |btype, fcb|
675
- case btype
676
- when :blocks
677
- yield fcb
678
- when :filter
679
- %i[blocks]
680
- end
681
- end
682
- end
683
- end
684
-
685
659
  ##
686
660
  # Returns a lambda expression based on the given procname.
687
661
  # @param procname [String] The name of the process to generate a lambda for.
@@ -916,7 +890,7 @@ module MarkdownExec
916
890
  # save value to options hash if option is named
917
891
  #
918
892
  lambda { |value|
919
- name = item[:long_name]&.present? ? '--' + item[:long_name].to_s : '-' + item[:short_name].to_s
893
+ name = item[:long_name]&.present? ? "--#{item[:long_name]}" : "-#{item[:short_name]}"
920
894
  options_parsed << item.merge(name: name, value: value)
921
895
  (item[:proccode] ? item[:proccode].call(value) : value).tap do |converted|
922
896
  options[item[:opt_name]] = converted if item[:opt_name]
@@ -1013,7 +987,16 @@ module MarkdownExec
1013
987
  # Presents a TTY prompt to select an option or exit, returns selected option or nil
1014
988
  def select_option_or_exit(prompt_text, strings, opts = {})
1015
989
  @options.select_option_with_metadata(
1016
- prompt_text, strings, opts
990
+ prompt_text,
991
+ strings,
992
+ opts,
993
+ menu_blocks: strings.map do |string|
994
+ FCB.new(
995
+ chrome: true,
996
+ dname: string,
997
+ id: string
998
+ )
999
+ end
1017
1000
  )&.fetch(:selected)
1018
1001
  end
1019
1002
 
data/lib/mdoc.rb CHANGED
@@ -355,13 +355,12 @@ module MarkdownExec
355
355
  else
356
356
  opts[:hide_blocks_by_name] &&
357
357
  ((opts[:block_name_hidden_match]&.present? &&
358
- block.oname&.match(Regexp.new(opts[:block_name_hidden_match]))) ||
358
+ block.s2title&.match(Regexp.new(opts[:block_name_hidden_match]))) ||
359
359
  (opts[:block_name_include_match]&.present? &&
360
- block.oname&.match(Regexp.new(opts[:block_name_include_match]))) ||
360
+ block.s2title&.match(Regexp.new(opts[:block_name_include_match]))) ||
361
361
  (opts[:block_name_wrapper_match]&.present? &&
362
- block.oname&.match(Regexp.new(opts[:block_name_wrapper_match])))) &&
363
- (block.oname&.present? || block[:label]&.present?)
364
-
362
+ block.s2title&.match(Regexp.new(opts[:block_name_wrapper_match])))) &&
363
+ (block.s2title&.present? || block[:label]&.present?)
365
364
  end
366
365
  end
367
366
 
@@ -555,7 +554,7 @@ if $PROGRAM_NAME == __FILE__
555
554
  def test_hide_menu_block_on_name
556
555
  opts = { hide_blocks_by_name: true,
557
556
  block_name_hidden_match: 'block1' }
558
- block = FCB.new(oname: 'block1')
557
+ block = FCB.new(s2title: 'block1')
559
558
  result = @doc.hide_menu_block_on_name(opts, block)
560
559
  assert result # this should be true based on the given logic
561
560
  end
data/lib/menu.src.yml CHANGED
@@ -54,6 +54,7 @@
54
54
 
55
55
  - :opt_name: block_name_match
56
56
  :env_var: MDE_BLOCK_NAME_MATCH
57
+ :description: Pattern for the block name in the line defining the block
57
58
  :default: ":(?<title>\\S+)( |$)"
58
59
  :procname: val_as_str
59
60
 
data/lib/menu.yml CHANGED
@@ -44,6 +44,7 @@
44
44
  :procname: val_as_str
45
45
  - :opt_name: block_name_match
46
46
  :env_var: MDE_BLOCK_NAME_MATCH
47
+ :description: Pattern for the block name in the line defining the block
47
48
  :default: ":(?<title>\\S+)( |$)"
48
49
  :procname: val_as_str
49
50
  - :opt_name: block_name_nick_match
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.8.1
4
+ version: 2.8.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: 2025-02-13 00:00:00.000000000 Z
11
+ date: 2025-02-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: clipboard
@@ -107,9 +107,11 @@ files:
107
107
  - assets/select_a_block.png
108
108
  - assets/select_a_file.png
109
109
  - bats/bats.bats
110
+ - bats/block-hide.bats
110
111
  - bats/block-type-opts.bats
111
112
  - bats/block-type-ux-auto.bats
112
113
  - bats/block-type-ux-exec.bats
114
+ - bats/block-type-ux-require.bats
113
115
  - bats/block-type-ux-row-format.bats
114
116
  - bats/block-type-ux-transform.bats
115
117
  - bats/block-type-vars.bats
@@ -140,11 +142,13 @@ files:
140
142
  - bin/tab_completion.sh
141
143
  - bin/tab_completion.sh.erb
142
144
  - docs/dev/bats-document-configuration.md
145
+ - docs/dev/block-hide.md
143
146
  - docs/dev/block-type-bash.md
144
147
  - docs/dev/block-type-opts.md
145
148
  - docs/dev/block-type-port.md
146
149
  - docs/dev/block-type-ux-auto.md
147
150
  - docs/dev/block-type-ux-exec.md
151
+ - docs/dev/block-type-ux-require.md
148
152
  - docs/dev/block-type-ux-row-format.md
149
153
  - docs/dev/block-type-ux-transform.md
150
154
  - docs/dev/block-type-vars.md