markdown_exec 2.7.5 → 2.8.1

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.
@@ -92,6 +92,10 @@ module HashDelegatorSelf
92
92
  blocks.find { |item| item.send(msg) == value } || default
93
93
  end
94
94
 
95
+ def block_match(blocks, msg, value, default = nil)
96
+ blocks.select { |item| value =~ item.send(msg) }
97
+ end
98
+
95
99
  def block_select(blocks, msg, value, default = nil)
96
100
  blocks.select { |item| item.send(msg) == value }
97
101
  end
@@ -297,14 +301,16 @@ module HashDelegatorSelf
297
301
  truncate: $table_cell_truncate
298
302
  )
299
303
 
300
- truncated_table_cell = false
304
+ exceeded_table_cell = false # any cell in table is exceeded
305
+ truncated_table_cell = false # any cell in table is truncated
301
306
  table__hs.each do |table_hs|
302
307
  table_hs.substrings.each do |substrings|
303
308
  substrings.each do |node|
304
- if node[:text].class == TrackedString
305
- truncated_table_cell = node[:text].truncated
306
- break if truncated_table_cell
307
- end
309
+ next unless node[:text].class == TrackedString
310
+
311
+ exceeded_table_cell ||= node[:text].exceeded
312
+ truncated_table_cell = node[:text].truncated
313
+ break if truncated_table_cell
308
314
  end
309
315
  break if truncated_table_cell
310
316
  end
@@ -337,9 +343,9 @@ module HashDelegatorSelf
337
343
 
338
344
  if ind.zero?
339
345
  fcb.truncated_table_cell = truncated_table_cell
340
- # if truncated_table_cell
341
- fcb.delete_key(:disabled)
342
- # end
346
+ if exceeded_table_cell
347
+ fcb.delete_key(:disabled)
348
+ end
343
349
  end
344
350
  end
345
351
  end
@@ -588,6 +594,7 @@ module MarkdownExec
588
594
  @prompt = HashDelegator.tty_prompt_without_disabled_symbol
589
595
 
590
596
  @opts_most_recent_filename = nil
597
+ @ux_most_recent_filename = nil
591
598
  @vars_most_recent_filename = nil
592
599
  @pass_args = []
593
600
  @run_state = OpenStruct.new(
@@ -865,7 +872,6 @@ module MarkdownExec
865
872
  blocks = []
866
873
  iter_blocks_from_nested_files do |btype, fcb|
867
874
  count += 1
868
-
869
875
  case btype
870
876
  when :blocks
871
877
  if @delegate_object[:bash]
@@ -873,7 +879,10 @@ module MarkdownExec
873
879
  block_calls_scan: @delegate_object[:block_calls_scan],
874
880
  block_name_match: @delegate_object[:block_name_match],
875
881
  block_name_nick_match: @delegate_object[:block_name_nick_match],
876
- id: "#{source_id}_bfnf_b_#{count}"
882
+ id: "#{source_id}_bfnf_b_#{count}",
883
+ menu_format: @delegate_object[:menu_ux_row_format],
884
+ prompt: @delegate_object[:prompt_ux_enter_a_value],
885
+ table_center: @delegate_object[:table_center]
877
886
  ) do |oname, color|
878
887
  apply_block_type_color_option(oname, color)
879
888
  end
@@ -925,7 +934,12 @@ module MarkdownExec
925
934
  end
926
935
  end
927
936
 
928
- # private
937
+ def build_menu_options(exit_option, display_mode_option,
938
+ menu_entries, display_format)
939
+ [exit_option,
940
+ display_mode_option,
941
+ *menu_entries.map(&display_format)].compact
942
+ end
929
943
 
930
944
  def build_replacement_dictionary(
931
945
  commands, link_state,
@@ -935,7 +949,7 @@ module MarkdownExec
935
949
  (link_state&.inherited_lines_block || ''), commands,
936
950
  initial_code_required: initial_code_required,
937
951
  key_format: key_format
938
- ) # !!t
952
+ )
939
953
  end
940
954
 
941
955
  def calc_logged_stdout_filename(block_name:)
@@ -1008,6 +1022,136 @@ module MarkdownExec
1008
1022
  ]
1009
1023
  end
1010
1024
 
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
1039
+ def code_from_ux_block_to_set_environment_variables(
1040
+ selected, mdoc, inherited_code: nil, force: true, only_default: false
1041
+ )
1042
+ # ww0 inherited_code
1043
+ # ww0 mdoc
1044
+ exit_prompt = @delegate_object[:prompt_filespec_back]
1045
+
1046
+ required = mdoc.collect_recursively_required_code(
1047
+ anyname: selected.pub_name,
1048
+ label_format_above: @delegate_object[:shell_code_label_format_above],
1049
+ label_format_below: @delegate_object[:shell_code_label_format_below],
1050
+ block_source: block_source
1051
+ )
1052
+
1053
+ 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?
1068
+
1069
+ n1 = neval(export.exec,
1070
+ (inherited_code || []) + required[:code])
1071
+
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
+ )
1082
+ end
1083
+ else
1084
+ n1
1085
+ end
1086
+
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
1126
+
1127
+ # invalid input, retry
1128
+
1129
+ end
1130
+ rescue Interrupt
1131
+ exportable = false
1132
+ end
1133
+
1134
+ # default
1135
+ else
1136
+ value = export.default
1137
+ end
1138
+
1139
+ if exportable && export.transform.present?
1140
+ value = format(export.transform, caps)
1141
+ end
1142
+ 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
+ end
1152
+ code_lines
1153
+ end
1154
+
1011
1155
  # sets ENV
1012
1156
  def code_from_vars_block_to_set_environment_variables(selected)
1013
1157
  code_lines = []
@@ -1027,6 +1171,14 @@ module MarkdownExec
1027
1171
  code_lines
1028
1172
  end
1029
1173
 
1174
+ def code_line_safe_assign(name, value, force:)
1175
+ if force
1176
+ "#{name}=#{Shellwords.escape(value)}"
1177
+ else
1178
+ "[[ -z $#{name} ]] && #{name}=#{Shellwords.escape(value)}"
1179
+ end
1180
+ end
1181
+
1030
1182
  def collect_line_decor_patterns(delegate_object)
1031
1183
  extract_patterns = lambda do |key|
1032
1184
  return [] unless delegate_object[key].present?
@@ -1412,7 +1564,7 @@ module MarkdownExec
1412
1564
  @delegate_object[criteria[:color]].to_sym,
1413
1565
  decor_patterns:
1414
1566
  @decor_patterns_from_delegate_object_for_block_create,
1415
- disabled: fcb.truncated_table_cell.nil? && !(criteria[:collapsible] && @delegate_object[criteria[:collapsible]]),
1567
+ disabled: !(criteria[:collapsible] && @delegate_object[criteria[:collapsible]]),
1416
1568
  fcb: fcb,
1417
1569
  id: "#{id}.#{index}",
1418
1570
  format_option: criteria[:format] &&
@@ -1790,6 +1942,18 @@ module MarkdownExec
1790
1942
  )
1791
1943
  next_state_set_code(selected, link_state, required_lines)
1792
1944
 
1945
+ elsif selected.type == BlockType::UX
1946
+ debounce_reset
1947
+ next_state_append_code(
1948
+ selected,
1949
+ link_state,
1950
+ code_from_ux_block_to_set_environment_variables(
1951
+ selected,
1952
+ @dml_mdoc,
1953
+ inherited_code: @dml_link_state.inherited_lines
1954
+ )
1955
+ )
1956
+
1793
1957
  elsif selected.type == BlockType::VARS
1794
1958
  debounce_reset
1795
1959
  next_state_append_code(selected, link_state,
@@ -1822,19 +1986,23 @@ module MarkdownExec
1822
1986
  block_source: block_source
1823
1987
  )
1824
1988
 
1825
- # if the same menu is being displayed, collect the display name
1826
- # of the selected menu item for use as the default item
1827
- [lfls.link_state,
1828
- lfls.load_file == LoadFile::LOAD ? nil : selected.dname,
1829
- # 2024-08-22 true to quit
1830
- lfls.load_file == LoadFile::EXIT]
1989
+ # 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)
1993
+ block_selection = BlockSelection.new(selected.id)
1994
+ end
1995
+
1996
+ { link_state: lfls.link_state,
1997
+ block_selection: block_selection,
1998
+ quit: lfls.load_file == LoadFile::EXIT }
1831
1999
  end
1832
2000
 
1833
2001
  def execute_block_in_state(block_name)
1834
2002
  @dml_block_state = block_state_for_name_from_cli(block_name)
1835
2003
  dump_and_warn_block_state(name: block_name,
1836
2004
  selected: @dml_block_state.block)
1837
- @dml_link_state, @dml_menu_default_dname, quit =
2005
+ next_block_state =
1838
2006
  execute_block_for_state_and_name(
1839
2007
  selected: @dml_block_state.block,
1840
2008
  mdoc: @dml_mdoc,
@@ -1846,7 +2014,10 @@ module MarkdownExec
1846
2014
  )
1847
2015
  }
1848
2016
  )
1849
- :break if quit
2017
+
2018
+ @dml_link_state = next_block_state[:link_state]
2019
+ @dml_block_selection = next_block_state[:block_selection]
2020
+ :break if next_block_state[:quit]
1850
2021
  end
1851
2022
 
1852
2023
  def execute_block_type_history_ux(
@@ -1993,6 +2164,7 @@ module MarkdownExec
1993
2164
  block_data['glob'] || glob
1994
2165
  )
1995
2166
  )
2167
+ dirs.sort_by! { |f| File.mtime(f) }.reverse!
1996
2168
 
1997
2169
  if !contains_glob?(block_data['directory']) &&
1998
2170
  !contains_glob?(block_data['glob'])
@@ -2003,7 +2175,7 @@ module MarkdownExec
2003
2175
  end
2004
2176
  elsif selected_option = select_option_with_metadata(
2005
2177
  prompt_title,
2006
- [exit_prompt] + dirs.sort.map do |file|
2178
+ [exit_prompt] + dirs.map do |file|
2007
2179
  { name: format(
2008
2180
  block_data['view'] || view,
2009
2181
  NamedCaptureExtractor.extract_named_group_match_data(
@@ -2167,41 +2339,25 @@ module MarkdownExec
2167
2339
  )
2168
2340
  # repeat select+display until user exits
2169
2341
 
2170
- pause_now = false
2171
- row_attrib = :row
2172
- loop do
2173
- if pause_now && (prompt_select_continue == MenuState::EXIT)
2174
- break
2175
- end
2176
-
2177
- # menu with Back and Facet options at top
2178
- case (name = prompt_select_code_filename(
2179
- [exit_prompt,
2180
- @delegate_object[:prompt_filespec_facet]] +
2181
- files_table_rows.map(&row_attrib),
2182
- string: @delegate_object[:prompt_select_history_file],
2183
- color_sym: :prompt_color_after_script_execution
2184
- ))
2185
- when exit_prompt
2186
- break
2187
- when @delegate_object[:prompt_filespec_facet]
2188
- row_attrib = row_attrib == :row ? :file : :row
2189
- pause_now = false
2190
- else
2191
- file = files_table_rows.select { |ftr| ftr.row == name }&.first
2192
- info = file_info(file.file)
2193
- stream.puts "#{file.file} - #{info[:lines]} lines / " \
2194
- "#{info[:size]} bytes"
2195
- stream.puts(
2196
- File.readlines(file.file,
2197
- chomp: false).map.with_index do |line, ind|
2198
- format(' %s. %s',
2199
- AnsiString.new(format('% 4d', ind + 1)).send(:violet),
2200
- line)
2201
- end
2202
- )
2203
- pause_now = pause_refresh
2204
- end
2342
+ interactive_menu_with_display_modes(
2343
+ files_table_rows,
2344
+ display_formats: [:row, :file],
2345
+ display_mode_option: @delegate_object[:prompt_filespec_facet],
2346
+ exit_option: exit_prompt,
2347
+ menu_title: @delegate_object[:prompt_select_history_file],
2348
+ pause_after_selection: pause_refresh
2349
+ ) do |file|
2350
+ info = file_info(file.file)
2351
+ stream.puts "#{file.file} - #{info[:lines]} lines / " \
2352
+ "#{info[:size]} bytes"
2353
+ stream.puts(
2354
+ File.readlines(file.file,
2355
+ chomp: false).map.with_index do |line, ind|
2356
+ format(' %s. %s',
2357
+ AnsiString.new(format('% 4d', ind + 1)).send(:violet),
2358
+ line)
2359
+ end
2360
+ )
2205
2361
  end
2206
2362
  end
2207
2363
 
@@ -2296,7 +2452,7 @@ module MarkdownExec
2296
2452
 
2297
2453
  variable_counts = count_named_group_occurrences(blocks, pattern,
2298
2454
  group_name: group_name)
2299
- return if variable_counts.nil?
2455
+ return if variable_counts.nil? || variable_counts == {}
2300
2456
 
2301
2457
  echo_commands = generate_echo_commands(variable_counts, echo_format)
2302
2458
 
@@ -2307,6 +2463,7 @@ module MarkdownExec
2307
2463
  )
2308
2464
 
2309
2465
  return if replacements.nil?
2466
+ return if replacements == EvaluateShellExpression::StatusFail
2310
2467
 
2311
2468
  expand_blocks_with_replacements(blocks, replacements)
2312
2469
  end
@@ -2519,6 +2676,56 @@ module MarkdownExec
2519
2676
  }
2520
2677
  end
2521
2678
 
2679
+ def interactive_menu_with_display_modes(
2680
+ menu_entries,
2681
+ display_formats:,
2682
+ display_mode_option:,
2683
+ exit_option:,
2684
+ menu_title:,
2685
+ pause_after_selection:
2686
+ )
2687
+ pause_menu = false
2688
+ current_display_format = display_formats.first
2689
+
2690
+ loop do
2691
+ break if pause_menu && (prompt_select_continue == MenuState::EXIT)
2692
+
2693
+ menu_options = build_menu_options(
2694
+ exit_option, display_mode_option,
2695
+ menu_entries, current_display_format
2696
+ )
2697
+
2698
+ selection = prompt_select_code_filename(
2699
+ menu_options,
2700
+ string: menu_title,
2701
+ color_sym: :prompt_color_after_script_execution
2702
+ )
2703
+
2704
+ case selection
2705
+ when exit_option
2706
+ break
2707
+ when display_mode_option
2708
+ current_display_format = next_item(
2709
+ display_formats, current_display_format
2710
+ )
2711
+ pause_menu = false
2712
+ else
2713
+ handle_selection(menu_entries, selection,
2714
+ current_display_format) do |item|
2715
+ yield item if block_given?
2716
+ end
2717
+ pause_menu = pause_after_selection
2718
+ end
2719
+ end
2720
+ end
2721
+
2722
+ def handle_selection(menu_entries, selection, current_display_format)
2723
+ selected_item = menu_entries.find do |entry|
2724
+ entry.send(current_display_format) == selection
2725
+ end
2726
+ yield selected_item if selected_item
2727
+ end
2728
+
2522
2729
  # Iterates through blocks in a file, applying the provided block to each line.
2523
2730
  # The iteration only occurs if the file exists.
2524
2731
  # @yield [Symbol] :filter Yields to obtain selected messages for processing.
@@ -2723,6 +2930,37 @@ module MarkdownExec
2723
2930
  true
2724
2931
  end
2725
2932
 
2933
+ def load_auto_ux_block(
2934
+ all_blocks,
2935
+ mdoc,
2936
+ block_name: @delegate_object[:document_load_ux_block_name]
2937
+ )
2938
+ unless block_name.present? &&
2939
+ @ux_most_recent_filename != @delegate_object[:filename]
2940
+ return
2941
+ end
2942
+
2943
+ blocks = HashDelegator.block_select(all_blocks, :oname, block_name)
2944
+ if blocks.empty?
2945
+ blocks = HashDelegator.block_match(all_blocks, :nickname,
2946
+ Regexp.new(block_name))
2947
+ end
2948
+ return if blocks.empty?
2949
+
2950
+ @ux_most_recent_filename = @delegate_object[:filename]
2951
+
2952
+ (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
+ )
2960
+ )
2961
+ end).to_a
2962
+ end
2963
+
2726
2964
  def load_auto_vars_block(all_blocks,
2727
2965
  block_name: @delegate_object[:document_load_vars_block_name])
2728
2966
  unless block_name.present? &&
@@ -2871,6 +3109,16 @@ module MarkdownExec
2871
3109
  reload_blocks = true
2872
3110
  end
2873
3111
 
3112
+ # load document ux block
3113
+ #
3114
+ if code_lines = load_auto_ux_block(all_blocks, mdoc)
3115
+ new_code = HashDelegator.code_merge(link_state.inherited_lines,
3116
+ code_lines)
3117
+ next_state_set_code(nil, link_state, new_code)
3118
+ link_state.inherited_lines = new_code
3119
+ reload_blocks = true
3120
+ end
3121
+
2874
3122
  # load document vars block
2875
3123
  #
2876
3124
  if code_lines = load_auto_vars_block(all_blocks)
@@ -2924,7 +3172,6 @@ module MarkdownExec
2924
3172
  HashDelegator.tables_into_columns!(menu_blocks, @delegate_object,
2925
3173
  screen_width_for_table)
2926
3174
 
2927
-
2928
3175
  [all_blocks, menu_blocks, mdoc]
2929
3176
  end
2930
3177
 
@@ -2988,7 +3235,6 @@ module MarkdownExec
2988
3235
  def menu_toggle_collapsible_block(selected)
2989
3236
  # return true if @compress_ids.key?(fcb.id) && !!@compress_ids[fcb.id]
2990
3237
  # return false if @expand_ids.key?(fcb.id) && !!@expand_ids[fcb.id]
2991
- # binding.irb
2992
3238
  if @compressed_ids.key?(selected.id) && !!@compressed_ids[selected.id]
2993
3239
  @compressed_ids.delete(selected.id)
2994
3240
  @expanded_ids[selected.id] = selected.level
@@ -3010,6 +3256,13 @@ module MarkdownExec
3010
3256
  end
3011
3257
  end
3012
3258
 
3259
+ def next_item(list, current_item)
3260
+ index = list.index(current_item)
3261
+ return nil unless index # Return nil if the item is not in the list
3262
+
3263
+ list[(index + 1) % list.size] # Get the next item, wrap around if at the end
3264
+ end
3265
+
3013
3266
  def next_state_append_code(selected, link_state, code_lines)
3014
3267
  next_state_set_code(
3015
3268
  selected,
@@ -3705,15 +3958,17 @@ module MarkdownExec
3705
3958
  end
3706
3959
 
3707
3960
  def screen_width
3708
- if @delegate_object[:screen_width] && @delegate_object[:screen_width].positive?
3709
- @delegate_object[:screen_width]
3961
+ width = @delegate_object[:screen_width]
3962
+ if width && width.positive?
3963
+ width
3710
3964
  else
3711
3965
  @delegate_object[:console_width]
3712
3966
  end
3713
3967
  end
3714
3968
 
3715
3969
  def screen_width_for_table
3716
- screen_width - prompt_margin_left_width - prompt_margin_right_width - 2 # prompt is symbol + space (width: 2)
3970
+ # menu adds newline after some lines if sized to the edge
3971
+ screen_width - prompt_margin_left_width - prompt_margin_right_width - 3 # menu prompt symbol (1) + space (1) + gap (1)
3717
3972
  end
3718
3973
 
3719
3974
  def screen_width_for_wrapping
@@ -3910,7 +4165,7 @@ module MarkdownExec
3910
4165
  disabled = if fcb_title_groups.fetch(:type, '') == BlockType::YAML
3911
4166
  TtyMenu::DISABLE
3912
4167
  else
3913
- nil
4168
+ TtyMenu::ENABLE
3914
4169
  end
3915
4170
 
3916
4171
  MarkdownExec::FCB.new(
@@ -4036,11 +4291,11 @@ module MarkdownExec
4036
4291
  @delegate_object.merge!(options)
4037
4292
  end
4038
4293
 
4039
- def vux_await_user_selection
4294
+ def vux_await_user_selection(prior_answer: @dml_block_selection)
4040
4295
  @dml_block_state = load_cli_or_user_selected_block(
4041
4296
  all_blocks: @dml_blocks_in_file,
4042
4297
  menu_blocks: @dml_menu_blocks,
4043
- prior_answer: @dml_menu_default_dname
4298
+ prior_answer: prior_answer
4044
4299
  )
4045
4300
  if !@dml_block_state
4046
4301
  # HashDelegator.error_handler('block_state missing', { abort: true })
@@ -4194,7 +4449,7 @@ module MarkdownExec
4194
4449
  @dml_link_state.block_name.present?
4195
4450
  @cli_block_name = @dml_link_state.block_name
4196
4451
  @dml_now_using_cli = @run_state.source.block_name_from_cli
4197
- @dml_menu_default_dname = nil
4452
+ @dml_block_selection = nil
4198
4453
  @dml_block_state = SelectedBlockMenuState.new
4199
4454
  @doc_saved_lines_files = []
4200
4455
 
@@ -4512,7 +4767,9 @@ module MarkdownExec
4512
4767
  else
4513
4768
  # puts "? - Select a block to execute (or type #{$texit}
4514
4769
  # to exit):"
4515
- return :break if vux_await_user_selection == :break
4770
+ return :break if vux_await_user_selection(
4771
+ prior_answer: @dml_block_selection
4772
+ ) == :break
4516
4773
  return :break if @dml_block_state.block.nil? # no block matched
4517
4774
  end
4518
4775
  # puts "! - Executing block: #{data}"
@@ -4562,7 +4819,13 @@ module MarkdownExec
4562
4819
  block.dname.include?(prior_answer)
4563
4820
  end&.name
4564
4821
  when Struct
4565
- prior_answer.index || prior_answer.name
4822
+ if prior_answer.id
4823
+ menu_items.find_index do |block|
4824
+ block[:id] == prior_answer.id
4825
+ end + 1
4826
+ else
4827
+ prior_answer.index || prior_answer.name
4828
+ end
4566
4829
  end
4567
4830
  # prior_answer value may not match if color is different from
4568
4831
  # originating menu (opts changed while processing)
@@ -3,10 +3,11 @@
3
3
  require_relative 'ansi_string'
4
4
 
5
5
  class TrackedString < String
6
- attr_accessor :truncated
6
+ attr_accessor :exceeded, :truncated
7
7
 
8
8
  def initialize(str)
9
- super(str)
9
+ super
10
+ @exceeded = false
10
11
  @truncated = false
11
12
  end
12
13
  end
@@ -7,5 +7,5 @@ module MarkdownExec
7
7
  BIN_NAME = 'mde'
8
8
  GEM_NAME = 'markdown_exec'
9
9
  TAP_DEBUG = 'MDE_DEBUG'
10
- VERSION = '2.7.5'
10
+ VERSION = '2.8.1'
11
11
  end
data/lib/markdown_exec.rb CHANGED
@@ -256,7 +256,7 @@ module MarkdownExec
256
256
  block_name_nick_match)
257
257
  return unless line.match(fenced_start_and_end_regex)
258
258
 
259
- bm = NamedCaptureExtractor::extract_named_groups(line, block_name_match)
259
+ bm = NamedCaptureExtractor.extract_named_groups(line, block_name_match)
260
260
  return if bm.nil?
261
261
 
262
262
  name = bm[:title]
@@ -282,7 +282,6 @@ module MarkdownExec
282
282
  include StringUtil
283
283
 
284
284
  def initialize(options = {})
285
- # ww0 'options', options, caller.deref
286
285
  @option_parser = nil
287
286
 
288
287
  @options = HashDelegator.new(options)
@@ -405,7 +404,7 @@ module MarkdownExec
405
404
  ## Executes the block specified in the options
406
405
  #
407
406
  def execute_block_with_error_handling
408
- @options.register_console_attributes(@options)
407
+ @options.register_console_attributes(@options)
409
408
  finalize_cli_argument_processing
410
409
  execute_initial_commands_and_main_loop(@options, @options.run_state)
411
410
  rescue FileMissingError
@@ -430,11 +429,9 @@ module MarkdownExec
430
429
  def execute_simple_commands(options, stage: nil)
431
430
  # !!p stage
432
431
  simple_commands(options).each do |key, (cstage, proc)|
433
- if @options[key].is_a?(TrueClass) || @options[key].present?
434
- if stage && stage == cstage
435
- proc.call
436
- return true
437
- end
432
+ if (@options[key].is_a?(TrueClass) || @options[key].present?) && (stage && stage == cstage)
433
+ proc.call
434
+ return true
438
435
  end
439
436
  end
440
437
  false