markdown_exec 1.6 → 1.8

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: 97323ce7d6c677603ca89432c9ca64e45ff205a5b6cc03a71f4be1210bf8104a
4
- data.tar.gz: ccce852fe96571b00c4443012371ea5ad29caec29dfdc9649cec7da2c091defe
3
+ metadata.gz: c4fdb41b414911d16030ffbfb8c4b07ca8c09e3684f21e123d0d99cd738dba3d
4
+ data.tar.gz: 70c1ec9fb9b795d0cbdcc87ceb03809a57af5901a70dc2b1d319c9451592d687
5
5
  SHA512:
6
- metadata.gz: bc08d47d135d9a078240c6e3001322ec8b35b8fb4f7febeabec02729240d7524a40464d9d563aeb15e5c8d09695bd0b512251d970dfede46cf07bd377af72181
7
- data.tar.gz: ec61f969d204b0216c02e2e13d270363aef35ecf3ad6ff5a26d653e2d5c8f1608ff3e70a24ab65ab3bd48d8c546e1a6c627734c8e03e08a2440c18b1d9db7fed
6
+ metadata.gz: abea63db83a4d785bce7c2ec1c9babebe6d78637872a068c4d6b2169832de8ea707a2c3ae426f6cd5ea548269194a797d95abdd7fceb286c4efa49da9d591bfe
7
+ data.tar.gz: 1b102cb3e898789d6ddf2a401f90cfee04403ea135a14a5067673b250855aef569ca3b39a171570930ef5946d52874d022fb19fd9cf7c1561737144aefc5ef3c
data/.rubocop.yml CHANGED
@@ -14,9 +14,9 @@ Layout/LineContinuationLeadingSpace:
14
14
  Enabled: false
15
15
 
16
16
  Layout/LineLength:
17
- Max: 72
17
+ # Max: 78
18
18
  # Max: 80
19
- # Max: 96
19
+ Max: 96
20
20
 
21
21
  Lint/Debugger:
22
22
  Enabled: false
@@ -72,6 +72,9 @@ Style/FormatStringToken:
72
72
  Style/GlobalVars:
73
73
  Enabled: false
74
74
 
75
+ Style/Lambda:
76
+ Enabled: false
77
+
75
78
  Style/MixinUsage:
76
79
  Enabled: false
77
80
 
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- markdown_exec (1.6)
4
+ markdown_exec (1.8)
5
5
  clipboard (~> 1.3.6)
6
6
  open3 (~> 0.1.1)
7
7
  optparse (~> 0.1.1)
data/Rakefile CHANGED
@@ -79,8 +79,10 @@ task :minitest do
79
79
  commands = [
80
80
  './lib/block_label.rb',
81
81
  './lib/cached_nested_file_reader.rb',
82
+ './lib/directory_searcher.rb',
82
83
  './lib/fcb.rb',
83
84
  './lib/filter.rb',
85
+ './lib/hash_delegator.rb',
84
86
  './lib/markdown_exec.rb',
85
87
  './lib/mdoc.rb',
86
88
  './lib/object_present.rb',
@@ -13,7 +13,7 @@ __filedirs_all()
13
13
  }
14
14
 
15
15
  _mde_echo_version() {
16
- echo "1.6"
16
+ echo "1.8"
17
17
  }
18
18
 
19
19
  _mde() {
@@ -40,6 +40,14 @@ _mde() {
40
40
 
41
41
  -f) COMPREPLY="."; return 0 ;;
42
42
 
43
+ --find) COMPREPLY="''"; return 0 ;;
44
+
45
+ -?) COMPREPLY="''"; return 0 ;;
46
+
47
+ --how) COMPREPLY="''"; return 0 ;;
48
+
49
+ -?) COMPREPLY="''"; return 0 ;;
50
+
43
51
  --list-count) COMPREPLY="32"; return 0 ;;
44
52
 
45
53
  --output-execution-summary) COMPREPLY="0"; return 0 ;;
@@ -74,7 +82,7 @@ _mde() {
74
82
  # present matching option names
75
83
  #
76
84
  if [[ ${cur} == -* ]] ; then
77
- opts=("--block-name" "--config" "--debug" "--exit" "--filename" "--help" "--list-blocks" "--list-count" "--list-default-env" "--list-default-yaml" "--list-docs" "--list-recent-output" "--list-recent-scripts" "--output-execution-summary" "--output-script" "--output-stdout" "--path" "--pwd" "--run-last-script" "--save-executed-script" "--save-execution-output" "--saved-script-folder" "--saved-stdout-folder" "--select-recent-output" "--select-recent-script" "--tab-completions" "--user-must-approve" "--version" "--display-level")
85
+ opts=("--block-name" "--config" "--debug" "--exit" "--filename" "--find" "--help" "--how" "--list-blocks" "--list-count" "--list-default-env" "--list-default-yaml" "--list-docs" "--list-recent-output" "--list-recent-scripts" "--output-execution-summary" "--output-script" "--output-stdout" "--path" "--pwd" "--run-last-script" "--save-executed-script" "--save-execution-output" "--saved-script-folder" "--saved-stdout-folder" "--select-recent-output" "--select-recent-script" "--tab-completions" "--user-must-approve" "--version" "--display-level")
78
86
  COMPREPLY=( $(compgen -W "$(printf "'%s' " "${opts[@]}")" -- "${cur}") )
79
87
 
80
88
  return 0
@@ -101,6 +109,14 @@ _mde() {
101
109
 
102
110
  -f) COMPREPLY=".RELATIVE_PATH."; return 0 ;;
103
111
 
112
+ --find) COMPREPLY=".FIND."; return 0 ;;
113
+
114
+ -?) COMPREPLY=".FIND."; return 0 ;;
115
+
116
+ --how) COMPREPLY=".HOW."; return 0 ;;
117
+
118
+ -?) COMPREPLY=".HOW."; return 0 ;;
119
+
104
120
  --list-count) COMPREPLY=".INT.1-."; return 0 ;;
105
121
 
106
122
  --output-execution-summary) COMPREPLY=".BOOL."; return 0 ;;
@@ -138,4 +154,4 @@ _mde() {
138
154
 
139
155
  complete -o filenames -o nospace -F _mde mde
140
156
  # _mde_echo_version
141
- # echo "Updated: 2023-11-13 16:19:21 UTC"
157
+ # echo "Updated: 2023-12-11 19:58:50 UTC"
@@ -0,0 +1,48 @@
1
+ # Demo configuring options
2
+
3
+ ::: These Opts blocks set the color for all elements.
4
+
5
+ ```opts :(document_options)
6
+ ```
7
+ ```opts :(default)
8
+ exception_color_detail: fg_rgbh_E0_E0_20 # Color of exception detail
9
+ exception_color_name: fg_rgbh_E0_20_20 # Color of exception name
10
+ execution_report_preview_frame_color: fg_rgbh_20_80_80 # execution_report_preview_frame_color
11
+ menu_bash_color: fg_rgbh_40_C0_F0 # Color of menu bash
12
+ menu_chrome_color: fg_rgbh_80_80_20 # Color of menu chrome
13
+ menu_divider_color: fg_rgbh_20_98_80 # Color of menu divider
14
+ menu_link_color: fg_rgbh_20_E0_20 # Color of menu link
15
+ menu_note_color: fg_rgbh_40_A0_A0 # Color of menu note
16
+ menu_opts_color: fg_rgbh_E0_60_E0 # Color of menu opts
17
+ menu_opts_set_color: fg_rgbh_E0_20_20 # Color of menu opts
18
+ menu_task_color: fg_rgbh_A0_20_D0 # Color of menu task
19
+ menu_vars_color: fg_rgbh_E0_80_20 # Color of menu vars
20
+ menu_vars_set_color: fg_rgbh_E0_80_20 # Color of menu vars
21
+ output_execution_label_name_color: fg_rgbh_20_D8_80 # Color of output_execution_label_name
22
+ output_execution_label_value_color: fg_rgbh_20_E0_80 # Color of output_execution_label_value
23
+ prompt_color_after_script_execution: fg_rgbh_20_E8_80 # Color of prompt after script execution
24
+ script_execution_frame_color: fg_rgbh_20_80_80 # script_execution_frame_color
25
+ script_preview_frame_color: fg_rgbh_20_80_80 # Color of output divider
26
+ warning_color: fg_rgbh_E0_E0_20 # Color of warning message
27
+ ```
28
+
29
+ ::: Example blocks
30
+
31
+ ```bash :Bash1
32
+ ```
33
+ ```link :Link1
34
+ ```
35
+ ```opts :Opts1
36
+ ```
37
+ ```port :Port1
38
+ ```
39
+ ```vars :Vars1
40
+ ```
41
+ [ ] Task1
42
+ blue; fg_rgbh_00_00_FF
43
+ green; fg_rgbh_00_FF_00
44
+ indigo; fg_rgbh_4B_00_82
45
+ orange; fg_rgbh_FF_7F_00
46
+ red; fg_rgbh_FF_00_00
47
+ violet; fg_rgbh_94_00_D3
48
+ yellow; fg_rgbh_FF_FF_00
data/examples/import0.md CHANGED
@@ -1,8 +1,44 @@
1
- ```bash :01
2
- 01
3
- ```
1
+ This is Page 0
2
+
4
3
  @import import1.md
5
- ```bash :03
6
- 03
4
+
5
+ ```opts :(document_options)
6
+ user_must_approve: true
7
+ ```
8
+
9
+ ::: Page 0 code blocks
10
+
11
+ ```bash :page0_block1 +(page0_block2) +(page1_block2)
12
+ echo "page 0 block 1 visible"
13
+ # requires page 0 block 2
14
+ # imports page 1
15
+ # requires page 1 block 2
16
+ ```
17
+
18
+ ```bash :(page0_block2)
19
+ echo "page 0 block 2 hidden"
7
20
  ```
8
21
 
22
+ ::: Control display of code blocks
23
+
24
+ ```opts :hide_imported_blocks
25
+ menu_include_imported_blocks: false
26
+ ```
27
+
28
+ ```opts :show_imported_blocks
29
+ menu_include_imported_blocks: true
30
+ ```
31
+
32
+ ::: Control display of notes
33
+
34
+ ```opts :hide_imported_notes
35
+ menu_include_imported_notes: false
36
+ ```
37
+
38
+ ```opts :show_imported_notes
39
+ menu_include_imported_notes: true
40
+ ```
41
+
42
+ ```link :page_1
43
+ file: examples/import1.md
44
+ ```
data/examples/import1.md CHANGED
@@ -1,10 +1,11 @@
1
- ```bash :11
2
- 11
3
- ```
4
- ```bash :12
5
- 12
6
- ```
7
- ```bash:13
8
- 13
1
+ This is Page 1
2
+
3
+ ::: Page 1 code blocks
4
+
5
+ ```bash :page1_block1
6
+ echo "page 1 block 1 visible"
9
7
  ```
10
8
 
9
+ ```bash :(page1_block2)
10
+ echo "page 1 block 2 hidden"
11
+ ```
data/examples/include.md CHANGED
@@ -1,12 +1,19 @@
1
1
  ```bash :(one)
2
- a
2
+ echo block "one"
3
3
  ```
4
+
4
5
  ```bash :two +(one)
5
- b
6
+ echo block "two" requires one
6
7
  ```
8
+
7
9
  ```bash :(three) +two +(one)
8
- c
10
+ echo block "three" requires two and one
9
11
  ```
12
+
10
13
  ```bash :four +(three)
11
- d
14
+ echo block "four" requires three
15
+ ```
16
+
17
+ ```bash :trigger_unmet_dependency +(unmet)
18
+ echo block "five" requires an unmet dependency
12
19
  ```
data/examples/linked1.md CHANGED
@@ -11,16 +11,20 @@ colorize_env_vars 'vars for page2' PAGE2_VAR_VIA_INHERIT page2_var_via_environme
11
11
  colorize_env_vars 'vars for page3' PAGE3_VAR_VIA_INHERIT page3_var_via_environment
12
12
  ```
13
13
 
14
+ ```bash :(vars2)
15
+ PAGE2_VAR_VIA_INHERIT=for_page2_from_page1_via_inherited_code_file
16
+ ```
17
+
18
+ ```link :(linked2)
19
+ file: examples/linked2.md
20
+ ```
21
+
14
22
  ::: This Link block
15
23
  ::: 1. requires a block that sets environment variable PAGE2_VAR_VIA_INHERIT,
16
24
  ::: 2. navigates to document 2, and
17
25
  ::: 3. executes block "show_vars" to display the imported PAGE2_VAR_VIA_INHERIT.
18
26
  ::: Any script generated by page 2 will contain the inherited code.
19
27
 
20
- ```bash :(vars2)
21
- PAGE2_VAR_VIA_INHERIT=for_page2_from_page1_via_inherited_code_file
22
- ```
23
-
24
28
  ```link :linked2_import_vars +(vars2)
25
29
  file: examples/linked2.md
26
30
  block: show_vars
data/examples/opts.md CHANGED
@@ -19,4 +19,11 @@ menu_task_color: fg_rgb_127_127_255
19
19
  menu_divider_color: green
20
20
  menu_link_color: fg_rgbh_88_cc_66
21
21
  menu_note_color: yellow
22
+
23
+ menu_note_match: "^\\s*(?<line>[^\\s/].*)\\s*$" # Pattern for notes in block selection menu; start with any char except '/'
22
24
  ```
25
+
26
+ note 1
27
+ note 2 ends with /
28
+ / note 3 starts with /
29
+ note 4
@@ -0,0 +1,161 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ # encoding=utf-8
5
+
6
+ class AnsiFormatter
7
+ def initialize(options = {})
8
+ @options = options
9
+ end
10
+
11
+ def format_and_highlight_array(
12
+ data,
13
+ highlight_color_sym: :exception_color_detail,
14
+ plain_color_sym: :menu_chrome_color,
15
+ label: 'Data:',
16
+ highlight: [],
17
+ line_prefix: ' ',
18
+ line_postfix: '',
19
+ detail_sep: ''
20
+ )
21
+ (data&.map do |item|
22
+ scan_and_process_multiple_substrings(item, highlight, plain_color_sym,
23
+ highlight_color_sym).join
24
+ # color_sym = highlight.include?(item) ? highlight_color_sym : c
25
+ # string_send_color(item, color_sym)
26
+ end || []) #.join
27
+ # formatted_deps
28
+ # "#{line_prefix}#{string_send_color(label, highlight_color_sym)}#{line_postfix}\n" + formatted_deps.join("\n")
29
+ end
30
+
31
+ # Formats and highlights a list of data. data are presented with indentation,
32
+ # and specific items can be highlighted in a specified color, while others are shown in a plain color.
33
+ #
34
+ # @param data [Hash] A hash of data, where each key is a dependency name,
35
+ # and its value is an array of sub-items.
36
+ # @param highlight_color_sym [Symbol] The color method to apply to highlighted items.
37
+ # Default is :exception_color_detail.
38
+ # @param plain_color_sym [Symbol] The color method for non-highlighted items.
39
+ # Default is :menu_chrome_color.
40
+ # @param label [String] The label to prefix the list of data with.
41
+ # Default is 'data:'.
42
+ # @param highlight [Array] An array of items to highlight. Each item in this array will be
43
+ # formatted with the specified highlight color.
44
+ # @param line_prefix [String] Prefix for each line. Default is ' '.
45
+ # @param line_postfix [String] Postfix for each line. Default is ''.
46
+ # @param detail_sep [String] Separator for items in the sub-list. Default is ' '.
47
+ # @return [String] A formatted string representation of the data with highlighted items.
48
+ def format_and_highlight_hash(
49
+ data,
50
+ highlight_color_sym: :exception_color_detail,
51
+ plain_color_sym: :menu_chrome_color,
52
+ label: 'Data:',
53
+ highlight: [],
54
+ line_prefix: ' ',
55
+ line_postfix: '',
56
+ detail_sep: ' '
57
+ )
58
+ formatted_deps = data&.map do |dep_name, sub_items|
59
+ formatted_sub_items = sub_items.map do |item|
60
+ color_sym = highlight.include?(item) ? highlight_color_sym : plain_color_sym
61
+ string_send_color(item, color_sym)
62
+ end.join(detail_sep)
63
+
64
+ "#{line_prefix}- #{string_send_color(dep_name,
65
+ highlight.include?(dep_name) ? highlight_color_sym : plain_color_sym)}: #{formatted_sub_items}#{line_postfix}"
66
+ end || []
67
+
68
+ "#{line_prefix}#{string_send_color(label,
69
+ highlight_color_sym)}#{line_postfix}\n" + formatted_deps.join("\n")
70
+ end
71
+
72
+ # Function to scan a string and process its segments based on multiple substrings
73
+ # @param str [String] The string to scan.
74
+ # @param substrings [Array<String>] The substrings to match in the string.
75
+ # @param plain_sym [Symbol] The symbol for non-matching segments.
76
+ # @param color_sym [Symbol] The symbol for matching segments.
77
+ # @return [Array<String>] The processed segments.
78
+ def scan_and_process_multiple_substrings(str, substrings, plain_sym, color_sym)
79
+ return string_send_color(str, plain_sym) if substrings.empty? || substrings.any?(&:empty?)
80
+
81
+ results = []
82
+ remaining_str = str.dup
83
+
84
+ while remaining_str.length.positive?
85
+ match_indices = substrings.map { |substring| remaining_str.index(substring) }.compact
86
+ earliest_match = match_indices.min
87
+
88
+ if earliest_match
89
+ # Process non-matching segment before the earliest match, if any
90
+ unless earliest_match.zero?
91
+ non_matching_segment = remaining_str.slice!(0...earliest_match)
92
+ results << string_send_color(non_matching_segment, plain_sym)
93
+ end
94
+
95
+ # Find which substring has this earliest match
96
+ matching_substring = substrings.find do |substring|
97
+ remaining_str.index(substring) == earliest_match
98
+ end
99
+
100
+ if matching_substring
101
+ matching_segment = remaining_str.slice!(0...matching_substring.length)
102
+ results << string_send_color(matching_segment, color_sym)
103
+ end
104
+ else
105
+ # Process the remaining non-matching segment
106
+ results << string_send_color(remaining_str, plain_sym)
107
+ break
108
+ end
109
+ end
110
+
111
+ results
112
+ end
113
+
114
+ # Function to scan a string and process its segments
115
+ # @param str [String] The string to scan.
116
+ # @param substring [String] The substring to match in the string.
117
+ # @param plain_sym [Symbol] The symbol for non-matching segments.
118
+ # @param color_sym [Symbol] The symbol for matching segments.
119
+ # @return [Array<String>] The processed segments.
120
+ def scan_and_process_string(str, substring, plain_sym, color_sym)
121
+ return string_send_color(str, plain_sym) unless substring.present?
122
+
123
+ results = []
124
+ remaining_str = str.dup
125
+
126
+ while remaining_str.length.positive?
127
+ match_index = remaining_str.index(substring)
128
+ if match_index
129
+ # Process non-matching segment before the match, if any
130
+ unless match_index.zero?
131
+ non_matching_segment = remaining_str.slice!(0...match_index)
132
+ results << string_send_color(non_matching_segment, plain_sym)
133
+ end
134
+
135
+ # Process the matching segment
136
+ matching_segment = remaining_str.slice!(0...substring.length)
137
+ results << string_send_color(matching_segment, color_sym)
138
+ else
139
+ # Process the remaining non-matching segment
140
+ results << string_send_color(remaining_str, plain_sym)
141
+ break
142
+ end
143
+ end
144
+
145
+ results
146
+ end
147
+
148
+ # # Example usage
149
+ # scan_and_process_string("Hello world, hello universe", "hello", :plain, :color)
150
+
151
+ # Applies a color method to a string based on the provided color symbol.
152
+ # The color method is fetched from @options and applied to the string.
153
+ # @param string [String] The string to which the color will be applied.
154
+ # @param color_sym [Symbol] The symbol representing the color method.
155
+ # @param default [String] Default color method to use if color_sym is not found in @options.
156
+ # @return [String] The string with the applied color method.
157
+ def string_send_color(string, color_sym, default: 'plain')
158
+ color_method = @options.fetch(color_sym, default).to_sym
159
+ string.to_s.send(color_method)
160
+ end
161
+ end
data/lib/array.rb ADDED
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ # encoding=utf-8
5
+
6
+ class Array
7
+ # Processes each element of the array, yielding the previous, current, and next elements to the given block.
8
+ # Deletes the current element if the block returns true.
9
+ # @return [Array] The modified array after conditional deletions.
10
+ def process_and_conditionally_delete!
11
+ i = 0
12
+ while i < length
13
+ prev_item = self[i - 1] unless i.zero?
14
+ current_item = self[i]
15
+ next_item = self[i + 1]
16
+
17
+ should_delete = yield prev_item, current_item, next_item
18
+ if should_delete
19
+ delete_at(i)
20
+ else
21
+ i += 1
22
+ end
23
+ end
24
+
25
+ self
26
+ end
27
+ end
data/lib/array_util.rb ADDED
@@ -0,0 +1,21 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ # encoding=utf-8
5
+
6
+ module ArrayUtil
7
+ def self.partition_by_predicate(arr)
8
+ true_list = []
9
+ false_list = []
10
+
11
+ arr.each do |element|
12
+ if yield(element)
13
+ true_list << element
14
+ else
15
+ false_list << element
16
+ end
17
+ end
18
+
19
+ [true_list, false_list]
20
+ end
21
+ end
@@ -5,6 +5,16 @@
5
5
 
6
6
  # version 2023-10-03
7
7
 
8
+ require 'fileutils'
9
+ require_relative 'exceptions'
10
+
11
+ # a struct to hold the data for a single line
12
+ NestedLine = Struct.new(:text, :depth) do
13
+ def to_s
14
+ text
15
+ end
16
+ end
17
+
8
18
  ##
9
19
  # The CachedNestedFileReader class provides functionality to read file lines with the ability
10
20
  # to process '#import filename' directives. When such a directive is encountered in a file,
@@ -13,42 +23,58 @@
13
23
  # It allows clients to read lines with or without providing a block.
14
24
  #
15
25
  class CachedNestedFileReader
26
+ include Exceptions
27
+
16
28
  def initialize(import_pattern: /^ *#import (.+)$/)
17
29
  @file_cache = {}
18
30
  @import_pattern = import_pattern
19
31
  end
20
32
 
21
- def readlines(filename, &block)
33
+ def error_handler(name = '', opts = {})
34
+ Exceptions.error_handler(
35
+ "CachedNestedFileReader.#{name} -- #{$!}",
36
+ opts
37
+ )
38
+ end
39
+
40
+ def warn_format(name, message, opts = {})
41
+ Exceptions.warn_format(
42
+ "CachedNestedFileReader.#{name} -- #{message}",
43
+ opts
44
+ )
45
+ end
46
+
47
+ def readlines(filename, depth = 0, &block)
22
48
  if @file_cache.key?(filename)
23
- @file_cache[filename].each(&block) if block_given?
49
+ @file_cache[filename].each(&block) if block
24
50
  return @file_cache[filename]
25
51
  end
26
52
 
27
53
  directory_path = File.dirname(filename)
28
- lines = File.readlines(filename, chomp: true)
54
+ # lines = File.readlines(filename, chomp: true)
29
55
  processed_lines = []
30
56
 
31
- lines.each do |line|
32
- if (match = line.match(@import_pattern))
33
- included_file_path = if match[1].strip.match %r{^/}
34
- match[1].strip
57
+ File.readlines(filename, chomp: true).each do |line|
58
+ if Regexp.new(@import_pattern) =~ line
59
+ name_strip = $~[:name].strip
60
+ included_file_path = if name_strip =~ %r{^/}
61
+ name_strip
35
62
  else
36
- File.join(directory_path, match[1].strip)
63
+ File.join(directory_path, name_strip)
37
64
  end
38
- processed_lines += readlines(included_file_path, &block)
65
+ processed_lines += readlines(included_file_path, depth + 1,
66
+ &block)
39
67
  else
40
- processed_lines.push(line)
41
- yield line if block_given?
68
+ nested_line = NestedLine.new(line, depth)
69
+ processed_lines.push(nested_line)
70
+ block&.call(nested_line)
42
71
  end
43
72
  end
44
73
 
45
74
  @file_cache[filename] = processed_lines
46
- end
47
-
48
- private
49
-
50
- def fetch_lines(filename)
51
- @fetch_lines_cache[filename] ||= File.readlines(filename, chomp: true)
75
+ rescue Errno::ENOENT
76
+ # Exceptions.error_handler('readlines', { abort: true })
77
+ warn_format('readlines', "No such file -- #{filename}", { abort: true })
52
78
  end
53
79
  end
54
80
 
@@ -56,10 +82,6 @@ if $PROGRAM_NAME == __FILE__
56
82
  require 'minitest/autorun'
57
83
  require 'tempfile'
58
84
 
59
- ##
60
- # The CachedNestedFileReaderTest class provides testing for
61
- # the CachedNestedFileReader class.
62
- #
63
85
  class CachedNestedFileReaderTest < Minitest::Test
64
86
  def setup
65
87
  @file2 = Tempfile.new('test2.txt')
@@ -69,7 +91,7 @@ if $PROGRAM_NAME == __FILE__
69
91
  @file1 = Tempfile.new('test1.txt')
70
92
  @file1.write("Line1\nLine2\n #insert #{@file2.path}\nLine3")
71
93
  @file1.rewind
72
- @reader = CachedNestedFileReader.new(import_pattern: /^ *#insert (.+)$/)
94
+ @reader = CachedNestedFileReader.new(import_pattern: /^ *#insert (?'name'.+)$/)
73
95
  end
74
96
 
75
97
  def teardown
@@ -81,28 +103,26 @@ if $PROGRAM_NAME == __FILE__
81
103
  end
82
104
 
83
105
  def test_readlines_without_imports
84
- result = []
85
- @reader.readlines(@file2.path) { |line| result << line }
106
+ result = @reader.readlines(@file2.path).map(&:to_s)
86
107
  assert_equal %w[ImportedLine1 ImportedLine2], result
87
108
  end
88
109
 
89
110
  def test_readlines_with_imports
90
- result = []
91
- @reader.readlines(@file1.path) { |line| result << line }
92
- assert_equal %w[Line1 Line2 ImportedLine1 ImportedLine2 Line3], result
111
+ result = @reader.readlines(@file1.path).map(&:to_s)
112
+ assert_equal %w[Line1 Line2 ImportedLine1 ImportedLine2 Line3],
113
+ result
93
114
  end
94
115
 
95
116
  def test_caching_functionality
96
117
  # First read
97
- result1 = []
98
- @reader.readlines(@file2.path) { |line| result1 << line }
118
+
119
+ result1 = @reader.readlines(@file2.path).map(&:to_s)
99
120
 
100
121
  # Simulate file content change
101
122
  @file2.reopen(@file2.path, 'w') { |f| f.write('ChangedLine') }
102
123
 
103
124
  # Second read (should read from cache, not the changed file)
104
- result2 = []
105
- @reader.readlines(@file2.path) { |line| result2 << line }
125
+ result2 = @reader.readlines(@file2.path).map(&:to_s)
106
126
 
107
127
  assert_equal result1, result2
108
128
  assert_equal %w[ImportedLine1 ImportedLine2], result2