markdown_exec 2.8.0 → 2.8.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +3 -0
- data/Gemfile.lock +1 -1
- data/bats/block-type-ux-auto.bats +8 -0
- data/bats/block-type-ux-exec.bats +8 -0
- data/bats/block-type-ux-row-format.bats +8 -0
- data/bats/block-type-ux-transform.bats +8 -0
- data/bin/tab_completion.sh +1 -1
- data/docs/dev/block-type-ux-auto.md +43 -0
- data/docs/dev/block-type-ux-exec.md +42 -0
- data/docs/dev/block-type-ux-row-format.md +47 -0
- data/docs/dev/block-type-ux-transform.md +41 -0
- data/lib/constants.rb +2 -0
- data/lib/fcb.rb +0 -32
- data/lib/hash_delegator.rb +115 -53
- data/lib/markdown_exec/version.rb +1 -1
- data/lib/mdoc.rb +51 -21
- metadata +10 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d752af0db5e1c1a770b64f9341c3d08e1e9bc8612230a9cb44ddc7fddc4c3051
|
4
|
+
data.tar.gz: 5ba8524b3323bd8333b82a5d0607fbb9db59a5157a1c7ae0564b3f624f26addd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 29b210e56b46a1edf099c02267e2b3c7cdae6701f7ee99d5a946d06eea7272da3534765110ec36a6de017a10d0f4833c9075c27dacb0cec8b050192d3892d748
|
7
|
+
data.tar.gz: e73cd906ce9035c8c78d2e301866af4a76bc7a730c5109fc8cc59ecf64679cb578fb04b324e700df064886d250c394c441f77850b9e21230d346d08bd92a9a5f
|
data/.rubocop.yml
CHANGED
data/Gemfile.lock
CHANGED
@@ -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
|
+
}
|
data/bin/tab_completion.sh
CHANGED
@@ -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
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
|
data/lib/hash_delegator.rb
CHANGED
@@ -934,7 +934,12 @@ module MarkdownExec
|
|
934
934
|
end
|
935
935
|
end
|
936
936
|
|
937
|
-
|
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,
|
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
|
-
#
|
1985
|
-
|
1986
|
-
|
1987
|
-
|
1988
|
-
|
1989
|
-
|
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
|
-
|
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
|
-
|
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.
|
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
|
-
|
2330
|
-
|
2331
|
-
|
2332
|
-
|
2333
|
-
|
2334
|
-
|
2335
|
-
|
2336
|
-
|
2337
|
-
|
2338
|
-
|
2339
|
-
|
2340
|
-
|
2341
|
-
|
2342
|
-
|
2343
|
-
|
2344
|
-
|
2345
|
-
|
2346
|
-
|
2347
|
-
|
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
|
-
|
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:
|
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
|
-
@
|
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
|
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
|
-
|
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)
|
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 =
|
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) ||
|
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
|
-
|
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(
|
128
|
-
|
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(
|
154
|
-
|
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
|
-
|
234
|
-
|
235
|
-
|
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,
|
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(
|
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(
|
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(
|
419
|
-
|
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)
|
467
|
-
|
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,
|
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'],
|
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(
|
589
|
-
|
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.
|
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-
|
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
|