markdown_exec 1.6 → 1.8

Sign up to get free protection for your applications and to get access to all the features.
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