markdown_exec 1.6 → 1.7

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: 97045160c53b7dca3998f6d700bf136f500826141d226f9f2cc650d15e6d1ba7
4
+ data.tar.gz: c69c23b07fcb3304d0209f79596619fbe54d0c2bb9a03f94c8598e3358c25ed7
5
5
  SHA512:
6
- metadata.gz: bc08d47d135d9a078240c6e3001322ec8b35b8fb4f7febeabec02729240d7524a40464d9d563aeb15e5c8d09695bd0b512251d970dfede46cf07bd377af72181
7
- data.tar.gz: ec61f969d204b0216c02e2e13d270363aef35ecf3ad6ff5a26d653e2d5c8f1608ff3e70a24ab65ab3bd48d8c546e1a6c627734c8e03e08a2440c18b1d9db7fed
6
+ metadata.gz: a525dc3c727c38aba2d52382871650b6d2636891028a6def27f8958fcd78ae46afcb8fbbeb0f1bfdb0d550beb22c7cc90c67744c52143490f0a27c75c9158442
7
+ data.tar.gz: ae304dc41d17d2763a17b518da50956f0271ca401a4bc78929200eeb17ab3d19dfd148db76f104aed8216120c38673d19c9e56af018d3c9d83534c8901cc0915
data/.rubocop.yml CHANGED
@@ -14,7 +14,7 @@ Layout/LineContinuationLeadingSpace:
14
14
  Enabled: false
15
15
 
16
16
  Layout/LineLength:
17
- Max: 72
17
+ Max: 78
18
18
  # Max: 80
19
19
  # Max: 96
20
20
 
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.7)
5
5
  clipboard (~> 1.3.6)
6
6
  open3 (~> 0.1.1)
7
7
  optparse (~> 0.1.1)
data/Rakefile CHANGED
@@ -81,6 +81,7 @@ task :minitest do
81
81
  './lib/cached_nested_file_reader.rb',
82
82
  './lib/fcb.rb',
83
83
  './lib/filter.rb',
84
+ './lib/hash_delegator.rb',
84
85
  './lib/markdown_exec.rb',
85
86
  './lib/mdoc.rb',
86
87
  './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.7"
17
17
  }
18
18
 
19
19
  _mde() {
@@ -138,4 +138,4 @@ _mde() {
138
138
 
139
139
  complete -o filenames -o nospace -F _mde mde
140
140
  # _mde_echo_version
141
- # echo "Updated: 2023-11-13 16:19:21 UTC"
141
+ # echo "Updated: 2023-12-01 18:34:38 UTC"
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/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/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
data/lib/constants.rb ADDED
@@ -0,0 +1,46 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ # encoding=utf-8
5
+
6
+ class ExecutionStreams
7
+ StdErr = :stderr
8
+ StdIn = :stdin
9
+ StdOut = :stdout
10
+ end
11
+
12
+ class LoadFile
13
+ Load = true
14
+ Reuse = false
15
+ end
16
+
17
+ LoadFileNextBlock = Struct.new(:load_file, :next_block)
18
+
19
+ class MenuControl
20
+ Fresh = false
21
+ Repeat = true
22
+ end
23
+
24
+ class MenuOptions
25
+ YES = 1
26
+ NO = 2
27
+ SCRIPT_TO_CLIPBOARD = 3
28
+ SAVE_SCRIPT = 4
29
+ end
30
+
31
+ class MenuState
32
+ BACK = :back
33
+ CONTINUE = :continue
34
+ EXIT = :exit
35
+ end
36
+
37
+ # selected block and subsequent menu state
38
+ #
39
+ SelectedBlockMenuState = Struct.new(:block, :state)
40
+
41
+ SHELL_COLOR_OPTIONS = {
42
+ BlockType::BASH => :menu_bash_color,
43
+ BlockType::LINK => :menu_link_color,
44
+ BlockType::OPTS => :menu_opts_color,
45
+ BlockType::VARS => :menu_vars_color
46
+ }.freeze
data/lib/env.rb CHANGED
@@ -18,7 +18,8 @@ module Env
18
18
 
19
19
  # :reek:UtilityFunction
20
20
  def env_bool_false(name)
21
- !(val = (name && ENV.fetch(name, nil))).nil? && !(val.empty? || val == '0')
21
+ !(val = (name && ENV.fetch(name,
22
+ nil))).nil? && !(val.empty? || val == '0')
22
23
  end
23
24
 
24
25
  # skip :reek:DataClump
data/lib/exceptions.rb ADDED
@@ -0,0 +1,34 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ # encoding=utf-8
5
+
6
+ module Exceptions
7
+ def self.error_handler(name = '', opts = {}, format_string: "\nError: %{name} -- %{message}", color_symbol: :red, take_count: 16)
8
+ warn(error = format(format_string,
9
+ { name: name, message: $! }).send(color_symbol))
10
+ warn($@.select do |s|
11
+ s.include? 'markdown_exec'
12
+ end.reject { |s| s.include? 'vendor' }.take(take_count).map.with_index { |line, ind| " * #{ind}: #{line}" })
13
+
14
+ binding.pry if $tap_enable
15
+ raise ArgumentError, error unless opts.fetch(:abort, true)
16
+
17
+ exit 1
18
+ end
19
+
20
+ def self.warn_format(message = '', opts = {})
21
+ warn(
22
+ error = format(
23
+ opts.fetch(:format_string, "\nError: %{error}"),
24
+ { error: message }
25
+ ).send(opts.fetch(:color_symbol, :yellow))
26
+ )
27
+ # warn(caller.take(4).map.with_index { |line, ind| " * #{ind}: #{line}" })
28
+
29
+ binding.pry if $tap_enable
30
+ raise ArgumentError, error unless opts.fetch(:abort, false)
31
+
32
+ exit 1
33
+ end
34
+ end
data/lib/fcb.rb CHANGED
@@ -19,6 +19,7 @@ module MarkdownExec
19
19
  call: nil,
20
20
  headings: [],
21
21
  dname: nil,
22
+ indent: '',
22
23
  name: nil,
23
24
  oname: nil,
24
25
  reqs: [],
@@ -29,6 +30,39 @@ module MarkdownExec
29
30
  }.merge(options)
30
31
  end
31
32
 
33
+ def title=(value)
34
+ @attrs[:title] = value
35
+ end
36
+
37
+ # Derives a title from the body of an FCB object.
38
+ # @param fcb [Object] The FCB object whose title is to be derived.
39
+ # @return [String] The derived title.
40
+ def derive_title_from_body
41
+ body_content = @attrs[:body]
42
+ unless body_content
43
+ @attrs[:title] = ''
44
+ return
45
+ end
46
+
47
+ @attrs[:title] = if body_content.count == 1
48
+ body_content.first
49
+ else
50
+ format_multiline_body_as_title(body_content)
51
+ end
52
+ end
53
+
54
+ private
55
+
56
+ # Formats multiline body content as a title string.
57
+ # indents all but first line with two spaces so it displays correctly in menu
58
+ # @param body_lines [Array<String>] The lines of body content.
59
+ # @return [String] Formatted title.
60
+ def format_multiline_body_as_title(body_lines)
61
+ body_lines.map.with_index do |line, index|
62
+ index.zero? ? line : " #{line}"
63
+ end.join("\n") << "\n"
64
+ end
65
+
32
66
  # :reek:ManualDispatch
33
67
  def method_missing(method, *args, &block)
34
68
  method_name = method.to_s
@@ -48,7 +82,9 @@ module MarkdownExec
48
82
  raise err # Here, we simply propagate the original error instead of wrapping it in a StandardError.
49
83
  end
50
84
 
51
- def respond_to_missing?(method_name, _include_private = false)
85
+ public
86
+
87
+ def respond_to_missing?(method_name, include_private = false)
52
88
  @attrs.key?(method_name.to_sym) || super
53
89
  end
54
90
 
@@ -63,6 +99,9 @@ module MarkdownExec
63
99
  end
64
100
 
65
101
  if $PROGRAM_NAME == __FILE__
102
+ require 'bundler/setup'
103
+ Bundler.require(:default)
104
+
66
105
  require 'minitest/autorun'
67
106
  require 'yaml'
68
107
 
@@ -73,6 +112,7 @@ if $PROGRAM_NAME == __FILE__
73
112
  call: 'Sample call',
74
113
  headings: %w[Header1 Header2],
75
114
  dname: 'Sample name',
115
+ indent: '',
76
116
  name: 'Sample name',
77
117
  oname: 'Sample name',
78
118
  reqs: %w[req1 req2],
data/lib/filter.rb CHANGED
@@ -38,14 +38,18 @@ module MarkdownExec
38
38
  name = fcb.oname
39
39
  shell = fcb.fetch(:shell, '')
40
40
 
41
+ ### filter in menu, not in source code
42
+ filters[:depth] =
43
+ fcb.fetch(:depth,
44
+ 0).positive? && !options[:menu_include_imported_blocks]
41
45
  apply_name_filters(options, filters, name)
42
46
  apply_shell_filters(options, filters, shell)
43
47
  apply_other_filters(options, filters, fcb)
44
48
 
45
49
  evaluate_filters(options, filters)
46
- rescue StandardError => err
47
- warn("ERROR ** Filter::fcb_select?(); #{err.inspect}")
48
- raise err
50
+ rescue StandardError
51
+ warn("ERROR ** Filter::fcb_select?(); #{$!.inspect}")
52
+ raise ArgumentError, $!
49
53
  end
50
54
 
51
55
  # Applies name-based filters to determine whether to include or
@@ -68,14 +72,16 @@ module MarkdownExec
68
72
  end
69
73
 
70
74
  if name.present? && filters[:name_select].nil? && options[:select_by_name_regex].present?
71
- filters[:name_select] = !!(name =~ /#{options[:select_by_name_regex]}/)
75
+ filters[:name_select] =
76
+ !!(name =~ /#{options[:select_by_name_regex]}/)
72
77
  end
73
78
 
74
79
  unless name.present? && filters[:name_exclude].nil? && options[:exclude_by_name_regex].present?
75
80
  return
76
81
  end
77
82
 
78
- filters[:name_exclude] = !!(name =~ /#{options[:exclude_by_name_regex]}/)
83
+ filters[:name_exclude] =
84
+ !!(name =~ /#{options[:exclude_by_name_regex]}/)
79
85
  end
80
86
 
81
87
  # Applies shell-based filters to determine whether to include or
@@ -90,12 +96,16 @@ module MarkdownExec
90
96
  filters[:shell_expect] = shell == 'expect'
91
97
 
92
98
  if shell.present? && options[:select_by_shell_regex].present?
93
- filters[:shell_select] = !!(shell =~ /#{options[:select_by_shell_regex]}/)
99
+ filters[:shell_select] =
100
+ !!(shell =~ /#{options[:select_by_shell_regex]}/)
94
101
  end
95
102
 
96
- return unless shell.present? && options[:exclude_by_shell_regex].present?
103
+ unless shell.present? && options[:exclude_by_shell_regex].present?
104
+ return
105
+ end
97
106
 
98
- filters[:shell_exclude] = !!(shell =~ /#{options[:exclude_by_shell_regex]}/)
107
+ filters[:shell_exclude] =
108
+ !!(shell =~ /#{options[:exclude_by_shell_regex]}/)
99
109
  end
100
110
 
101
111
  # Applies additional filters to determine whether to include or
@@ -138,7 +148,9 @@ module MarkdownExec
138
148
  # if it should be excluded.
139
149
  #
140
150
  def self.evaluate_filters(options, filters)
141
- if filters[:fcb_chrome] == true
151
+ if filters[:depth] == true
152
+ false
153
+ elsif filters[:fcb_chrome] == true
142
154
  !options[:no_chrome]
143
155
  elsif options[:exclude_expect_blocks] && filters[:shell_expect] == true
144
156
  false
@@ -160,15 +172,18 @@ module MarkdownExec
160
172
  end
161
173
  end
162
174
 
163
- # blocks for menu, without missing exit and back chrome
164
- # remove hidden blocks
175
+ # check if a block is not in the menu based on multiple match patterns
165
176
  #
166
- def self.prepared_not_in_menu?(options, fcb)
167
- fcb[:shell] == BlockType::BASH &&
168
- ((options[:block_name_include_match].present? &&
169
- fcb[:oname] =~ /#{options[:block_name_include_match]}/) ||
170
- (options[:block_name_wrapper_match].present? &&
171
- fcb[:oname] =~ /#{options[:block_name_wrapper_match]}/))
177
+ # @param options [Hash] Options hash containing various settings
178
+ # @param fcb [Hash] Hash representing a file code block
179
+ # @param match_patterns [Array<String>] Array of regular expression patterns for matching
180
+ # @return [Boolean] True if the block should not be in the menu, false otherwise
181
+ def self.prepared_not_in_menu?(options, fcb, match_patterns)
182
+ return false unless fcb[:shell] == BlockType::BASH
183
+
184
+ match_patterns.any? do |pattern|
185
+ options[pattern].present? && fcb[:oname] =~ /#{options[pattern]}/
186
+ end
172
187
  end
173
188
  end
174
189
  end
data/lib/fout.rb ADDED
@@ -0,0 +1,52 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ # encoding=utf-8
5
+
6
+ # stdout manager
7
+ #
8
+ # module FOut
9
+ class FOut
10
+ def initialize(config)
11
+ @config = config
12
+ end
13
+
14
+ def approved_fout?(level)
15
+ level <= fetch_display_level
16
+ end
17
+
18
+ # integer value for comparison
19
+ #
20
+ def fetch_display_level
21
+ @config.fetch(:display_level, 1)
22
+ end
23
+
24
+ # integer value for comparison
25
+ #
26
+ def fetch_display_level_xbase_prefix
27
+ @config.fetch(:level_xbase_prefix, '')
28
+ end
29
+
30
+ # standard output; not for debug
31
+ #
32
+ def fout(str)
33
+ puts str
34
+ end
35
+
36
+ def fout_list(str)
37
+ puts str
38
+ end
39
+
40
+ def fout_section(name, data)
41
+ puts "# #{name}"
42
+ puts data.to_yaml
43
+ end
44
+
45
+ # display output at level or lower than filter (DISPLAY_LEVEL_DEFAULT)
46
+ #
47
+ def lout(str, level: DISPLAY_LEVEL_BASE)
48
+ return unless approved_fout?(level)
49
+
50
+ fout level == DISPLAY_LEVEL_BASE ? str : fetch_display_level_xbase_prefix + str
51
+ end
52
+ end