markdown_exec 2.3.0 → 2.4.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 (72) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +11 -2
  3. data/CHANGELOG.md +19 -0
  4. data/Gemfile.lock +1 -1
  5. data/Rakefile +32 -8
  6. data/bats/bats.bats +33 -0
  7. data/bats/block-types.bats +56 -0
  8. data/bats/cli.bats +74 -0
  9. data/bats/fail.bats +11 -0
  10. data/bats/history.bats +34 -0
  11. data/bats/markup.bats +66 -0
  12. data/bats/mde.bats +29 -0
  13. data/bats/options.bats +92 -0
  14. data/bats/test_helper.bash +152 -0
  15. data/bin/tab_completion.sh +44 -20
  16. data/docs/dev/block-type-opts.md +10 -0
  17. data/docs/dev/block-type-port.md +24 -0
  18. data/docs/dev/block-type-vars.md +7 -0
  19. data/docs/dev/pass-through-arguments.md +8 -0
  20. data/docs/dev/specs-import.md +9 -0
  21. data/docs/dev/specs.md +83 -0
  22. data/docs/dev/text-decoration.md +7 -0
  23. data/examples/bash-blocks.md +4 -4
  24. data/examples/block-names.md +2 -2
  25. data/examples/import0.md +23 -0
  26. data/examples/import1.md +13 -0
  27. data/examples/link-blocks-vars.md +3 -3
  28. data/examples/opts-blocks-require.md +6 -6
  29. data/examples/table-markup.md +31 -0
  30. data/examples/text-markup.md +58 -0
  31. data/examples/vars-blocks.md +2 -2
  32. data/examples/wrap.md +87 -9
  33. data/lib/ansi_formatter.rb +12 -6
  34. data/lib/ansi_string.rb +153 -0
  35. data/lib/argument_processor.rb +160 -0
  36. data/lib/cached_nested_file_reader.rb +4 -2
  37. data/lib/ce_get_cost_and_usage.rb +4 -3
  38. data/lib/cli.rb +1 -1
  39. data/lib/colorize.rb +39 -11
  40. data/lib/constants.rb +17 -0
  41. data/lib/directory_searcher.rb +4 -2
  42. data/lib/doh.rb +190 -0
  43. data/lib/env.rb +1 -1
  44. data/lib/exceptions.rb +9 -6
  45. data/lib/fcb.rb +0 -199
  46. data/lib/filter.rb +18 -5
  47. data/lib/find_files.rb +8 -3
  48. data/lib/format_table.rb +406 -0
  49. data/lib/hash_delegator.rb +888 -603
  50. data/lib/hierarchy_string.rb +113 -25
  51. data/lib/input_sequencer.rb +16 -10
  52. data/lib/instance_method_wrapper.rb +2 -1
  53. data/lib/layered_hash.rb +143 -0
  54. data/lib/link_history.rb +22 -8
  55. data/lib/markdown_exec/version.rb +1 -1
  56. data/lib/markdown_exec.rb +413 -165
  57. data/lib/mdoc.rb +27 -34
  58. data/lib/menu.src.yml +825 -710
  59. data/lib/menu.yml +799 -703
  60. data/lib/namer.rb +6 -12
  61. data/lib/object_present.rb +1 -1
  62. data/lib/option_value.rb +7 -3
  63. data/lib/poly.rb +33 -14
  64. data/lib/resize_terminal.rb +60 -52
  65. data/lib/saved_assets.rb +45 -34
  66. data/lib/saved_files_matcher.rb +6 -3
  67. data/lib/streams_out.rb +7 -1
  68. data/lib/table_extractor.rb +166 -0
  69. data/lib/tap.rb +5 -6
  70. data/lib/text_analyzer.rb +144 -8
  71. metadata +26 -3
  72. data/lib/std_out_err_logger.rb +0 -119
data/lib/mdoc.rb CHANGED
@@ -31,8 +31,8 @@ module MarkdownExec
31
31
  def collect_block_code_cann(fcb)
32
32
  body = fcb.body.join("\n")
33
33
  xcall = fcb[:cann][1..-2]
34
- mstdin = xcall.match(/<(?<type>\$)?(?<name>[A-Za-z_\-.\w]+)/)
35
- mstdout = xcall.match(/>(?<type>\$)?(?<name>[A-Za-z_\-.\w]+)/)
34
+ mstdin = xcall.match(/<(?<type>\$)?(?<name>[\-.\w]+)/)
35
+ mstdout = xcall.match(/>(?<type>\$)?(?<name>[\-.\w]+)/)
36
36
 
37
37
  yqcmd = if mstdin[:type]
38
38
  "echo \"$#{mstdin[:name]}\" | yq '#{body}'"
@@ -103,8 +103,9 @@ module MarkdownExec
103
103
  # 2024-08-04 match nickname
104
104
  unmet_dependencies.delete(fcb.pub_name) || unmet_dependencies.delete(fcb.nickname) || unmet_dependencies.delete(fcb.oname) # may not exist if block name is duplicated
105
105
  if (call = fcb.call)
106
- [get_block_by_anyname("[#{call.match(/^%\((\S+) |\)/)[1]}]")
107
- .merge({ cann: call })]
106
+ fcb1 = get_block_by_anyname("[#{call.match(/^%\((\S+) |\)/)[1]}]")
107
+ fcb1.cann = call
108
+ [fcb1]
108
109
  else
109
110
  []
110
111
  end + [fcb]
@@ -268,13 +269,13 @@ module MarkdownExec
268
269
  label_format_below)
269
270
  block_name_for_bash_comment = fcb.pub_name.gsub(/\s+/, '_')
270
271
 
271
- label_above = if label_format_above
272
+ label_above = if label_format_above.present?
272
273
  format(label_format_above,
273
274
  block_source.merge({ block_name: block_name_for_bash_comment }))
274
275
  else
275
276
  nil
276
277
  end
277
- label_below = if label_format_below
278
+ label_below = if label_format_below.present?
278
279
  format(label_format_below,
279
280
  block_source.merge({ block_name: block_name_for_bash_comment }))
280
281
  else
@@ -357,7 +358,8 @@ module MarkdownExec
357
358
  return memo if memo.keys.include? source
358
359
 
359
360
  block = get_block_by_anyname(source)
360
- if block.nil? || block.keys.empty?
361
+ # if block.nil? || block.keys.nil? || block.keys.empty?
362
+ if block.nil?
361
363
  raise "Named code block `#{source}` not found. (@#{__LINE__})"
362
364
  end
363
365
 
@@ -379,11 +381,9 @@ module MarkdownExec
379
381
  def collect_dependencies(source, memo = {})
380
382
  return memo unless source
381
383
 
382
- if (block = get_block_by_anyname(source)).nil? || block.keys.empty?
383
- return memo if true
384
-
384
+ block = get_block_by_anyname(source)
385
+ if block.nil? || block.instance_of?(Hash)
385
386
  raise "Named code block `#{source}` not found. (@#{__LINE__})"
386
-
387
387
  end
388
388
 
389
389
  return memo unless block.reqs
@@ -459,17 +459,16 @@ if $PROGRAM_NAME == __FILE__
459
459
  assert_empty @mdoc.collect_dependencies(nil)
460
460
  end
461
461
 
462
- if false # must raise error
463
- def test_collect_dependencies_with_nonexistent_source
464
- assert_raises(RuntimeError) do
465
- @mdoc.collect_dependencies('nonexistent')
466
- end
462
+ ### must raise error
463
+ def test_collect_dependencies_with_nonexistent_source
464
+ assert_raises(RuntimeError) do
465
+ @mdoc.collect_dependencies('nonexistent')
467
466
  end
468
- end
467
+ end if false
469
468
 
470
469
  def test_collect_dependencies_with_valid_source
471
- @mdoc.stubs(:get_block_by_anyname).with('source1').returns({ reqs: ['source2'] })
472
- @mdoc.stubs(:get_block_by_anyname).with('source2').returns({ reqs: [] })
470
+ @mdoc.stubs(:get_block_by_anyname).with('source1').returns(OpenStruct.new(reqs: ['source2']))
471
+ @mdoc.stubs(:get_block_by_anyname).with('source2').returns(OpenStruct.new(reqs: []))
473
472
 
474
473
  expected = { 'source1' => ['source2'], 'source2' => [] }
475
474
  assert_equal expected, @mdoc.collect_dependencies('source1')
@@ -507,16 +506,12 @@ if $PROGRAM_NAME == __FILE__
507
506
  { oname: 'block1', body: ['code for block1'], reqs: ['block2'] },
508
507
  { oname: 'block2', body: ['code for block2'], reqs: nil },
509
508
  { oname: 'block3', body: ['code for block3'], reqs: ['block1'] }
510
- ]
509
+ ].map do |row|
510
+ OpenStruct.new(nickname: nil, **row)
511
+ end
511
512
  @doc = MDoc.new(@table)
512
513
  end
513
514
 
514
- # def test_collect_recursively_required_code
515
- # result = @doc.collect_recursively_required_code('block1')[:code]
516
- # expected_result = @table[0][:body] + @table[1][:body]
517
- # assert_equal expected_result, result
518
- # end
519
-
520
515
  def test_get_block_by_name
521
516
  result = @doc.get_block_by_anyname('block1')
522
517
  assert_equal @table[0], result
@@ -525,7 +520,6 @@ if $PROGRAM_NAME == __FILE__
525
520
  assert_equal({}, result_missing)
526
521
  end
527
522
 
528
- ### broken test
529
523
  def test_collect_block_dependencies
530
524
  result = @doc.collect_block_dependencies(anyname: 'block3')[:blocks]
531
525
  expected_result = [@table[0], @table[1], @table[2]]
@@ -534,7 +528,7 @@ if $PROGRAM_NAME == __FILE__
534
528
  assert_raises(RuntimeError) do
535
529
  @doc.collect_block_dependencies(anyname: 'missing_block')
536
530
  end
537
- end
531
+ end if false ### broken test
538
532
 
539
533
  def test_hide_menu_block_on_name
540
534
  opts = { hide_blocks_by_name: true,
@@ -544,12 +538,11 @@ if $PROGRAM_NAME == __FILE__
544
538
  assert result # this should be true based on the given logic
545
539
  end
546
540
 
547
- ### broken test
548
- # def test_fcbs_per_options
549
- # opts = { hide_blocks_by_name: true, block_name_hidden_match: 'block1' }
550
- # result = @doc.fcbs_per_options(opts)
551
- # assert_equal [@table[1], @table[2]], result
552
- # end
541
+ def test_fcbs_per_options
542
+ opts = { hide_blocks_by_name: true, block_name_hidden_match: 'block1' }
543
+ result = @doc.fcbs_per_options(opts)
544
+ assert_equal [@table[1], @table[2]], result
545
+ end if false ### broken test
553
546
 
554
547
  def test_recursively_required
555
548
  result = @doc.recursively_required_hash('block3')