markdown_exec 2.2.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 +16 -4
- data/CHANGELOG.md +28 -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 +40 -5
- 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 +41 -0
- 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 +939 -611
- data/lib/hierarchy_string.rb +221 -0
- data/lib/input_sequencer.rb +19 -11
- 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 +420 -165
- data/lib/mdoc.rb +38 -38
- data/lib/menu.src.yml +832 -680
- data/lib/menu.yml +814 -689
- 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 +236 -0
- metadata +28 -3
- data/lib/std_out_err_logger.rb +0 -119
@@ -0,0 +1,221 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'ansi_string'
|
4
|
+
|
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.
|
29
|
+
class HierarchyString
|
30
|
+
attr_accessor :substrings
|
31
|
+
|
32
|
+
# Initialize with a single hash or an array of hashes
|
33
|
+
def initialize(substrings, text_sym: :text, style_sym: :color)
|
34
|
+
@substrings = parse_substrings(substrings)
|
35
|
+
@text_sym = text_sym
|
36
|
+
@style_sym = style_sym
|
37
|
+
end
|
38
|
+
|
39
|
+
def map_substring_text_yield(tree, &block)
|
40
|
+
case tree
|
41
|
+
when Array
|
42
|
+
tree.each.with_index do |node, ind|
|
43
|
+
case node
|
44
|
+
when String
|
45
|
+
tree[ind] = yield node
|
46
|
+
else
|
47
|
+
map_substring_text_yield(node, &block)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
when Hash
|
51
|
+
text = yield tree[@text_sym]
|
52
|
+
tree[@text_sym] = text
|
53
|
+
|
54
|
+
tree
|
55
|
+
when String
|
56
|
+
yield tree
|
57
|
+
else
|
58
|
+
raise ArgumentError, 'Invalid type.'
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
# operate on substring
|
63
|
+
def replace_text!
|
64
|
+
map_substring_text_yield(@substrings) do |node|
|
65
|
+
case node
|
66
|
+
when Hash
|
67
|
+
text = yield node[@text_sym]
|
68
|
+
node[@text_sym] = text
|
69
|
+
when String
|
70
|
+
yield node
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
# Method to concatenate all substrings into a single string
|
76
|
+
def concatenate
|
77
|
+
concatenate_substrings(@substrings)
|
78
|
+
end
|
79
|
+
|
80
|
+
# Method to decorate all substrings into a single string
|
81
|
+
def decorate
|
82
|
+
decorate_substrings(@substrings)
|
83
|
+
end
|
84
|
+
|
85
|
+
# Handle string inspection methods and pass them to the concatenated string
|
86
|
+
def method_missing(method_name, *arguments, &block)
|
87
|
+
if ''.respond_to?(method_name)
|
88
|
+
concatenate.send(method_name, *arguments, &block)
|
89
|
+
else
|
90
|
+
super
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
# Ensure proper handling of method checks
|
95
|
+
def respond_to_missing?(method_name, include_private = false)
|
96
|
+
''.respond_to?(method_name) || super
|
97
|
+
end
|
98
|
+
|
99
|
+
private
|
100
|
+
|
101
|
+
# Parse the input substrings into a nested array of hashes structure
|
102
|
+
def parse_substrings(substrings)
|
103
|
+
case substrings
|
104
|
+
when Hash
|
105
|
+
[substrings]
|
106
|
+
when Array
|
107
|
+
substrings.map { |s| parse_substrings(s) }
|
108
|
+
else
|
109
|
+
substrings
|
110
|
+
# raise ArgumentError, 'Invalid input type. Expected Hash or Array.'
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
# Recursively concatenate substrings
|
115
|
+
def concatenate_substrings(substrings)
|
116
|
+
substrings.map do |s|
|
117
|
+
case s
|
118
|
+
when Hash
|
119
|
+
s[@text_sym]
|
120
|
+
when Array
|
121
|
+
concatenate_substrings(s)
|
122
|
+
end
|
123
|
+
end.join
|
124
|
+
end
|
125
|
+
|
126
|
+
# Recursively decorate substrings
|
127
|
+
def decorate_substrings(substrings, prior_color = '')
|
128
|
+
substrings.map do |s|
|
129
|
+
case s
|
130
|
+
when Hash
|
131
|
+
if s[@style_sym]
|
132
|
+
AnsiString.new(s[@text_sym]).send(s[@style_sym]) + prior_color
|
133
|
+
else
|
134
|
+
s[@text_sym]
|
135
|
+
end
|
136
|
+
when Array
|
137
|
+
decorate_substrings(s, prior_color)
|
138
|
+
end
|
139
|
+
end.join
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
return if $PROGRAM_NAME != __FILE__
|
144
|
+
|
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 $!, $@
|
@@ -79,7 +86,8 @@ class InputSequencer
|
|
79
86
|
)
|
80
87
|
exit_when_bq_empty = !bq_is_empty? # true when running blocks from cli; unless "stay" is used
|
81
88
|
loop do
|
82
|
-
break if run_yield(:parse_document, now_menu.document_filename,
|
89
|
+
break if run_yield(:parse_document, now_menu.document_filename,
|
90
|
+
&block) == :break
|
83
91
|
|
84
92
|
# self.imw_ins now_menu, 'now_menu'
|
85
93
|
|
@@ -90,16 +98,17 @@ class InputSequencer
|
|
90
98
|
run_yield :display_menu, &block
|
91
99
|
|
92
100
|
choice = run_yield :user_choice, &block
|
101
|
+
break if choice == :break
|
93
102
|
|
94
|
-
raise 'Block not recognized.' if choice.nil?
|
95
|
-
|
103
|
+
raise BlockMissing, 'Block not recognized.' if choice.nil?
|
104
|
+
# Exit loop and method to terminate the app
|
105
|
+
break if run_yield(:exit?, choice&.to_s.downcase, &block)
|
96
106
|
|
97
107
|
next_state = run_yield :execute_block, choice, &block
|
98
108
|
# imw_ins next_state, 'next_state'
|
99
|
-
|
109
|
+
break if next_state == :break
|
100
110
|
|
101
111
|
next_menu = next_state
|
102
|
-
|
103
112
|
else
|
104
113
|
if now_menu.block_name && !now_menu.block_name.empty?
|
105
114
|
block_name = now_menu.block_name
|
@@ -115,6 +124,8 @@ class InputSequencer
|
|
115
124
|
InputSequencer.next_link_state(display_menu: true)
|
116
125
|
else
|
117
126
|
state = run_yield :execute_block, block_name, &block
|
127
|
+
break if state == :break
|
128
|
+
|
118
129
|
state.display_menu = bq_is_empty?
|
119
130
|
state
|
120
131
|
end
|
@@ -123,11 +134,8 @@ class InputSequencer
|
|
123
134
|
end
|
124
135
|
now_menu = InputSequencer.merge_link_state(now_menu, next_menu)
|
125
136
|
end
|
126
|
-
|
127
|
-
|
128
|
-
pp $!, $@
|
129
|
-
exit 1
|
130
|
-
# rubocop:enable Style/RescueStandardError
|
137
|
+
|
138
|
+
run_yield :close_ux, &block
|
131
139
|
end
|
132
140
|
end
|
133
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
|
|