markdown_exec 3.3.0 → 3.5.0

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.
Files changed (54) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +27 -0
  3. data/Gemfile +1 -0
  4. data/Gemfile.lock +8 -1
  5. data/README.md +262 -116
  6. data/Rakefile +2 -1
  7. data/bats/block-type-shell-require-ux.bats +15 -0
  8. data/bats/block-type-ux-auto.bats +1 -1
  9. data/bats/block-type-ux-default.bats +1 -1
  10. data/bats/block-type-ux-echo-hash.bats +2 -2
  11. data/bats/block-type-ux-exec-hash.bats +2 -2
  12. data/bats/block-type-ux-exec.bats +1 -1
  13. data/bats/block-type-ux-no-name.bats +8 -0
  14. data/bats/block-type-ux-require-context.bats +14 -0
  15. data/bats/block-type-ux-row-format.bats +1 -1
  16. data/bats/block-type-ux-transform.bats +1 -1
  17. data/bats/command-substitution-options.bats +2 -2
  18. data/bats/import-directive-line-continuation.bats +9 -0
  19. data/bats/import-directive-parameter-symbols.bats +1 -1
  20. data/bats/import-parameter-symbols.bats +1 -1
  21. data/bats/option-expansion.bats +1 -1
  22. data/bats/options.bats +2 -2
  23. data/bats/table-column-truncate.bats +1 -1
  24. data/bats/table.bats +1 -1
  25. data/bats/test_helper.bash +4 -3
  26. data/demo/trap.demo1.gif +0 -0
  27. data/demo/trap.demo1.mp4 +0 -0
  28. data/docs/dev/block-type-shell-require-ux.md +18 -0
  29. data/docs/dev/block-type-ux-format.md +10 -0
  30. data/docs/dev/block-type-ux-no-name.md +17 -0
  31. data/docs/dev/block-type-ux-require-context.md +32 -0
  32. data/docs/dev/block-type-ux-require.md +8 -4
  33. data/docs/dev/block-type-ux-row-format.md +1 -1
  34. data/docs/dev/import-directive-line-continuation.md +5 -0
  35. data/docs/dev/import-directive-parameter-symbols.md +0 -2
  36. data/docs/dev/import-parameter-symbols-template.md +7 -5
  37. data/docs/dev/import-parameter-symbols.md +10 -2
  38. data/docs/dev/table-column-truncate.md +1 -1
  39. data/examples/colors.md +31 -29
  40. data/lib/cached_nested_file_reader.rb +31 -51
  41. data/lib/command_result.rb +5 -5
  42. data/lib/constants.rb +3 -1
  43. data/lib/fcb.rb +22 -8
  44. data/lib/format_table.rb +22 -7
  45. data/lib/hash_delegator.rb +77 -33
  46. data/lib/link_history.rb +1 -1
  47. data/lib/markdown_exec/version.rb +1 -1
  48. data/lib/menu.src.yml +47 -38
  49. data/lib/menu.yml +43 -34
  50. data/lib/parameter_expansion.rb +918 -0
  51. data/lib/parse_animation_to_tts.rb +4417 -0
  52. data/lib/resize_terminal.rb +19 -16
  53. data/lib/ww.rb +493 -15
  54. metadata +15 -2
@@ -4,5 +4,5 @@ load 'test_helper'
4
4
 
5
5
  @test 'Transformed output of executed commands' {
6
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_ 6d 61 72 6b 64 6f 77 6e 5f 65 78 65 63 0a __With validate and transform, output has no newline._Var1=markdown_exec_ 6d 61 72 6b 64 6f 77 6e 5f 65 78 65 63 __With transform :chomp, output has no newline._Var2=markdown_exec_ 6d 61 72 6b 64 6f 77 6e 5f 65 78 65 63 __With transform :upcase, output is in upper case w/ newline._Var3=MARKDOWN_EXEC_ 4d 41 52 4b 44 4f 57 4e 5f 45 58 45 43 0a '
7
+ '_Execution output has a trailing newline._Var0=markdown_exec__ 6d 61 72 6b 64 6f 77 6e 5f 65 78 65 63 0a __With validate and transform, output has no newline._Var1=markdown_exec_ 6d 61 72 6b 64 6f 77 6e 5f 65 78 65 63 __With transform :chomp, output has no newline._Var2=markdown_exec_ 6d 61 72 6b 64 6f 77 6e 5f 65 78 65 63 __With transform :upcase, output is in upper case w/ newline._Var3=MARKDOWN_EXEC__ 4d 41 52 4b 44 4f 57 4e 5f 45 58 45 43 0a '
8
8
  }
@@ -5,10 +5,10 @@ load 'test_helper'
5
5
  @test 'Operator $' {
6
6
  spec_mde_xansi_dname_doc_blocks_expect docs/dev/command-substitution-options.md \
7
7
  'operator_$' \
8
- 'Command substitution__The current value of environment variable Common_Name_is displayed using two different operators._The command echo $SHLVL is executed via command_substitution, using two different operators.__| Operato | Variable Expansio | Command Substitutio |_| ------- | ----------------- | ------------------- |_| $ | Tapanuli Oranguta | Pongo tapanuliensis |_| @ | @{Common_Name} | @(echo $Species) |__Toggle between operators.__operator_$__operator_@'
8
+ 'Command substitution__The current value of environment variable Common_Name_is displayed using two different operators._The command echo $SHLVL is executed via command_substitution, using two different operators.__| Operator | Variable Expansion | Command Substitution |_| -------- | ------------------ | -------------------- |_| $ | Tapanuli Orangutan | Pongo tapanuliensis |_| @ | @{Common_Name} | @(echo $Species) |__Toggle between operators.__operator_$__operator_@'
9
9
  }
10
10
 
11
11
  @test 'Operator @' {
12
12
  spec_mde_xansi_dname_doc_blocks_expect docs/dev/command-substitution-options.md \
13
- 'Command substitution__The current value of environment variable Common_Name_is displayed using two different operators._The command echo $SHLVL is executed via command_substitution, using two different operators.__| Operato | Variable Expansio | Command Substitutio |_| ------- | ----------------- | ------------------- |_| $ | ${Common_Name} | $(echo $Species) |_| @ | Tapanuli Oranguta | Pongo tapanuliensis |__Toggle between operators.__operator_$__operator_@'
13
+ 'Command substitution__The current value of environment variable Common_Name_is displayed using two different operators._The command echo $SHLVL is executed via command_substitution, using two different operators.__| Operator | Variable Expansion | Command Substitution |_| -------- | ------------------ | -------------------- |_| $ | ${Common_Name} | $(echo $Species) |_| @ | Tapanuli Orangutan | Pongo tapanuliensis |__Toggle between operators.__operator_$__operator_@'
14
14
  }
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env bats
2
+
3
+ load 'test_helper'
4
+
5
+ @test '' {
6
+ spec_mde_xansi_dname_doc_blocks_expect docs/dev/import-directive-line-continuation.md \
7
+ --blocks dname \
8
+ 'Stem: U1_Species: Illacme tobini'
9
+ }
@@ -5,5 +5,5 @@ load 'test_helper'
5
5
  @test '' {
6
6
  spec_mde_xansi_dname_doc_blocks_expect docs/dev/import-directive-parameter-symbols.md \
7
7
  --blocks dname \
8
- 'Stem: U1_Species: Illacme tobini_Genus: Illacme_Stem: U2_Species: Hydrodynastes bicinctus_Genus: Hydrodynastes'
8
+ 'Stem: U1_Species: Illacme tobini_Stem: U2_Species: Hydrodynastes bicinctus'
9
9
  }
@@ -4,5 +4,5 @@ load 'test_helper'
4
4
 
5
5
  @test 'Initial values' {
6
6
  spec_mde_xansi_dname_doc_blocks_expect docs/dev/import-parameter-symbols.md \
7
- 'COMMON_NAME=Tapanuli Orangutan_Command substitution: Tapanuli Orangutan_echo "Command substitution: ${NAMEC}"__Evaluated expression: Tapanuli Orangutan_echo "Evaluated expression: ${NAMEE}"__Raw literal: Tapanuli Orangutan_echo "Raw literal: Tapanuli Orangutan"__Force-quoted literal: Tapanuli Orangutan_echo "Force-quoted literal: ${NAMEQ}"__Variable reference: Tapanuli Orangutan_echo "Variable reference: ${COMMON_NAME}"'
7
+ 'COMMON_NAME=Tapanuli Orangutan_Evaluated expression: Tapanuli Orangutan_echo "Evaluated expression: $(printf %s "$COMMON_NAME")"__Raw literal: Tapanuli Orangutan_echo "Raw literal: Tapanuli Orangutan"__Force-quoted literal: Tapanuli Orangutan_echo "Force-quoted literal: Tapanuli Orangutan"__Variable reference: Tapanuli Orangutan_echo "Variable reference: ${COMMON_NAME}"'
8
8
  }
@@ -4,5 +4,5 @@ load 'test_helper'
4
4
 
5
5
  @test '' {
6
6
  spec_mde_xansi_dname_doc_blocks_expect docs/dev/option-expansion.md \
7
- '_| Optio | Description | Value | Va | Def |_| ----- | -------------------------------- | ----- | -- | --- |_| scree | Screen width for document and in | 2 | 64 | 0 |_| table | | 5 | fa | tru |'
7
+ '_| Opti | Description | Valu | Va | Defau |_| ---- | ---------------------------- | ---- | -- | ----- |_| scre | Screen width for document an | 2 | 64 | 0 |_| tabl | | 5 | fa | true |'
8
8
  }
data/bats/options.bats CHANGED
@@ -30,13 +30,13 @@ load 'test_helper'
30
30
  @test 'Options - list blocks' {
31
31
  BATS_OUTPUT_FILTER=A
32
32
  spec_mde_args_expect --list-blocks-message oname --list-blocks-type 0 examples/colors.md --list-blocks \
33
- 'load_colors load_colors2 Bash1 Edit1 History1 Link1 Load1 Opts1 Port1 Save1 Vars1'
33
+ 'load_colors load_colors2 Unspecified1 Unknown1 Bash1 Edit-inherited-blocks History1 Link1 Load1 Opts1 Port1 Save1 Vars1'
34
34
  }
35
35
 
36
36
  @test 'Options - list blocks, eval' {
37
37
  BATS_OUTPUT_FILTER=A
38
38
  spec_mde_args_expect --list-blocks-eval block.oname examples/colors.md --list-blocks \
39
- 'load_colors load_colors2 Bash1 Edit1 History1 Link1 Load1 Opts1 Port1 Save1 Vars1'
39
+ 'load_colors load_colors2 Unspecified1 Unknown1 Bash1 Edit-inherited-blocks History1 Link1 Load1 Opts1 Port1 Save1 Vars1'
40
40
  }
41
41
 
42
42
  @test 'Options - how' {
@@ -4,5 +4,5 @@ load 'test_helper'
4
4
 
5
5
  @test 'Tables - truncate columns' {
6
6
  spec_mde_xansi_dname_doc_blocks_expect docs/dev/table-column-truncate.md \
7
- 'DEMONSTRATE TRUNCATION OF TEXT IN TABLE CELLS__| Common Name | Species | Genus | Family | Year Di |_| ------------ | ------------ | ----- | ------- | ------- |_| Tapanuli Ora | Pongo tapanu | Pongo | Hominid | 2017 |_| Psychedelic | Histiophryne | Histi | Antenna | 2009 |_| Ruby Seadrag | Phyllopteryx | Phyll | Syngnat | 2015 |_| Illacme tobi | Illacme tobi | Illac | Siphono | 2016 |_| Spiny Dandel | Taraxacum ja | Tarax | Asterac | 2022 |_'
7
+ 'DEMONSTRATE TRUNCATION OF TEXT IN TABLE CELLS__| Common Name | Species | Genus | Family | Year Discover |_| ------------------- | ------------------ | -------- | ----------- | ------------- |_| Tapanuli Orangutan | Pongo tapanuliensi | Pongo | Hominidae | 2017 |_| Psychedelic Frogfis | Histiophryne psych | Histioph | Antennariid | 2009 |_| Ruby Seadragon | Phyllopteryx dewys | Phyllopt | Syngnathida | 2015 |_| Illacme tobini (Mil | Illacme tobini | Illacme | Siphonorhin | 2016 |_| Spiny Dandelion | Taraxacum japonicu | Taraxacu | Asteraceae | 2022 |_'
8
8
  }
data/bats/table.bats CHANGED
@@ -4,7 +4,7 @@ load 'test_helper'
4
4
 
5
5
  @test 'Tables - indented' {
6
6
  spec_mde_xansi_dname_doc_blocks_expect docs/dev/table-indent.md \
7
- 'DEMONSTRATE TABLE INDENTATION__Table flush at left._Centered columns._| Common Name | Species | Genus | Family | Year Discover |_| ------------------ | ---------------------- | ---------- | ----------- | ------------- |_| Tapanuli Orangutan | Pongo tapanuliensis | Pongo | Hominidae | 2017 |_| Psychedelic Frogfi | Histiophryne psychedel | Histiophry | Antennariid | 2009 |_| Ruby Seadragon | Phyllopteryx dewysea | Phyllopter | Syngnathida | 2015 |__ Table indented with two spaces._ Left-justified columns._ | Common Name | Species | Genus | Family | Year Discovere |_ | ------------------------- | ------------- | ------ | -------------- | -------------- |_ | Illacme tobini (Millipede | Illacme tobin | Illacm | Siphonorhinida | 2016 |__ Table indented with one tab._ Right-justified columns._ | Common Name | Species | Genus | Family | Year Discovered |_ | --------------- | ------------------- | --------- | ---------- | --------------- |_ | Spiny Dandelion | Taraxacum japonicum | Taraxacum | Asteraceae | 2022 |'
7
+ 'DEMONSTRATE TABLE INDENTATION__Table flush at left._Centered columns._| Common Name | Species | Genus | Family | Year Discovered |_| ------------------ | ----------------------- | ----------- | ------------ | --------------- |_| Tapanuli Orangutan | Pongo tapanuliensis | Pongo | Hominidae | 2017 |_| Psychedelic Frogfi | Histiophryne psychedeli | Histiophryn | Antennariida | 2009 |_| Ruby Seadragon | Phyllopteryx dewysea | Phylloptery | Syngnathidae | 2015 |__ Table indented with two spaces._ Left-justified columns._ | Common Name | Species | Genus | Family | Year Discovered |_ | -------------------------- | -------------- | ------- | --------------- | --------------- |_ | Illacme tobini (Millipede) | Illacme tobini | Illacme | Siphonorhinidae | 2016 |__ Table indented with one tab._ Right-justified columns._ | Common Name | Species | Genus | Family | Year Discovered |_ | --------------- | ------------------- | --------- | ---------- | --------------- |_ | Spiny Dandelion | Taraxacum japonicum | Taraxacum | Asteraceae | 2022 |'
8
8
  }
9
9
 
10
10
  @test 'Tables - invalid' {
@@ -7,6 +7,7 @@ EXIT_MENU=__Exit # name of menu Exit option
7
7
  # • expected byte (0xHEX) and printable character (or “.”)
8
8
  # • actual byte (0xHEX) and printable character (or “.”)
9
9
  compare_bytes () {
10
+ readonly line_count=16
10
11
  set +e
11
12
  local mode="$1"; shift
12
13
  if [[ "$mode" == "--file" ]]; then
@@ -19,13 +20,13 @@ compare_bytes () {
19
20
  # feed the two strings into cmp via process-substitution
20
21
  cmp --verbose <(printf '%s' "$live") <(printf '%s' "$expect")
21
22
  fi |
22
- head -n 3 |
23
+ head -n $line_count |
23
24
  gawk '{
24
25
  live = strtonum(0 $2)
25
26
  expect = strtonum(0 $3)
26
27
  offset = $1 - 1
27
- printf "Offset 0x%X (%4d): output \"%c\" 0x%02X (%3d) vs expect \"%c\" 0x%02X (%3d)\n", \
28
- offset, offset, live, live, live, expect, expect, expect
28
+ printf "Offset 0x%X (%4d): expect \"%c\" 0x%02X (%3d) vs output \"%c\" 0x%02X (%3d)\n", \
29
+ offset, offset, expect, expect, expect, live, live, live
29
30
  }'
30
31
  set -e
31
32
  }
Binary file
Binary file
@@ -0,0 +1,18 @@
1
+ / No blocks are evaluated at initialization.
2
+ / When the shell block is activated, the UX block is required.
3
+ ```bash :require-a-UX-block +[ux1]
4
+ ENTITY='Mythical Monkey'
5
+ ```
6
+ / Display variables set in the UX block.
7
+ ${FIRST}
8
+ ${LAST}
9
+ / Parse and copy the name into variables.
10
+ ```ux :[ux1]
11
+ echo:
12
+ FIRST: '${ENTITY%% *}'
13
+ LAST: '${ENTITY##* }'
14
+ FULL_NAME: '$ENTITY'
15
+ init: false
16
+ readonly: true
17
+ ```
18
+ @import bats-document-configuration.md
@@ -0,0 +1,10 @@
1
+ / v2025-06-28
2
+ / Demonstrate using a format key does not inhibit activation of the same block
3
+ /
4
+ ```ux
5
+ act: :echo
6
+ echo: '`date`'
7
+ format: 'Date: ${DATE}'
8
+ name: DATE
9
+ ```
10
+ @import bats-document-configuration.md
@@ -0,0 +1,17 @@
1
+ / This automatic block sets multiple variables and displays the first variable.
2
+ ```ux
3
+ echo:
4
+ BASENAME1: "$(basename `pwd`)"
5
+ DOCUMENTS1: "${BASENAME1%%_*}"
6
+ OPERATION1: "${BASENAME1##*_}"
7
+ ```
8
+ ```ux
9
+ exec:
10
+ BASENAME2: >-
11
+ basename `pwd`
12
+ DOCUMENTS2: >-
13
+ echo "${BASENAME2%%_*}"
14
+ OPERATION2: >-
15
+ echo "${BASENAME2##*_}"
16
+ ```
17
+ @import bats-document-configuration.md
@@ -0,0 +1,32 @@
1
+ / Neither block is evaluated at initialization.
2
+ / When the first UX block is activated, it is evaluated.
3
+ / The variable set in the first UX block is available to the second,
4
+ / which is required by the first, resulting in its evaluation.
5
+ ```ux :[ux1] +[ux2] +(ENTITY)
6
+ act: :echo
7
+ echo:
8
+ UX1: '$ENTITY'
9
+ format: |-
10
+ Get the common name...
11
+ init: false
12
+ ```
13
+ / The shell required code and the first evaluated UX block are the context
14
+ / when the the `echo` expressions are being evaluated in the second UX block.
15
+ / The first evaluated UX block is the context when the `format` value is being expanded.
16
+ ```ux :[ux2]
17
+ act: :echo
18
+ echo:
19
+ UX2: '$UX1'
20
+ ENTITY2: '$ENTITY'
21
+ format: |-
22
+ Entity: ${ENTITY}
23
+ ENTITY2: ${ENTITY2}
24
+ UX1: ${UX1}
25
+ Common name: ${UX2}
26
+ init: false
27
+ readonly: true
28
+ ```
29
+ ```bash :(ENTITY)
30
+ ENTITY='Mythical Monkey'
31
+ ```
32
+ @import bats-document-configuration.md
@@ -1,7 +1,3 @@
1
- / This is an hidden shell block that is required by UX blocks.
2
- ``` :(shell)
3
- ENTITY='Pongo tapanuliensis,Pongo'
4
- ```
5
1
  ```ux +(shell)
6
2
  echo: "${ENTITY%%,*}"
7
3
  force: true
@@ -24,6 +20,14 @@ echo: "$NAME"
24
20
  force: true
25
21
  name: NAME2
26
22
  ```
23
+ /
24
+ / This is a hidden shell block that is required by a UX block.
25
+ / All shell blocks required by a UX block are collected in a sequence
26
+ / that is the context for the evaluation of the expressions in the UX block.
27
+ ``` :(shell)
28
+ ENTITY='Pongo tapanuliensis,Pongo'
29
+ ```
30
+ /
27
31
  / This block is not visible. Execute to display the inherited lines for testing.
28
32
  ```opts :(menu_with_inherited_lines)
29
33
  menu_with_inherited_lines: true
@@ -40,7 +40,7 @@ name: Family
40
40
  @import bats-document-configuration.md
41
41
  ```opts :(document_opts)
42
42
  menu_ux_row_format: '| %{name}| ${%{name}}| %{prompt}'
43
- screen_width: 72
43
+ screen_width: 76
44
44
  table_center: true
45
45
  ux_auto_load_force_default: true
46
46
  ```
@@ -0,0 +1,5 @@
1
+ @import ./import/parameter-symbols.md \
2
+ __PS_STEM_SPECIES:q='Illacme tobini' \
3
+ __PS_STEM_GENUS:q=Illacme \
4
+ PS_STEM=U1
5
+ @import bats-document-configuration.md
@@ -1,9 +1,7 @@
1
1
  / use MDE 3.3.0 import parameter symbols
2
2
  /
3
3
  @import ./import/parameter-symbols.md __PS_STEM_SPECIES:q='Illacme tobini' __PS_STEM_GENUS:q=Illacme PS_STEM=U1
4
- Genus: ${__U1_GENUS}
5
4
  /
6
5
  @import ./import/parameter-symbols.md __PS_STEM_SPECIES:q='Hydrodynastes bicinctus' __PS_STEM_GENUS:q=Hydrodynastes PS_STEM=U2
7
- Genus: ${__U2_GENUS}
8
6
  /
9
7
  @import ./bats-document-configuration.md
@@ -1,8 +1,10 @@
1
- **Command substitution:** `NAMEC`
2
- ```bash
3
- echo "Command substitution: NAMEC"
4
- ```
5
-
1
+ / 2025-11-13 the name of the variable generated
2
+ / changes on every load is not predictable
3
+ /**Command substitution:** `NAMEC`
4
+ /```bash
5
+ /echo "Command substitution: NAMEC"
6
+ /```
7
+ /
6
8
  **Evaluated expression:** `NAMEE`
7
9
  ```bash
8
10
  echo "Evaluated expression: NAMEE"
@@ -2,5 +2,13 @@
2
2
  echo: Tapanuli Orangutan
3
3
  name: COMMON_NAME
4
4
  ```
5
- @import import-parameter-symbols-template.md NAMEC:c='printf %s "$COMMON_NAME"' NAMEE:e=$COMMON_NAME NAMEL="Tapanuli Orangutan" NAMEQ:q="Tapanuli Orangutan" NAMEV:v=COMMON_NAME
6
- @import bats-document-configuration.md
5
+ @import import-parameter-symbols-template.md \
6
+ NAMEC:cq='printf %s "$COMMON_NAME"' \
7
+ NAMEE:eq=$COMMON_NAME \
8
+ NAMEL="Tapanuli Orangutan" \
9
+ NAMEQ:qq="Tapanuli Orangutan" \
10
+ NAMEV:vq=COMMON_NAME
11
+ @import bats-document-configuration.md
12
+ ```opts :(document_opts)
13
+ dump_inherited_lines: false
14
+ ```
@@ -12,6 +12,6 @@
12
12
  @import bats-document-configuration.md
13
13
  ```opts :(document_opts)
14
14
  heading1_center: false
15
- screen_width: 60
15
+ screen_width: 90
16
16
  table_center: false
17
17
  ```
data/examples/colors.md CHANGED
@@ -1,27 +1,19 @@
1
1
  # Demo configuring options
2
-
2
+ / v2025-09-30
3
3
  ::: These Opts blocks set the color for all elements.
4
-
5
- <https://en.wikipedia.org/wiki/Complementary_colors#/media/File:RGB_color_wheel.svg>
6
-
7
- / ff0000 red - exception text
8
- / ff7f00 orange - warning text
9
- / ffff00 yellow - notification text
10
- / 7fff00 chartreuse green - output frame
11
- / 00ff00 green - prompt
12
- / 00ff7f spring green - input frame
13
- / 00ffff cyan - menu text
14
- / 007fff azure - menu frame
15
- / 0000ff blue
16
- / 7f00ff violet - opts frame
17
- / ff00ff magenta - opts text
18
- / ff007f rose - exception frame
19
-
4
+ / blue fg_rgbh_00_00_FF
5
+ / green fg_rgbh_00_FF_00
6
+ / indigo fg_rgbh_4B_00_82
7
+ / orange fg_rgbh_FF_7F_00
8
+ / red fg_rgbh_FF_00_00
9
+ / violet fg_rgbh_94_00_D3
10
+ / yellow fg_rgbh_FF_FF_00
20
11
  ```opts :load_colors
21
12
  exception_color_detail: fg_rgbh_1f_00_7f
22
13
  exception_color_name: fg_rgbh_1f_00_00
23
14
  execution_report_preview_frame_color: fg_rgbh_7f_1f_00
24
15
  menu_bash_color: fg_rgbh_00_c0_c0
16
+ menu_block_color: fg_rgbh_47_ce_eb
25
17
  menu_chrome_color: fg_rgbh_40_c0_c0
26
18
  menu_divider_color: fg_rgbh_80_d0_c0
27
19
  menu_edit_color: fg_rgbh_e0_e0_20
@@ -44,11 +36,13 @@ script_preview_frame_color: fg_rgbh_7f_1f_00
44
36
  warning_color: fg_rgbh_1f_7f_00
45
37
  ```
46
38
 
39
+ / more green, less blue
47
40
  ```opts :load_colors2
48
41
  exception_color_detail: fg_rgbh_ff_00_7f
49
42
  exception_color_name: fg_rgbh_ff_00_00
50
43
  execution_report_preview_frame_color: fg_rgbh_7f_ff_00
51
44
  menu_bash_color: fg_rgbh_00_c0_c0
45
+ menu_block_color: fg_rgbh_47_fe_bb
52
46
  menu_chrome_color: fg_rgbh_40_c0_c0
53
47
  menu_divider_color: fg_rgbh_80_d0_c0
54
48
  menu_edit_color: fg_rgbh_e2_e2_20
@@ -72,12 +66,18 @@ script_preview_frame_color: fg_rgbh_7f_ff_00
72
66
  warning_color: fg_rgbh_ff_7f_00
73
67
  ```
74
68
 
75
- ::: Example blocks
69
+ ::: Divider color
70
+
71
+ ::: Fenced code blocks of different types
72
+ Each block has a name. Its name is decorated according to the type of the block.
73
+ ``` :Unspecified1
76
74
  ```
75
+ ```unknown :Unknown1
77
76
  ```
78
77
  ```bash :Bash1
79
78
  ```
80
- ```edit :Edit1
79
+ / Chrome decoration
80
+ ```edit :Edit-inherited-blocks
81
81
  ```
82
82
  ```history :History1
83
83
  ```
@@ -85,20 +85,22 @@ warning_color: fg_rgbh_ff_7f_00
85
85
  ```
86
86
  ```load :Load1
87
87
  ```
88
+ / Note decoration
89
+ A Note
90
+ / Opts decoration
88
91
  ```opts :Opts1
89
92
  ```
90
93
  ```port :Port1
91
94
  ```
95
+ / Save decoration
92
96
  ```save :Save1
93
97
  ```
94
- ```vars :Vars1
98
+ / Task decoration
99
+ [ ] Task
100
+ / UX decoration
101
+ ```ux
102
+ format: UX-1
95
103
  ```
96
- [ ] Task1
97
-
98
- / blue; fg_rgbh_00_00_FF
99
- / green; fg_rgbh_00_FF_00
100
- / indigo; fg_rgbh_4B_00_82
101
- / orange; fg_rgbh_FF_7F_00
102
- / red; fg_rgbh_FF_00_00
103
- / violet; fg_rgbh_94_00_D3
104
- / yellow; fg_rgbh_FF_FF_00
104
+ / Vars decoration
105
+ ```vars :Vars1
106
+ ```
@@ -89,21 +89,38 @@ class CachedNestedFileReader
89
89
 
90
90
  directory_path = File.dirname(filename)
91
91
  processed_lines = []
92
- File.readlines(filename, chomp: true).each.with_index do |line, ind|
92
+ continued_line = nil # continued import directive
93
+ File.readlines(filename, chomp: true).each.with_index do |segment, ind|
93
94
  wwt :readline, 'depth:', depth, 'filename:', filename, 'ind:', ind,
94
- 'line:', line
95
- if Regexp.new(@import_directive_line_pattern) =~ line
95
+ 'segment:', segment
96
+
97
+ if continued_line || (Regexp.new(@import_directive_line_pattern) =~ segment)
98
+ line = (continued_line || '') + segment
99
+ # if segment ends in a continuation, prepend to next line
100
+ if line.end_with?('\\')
101
+ continued_line = line.chomp('\\')
102
+ next
103
+ end
104
+
105
+ continued_line = nil
106
+
107
+ # apply substitutions to the @import line
108
+ line_sub1 = apply_line_substitutions(line, substitutions,
109
+ use_template_delimiters)
110
+
111
+ # parse the @import line
112
+ Regexp.new(@import_directive_line_pattern) =~ line_sub1
96
113
  name_strip = $~[:name].strip
97
114
  params_string = $~[:params] || ''
98
115
  import_indention = indention + $~[:indention]
99
-
100
116
  # Parse parameters for text substitution
101
117
  import_substitutions, add_code = parse_import_params(params_string)
118
+
102
119
  if add_code
103
120
  # strings as NestedLines
104
- add_lines = add_code.map.with_index do |line, ind2|
121
+ add_lines = add_code.map.with_index do |line2, ind2|
105
122
  nested_line = NestedLine.new(
106
- line,
123
+ line2,
107
124
  depth + 1,
108
125
  import_indention,
109
126
  filename,
@@ -161,7 +178,7 @@ class CachedNestedFileReader
161
178
  processed_lines += processed_imported_lines
162
179
  else
163
180
  # Apply substitutions to the current line
164
- substituted_line = apply_line_substitutions(line, substitutions,
181
+ substituted_line = apply_line_substitutions(segment, substitutions,
165
182
  use_template_delimiters)
166
183
  nested_line = NestedLine.new(substituted_line, depth, indention,
167
184
  filename, ind)
@@ -175,6 +192,8 @@ class CachedNestedFileReader
175
192
  rescue Errno::ENOENT => err
176
193
  warn_format('readlines', "#{err} @@ #{context}",
177
194
  { abort: true })
195
+ rescue StandardError
196
+ wwe $!
178
197
  end
179
198
 
180
199
  private
@@ -208,53 +227,14 @@ class CachedNestedFileReader
208
227
  scanned_params.each do |key, op, value|
209
228
  wwt :import, 'key:', key, 'op:', op, 'value:', value
210
229
 
211
- # adjust key for current stem value
212
- varname = key
213
- case op
214
- when @symbol_command_substitution,
215
- @symbol_evaluated_expression,
216
- @symbol_force_quoted_literal,
217
- @symbol_variable_reference
218
- # perform all substitutions per equal_op_params
219
- equal_op_params.each do |equal_key, _equal_op, equal_value|
220
- varname = varname.gsub(equal_key, equal_value)
221
- end
222
- wwt :import_key, 'varname:', varname
223
- end
230
+ require_relative 'parameter_expansion'
231
+ expansion, new_var = ParameterExpansion.expand_parameter(key, op[1..-2], value)
232
+ value = expansion
224
233
 
225
- case op
226
- when @symbol_raw_literal
227
- # skip replacement of equal values otherwise,
228
- # the text is not available for other substitutions
229
- next unless key != value
230
-
231
- # replace the literal below
232
- when @symbol_command_substitution
233
- # add code to set the variable to the value of the parameter
234
- add_code += shell_code_block_for_assignment(
235
- varname, %($(#{value}))
236
- )
237
- # replace key with expansion of the added variable
238
- value = "${#{varname}}"
239
- when @symbol_evaluated_expression
240
- # add code to set the variable to the value of the parameter
241
- add_code += shell_code_block_for_assignment(
242
- varname, %("#{value}")
243
- )
244
- # replace key with expansion of the added variable
245
- value = "${#{varname}}"
246
- when @symbol_force_quoted_literal
247
- # add code to set the variable to the value of the parameter
234
+ unless new_var.nil?
248
235
  add_code += shell_code_block_for_assignment(
249
- varname, Shellwords.escape(value)
236
+ new_var.name, Shellwords.escape(new_var.assignment_code)
250
237
  )
251
- # replace key with expansion of the added variable
252
- value = "${#{varname}}"
253
- when @symbol_variable_reference
254
- # variable exists
255
- value = "${#{value}}"
256
- else
257
- wwe "Invalid op '#{op}'"
258
238
  end
259
239
 
260
240
  params[key] = value
@@ -33,11 +33,11 @@ class CommandResult
33
33
  exit_status.zero?
34
34
  end
35
35
 
36
- # def new_lines
37
- # value = @attributes[:new_lines]
38
- # ww caller.deref[0..4], value
39
- # value
40
- # end
36
+ def new_lines
37
+ value = @attributes[:new_lines] || []
38
+ ww caller.deref[0..4], value
39
+ value
40
+ end
41
41
 
42
42
  # # trap assignment to new_lines
43
43
  # def new_lines=(value)
data/lib/constants.rb CHANGED
@@ -35,7 +35,9 @@ BLOCK_TYPE_COLOR_OPTIONS = {
35
35
  :readonly => :menu_ux_color_readonly,
36
36
  true => :menu_ux_color
37
37
  },
38
- BlockType::VARS => :menu_vars_color
38
+ BlockType::VARS => :menu_vars_color,
39
+ # default for remaining block types
40
+ true => :menu_block_color
39
41
  }.freeze
40
42
 
41
43
  COLLAPSIBLE_SYMBOL_COLLAPSED = '⬢' # '<+>' # '∆'
data/lib/fcb.rb CHANGED
@@ -7,15 +7,23 @@ require_relative 'namer'
7
7
  BT_UX_FLD_REQUIRED = 'required'
8
8
  def parse_yaml_of_ux_block(
9
9
  data,
10
- menu_format: nil,
11
10
  prompt: nil,
12
11
  validate: nil
13
12
  )
14
- export = data['export']
15
- export = data if export.nil?
16
- name = export['name']
13
+ export = data if (export = data['export']).nil?
17
14
 
18
- raise "Name is missing in UX block: #{data.inspect}" unless name.present?
15
+ # a single variable name is required to display a single value
16
+ menu_format = export['format'] || export['menu_format']
17
+ name = export['name']
18
+ # if name is missing, use the last key in the echo or exec hashes
19
+ if !name&.present?
20
+ name = if export['echo'].is_a? Hash
21
+ export['echo'].keys.last
22
+ elsif export['exec'].is_a? Hash
23
+ export['exec'].keys.last
24
+ end
25
+ end
26
+ raise "Name is missing in UX block: #{data.inspect}" unless name.present? || menu_format.present?
19
27
 
20
28
  OpenStruct.new(
21
29
  act: export['act'],
@@ -25,7 +33,7 @@ def parse_yaml_of_ux_block(
25
33
  exec: export['exec'],
26
34
  force: export['force'],
27
35
  init: export['init'],
28
- menu_format: export['format'] || export['menu_format'], # || menu_format,####
36
+ menu_format: menu_format,
29
37
  name: name,
30
38
  prompt: export['prompt'] || prompt,
31
39
  readonly: export['readonly'].nil? ? false : export['readonly'],
@@ -47,6 +55,7 @@ module MarkdownExec
47
55
  class FCB
48
56
  def initialize(options = {})
49
57
  @attrs = {
58
+ block: nil,
50
59
  body: nil,
51
60
  call: nil,
52
61
  dname: nil,
@@ -66,6 +75,10 @@ module MarkdownExec
66
75
  }.merge(options)
67
76
  end
68
77
 
78
+ def append_block_line(line)
79
+ @attrs[:block].push line
80
+ end
81
+
69
82
  def pub_name(**kwargs)
70
83
  self.class.pub_name(@attrs, **kwargs)
71
84
  end
@@ -388,13 +401,13 @@ module MarkdownExec
388
401
 
389
402
  # calc the decoration sybol for the current block
390
403
  def option_to_decorate_ux_block
391
- symbol_or_hash = BLOCK_TYPE_COLOR_OPTIONS[@attrs[:type]]
404
+ symbol_or_hash = BLOCK_TYPE_COLOR_OPTIONS[@attrs[:type]] || BLOCK_TYPE_COLOR_OPTIONS[true]
392
405
  if @attrs[:type] == BlockType::UX
393
406
  # only UX blocks accept a symbol or a hash
394
407
  if symbol_or_hash.is_a? Hash
395
408
  # default to the first symbol
396
409
  symbol = symbol_or_hash.first.last
397
- symbol_or_hash.keys.each do |key|
410
+ symbol_or_hash.each_key do |key|
398
411
  if key == true
399
412
  symbol = symbol_or_hash[key]
400
413
  break
@@ -518,6 +531,7 @@ if $PROGRAM_NAME == __FILE__
518
531
  class FCBTest < Minitest::Test
519
532
  def setup
520
533
  @fcb_data = {
534
+ block: nil,
521
535
  body: 'Sample body',
522
536
  call: 'Sample call',
523
537
  dname: 'Sample name',