markdown_exec 1.6 → 1.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +1 -1
- data/Gemfile.lock +1 -1
- data/Rakefile +1 -0
- data/bin/tab_completion.sh +2 -2
- data/examples/import0.md +41 -5
- data/examples/import1.md +9 -8
- data/examples/linked1.md +8 -4
- data/lib/array.rb +27 -0
- data/lib/array_util.rb +21 -0
- data/lib/cached_nested_file_reader.rb +51 -31
- data/lib/constants.rb +46 -0
- data/lib/env.rb +2 -1
- data/lib/exceptions.rb +34 -0
- data/lib/fcb.rb +41 -1
- data/lib/filter.rb +32 -17
- data/lib/fout.rb +52 -0
- data/lib/hash.rb +21 -0
- data/lib/hash_delegator.rb +2709 -0
- data/lib/markdown_exec/version.rb +1 -1
- data/lib/markdown_exec.rb +137 -1458
- data/lib/mdoc.rb +0 -3
- data/lib/menu.src.yml +137 -27
- data/lib/menu.yml +131 -23
- data/lib/method_sorter.rb +19 -17
- data/lib/object_present.rb +1 -1
- data/lib/option_value.rb +4 -2
- data/lib/pty1.rb +16 -16
- data/lib/regexp.rb +4 -5
- data/lib/saved_assets.rb +4 -2
- data/lib/saved_files_matcher.rb +7 -3
- data/lib/shared.rb +0 -5
- data/lib/string_util.rb +22 -0
- data/lib/tap.rb +5 -2
- metadata +10 -3
- data/lib/environment_opt_parse.rb +0 -209
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 97045160c53b7dca3998f6d700bf136f500826141d226f9f2cc650d15e6d1ba7
|
4
|
+
data.tar.gz: c69c23b07fcb3304d0209f79596619fbe54d0c2bb9a03f94c8598e3358c25ed7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a525dc3c727c38aba2d52382871650b6d2636891028a6def27f8958fcd78ae46afcb8fbbeb0f1bfdb0d550beb22c7cc90c67744c52143490f0a27c75c9158442
|
7
|
+
data.tar.gz: ae304dc41d17d2763a17b518da50956f0271ca401a4bc78929200eeb17ab3d19dfd148db76f104aed8216120c38673d19c9e56af018d3c9d83534c8901cc0915
|
data/.rubocop.yml
CHANGED
data/Gemfile.lock
CHANGED
data/Rakefile
CHANGED
data/bin/tab_completion.sh
CHANGED
@@ -13,7 +13,7 @@ __filedirs_all()
|
|
13
13
|
}
|
14
14
|
|
15
15
|
_mde_echo_version() {
|
16
|
-
echo "1.
|
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-
|
141
|
+
# echo "Updated: 2023-12-01 18:34:38 UTC"
|
data/examples/import0.md
CHANGED
@@ -1,8 +1,44 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
```
|
1
|
+
This is Page 0
|
2
|
+
|
4
3
|
@import import1.md
|
5
|
-
|
6
|
-
|
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
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
|
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
|
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
|
-
|
32
|
-
if
|
33
|
-
|
34
|
-
|
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,
|
63
|
+
File.join(directory_path, name_strip)
|
37
64
|
end
|
38
|
-
processed_lines += readlines(included_file_path,
|
65
|
+
processed_lines += readlines(included_file_path, depth + 1,
|
66
|
+
&block)
|
39
67
|
else
|
40
|
-
|
41
|
-
|
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
|
-
|
47
|
-
|
48
|
-
|
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
|
-
|
92
|
-
|
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
|
-
|
98
|
-
@reader.readlines(@file2.path)
|
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,
|
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
|
-
|
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
|
47
|
-
warn("ERROR ** Filter::fcb_select?(); #{
|
48
|
-
raise
|
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] =
|
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] =
|
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] =
|
99
|
+
filters[:shell_select] =
|
100
|
+
!!(shell =~ /#{options[:select_by_shell_regex]}/)
|
94
101
|
end
|
95
102
|
|
96
|
-
|
103
|
+
unless shell.present? && options[:exclude_by_shell_regex].present?
|
104
|
+
return
|
105
|
+
end
|
97
106
|
|
98
|
-
filters[:shell_exclude] =
|
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[:
|
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
|
-
#
|
164
|
-
# remove hidden blocks
|
175
|
+
# check if a block is not in the menu based on multiple match patterns
|
165
176
|
#
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
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
|