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 +4 -4
- data/.rubocop.yml +5 -2
- data/Gemfile.lock +1 -1
- data/Rakefile +2 -0
- data/bin/tab_completion.sh +19 -3
- data/examples/colors.md +48 -0
- data/examples/import0.md +41 -5
- data/examples/import1.md +9 -8
- data/examples/include.md +11 -4
- data/examples/linked1.md +8 -4
- data/examples/opts.md +7 -0
- data/lib/ansi_formatter.rb +161 -0
- 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/directory_searcher.rb +239 -0
- 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 +2796 -0
- data/lib/markdown_exec/version.rb +1 -1
- data/lib/markdown_exec.rb +190 -1474
- data/lib/mdoc.rb +148 -36
- data/lib/menu.src.yml +224 -37
- data/lib/menu.yml +209 -33
- data/lib/method_sorter.rb +19 -17
- data/lib/object_present.rb +1 -1
- data/lib/pty1.rb +16 -16
- data/lib/regexp.rb +2 -4
- data/lib/shared.rb +0 -5
- data/lib/string_util.rb +22 -0
- metadata +13 -3
- data/lib/environment_opt_parse.rb +0 -209
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
|
@@ -0,0 +1,239 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
# encoding=utf-8
|
5
|
+
|
6
|
+
require 'find'
|
7
|
+
|
8
|
+
# Formats and highlights a list of dependencies. Dependencies are presented with indentation,
|
9
|
+
# and specific items can be highlighted in a specified color, while others are shown in a plain color.
|
10
|
+
#
|
11
|
+
# @param dependencies [Hash] A hash of dependencies, where each key is a dependency name,
|
12
|
+
# and its value is an array of sub-items.
|
13
|
+
# @param highlight_color_sym [Symbol] The color method to apply to highlighted items.
|
14
|
+
# Default is :exception_color_detail.
|
15
|
+
# @param plain_color_sym [Symbol] The color method for non-highlighted items.
|
16
|
+
# Default is :menu_chrome_color.
|
17
|
+
# @param label [String] The label to prefix the list of dependencies with.
|
18
|
+
# Default is 'Dependencies:'.
|
19
|
+
# @param highlight [Array] An array of items to highlight. Each item in this array will be
|
20
|
+
# formatted with the specified highlight color.
|
21
|
+
# @param line_prefix [String] Prefix for each line. Default is ' '.
|
22
|
+
# @param line_postfix [String] Postfix for each line. Default is ''.
|
23
|
+
# @param detail_sep [String] Separator for items in the sub-list. Default is ' '.
|
24
|
+
# @return [String] A formatted string representation of the dependencies with highlighted items.
|
25
|
+
def format_and_highlight_dependencies(
|
26
|
+
dependencies,
|
27
|
+
highlight_color_sym: :exception_color_detail,
|
28
|
+
plain_color_sym: :menu_chrome_color,
|
29
|
+
label: 'Dependencies:',
|
30
|
+
highlight: [],
|
31
|
+
line_prefix: ' ',
|
32
|
+
line_postfix: '',
|
33
|
+
detail_sep: ' '
|
34
|
+
)
|
35
|
+
formatted_deps = dependencies&.map do |dep_name, sub_items|
|
36
|
+
formatted_sub_items = sub_items.map do |item|
|
37
|
+
color_sym = highlight.include?(item) ? highlight_color_sym : plain_color_sym
|
38
|
+
string_send_color(item, color_sym)
|
39
|
+
end.join(detail_sep)
|
40
|
+
|
41
|
+
"#{line_prefix}- #{string_send_color(dep_name,
|
42
|
+
highlight.include?(dep_name) ? highlight_color_sym : plain_color_sym)}: #{formatted_sub_items}#{line_postfix}"
|
43
|
+
end || []
|
44
|
+
|
45
|
+
"#{line_prefix}#{string_send_color(label,
|
46
|
+
highlight_color_sym)}#{line_postfix}\n" + formatted_deps.join("\n")
|
47
|
+
end
|
48
|
+
# warn menu_blocks.to_yaml.sub(/^(?:---\n)?/, "MenuBlocks:\n")
|
49
|
+
|
50
|
+
IndexedLine = Struct.new(:index, :line) do
|
51
|
+
def to_s
|
52
|
+
line
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
# Class DirectorySearcher
|
57
|
+
# This class provides methods to search for a specified pattern
|
58
|
+
# in directory names, file names, and contents of files within given paths.
|
59
|
+
class DirectorySearcher
|
60
|
+
attr_reader :pattern, :paths, :include_subdirectories, :filename_glob
|
61
|
+
|
62
|
+
# Constructor
|
63
|
+
# @param pattern [Regexp] The regular expression pattern to search for.
|
64
|
+
# @param paths [Array<String>] List of directories to search in.
|
65
|
+
# @param include_subdirectories [Boolean] Whether to search in subdirectories.
|
66
|
+
# @param filename_glob [String, nil] Glob pattern for file names.
|
67
|
+
def initialize(pattern, paths, include_subdirectories: true, filename_glob: '*.[Mm][Dd]') #'*.md'
|
68
|
+
@pattern = pattern
|
69
|
+
@paths = paths
|
70
|
+
@include_subdirectories = include_subdirectories
|
71
|
+
@filename_glob = filename_glob
|
72
|
+
end
|
73
|
+
|
74
|
+
# Searches for the pattern in directory names.
|
75
|
+
# @return [Array<String>] List of matching directory names.
|
76
|
+
def search_in_directory_names
|
77
|
+
match_dirs = []
|
78
|
+
@paths.each do |path|
|
79
|
+
Find.find(path) do |p|
|
80
|
+
# p 'search_in_directory_names', p
|
81
|
+
# Find.prune unless @include_subdirectories || path == p
|
82
|
+
match_dirs << p if File.directory?(p) && p.match?(@pattern)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
match_dirs
|
86
|
+
end
|
87
|
+
|
88
|
+
# Searches for the pattern in file names.
|
89
|
+
# @return [Array<String>] List of matching file names.
|
90
|
+
def search_in_file_names
|
91
|
+
match_files = []
|
92
|
+
@paths.each do |path|
|
93
|
+
Find.find(path) do |p|
|
94
|
+
# Find.prune unless @include_subdirectories || path == p
|
95
|
+
next unless File.file?(p)
|
96
|
+
|
97
|
+
file_name = File.basename(p)
|
98
|
+
next if @filename_glob && !File.fnmatch(@filename_glob, file_name)
|
99
|
+
|
100
|
+
begin
|
101
|
+
match_files << p if file_name.encode('UTF-8', invalid: :replace, undef: :replace,
|
102
|
+
replace: '').match?(@pattern)
|
103
|
+
rescue EncodingError
|
104
|
+
# Optionally log the file with encoding issues
|
105
|
+
# puts "Encoding error in file: #{p}"
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
match_files
|
110
|
+
end
|
111
|
+
|
112
|
+
# Searches for the pattern in the contents of the files and returns matches along with their file paths and line numbers.
|
113
|
+
# @return [Hash] A hash where each key is a file path and each value is an array of hashes with :line_number and :line keys.
|
114
|
+
def search_in_file_contents
|
115
|
+
match_details = {}
|
116
|
+
|
117
|
+
@paths.each do |path|
|
118
|
+
Find.find(path) do |p|
|
119
|
+
Find.prune unless @include_subdirectories || path == p
|
120
|
+
next unless File.file?(p)
|
121
|
+
|
122
|
+
next if @filename_glob && !File.fnmatch(@filename_glob, File.basename(p))
|
123
|
+
|
124
|
+
begin
|
125
|
+
File.foreach(p).with_index(1) do |line, line_num| # Index starts from 1 for line numbers
|
126
|
+
line_utf8 = line.encode('UTF-8', invalid: :replace, undef: :replace, replace: '')
|
127
|
+
if line_utf8.match?(@pattern)
|
128
|
+
match_details[p] ||= []
|
129
|
+
# match_details[p] << { number: line_num, line: line_utf8.chomp }
|
130
|
+
match_details[p] << IndexedLine.new(line_num, line_utf8.chomp)
|
131
|
+
end
|
132
|
+
end
|
133
|
+
rescue EncodingError
|
134
|
+
# Optionally log the file with encoding issues
|
135
|
+
# puts "Encoding error in file: #{p}"
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
match_details
|
141
|
+
end
|
142
|
+
|
143
|
+
# # Searches for the pattern in the contents of the files.
|
144
|
+
# # @return [Array<String>] List of matching lines from files.
|
145
|
+
# def search_in_file_contents
|
146
|
+
# match_lines = []
|
147
|
+
# @paths.each do |path|
|
148
|
+
# Find.find(path) do |p|
|
149
|
+
# Find.prune unless @include_subdirectories || path == p
|
150
|
+
# next unless File.file?(p)
|
151
|
+
|
152
|
+
# next if @filename_glob && !File.fnmatch(@filename_glob, File.basename(p))
|
153
|
+
|
154
|
+
# begin
|
155
|
+
# File.foreach(p).with_index do |line, _line_num|
|
156
|
+
# line_utf8 = line.encode('UTF-8', invalid: :replace, undef: :replace, replace: '')
|
157
|
+
# match_lines << line_utf8.chomp if line_utf8.match?(@pattern)
|
158
|
+
# end
|
159
|
+
# rescue EncodingError
|
160
|
+
# # Optionally log the file with encoding issues
|
161
|
+
# # puts "Encoding error in file: #{p}"
|
162
|
+
# end
|
163
|
+
# end
|
164
|
+
# end
|
165
|
+
# match_lines
|
166
|
+
# end
|
167
|
+
end
|
168
|
+
|
169
|
+
if $PROGRAM_NAME == __FILE__
|
170
|
+
require 'bundler/setup'
|
171
|
+
Bundler.require(:default)
|
172
|
+
|
173
|
+
require 'minitest/autorun'
|
174
|
+
# require 'mocha/minitest'
|
175
|
+
# require_relative 'directory_searcher'
|
176
|
+
|
177
|
+
# Test class for DirectorySearcher
|
178
|
+
class DirectorySearcherTest < Minitest::Test
|
179
|
+
# Setup method to initialize common test data
|
180
|
+
def setup
|
181
|
+
@pattern = /test_pattern/
|
182
|
+
@paths = ['./spec']
|
183
|
+
@searcher = DirectorySearcher.new(@pattern, @paths)
|
184
|
+
end
|
185
|
+
|
186
|
+
# Test search_in_directory_names method
|
187
|
+
def test_search_in_directory_names
|
188
|
+
# Add assertions based on your test directory structure and expected results
|
189
|
+
assert_equal [], @searcher.search_in_directory_names
|
190
|
+
end
|
191
|
+
|
192
|
+
# Test search_in_file_names method
|
193
|
+
def test_search_in_file_names
|
194
|
+
# Add assertions based on your test directory structure and expected results
|
195
|
+
assert_equal [], @searcher.search_in_file_names
|
196
|
+
end
|
197
|
+
|
198
|
+
# Test search_in_file_contents method
|
199
|
+
def test_search_in_file_contents
|
200
|
+
# Add assertions based on your test directory structure and expected results
|
201
|
+
assert_equal ({}), @searcher.search_in_file_contents
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
# Test class for DirectorySearcher
|
206
|
+
class DirectorySearcherTest2 < Minitest::Test
|
207
|
+
# Setup method to initialize common test data
|
208
|
+
def setup
|
209
|
+
@pattern_spec = /spec/
|
210
|
+
@paths = ['./spec']
|
211
|
+
@filename_glob = nil
|
212
|
+
@searcher_spec = DirectorySearcher.new(@pattern_spec, @paths,
|
213
|
+
filename_glob: @filename_glob)
|
214
|
+
end
|
215
|
+
|
216
|
+
# Test search_in_directory_names method for 'spec'
|
217
|
+
def test_search_in_directory_names_for_spec
|
218
|
+
# Replace with actual expected directory names containing 'spec'
|
219
|
+
expected_dirs = ['./spec']
|
220
|
+
assert_equal expected_dirs, @searcher_spec.search_in_directory_names
|
221
|
+
end
|
222
|
+
|
223
|
+
# Test search_in_file_names method for 'spec'
|
224
|
+
def test_search_in_file_names_for_spec
|
225
|
+
# Replace with actual expected file names containing 'spec'
|
226
|
+
expected_files = ['./spec/cli_spec.rb', './spec/env_spec.rb',
|
227
|
+
'./spec/markdown_exec_spec.rb', './spec/tap_spec.rb']
|
228
|
+
assert_equal expected_files, @searcher_spec.search_in_file_names
|
229
|
+
end
|
230
|
+
|
231
|
+
# # Test search_in_file_contents method for 'spec'
|
232
|
+
# def test_search_in_file_contents_for_spec
|
233
|
+
# # Replace with actual expected lines containing 'spec'
|
234
|
+
# expected_lines = {['Line with spec 1', 'Line with spec 2']}
|
235
|
+
# assert_equal expected_lines, @searcher_spec.search_in_file_contents
|
236
|
+
# end
|
237
|
+
end
|
238
|
+
|
239
|
+
end
|
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
|
data/lib/hash.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
# encoding=utf-8
|
5
|
+
|
6
|
+
# hash with keys sorted by name
|
7
|
+
# add Hash.sym_keys
|
8
|
+
#
|
9
|
+
class Hash
|
10
|
+
unless defined?(sort_by_key)
|
11
|
+
def sort_by_key
|
12
|
+
keys.sort.to_h { |key| [key, self[key]] }
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
unless defined?(sym_keys)
|
17
|
+
def sym_keys
|
18
|
+
transform_keys(&:to_sym)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|