markdown_exec 2.3.0 → 2.4.0
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 +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
|
|