markdown_exec 2.8.1 → 2.8.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: 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