markdown_exec 2.8.0 → 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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c36bb5c2d9e91eeeae59067f91fc88a3ad8e6b1a27ebfb474ff900903d030042
4
- data.tar.gz: b002fc24e78006e830fdc66bb0be4df05fe9df62e6c036965eefbb7047f37ec7
3
+ metadata.gz: d752af0db5e1c1a770b64f9341c3d08e1e9bc8612230a9cb44ddc7fddc4c3051
4
+ data.tar.gz: 5ba8524b3323bd8333b82a5d0607fbb9db59a5157a1c7ae0564b3f624f26addd
5
5
  SHA512:
6
- metadata.gz: 8eedac9012c2c0103afe99a8ea0cd235b26b3ab62618b35d79af6f685a56195818d28ba70588f93d754c76e5c4b3bb524de0ed09fd97864bdc79a424015911a9
7
- data.tar.gz: d24b8c56e50416032de644f00d11f6bb81689617e47da57ec1e4b39a693c867dedff268ddd00e023bc134fc40ee9ae9b452a808131d129b378508464ac0793f5
6
+ metadata.gz: 29b210e56b46a1edf099c02267e2b3c7cdae6701f7ee99d5a946d06eea7272da3534765110ec36a6de017a10d0f4833c9075c27dacb0cec8b050192d3892d748
7
+ data.tar.gz: e73cd906ce9035c8c78d2e301866af4a76bc7a730c5109fc8cc59ecf64679cb578fb04b324e700df064886d250c394c441f77850b9e21230d346d08bd92a9a5f
data/.rubocop.yml CHANGED
@@ -97,6 +97,9 @@ Style/GlobalVars:
97
97
  Style/IfUnlessModifier: # 2024-08 suggests lines that are too long
98
98
  Enabled: false
99
99
 
100
+ Style/KeywordParametersOrder:
101
+ Enabled: false
102
+
100
103
  Style/Lambda:
101
104
  Enabled: false
102
105
 
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- markdown_exec (2.8.0)
4
+ markdown_exec (2.8.1)
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 'Initial values' {
6
+ spec_mde_xansi_dname_doc_blocks_expect docs/dev/block-type-ux-auto.md \
7
+ 'v1 = _v2 = _v3 = 12_v4 = 21_v5 = markdown_exec_v6 = 31'
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-exec.md \
7
+ "ux0=_ux1=Unknown_ux2=markdown_exec_ux3=markdown_exec_ux4=Xform: 'markdown'"
8
+ }
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bats
2
+
3
+ load 'test_helper'
4
+
5
+ @test 'Row format merges with prior table' {
6
+ spec_mde_xansi_dname_doc_blocks_expect docs/dev/block-type-ux-row-format.md \
7
+ ' | Variable | Value | Prompt |_ | --------- | ---------------- | ------------------- |_ | Species | Pongo tapanulien | New species? |_ | Name: Gen | Value: Pongo | Prompt: New genus? |_ | Family | Hominidae | Enter a value: |'
8
+ }
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bats
2
+
3
+ load 'test_helper'
4
+
5
+ @test 'Transformed output of executed commands' {
6
+ spec_mde_xansi_dname_doc_blocks_expect docs/dev/block-type-ux-transform.md \
7
+ '_Execution output has a trailing newline._Var0=markdown_exec_00000000 6d 61 72 6b 64 6f 77 6e 5f 65 78 65 63 0a |markdown_exec.|__With validate and transform, output has no newline._Var1=markdown_exec_00000000 6d 61 72 6b 64 6f 77 6e 5f 65 78 65 63 |markdown_exec|__With transform :chomp, output has no newline._Var2=markdown_exec_00000000 6d 61 72 6b 64 6f 77 6e 5f 65 78 65 63 |markdown_exec|__With transform :upcase, output is in upper case w/ newline._Var3=MARKDOWN_EXEC_00000000 4d 41 52 4b 44 4f 57 4e 5f 45 58 45 43 0a |MARKDOWN_EXEC.|'
8
+ }
@@ -13,7 +13,7 @@ __filedirs_all()
13
13
  }
14
14
 
15
15
  _mde_echo_version() {
16
- echo "2.8.0"
16
+ echo "2.8.1"
17
17
  }
18
18
 
19
19
  _mde() {
@@ -0,0 +1,43 @@
1
+ / v2025-02-08
2
+ / name only
3
+ ```ux
4
+ name: v1
5
+ ```
6
+ / name and default
7
+ / transform and validate options not applied to default
8
+ ```ux
9
+ default: 11
10
+ name: v2
11
+ ```
12
+ / name and default; auto-load
13
+ / prompt option is ignored during auto-load
14
+ ```ux :[document_ux_v3]
15
+ default: 12
16
+ name: v3
17
+ ```
18
+ / name, default, exec; auto-load static
19
+ ```ux :[document_ux_v4]
20
+ default: 21
21
+ exec: basename $(pwd)
22
+ name: v4
23
+ ```
24
+ / name, default, exec; auto-load executed `basename $(pwd)`
25
+ / allowed is ignored by exec
26
+ ```ux :[document_ux_v5]
27
+ default: :exec
28
+ exec: basename $(pwd)
29
+ name: v5
30
+ ```
31
+ / name, default, allowed; auto-load static default
32
+ ```ux :[document_ux_v6]
33
+ allowed:
34
+ - 32
35
+ - 33
36
+ default: 31
37
+ name: v6
38
+ ```
39
+ @import bats-document-configuration.md
40
+ ```opts :(document_opts)
41
+ menu_ux_row_format: '%{name} = ${%{name}}'
42
+ ux_auto_load_force_default: true
43
+ ```
@@ -0,0 +1,42 @@
1
+ / auto-load block, does not execute command to calculate
2
+ / click block to calculate
3
+ ```ux :[document_ux0]
4
+ exec: basename $(pwd)
5
+ name: ux0
6
+ ```
7
+ / auto-load block and execute command to calculate
8
+ / click block to recalculate
9
+ ```ux :[document_ux1]
10
+ default: Unknown
11
+ exec: basename $(pwd)
12
+ name: ux1
13
+ ```
14
+ / auto-load block and execute command to calculate
15
+ / click block to recalculate
16
+ ```ux :[document_ux2]
17
+ default: :exec
18
+ exec: basename $(pwd)
19
+ name: ux2
20
+ ```
21
+ / required block defining a function used in exec
22
+ ```bash :(bash3)
23
+ # function from bash3
24
+ val () { basename $(pwd) ; }
25
+ ```
26
+ ```ux :[document_ux3] +(bash3)
27
+ default: :exec
28
+ exec: val
29
+ name: ux3
30
+ ```
31
+ / default is computed
32
+ / output of execution is validated/parsed
33
+ / parsing is transformed
34
+ ```ux :[document_ux4]
35
+ default: :exec
36
+ exec: basename $(pwd)
37
+ name: ux4
38
+ transform: "Xform: '%{name}'"
39
+ validate: |
40
+ ^(?<name>.*)(_.*)$
41
+ ```
42
+ @import bats-document-configuration.md
@@ -0,0 +1,47 @@
1
+ / v2025-02-08
2
+ | Variable| Value| Prompt
3
+ | -| -| -
4
+ / auto-load default value
5
+ / custom prompt
6
+ / select list
7
+ / default value
8
+ ```ux :[document_ux_Species]
9
+ allowed:
10
+ - Pongo tapanuliensis
11
+ - Histiophryne psychedelica
12
+ - Phyllopteryx dewysea
13
+ default: Pongo tapanuliensis
14
+ name: Species
15
+ prompt: New species?
16
+ ```
17
+ / auto-load default value
18
+ / cell text is prefixed Name/Value/Prompt
19
+ / select list contains additional text
20
+ / selected value is validated with named groups
21
+ / selected value is transformed; named capture is prefixed Xform
22
+ ```ux :[document_ux_Genus]
23
+ allowed:
24
+ - 1. Pongo
25
+ - 2. Histiophryne
26
+ - 3. Phyllopteryx
27
+ default: Pongo
28
+ menu_format: "| Name: %{name}| Value: ${%{name}}| Prompt: %{prompt}"
29
+ name: Genus
30
+ prompt: New genus?
31
+ transform: "Xform: '%{name}'"
32
+ validate: |
33
+ ^\d+\. *(?<name>[^ ].*)$
34
+ ```
35
+ / default
36
+ / auto-load default value
37
+ ```ux :[document_ux_Family]
38
+ default: Hominidae
39
+ name: Family
40
+ ```
41
+ @import bats-document-configuration.md
42
+ ```opts :(document_opts)
43
+ menu_ux_row_format: '| %{name}| ${%{name}}| %{prompt}'
44
+ screen_width: 64
45
+ table_center: true
46
+ ux_auto_load_force_default: true
47
+ ```
@@ -0,0 +1,41 @@
1
+ :::
2
+ **Execution output has a trailing newline.**
3
+ ```ux :[document_ux_transform_0]
4
+ default: :exec
5
+ exec: basename $(pwd)
6
+ name: Var0
7
+ ```
8
+ $(echo -n "$Var0" | hexdump -C)
9
+ :::
10
+ **With validate and transform, output has no newline.**
11
+ ```ux :[document_ux_transform_1]
12
+ default: :exec
13
+ exec: basename $(pwd)
14
+ name: Var1
15
+ transform: '%{name}'
16
+ validate: (?<name>.+)
17
+ ```
18
+ $(echo -n "$Var1" | hexdump -C)
19
+ :::
20
+ **With transform `:chomp`, output has no newline.**
21
+ ```ux :[document_ux_transform_2]
22
+ default: :exec
23
+ exec: basename $(pwd)
24
+ name: Var2
25
+ transform: :chomp
26
+ ```
27
+ $(echo -n "$Var2" | hexdump -C)
28
+ :::
29
+ **With transform `:upcase`, output is in upper case w/ newline.**
30
+ ```ux :[document_ux_transform_3]
31
+ default: :exec
32
+ exec: basename $(pwd)
33
+ name: Var3
34
+ transform: :upcase
35
+ ```
36
+ $(echo -n "$Var3" | hexdump -C)
37
+ @import bats-document-configuration.md
38
+ ```opts :(document_opts)
39
+ divider4_collapsible: false
40
+ table_center: false
41
+ ```
data/lib/constants.rb CHANGED
@@ -100,8 +100,10 @@ end
100
100
 
101
101
  # selected block and subsequent menu state
102
102
  #
103
+ BlockSelection = Struct.new(:id)
103
104
  SelectedBlockMenuState = Struct.new(:block, :source, :state)
104
105
 
105
106
  class TtyMenu
107
+ ENABLE = nil
106
108
  DISABLE = ''
107
109
  end
data/lib/fcb.rb CHANGED
@@ -56,10 +56,6 @@ module MarkdownExec
56
56
  title: '',
57
57
  type: ''
58
58
  }.merge(options)
59
- # @attrs[:raw_body] ||= @attrs[:body]
60
- # @attrs[:raw_dname] ||= @attrs[:dname]
61
- # @attrs[:raw_s0printable] ||= @attrs[:s0printable]
62
- # @attrs[:raw_s1decorated] ||= @attrs[:s1decorated]
63
59
  end
64
60
 
65
61
  def code_name_included?(*names)
@@ -92,34 +88,6 @@ module MarkdownExec
92
88
  end
93
89
  end
94
90
 
95
- # def body=(value)
96
- # ww0 'body=', value
97
- # # binding.irb
98
- # @attrs[:raw_body] ||= value
99
- # @attrs[:body] = value
100
- # end
101
-
102
- # def dname=(value)
103
- # ww0 'dname=', value
104
- # binding.irb if value == ' | Species| Not specified'
105
- # @attrs[:raw_dname] ||= value
106
- # @attrs[:dname] = value
107
- # end
108
-
109
- # def s0printable=(value)
110
- # ww0 's0printable=', value
111
- # # binding.irb
112
- # @attrs[:raw_s0printable] ||= value
113
- # @attrs[:s0printable] = value
114
- # end
115
-
116
- # def s1decorated=(value)
117
- # ww0 's1decorated=', value
118
- # # binding.irb
119
- # @attrs[:raw_s1decorated] ||= value
120
- # @attrs[:s1decorated] = value
121
- # end
122
-
123
91
  # Processes a block to generate its summary, modifying its attributes
124
92
  # based on various matching criteria.
125
93
  # It handles special formatting for bash blocks, extracting and setting
@@ -934,7 +934,12 @@ module MarkdownExec
934
934
  end
935
935
  end
936
936
 
937
- # 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
938
943
 
939
944
  def build_replacement_dictionary(
940
945
  commands, link_state,
@@ -1061,7 +1066,8 @@ module MarkdownExec
1061
1066
  when :exec
1062
1067
  raise unless export.exec.present?
1063
1068
 
1064
- n1 = neval(export.exec, (inherited_code || []) + required[:code])
1069
+ n1 = neval(export.exec,
1070
+ (inherited_code || []) + required[:code])
1065
1071
 
1066
1072
  if export.transform.present?
1067
1073
  if export.transform.is_a? Symbol
@@ -1167,7 +1173,6 @@ module MarkdownExec
1167
1173
 
1168
1174
  def code_line_safe_assign(name, value, force:)
1169
1175
  if force
1170
- # ww0 value
1171
1176
  "#{name}=#{Shellwords.escape(value)}"
1172
1177
  else
1173
1178
  "[[ -z $#{name} ]] && #{name}=#{Shellwords.escape(value)}"
@@ -1981,19 +1986,23 @@ module MarkdownExec
1981
1986
  block_source: block_source
1982
1987
  )
1983
1988
 
1984
- # if the same menu is being displayed, collect the display name
1985
- # of the selected menu item for use as the default item
1986
- [lfls.link_state,
1987
- lfls.load_file == LoadFile::LOAD ? nil : selected.dname,
1988
- # 2024-08-22 true to quit
1989
- 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 }
1990
1999
  end
1991
2000
 
1992
2001
  def execute_block_in_state(block_name)
1993
2002
  @dml_block_state = block_state_for_name_from_cli(block_name)
1994
2003
  dump_and_warn_block_state(name: block_name,
1995
2004
  selected: @dml_block_state.block)
1996
- @dml_link_state, @dml_menu_default_dname, quit =
2005
+ next_block_state =
1997
2006
  execute_block_for_state_and_name(
1998
2007
  selected: @dml_block_state.block,
1999
2008
  mdoc: @dml_mdoc,
@@ -2005,7 +2014,10 @@ module MarkdownExec
2005
2014
  )
2006
2015
  }
2007
2016
  )
2008
- :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]
2009
2021
  end
2010
2022
 
2011
2023
  def execute_block_type_history_ux(
@@ -2152,6 +2164,7 @@ module MarkdownExec
2152
2164
  block_data['glob'] || glob
2153
2165
  )
2154
2166
  )
2167
+ dirs.sort_by! { |f| File.mtime(f) }.reverse!
2155
2168
 
2156
2169
  if !contains_glob?(block_data['directory']) &&
2157
2170
  !contains_glob?(block_data['glob'])
@@ -2162,7 +2175,7 @@ module MarkdownExec
2162
2175
  end
2163
2176
  elsif selected_option = select_option_with_metadata(
2164
2177
  prompt_title,
2165
- [exit_prompt] + dirs.sort.map do |file|
2178
+ [exit_prompt] + dirs.map do |file|
2166
2179
  { name: format(
2167
2180
  block_data['view'] || view,
2168
2181
  NamedCaptureExtractor.extract_named_group_match_data(
@@ -2326,41 +2339,25 @@ module MarkdownExec
2326
2339
  )
2327
2340
  # repeat select+display until user exits
2328
2341
 
2329
- pause_now = false
2330
- row_attrib = :row
2331
- loop do
2332
- if pause_now && (prompt_select_continue == MenuState::EXIT)
2333
- break
2334
- end
2335
-
2336
- # menu with Back and Facet options at top
2337
- case (name = prompt_select_code_filename(
2338
- [exit_prompt,
2339
- @delegate_object[:prompt_filespec_facet]] +
2340
- files_table_rows.map(&row_attrib),
2341
- string: @delegate_object[:prompt_select_history_file],
2342
- color_sym: :prompt_color_after_script_execution
2343
- ))
2344
- when exit_prompt
2345
- break
2346
- when @delegate_object[:prompt_filespec_facet]
2347
- row_attrib = row_attrib == :row ? :file : :row
2348
- pause_now = false
2349
- else
2350
- file = files_table_rows.select { |ftr| ftr.row == name }&.first
2351
- info = file_info(file.file)
2352
- stream.puts "#{file.file} - #{info[:lines]} lines / " \
2353
- "#{info[:size]} bytes"
2354
- stream.puts(
2355
- File.readlines(file.file,
2356
- chomp: false).map.with_index do |line, ind|
2357
- format(' %s. %s',
2358
- AnsiString.new(format('% 4d', ind + 1)).send(:violet),
2359
- line)
2360
- end
2361
- )
2362
- pause_now = pause_refresh
2363
- 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
+ )
2364
2361
  end
2365
2362
  end
2366
2363
 
@@ -2679,6 +2676,56 @@ module MarkdownExec
2679
2676
  }
2680
2677
  end
2681
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
+
2682
2729
  # Iterates through blocks in a file, applying the provided block to each line.
2683
2730
  # The iteration only occurs if the file exists.
2684
2731
  # @yield [Symbol] :filter Yields to obtain selected messages for processing.
@@ -3209,6 +3256,13 @@ module MarkdownExec
3209
3256
  end
3210
3257
  end
3211
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
+
3212
3266
  def next_state_append_code(selected, link_state, code_lines)
3213
3267
  next_state_set_code(
3214
3268
  selected,
@@ -4111,7 +4165,7 @@ module MarkdownExec
4111
4165
  disabled = if fcb_title_groups.fetch(:type, '') == BlockType::YAML
4112
4166
  TtyMenu::DISABLE
4113
4167
  else
4114
- nil
4168
+ TtyMenu::ENABLE
4115
4169
  end
4116
4170
 
4117
4171
  MarkdownExec::FCB.new(
@@ -4237,11 +4291,11 @@ module MarkdownExec
4237
4291
  @delegate_object.merge!(options)
4238
4292
  end
4239
4293
 
4240
- def vux_await_user_selection
4294
+ def vux_await_user_selection(prior_answer: @dml_block_selection)
4241
4295
  @dml_block_state = load_cli_or_user_selected_block(
4242
4296
  all_blocks: @dml_blocks_in_file,
4243
4297
  menu_blocks: @dml_menu_blocks,
4244
- prior_answer: @dml_menu_default_dname
4298
+ prior_answer: prior_answer
4245
4299
  )
4246
4300
  if !@dml_block_state
4247
4301
  # HashDelegator.error_handler('block_state missing', { abort: true })
@@ -4395,7 +4449,7 @@ module MarkdownExec
4395
4449
  @dml_link_state.block_name.present?
4396
4450
  @cli_block_name = @dml_link_state.block_name
4397
4451
  @dml_now_using_cli = @run_state.source.block_name_from_cli
4398
- @dml_menu_default_dname = nil
4452
+ @dml_block_selection = nil
4399
4453
  @dml_block_state = SelectedBlockMenuState.new
4400
4454
  @doc_saved_lines_files = []
4401
4455
 
@@ -4713,7 +4767,9 @@ module MarkdownExec
4713
4767
  else
4714
4768
  # puts "? - Select a block to execute (or type #{$texit}
4715
4769
  # to exit):"
4716
- return :break if vux_await_user_selection == :break
4770
+ return :break if vux_await_user_selection(
4771
+ prior_answer: @dml_block_selection
4772
+ ) == :break
4717
4773
  return :break if @dml_block_state.block.nil? # no block matched
4718
4774
  end
4719
4775
  # puts "! - Executing block: #{data}"
@@ -4763,7 +4819,13 @@ module MarkdownExec
4763
4819
  block.dname.include?(prior_answer)
4764
4820
  end&.name
4765
4821
  when Struct
4766
- 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
4767
4829
  end
4768
4830
  # prior_answer value may not match if color is different from
4769
4831
  # originating menu (opts changed while processing)
@@ -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.0'
10
+ VERSION = '2.8.1'
11
11
  end
data/lib/mdoc.rb CHANGED
@@ -85,14 +85,17 @@ module MarkdownExec
85
85
 
86
86
  dependencies = collect_dependencies(nickname)
87
87
  # !!t dependencies.count
88
- all_dependency_names = collect_unique_names(dependencies).push(nickname).uniq
88
+ all_dependency_names =
89
+ collect_unique_names(dependencies).push(nickname).uniq
89
90
  # !!t all_dependency_names.count
90
91
 
91
92
  # select blocks in order of appearance in source documents
92
93
  #
93
94
  blocks = @table.select do |fcb|
94
95
  # 2024-08-04 match nickname
95
- all_dependency_names.include?(fcb.pub_name) || all_dependency_names.include?(fcb.nickname) || all_dependency_names.include?(fcb.oname)
96
+ all_dependency_names.include?(fcb.pub_name) ||
97
+ all_dependency_names.include?(fcb.nickname) ||
98
+ all_dependency_names.include?(fcb.oname)
96
99
  end
97
100
  # !!t blocks.count
98
101
 
@@ -102,7 +105,10 @@ module MarkdownExec
102
105
  blocks = blocks.map do |fcb|
103
106
  # 2024-08-04 match oname for long block names
104
107
  # 2024-08-04 match nickname
105
- unmet_dependencies.delete(fcb.pub_name) || unmet_dependencies.delete(fcb.nickname) || unmet_dependencies.delete(fcb.oname) # may not exist if block name is duplicated
108
+ # may not exist if block name is duplicated
109
+ unmet_dependencies.delete(fcb.pub_name) ||
110
+ unmet_dependencies.delete(fcb.nickname) ||
111
+ unmet_dependencies.delete(fcb.oname)
106
112
  if (call = fcb.call)
107
113
  fcb1 = get_block_by_anyname("[#{call.match(/^%\((\S+) |\)/)[1]}]")
108
114
  fcb1.cann = call
@@ -124,8 +130,10 @@ module MarkdownExec
124
130
  # @param name [String] The name of the code block to start the collection from.
125
131
  # @return [Array<String>] An array of strings containing the collected code blocks.
126
132
  #
127
- def collect_recursively_required_code(anyname:, block_source:, label_body: true, label_format_above: nil,
128
- label_format_below: nil)
133
+ def collect_recursively_required_code(
134
+ anyname:, block_source:,
135
+ label_body: true, label_format_above: nil, label_format_below: nil
136
+ )
129
137
  block_search = collect_block_dependencies(anyname: anyname)
130
138
  if block_search[:blocks]
131
139
  blocks = collect_wrapped_blocks(block_search[:blocks])
@@ -150,8 +158,10 @@ module MarkdownExec
150
158
  elsif fcb.type == BlockType::PORT
151
159
  generate_env_variable_shell_commands(fcb)
152
160
  elsif label_body
153
- generate_label_body_code(fcb, block_source, label_format_above,
154
- label_format_below)
161
+ generate_label_body_code(
162
+ fcb, block_source,
163
+ label_format_above, label_format_below
164
+ )
155
165
  else # raw body
156
166
  fcb.body
157
167
  end
@@ -230,9 +240,14 @@ module MarkdownExec
230
240
  initialize: opts[:compressed_ids].nil?
231
241
  ) do |fcb, _hide, _collapsed_level|
232
242
  # update fcb per state
233
- if fcb.collapsible
234
- fcb.s1decorated = fcb.s1decorated + ' ' + (fcb.collapse ? opts[:menu_collapsible_symbol_collapsed] : opts[:menu_collapsible_symbol_expanded])
235
- end
243
+ next unless fcb.collapsible
244
+
245
+ fcb.s1decorated = fcb.s1decorated + ' ' +
246
+ (if fcb.collapse
247
+ opts[:menu_collapsible_symbol_collapsed]
248
+ else
249
+ opts[:menu_collapsible_symbol_expanded]
250
+ end)
236
251
  end
237
252
  opts[:compressed_ids] = collapser.compress_ids
238
253
  opts[:expanded_ids] = collapser.expand_ids
@@ -240,7 +255,9 @@ module MarkdownExec
240
255
  # remove
241
256
  # . empty chrome between code; edges are same as blanks
242
257
  #
243
- select_elements_with_neighbor_conditions(selrows) do |prev_element, current, next_element|
258
+ select_elements_with_neighbor_conditions(selrows) do |prev_element,
259
+ current,
260
+ next_element|
244
261
  !(current[:chrome] && !current.oname.present?) ||
245
262
  !(!prev_element.nil? &&
246
263
  prev_element.shell.present? &&
@@ -291,13 +308,17 @@ module MarkdownExec
291
308
 
292
309
  label_above = if label_format_above.present?
293
310
  format(label_format_above,
294
- block_source.merge({ block_name: block_name_for_bash_comment }))
311
+ block_source.merge(
312
+ { block_name: block_name_for_bash_comment }
313
+ ))
295
314
  else
296
315
  nil
297
316
  end
298
317
  label_below = if label_format_below.present?
299
318
  format(label_format_below,
300
- block_source.merge({ block_name: block_name_for_bash_comment }))
319
+ block_source.merge(
320
+ { block_name: block_name_for_bash_comment }
321
+ ))
301
322
  else
302
323
  nil
303
324
  end
@@ -415,8 +436,11 @@ module MarkdownExec
415
436
  memo
416
437
  end
417
438
 
418
- def select_elements_with_neighbor_conditions(array,
419
- last_selected_placeholder = nil, next_selected_placeholder = nil)
439
+ def select_elements_with_neighbor_conditions(
440
+ array,
441
+ last_selected_placeholder = nil,
442
+ next_selected_placeholder = nil
443
+ )
420
444
  selected_elements = []
421
445
  last_selected = last_selected_placeholder
422
446
 
@@ -463,8 +487,10 @@ if $PROGRAM_NAME == __FILE__
463
487
  end if false
464
488
 
465
489
  def test_collect_dependencies_with_valid_source
466
- @mdoc.stubs(:get_block_by_anyname).with('source1').returns(OpenStruct.new(reqs: ['source2']))
467
- @mdoc.stubs(:get_block_by_anyname).with('source2').returns(OpenStruct.new(reqs: []))
490
+ @mdoc.stubs(:get_block_by_anyname)
491
+ .with('source1').returns(OpenStruct.new(reqs: ['source2']))
492
+ @mdoc.stubs(:get_block_by_anyname)
493
+ .with('source2').returns(OpenStruct.new(reqs: []))
468
494
 
469
495
  expected = { 'source1' => ['source2'], 'source2' => [] }
470
496
  assert_equal expected, @mdoc.collect_dependencies('source1')
@@ -535,14 +561,17 @@ if $PROGRAM_NAME == __FILE__
535
561
  end
536
562
 
537
563
  def test_fcbs_per_options
538
- opts = { hide_blocks_by_name: true, block_name_hidden_match: 'block1' }
564
+ opts = { hide_blocks_by_name: true,
565
+ block_name_hidden_match: 'block1' }
539
566
  result = @doc.fcbs_per_options(opts)
540
567
  assert_equal [@table[1], @table[2]], result
541
568
  end if false ### broken test
542
569
 
543
570
  def test_recursively_required
544
571
  result = @doc.recursively_required_hash('block3')
545
- assert_equal ({ 'block3' => ['block1'], 'block1' => ['block2'], 'block2' => nil }),
572
+ assert_equal ({ 'block3' => ['block1'],
573
+ 'block1' => ['block2'],
574
+ 'block2' => nil }),
546
575
  result
547
576
 
548
577
  result_no_reqs = @doc.recursively_required_hash(nil)
@@ -585,8 +614,9 @@ if $PROGRAM_NAME == __FILE__
585
614
  # Test case 3: blocks with missing wraps
586
615
  assert_equal(
587
616
  %w[block4],
588
- @mdoc.collect_wrapped_blocks([OpenStruct.new(oname: 'block4',
589
- wraps: ['wrap4'])]).map(&:oname)
617
+ @mdoc.collect_wrapped_blocks(
618
+ [OpenStruct.new(oname: 'block4', wraps: ['wrap4'])]
619
+ ).map(&:oname)
590
620
  )
591
621
  end
592
622
  end
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.0
4
+ version: 2.8.1
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-10 00:00:00.000000000 Z
11
+ date: 2025-02-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: clipboard
@@ -108,6 +108,10 @@ files:
108
108
  - assets/select_a_file.png
109
109
  - bats/bats.bats
110
110
  - bats/block-type-opts.bats
111
+ - bats/block-type-ux-auto.bats
112
+ - bats/block-type-ux-exec.bats
113
+ - bats/block-type-ux-row-format.bats
114
+ - bats/block-type-ux-transform.bats
111
115
  - bats/block-type-vars.bats
112
116
  - bats/block-types.bats
113
117
  - bats/border.bats
@@ -139,6 +143,10 @@ files:
139
143
  - docs/dev/block-type-bash.md
140
144
  - docs/dev/block-type-opts.md
141
145
  - docs/dev/block-type-port.md
146
+ - docs/dev/block-type-ux-auto.md
147
+ - docs/dev/block-type-ux-exec.md
148
+ - docs/dev/block-type-ux-row-format.md
149
+ - docs/dev/block-type-ux-transform.md
142
150
  - docs/dev/block-type-vars.md
143
151
  - docs/dev/border.md
144
152
  - docs/dev/command-substitution.md