markdown_exec 2.3.0 → 2.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +11 -2
- data/CHANGELOG.md +19 -0
- data/Gemfile.lock +1 -1
- data/Rakefile +32 -8
- data/bats/bats.bats +33 -0
- data/bats/block-types.bats +56 -0
- data/bats/cli.bats +74 -0
- data/bats/fail.bats +11 -0
- data/bats/history.bats +34 -0
- data/bats/markup.bats +66 -0
- data/bats/mde.bats +29 -0
- data/bats/options.bats +92 -0
- data/bats/test_helper.bash +152 -0
- data/bin/tab_completion.sh +44 -20
- data/docs/dev/block-type-opts.md +10 -0
- data/docs/dev/block-type-port.md +24 -0
- data/docs/dev/block-type-vars.md +7 -0
- data/docs/dev/pass-through-arguments.md +8 -0
- data/docs/dev/specs-import.md +9 -0
- data/docs/dev/specs.md +83 -0
- data/docs/dev/text-decoration.md +7 -0
- data/examples/bash-blocks.md +4 -4
- data/examples/block-names.md +2 -2
- data/examples/import0.md +23 -0
- data/examples/import1.md +13 -0
- data/examples/link-blocks-vars.md +3 -3
- data/examples/opts-blocks-require.md +6 -6
- data/examples/table-markup.md +31 -0
- data/examples/text-markup.md +58 -0
- data/examples/vars-blocks.md +2 -2
- data/examples/wrap.md +87 -9
- data/lib/ansi_formatter.rb +12 -6
- data/lib/ansi_string.rb +153 -0
- data/lib/argument_processor.rb +160 -0
- data/lib/cached_nested_file_reader.rb +4 -2
- data/lib/ce_get_cost_and_usage.rb +4 -3
- data/lib/cli.rb +1 -1
- data/lib/colorize.rb +39 -11
- data/lib/constants.rb +17 -0
- data/lib/directory_searcher.rb +4 -2
- data/lib/doh.rb +190 -0
- data/lib/env.rb +1 -1
- data/lib/exceptions.rb +9 -6
- data/lib/fcb.rb +0 -199
- data/lib/filter.rb +18 -5
- data/lib/find_files.rb +8 -3
- data/lib/format_table.rb +406 -0
- data/lib/hash_delegator.rb +888 -603
- data/lib/hierarchy_string.rb +113 -25
- data/lib/input_sequencer.rb +16 -10
- data/lib/instance_method_wrapper.rb +2 -1
- data/lib/layered_hash.rb +143 -0
- data/lib/link_history.rb +22 -8
- data/lib/markdown_exec/version.rb +1 -1
- data/lib/markdown_exec.rb +413 -165
- data/lib/mdoc.rb +27 -34
- data/lib/menu.src.yml +825 -710
- data/lib/menu.yml +799 -703
- data/lib/namer.rb +6 -12
- data/lib/object_present.rb +1 -1
- data/lib/option_value.rb +7 -3
- data/lib/poly.rb +33 -14
- data/lib/resize_terminal.rb +60 -52
- data/lib/saved_assets.rb +45 -34
- data/lib/saved_files_matcher.rb +6 -3
- data/lib/streams_out.rb +7 -1
- data/lib/table_extractor.rb +166 -0
- data/lib/tap.rb +5 -6
- data/lib/text_analyzer.rb +144 -8
- metadata +26 -3
- data/lib/std_out_err_logger.rb +0 -119
data/lib/hierarchy_string.rb
CHANGED
@@ -1,12 +1,39 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require_relative 'ansi_string'
|
4
|
+
|
3
5
|
# Class representing a hierarchy of substrings stored as Hash nodes
|
6
|
+
# HierarchyString is a class that represents and manipulates strings based on a hierarchical structure.
|
7
|
+
# The input to the class can be a single hash or an array of nested hashes, where each hash contains a
|
8
|
+
# text string and an optional decoration or transformation (like `:downcase`, `:upcase`, etc.).
|
9
|
+
#
|
10
|
+
# The primary functionalities of the class include:
|
11
|
+
#
|
12
|
+
# - **Initialization**: The class can be initialized with either a single hash or an array of nested hashes.
|
13
|
+
# Each hash contains a @text_sym key representing the string and a @style_sym key representing the transformation
|
14
|
+
# (optional).
|
15
|
+
#
|
16
|
+
# - **Concatenation**: The `concatenate` method concatenates all text strings in the hierarchy into a single string.
|
17
|
+
#
|
18
|
+
# - **Decoration**: The `decorate` method applies the specified transformation (like `:downcase`, `:upcase`) to the
|
19
|
+
# text in the hierarchy and returns the decorated string.
|
20
|
+
#
|
21
|
+
# - **Text Replacement**: The `replace_text!` method allows in-place replacement of text in the hierarchy by applying
|
22
|
+
# a block to each text string.
|
23
|
+
#
|
24
|
+
# - **Method Delegation**: The class uses `method_missing` and `respond_to_missing?` to delegate undefined method calls
|
25
|
+
# to the string object, allowing for dynamic method handling on the concatenated string (e.g., `capitalize`).
|
26
|
+
#
|
27
|
+
# This class is useful for situations where strings are represented in a hierarchical or nested structure and need
|
28
|
+
# to be manipulated or transformed in a consistent and customizable manner.
|
4
29
|
class HierarchyString
|
5
30
|
attr_accessor :substrings
|
6
31
|
|
7
32
|
# Initialize with a single hash or an array of hashes
|
8
|
-
def initialize(substrings)
|
33
|
+
def initialize(substrings, text_sym: :text, style_sym: :color)
|
9
34
|
@substrings = parse_substrings(substrings)
|
35
|
+
@text_sym = text_sym
|
36
|
+
@style_sym = style_sym
|
10
37
|
end
|
11
38
|
|
12
39
|
def map_substring_text_yield(tree, &block)
|
@@ -21,8 +48,8 @@ class HierarchyString
|
|
21
48
|
end
|
22
49
|
end
|
23
50
|
when Hash
|
24
|
-
text = yield tree[
|
25
|
-
tree[
|
51
|
+
text = yield tree[@text_sym]
|
52
|
+
tree[@text_sym] = text
|
26
53
|
|
27
54
|
tree
|
28
55
|
when String
|
@@ -37,8 +64,8 @@ class HierarchyString
|
|
37
64
|
map_substring_text_yield(@substrings) do |node|
|
38
65
|
case node
|
39
66
|
when Hash
|
40
|
-
text = yield node[
|
41
|
-
node[
|
67
|
+
text = yield node[@text_sym]
|
68
|
+
node[@text_sym] = text
|
42
69
|
when String
|
43
70
|
yield node
|
44
71
|
end
|
@@ -89,7 +116,7 @@ class HierarchyString
|
|
89
116
|
substrings.map do |s|
|
90
117
|
case s
|
91
118
|
when Hash
|
92
|
-
s[
|
119
|
+
s[@text_sym]
|
93
120
|
when Array
|
94
121
|
concatenate_substrings(s)
|
95
122
|
end
|
@@ -101,10 +128,10 @@ class HierarchyString
|
|
101
128
|
substrings.map do |s|
|
102
129
|
case s
|
103
130
|
when Hash
|
104
|
-
if s[
|
105
|
-
s[
|
131
|
+
if s[@style_sym]
|
132
|
+
AnsiString.new(s[@text_sym]).send(s[@style_sym]) + prior_color
|
106
133
|
else
|
107
|
-
s[
|
134
|
+
s[@text_sym]
|
108
135
|
end
|
109
136
|
when Array
|
110
137
|
decorate_substrings(s, prior_color)
|
@@ -115,19 +142,80 @@ end
|
|
115
142
|
|
116
143
|
return if $PROGRAM_NAME != __FILE__
|
117
144
|
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
145
|
+
require 'minitest/autorun'
|
146
|
+
|
147
|
+
class TestHierarchyString < Minitest::Test
|
148
|
+
def setup
|
149
|
+
text_sym = :text
|
150
|
+
style_sym = :color
|
151
|
+
|
152
|
+
@single_hash = { text_sym => 'Hello', style_sym => :downcase }
|
153
|
+
@nested_hashes = [
|
154
|
+
{ text_sym => 'Hello', style_sym => :downcase },
|
155
|
+
[
|
156
|
+
{ text_sym => ' ', style_sym => nil },
|
157
|
+
{ text_sym => 'World', style_sym => :upcase }
|
158
|
+
]
|
159
|
+
]
|
160
|
+
@hierarchy_single = HierarchyString.new(@single_hash)
|
161
|
+
@hierarchy_nested = HierarchyString.new(@nested_hashes)
|
162
|
+
end
|
163
|
+
|
164
|
+
def test_initialize_single_hash
|
165
|
+
text_sym = :text
|
166
|
+
style_sym = :color
|
167
|
+
|
168
|
+
assert_equal [{ text_sym => 'Hello', style_sym => :downcase }],
|
169
|
+
@hierarchy_single.substrings
|
170
|
+
end
|
171
|
+
|
172
|
+
def test_initialize_nested_hashes
|
173
|
+
text_sym = :text
|
174
|
+
style_sym = :color
|
175
|
+
|
176
|
+
expected = [
|
177
|
+
[{ text_sym => 'Hello', style_sym => :downcase }],
|
178
|
+
[
|
179
|
+
[{ text_sym => ' ', style_sym => nil }],
|
180
|
+
[{ text_sym => 'World', style_sym => :upcase }]
|
181
|
+
]
|
182
|
+
]
|
183
|
+
assert_equal expected, @hierarchy_nested.substrings
|
184
|
+
end
|
185
|
+
|
186
|
+
def test_concatenate_single_hash
|
187
|
+
assert_equal 'Hello', @hierarchy_single.concatenate
|
188
|
+
end
|
189
|
+
|
190
|
+
def test_concatenate_nested_hashes
|
191
|
+
assert_equal 'Hello World', @hierarchy_nested.concatenate
|
192
|
+
end
|
193
|
+
|
194
|
+
def test_decorate_single_hash
|
195
|
+
assert_equal 'Hello'.downcase, @hierarchy_single.decorate
|
196
|
+
end
|
197
|
+
|
198
|
+
def test_decorate_nested_hashes
|
199
|
+
assert_equal "#{'Hello'.downcase} #{'World'.upcase}",
|
200
|
+
@hierarchy_nested.decorate
|
201
|
+
end
|
202
|
+
|
203
|
+
def test_replace_text_single_hash
|
204
|
+
@hierarchy_single.replace_text!(&:upcase)
|
205
|
+
assert_equal 'HELLO', @hierarchy_single.concatenate
|
206
|
+
end
|
207
|
+
|
208
|
+
def test_replace_text_nested_hashes
|
209
|
+
@hierarchy_nested.replace_text!(&:upcase)
|
210
|
+
assert_equal 'HELLO WORLD', @hierarchy_nested.concatenate
|
211
|
+
end
|
212
|
+
|
213
|
+
def test_method_missing
|
214
|
+
assert_equal 'Hello', @hierarchy_single.capitalize
|
215
|
+
end
|
216
|
+
|
217
|
+
def test_respond_to_missing
|
218
|
+
assert @hierarchy_single.respond_to?(:capitalize)
|
219
|
+
refute @hierarchy_single.respond_to?(:non_existent_method)
|
220
|
+
end
|
221
|
+
end
|
data/lib/input_sequencer.rb
CHANGED
@@ -47,11 +47,16 @@ class InputSequencer
|
|
47
47
|
|
48
48
|
# Generates the next menu state based on provided attributes.
|
49
49
|
|
50
|
-
def self.next_link_state(
|
50
|
+
def self.next_link_state(
|
51
|
+
block_name: nil, display_menu: nil, document_filename: nil,
|
52
|
+
inherited_lines: nil, keep_code: false, prior_block_was_link: false
|
53
|
+
)
|
51
54
|
MarkdownExec::LinkState.new(
|
52
55
|
block_name: block_name,
|
53
56
|
display_menu: display_menu,
|
54
57
|
document_filename: document_filename,
|
58
|
+
inherited_lines: inherited_lines,
|
59
|
+
keep_code: keep_code,
|
55
60
|
prior_block_was_link: prior_block_was_link
|
56
61
|
)
|
57
62
|
end
|
@@ -59,6 +64,8 @@ class InputSequencer
|
|
59
64
|
# Orchestrates the flow of menu states and user interactions.
|
60
65
|
def run_yield(sym, *args, &block)
|
61
66
|
block.call sym, *args
|
67
|
+
rescue AppInterrupt
|
68
|
+
raise
|
62
69
|
# rubocop:disable Style/RescueStandardError
|
63
70
|
rescue
|
64
71
|
pp $!, $@
|
@@ -91,17 +98,17 @@ class InputSequencer
|
|
91
98
|
run_yield :display_menu, &block
|
92
99
|
|
93
100
|
choice = run_yield :user_choice, &block
|
101
|
+
break if choice == :break
|
94
102
|
|
95
|
-
raise 'Block not recognized.' if choice.nil?
|
103
|
+
raise BlockMissing, 'Block not recognized.' if choice.nil?
|
96
104
|
# Exit loop and method to terminate the app
|
97
|
-
break if run_yield(:exit?, choice&.downcase, &block)
|
105
|
+
break if run_yield(:exit?, choice&.to_s.downcase, &block)
|
98
106
|
|
99
107
|
next_state = run_yield :execute_block, choice, &block
|
100
108
|
# imw_ins next_state, 'next_state'
|
101
|
-
|
109
|
+
break if next_state == :break
|
102
110
|
|
103
111
|
next_menu = next_state
|
104
|
-
|
105
112
|
else
|
106
113
|
if now_menu.block_name && !now_menu.block_name.empty?
|
107
114
|
block_name = now_menu.block_name
|
@@ -117,6 +124,8 @@ class InputSequencer
|
|
117
124
|
InputSequencer.next_link_state(display_menu: true)
|
118
125
|
else
|
119
126
|
state = run_yield :execute_block, block_name, &block
|
127
|
+
break if state == :break
|
128
|
+
|
120
129
|
state.display_menu = bq_is_empty?
|
121
130
|
state
|
122
131
|
end
|
@@ -125,11 +134,8 @@ class InputSequencer
|
|
125
134
|
end
|
126
135
|
now_menu = InputSequencer.merge_link_state(now_menu, next_menu)
|
127
136
|
end
|
128
|
-
|
129
|
-
|
130
|
-
pp $!, $@
|
131
|
-
exit 1
|
132
|
-
# rubocop:enable Style/RescueStandardError
|
137
|
+
|
138
|
+
run_yield :close_ux, &block
|
133
139
|
end
|
134
140
|
end
|
135
141
|
|
@@ -68,7 +68,8 @@ module InstanceMethodWrapper
|
|
68
68
|
|
69
69
|
def self.prepended(base)
|
70
70
|
base.instance_methods(false).each do |method_name|
|
71
|
-
wrap_method(base,
|
71
|
+
wrap_method(base,
|
72
|
+
method_name) unless %i[method_missing].include? method_name
|
72
73
|
end
|
73
74
|
|
74
75
|
base.singleton_class.send(:define_method, :method_added) do |method_name|
|
data/lib/layered_hash.rb
ADDED
@@ -0,0 +1,143 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
# encoding=utf-8
|
5
|
+
|
6
|
+
class LayeredHash
|
7
|
+
def initialize(table = {}, layers: %i[main])
|
8
|
+
@layers = layers.map { |layer| [layer, {}] }.to_h
|
9
|
+
@current_layer = layers.first
|
10
|
+
@layers[@current_layer] = table
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def method_missing(method, *args, &block)
|
16
|
+
method_name = method.to_s
|
17
|
+
if @layers.respond_to?(method_name)
|
18
|
+
@layers.send(method_name, *args, &block)
|
19
|
+
elsif method_name[-1] == '='
|
20
|
+
@layers[method_name.chop.to_sym] = args[0]
|
21
|
+
elsif @layers.respond_to?(method_name)
|
22
|
+
@layers.send(method_name, *args)
|
23
|
+
else
|
24
|
+
@layers[method_name.to_sym]
|
25
|
+
end
|
26
|
+
rescue StandardError => err
|
27
|
+
warn("ERROR ** LayeredHash.method_missing(method: #{method_name}," \
|
28
|
+
" *args: #{args.inspect}, &block)")
|
29
|
+
warn err.inspect
|
30
|
+
warn(caller[0..4])
|
31
|
+
raise err
|
32
|
+
end
|
33
|
+
|
34
|
+
public
|
35
|
+
|
36
|
+
# Retrieves the value of a key from the current layer using hash notation
|
37
|
+
def [](key)
|
38
|
+
raise "Current layer not set" unless @current_layer
|
39
|
+
|
40
|
+
get_from_layer(@current_layer, key)
|
41
|
+
end
|
42
|
+
|
43
|
+
# Sets a key-value pair in the current layer using hash notation
|
44
|
+
def []=(key, value)
|
45
|
+
raise "Current layer not set" unless @current_layer
|
46
|
+
|
47
|
+
set(@current_layer, key, value)
|
48
|
+
end
|
49
|
+
|
50
|
+
def fetch(key, *args)
|
51
|
+
key_sym = key.to_sym
|
52
|
+
if respond_to?("get_#{key}")
|
53
|
+
send("get_#{key}")
|
54
|
+
# elsif @table.key?(key_sym)
|
55
|
+
elsif @layers[@current_layer].key?(key_sym)
|
56
|
+
# @table[key_sym]
|
57
|
+
@layers[@current_layer][key_sym]
|
58
|
+
elsif block_given?
|
59
|
+
yield key_sym
|
60
|
+
elsif args.count.positive?
|
61
|
+
args.first
|
62
|
+
else
|
63
|
+
binding.irb
|
64
|
+
raise KeyError, "key not found: #{key}"
|
65
|
+
end.tap { |ret|
|
66
|
+
pp([__LINE__, "Poly.fetch #{key} #{args}", '->',
|
67
|
+
ret]) if $pd
|
68
|
+
}
|
69
|
+
end
|
70
|
+
|
71
|
+
# Retrieves the value of a key from the highest priority layer that has a value
|
72
|
+
def get(key)
|
73
|
+
@layers.reverse_each do |_, hash|
|
74
|
+
return hash[key] if hash.key?(key)
|
75
|
+
end
|
76
|
+
nil
|
77
|
+
end
|
78
|
+
|
79
|
+
# Retrieves the value of a key from the specified layer
|
80
|
+
def get_from_layer(layer, key)
|
81
|
+
if @layers.key?(layer)
|
82
|
+
@layers[layer][key]
|
83
|
+
else
|
84
|
+
raise ArgumentError, "Layer #{layer} does not exist"
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def merge(*args)
|
89
|
+
@layers.merge(*args).tap { |ret|
|
90
|
+
pp([__LINE__, "LayeredHash.merge", '->', ret]) if $pd
|
91
|
+
}
|
92
|
+
end
|
93
|
+
|
94
|
+
def respond_to_missing?(method_name, include_private = false)
|
95
|
+
@layers.key?(method_name.to_sym) || super
|
96
|
+
end
|
97
|
+
|
98
|
+
# Sets a key-value pair in the specified layer
|
99
|
+
def set(layer, key, value)
|
100
|
+
if @layers.key?(layer)
|
101
|
+
@layers[layer][key] = value
|
102
|
+
else
|
103
|
+
raise ArgumentError, "Layer #{layer} does not exist"
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
# Sets the current layer for use with hash notation ([])
|
108
|
+
def set_current_layer(layer)
|
109
|
+
if @layers.key?(layer)
|
110
|
+
@current_layer = layer
|
111
|
+
else
|
112
|
+
raise ArgumentError, "Layer #{layer} does not exist"
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
def to_h
|
117
|
+
@layers.to_h
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
return if $PROGRAM_NAME != __FILE__
|
122
|
+
|
123
|
+
layered_hash = LayeredHash.new(layers: %i[low high])
|
124
|
+
|
125
|
+
# Set current layer
|
126
|
+
layered_hash.set_current_layer(:low)
|
127
|
+
|
128
|
+
# Set values in the current layer using hash notation
|
129
|
+
layered_hash[:key1] = 'low_value'
|
130
|
+
layered_hash[:key2] = 'low_only_value'
|
131
|
+
|
132
|
+
# Switch current layer
|
133
|
+
layered_hash.set_current_layer(:high)
|
134
|
+
|
135
|
+
# Set values in the new current layer using hash notation
|
136
|
+
layered_hash[:key1] = 'high_value'
|
137
|
+
|
138
|
+
# Get value from the specific current layer using hash notation
|
139
|
+
puts layered_hash[:key1] # Output: 'high_value'
|
140
|
+
|
141
|
+
# Get value from the highest priority layer
|
142
|
+
puts layered_hash.get(:key1) # Output: 'high_value'
|
143
|
+
puts layered_hash.get(:key2) # Output: 'low_only_value'
|
data/lib/link_history.rb
CHANGED
@@ -9,7 +9,7 @@ module MarkdownExec
|
|
9
9
|
class LinkState
|
10
10
|
attr_accessor :block_name, :display_menu, :document_filename,
|
11
11
|
:inherited_block_names, :inherited_dependencies,
|
12
|
-
:prior_block_was_link
|
12
|
+
:keep_code, :prior_block_was_link
|
13
13
|
|
14
14
|
# Initialize the LinkState with keyword arguments for each attribute.
|
15
15
|
# @param block_name [String, nil] the name of the block.
|
@@ -19,13 +19,14 @@ module MarkdownExec
|
|
19
19
|
# @param inherited_lines [Array<String>, nil] the inherited lines of code.
|
20
20
|
def initialize(block_name: nil, display_menu: nil, document_filename: nil,
|
21
21
|
inherited_block_names: [], inherited_dependencies: nil, inherited_lines: nil,
|
22
|
-
prior_block_was_link: nil)
|
22
|
+
keep_code: false, prior_block_was_link: nil)
|
23
23
|
@block_name = block_name
|
24
24
|
@display_menu = display_menu
|
25
25
|
@document_filename = document_filename
|
26
26
|
@inherited_block_names = inherited_block_names
|
27
27
|
@inherited_dependencies = inherited_dependencies
|
28
28
|
@inherited_lines = inherited_lines
|
29
|
+
@keep_code = keep_code
|
29
30
|
@prior_block_was_link = prior_block_was_link
|
30
31
|
end
|
31
32
|
|
@@ -46,27 +47,38 @@ module MarkdownExec
|
|
46
47
|
other.inherited_block_names == inherited_block_names &&
|
47
48
|
other.inherited_dependencies == inherited_dependencies &&
|
48
49
|
other.inherited_lines == inherited_lines &&
|
50
|
+
other.keep_code == keep_code &&
|
49
51
|
other.prior_block_was_link == prior_block_was_link
|
50
52
|
end
|
51
53
|
|
52
54
|
def inherited_lines
|
53
|
-
@inherited_lines.tap { |ret|
|
55
|
+
@inherited_lines.tap { |ret|
|
56
|
+
pp ['LinkState.inherited_lines() ->', ret] if $pd
|
57
|
+
}
|
54
58
|
end
|
55
59
|
|
56
60
|
def inherited_lines=(value)
|
57
|
-
@inherited_lines = value.tap { |ret|
|
61
|
+
@inherited_lines = value.tap { |ret|
|
62
|
+
pp ['LinkState.inherited_lines=() ->', ret] if $pd
|
63
|
+
}
|
58
64
|
end
|
59
65
|
|
60
66
|
def inherited_lines_append(value)
|
61
|
-
@inherited_lines = ((@inherited_lines || []) + value).tap { |ret|
|
67
|
+
@inherited_lines = ((@inherited_lines || []) + value).tap { |ret|
|
68
|
+
pp ['LinkState.inherited_lines_append() ->', ret] if $pd
|
69
|
+
}
|
62
70
|
end
|
63
71
|
|
64
72
|
def inherited_lines_block
|
65
|
-
@inherited_lines.join("\n").tap { |ret|
|
73
|
+
(@inherited_lines || []).join("\n").tap { |ret|
|
74
|
+
pp ['LinkState.inherited_lines_block() ->', ret] if $pd
|
75
|
+
}
|
66
76
|
end
|
67
77
|
|
68
78
|
def inherited_lines_count
|
69
|
-
(@inherited_lines&.count || 0).tap { |ret|
|
79
|
+
(@inherited_lines&.count || 0).tap { |ret|
|
80
|
+
pp ['LinkState.inherited_lines_count() ->', ret] if $pd
|
81
|
+
}
|
70
82
|
end
|
71
83
|
|
72
84
|
def inherited_lines_map
|
@@ -76,7 +88,9 @@ module MarkdownExec
|
|
76
88
|
end
|
77
89
|
|
78
90
|
def inherited_lines_present?
|
79
|
-
@inherited_lines.present?.tap { |ret|
|
91
|
+
@inherited_lines.present?.tap { |ret|
|
92
|
+
pp ['LinkState.inherited_lines_present?() ->', ret] if $pd
|
93
|
+
}
|
80
94
|
end
|
81
95
|
end
|
82
96
|
|