markdown_exec 1.3.7 → 1.3.9

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.
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: markdown_exec
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.7
4
+ version: 1.3.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Fareed Stevenson
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-10-16 00:00:00.000000000 Z
11
+ date: 2023-10-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: clipboard
@@ -105,28 +105,39 @@ files:
105
105
  - assets/output_of_execution.png
106
106
  - assets/select_a_block.png
107
107
  - assets/select_a_file.png
108
+ - bin/colorize_env_vars.sh
108
109
  - bin/console
109
110
  - bin/mde
110
111
  - bin/setup
111
112
  - bin/tab_completion.sh
112
113
  - bin/tab_completion.sh.erb
114
+ - examples/duplicate_block.md
115
+ - examples/import0.md
116
+ - examples/import1.md
117
+ - examples/include.md
118
+ - examples/infile_config.md
119
+ - examples/linked1.md
120
+ - examples/linked2.md
121
+ - examples/opts.md
122
+ - examples/pass-through.md
123
+ - examples/plant.md
124
+ - examples/port.md
125
+ - examples/vars.md
126
+ - examples/wrap.md
113
127
  - lib/block_label.rb
128
+ - lib/block_types.rb
114
129
  - lib/cached_nested_file_reader.rb
115
130
  - lib/cli.rb
116
131
  - lib/colorize.rb
117
132
  - lib/env.rb
118
- - lib/env_opts.rb
119
133
  - lib/environment_opt_parse.rb
120
134
  - lib/fcb.rb
121
135
  - lib/filter.rb
122
- - lib/markdown_block_manager.rb
123
136
  - lib/markdown_exec.rb
124
137
  - lib/markdown_exec/version.rb
125
138
  - lib/mdoc.rb
126
139
  - lib/menu.src.yml
127
140
  - lib/menu.yml
128
- - lib/menu_options.rb
129
- - lib/menu_options.yml
130
141
  - lib/object_present.rb
131
142
  - lib/option_value.rb
132
143
  - lib/regexp.rb
data/lib/env_opts.rb DELETED
@@ -1,242 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # encoding=utf-8
4
-
5
- require_relative 'tap'
6
-
7
- include Tap #; tap_config
8
-
9
- # define options with initial values
10
- # option to read value from environmnt variables
11
- # option to cast input values
12
- # value priority: default < environment < argument
13
- #
14
- # :reek:TooManyMethods
15
- class EnvOpts
16
- attr_reader :opts, :values
17
-
18
- def initialize(opts_raw = {}, argv = ARGV)
19
- @opts = {}
20
- @values = {}
21
- add_options(opts_raw)
22
- # parse(argv, &block) if block_given?
23
- block_given? ? parse(argv, &block) : parse(argv)
24
-
25
- self # rubocop:disable Lint/Void
26
- end
27
-
28
- # add options to menu
29
- # calculate help text
30
- #
31
- # :reek:NestedIterators
32
- def add_options(opts_raw)
33
- return self if opts_raw.nil?
34
-
35
- help_rows = opts_raw.map do |key, opt_raw|
36
- opt_name = key_name_to_option_name(key)
37
-
38
- # set_per_options(opt_name, opt_raw)
39
- @opts[opt_name] = (opt_raw ||= {})
40
- set_key_value_as_cast(opt_name, EnvOpts.optdefault(opt_raw))
41
- set_key_value_per_environment_as_cast(opt_name, opt_raw)
42
-
43
- [
44
- [20, '-', "--#{opt_name}"],
45
- [16, '-',
46
- if @opts[opt_name][:env].present?
47
- option_name_to_environment_name(opt_name, @opts[opt_name])
48
- else
49
- ''
50
- end],
51
- # [24, '-', get_environment_value_from_option(opt_name, @opts[opt_name])],
52
- [24, '-', @opts[opt_name][:default]],
53
- [6, '-', if (fixed = opt_raw.fetch(:fixed, nil)).nil?
54
- ":#{option_cast(@opts[opt_name])}"
55
- else
56
- fixed.to_s
57
- end]
58
- ]
59
- end
60
-
61
- max_widths = help_rows.reduce([0, 0, 0, 0]) do |memo, vals|
62
- vals.map.with_index do |val, ind|
63
- [memo[ind], val[2].to_s.length].max
64
- end
65
- end
66
-
67
- @values['help'] = help_rows.map do |row|
68
- row.map.with_index do |cell, ind|
69
- format("%#{cell[1]}#{max_widths[ind]}s", cell[2])
70
- end.join(' ')
71
- end.join("\n")
72
-
73
- self
74
- end
75
-
76
- # accept :d or :default option
77
- #
78
- def self.optdefault(opt_raw)
79
- return opt_raw[:d] unless opt_raw[:d].nil?
80
-
81
- opt_raw[:default]
82
- end
83
-
84
- def output_help
85
- puts @values['help']
86
- end
87
-
88
- # process arguments as mostly pairs of option name and value
89
- #
90
- def parse(argv = ARGV)
91
- return self if argv.nil? || !(argv&.count || 0).positive?
92
-
93
- args_ind = 0
94
- while args_ind < argv.count
95
- args_consumed = 0
96
- arg = argv.fetch(args_ind, '')
97
- if arg.start_with? '--'
98
- opt_name = arg[2..-1]
99
- args_consumed = consume_arguments(opt_name,
100
- argv.fetch(args_ind + 1, nil))
101
- end
102
-
103
- if args_consumed.zero?
104
- if arg == '--help'
105
- output_help
106
- exit
107
- elsif block_given?
108
- yield 'NAO', [arg]
109
- args_consumed = 1
110
- else
111
- warn "Invalid argument: #{arg.inspect} in #{argv.inspect}"
112
- exit 1
113
- end
114
- end
115
-
116
- args_ind += args_consumed
117
- end
118
-
119
- self
120
- end
121
-
122
- # set option current values per environment values
123
- #
124
- def options_per_environment_as_cast(opts_raw)
125
- return self if opts_raw.nil?
126
-
127
- opts_raw.each do |key, opt_raw|
128
- set_key_value_per_environment_as_cast(key_name_to_option_name(key),
129
- opt_raw)
130
- end
131
-
132
- self
133
- end
134
-
135
- # symbol name to option name
136
- # option names use hyphens
137
- #
138
- def self.symbol_name_to_option_name(name)
139
- name.to_s.gsub('_', '-')
140
- end
141
-
142
- private
143
-
144
- # convert key name or symbol to an option name
145
- #
146
- def key_name_to_option_name(key)
147
- (key.is_a?(Symbol) ? EnvOpts.symbol_name_to_option_name(key) : key)
148
- end
149
-
150
- # get cast of environment variable
151
- #
152
- def option_cast(opt_raw)
153
- (opt_raw[:cast].present? ? opt_raw[:cast].to_s : 'to_s')
154
- end
155
-
156
- # update value for named option
157
- # return number of arguments used
158
- #
159
- def consume_arguments(opt_name, value)
160
- return 0 if (opt_raw = @opts.fetch(opt_name, nil)).nil?
161
-
162
- return 0 unless opt_raw.fetch(:option, true)
163
-
164
- if !(fixed = opt_raw.fetch(:fixed, nil)).nil?
165
- set_key_value_as_cast(opt_name, fixed)
166
- 1
167
- elsif value.nil?
168
- 0
169
- else
170
- set_key_value_as_cast(opt_name, value)
171
- 2
172
- end
173
- end
174
-
175
- # option names use hyphens
176
- #
177
- def method_name_to_option_name(name)
178
- name.to_s.gsub('_', '-')
179
- end
180
-
181
- # read and write options using the option name as a method
182
- #
183
- def method_missing(method_name, *args)
184
- if method_name.to_s.end_with?('=')
185
- value = args.first
186
- name = method_name_to_option_name(method_name.to_s[0..-2])
187
- set_key_value_as_cast(name, value)
188
- else
189
- @values[method_name_to_option_name(method_name)]
190
- end
191
- end
192
-
193
- # option name to environment name
194
- # if true or empty, compute from option name
195
- #
196
- def option_name_to_environment_name(opt_name, opt_raw)
197
- case env_name = opt_raw.fetch(:env, '')
198
- when true, ''
199
- "#{@values['env-prefix']}#{opt_name.upcase.gsub('-', '_')}"
200
- else
201
- env_name
202
- end
203
- end
204
-
205
- # get environment value from option
206
- #
207
- def get_environment_value_from_option(opt_name, opt_raw)
208
- ENV.fetch(option_name_to_environment_name(opt_name, opt_raw),
209
- nil)
210
- end
211
-
212
- # option names are available as methods
213
- #
214
- # :reek:BooleanParameter
215
- def respond_to_missing?(method_name, include_private = false)
216
- (@opts.keys.include?(method_name_to_option_name(method_name)) || super)
217
- end
218
-
219
- def set_key_value_as_cast(key, value)
220
- opt = @opts[key]
221
- set_key_value_raw(key, (opt[:cast] ? value.send(opt[:cast]) : value))
222
- end
223
-
224
- # set key value_per environment as cast
225
- #
226
- def set_key_value_per_environment_as_cast(key, opt_raw)
227
- return if opt_raw[:env].nil?
228
-
229
- value = get_environment_value_from_option(key, opt_raw)
230
-
231
- return unless value
232
-
233
- set_key_value_as_cast(key,
234
- opt_raw[:cast] ? value.send(opt_raw[:cast]) : value)
235
- end
236
-
237
- # set key value (raw)
238
- #
239
- def set_key_value_raw(key, value)
240
- @values[key] = value
241
- end
242
- end
@@ -1,195 +0,0 @@
1
- #!/usr/bin/env ruby
2
- # frozen_string_literal: true
3
-
4
- # encoding=utf-8
5
-
6
- require_relative 'filter'
7
-
8
- module MarkdownExec
9
- ##
10
- # MarkdownBlockManager represents an imported markdown document.
11
- #
12
- # It provides methods to extract and manipulate specific sections
13
- # of the document, such as code blocks. It also supports recursion
14
- # to fetch related or dependent blocks.
15
- #
16
- class MarkdownBlockManager
17
- attr_reader :block_table
18
-
19
- def initialize(block_table)
20
- @block_table = block_table
21
- end
22
-
23
- def collect_required_code(name)
24
- gather_required_blocks(name)
25
- .map do |block|
26
- process_block_code(block)
27
- end.flatten(1)
28
- end
29
-
30
- def get_block(name, default = {})
31
- @block_table.select { |block| block.fetch(:name, '') == name }.fetch(0, default)
32
- end
33
-
34
- def gather_required_blocks(name)
35
- named_block = get_block(name)
36
- if named_block.nil? || named_block.keys.empty?
37
- raise "Named code block `#{name}` not found."
38
- end
39
-
40
- all_blocks = [named_block.fetch(:name, '')] + required_blocks(named_block[:reqs])
41
- @block_table.select { |block| all_blocks.include? block.fetch(:name, '') }
42
- .map do |block|
43
- process_block_references(block)
44
- end.flatten(1)
45
- end
46
-
47
- def hide_block_given_options(opts, block)
48
- (opts[:hide_blocks_by_name] &&
49
- block[:name]&.match(Regexp.new(opts[:block_name_hidden_match])) &&
50
- (block[:name]&.present? || block[:label]&.present?)
51
- )
52
- end
53
-
54
- def blocks_per_options(opts = {})
55
- filtered_blocks = @block_table.select do |block_group|
56
- Filter.block_selected? opts, block_group
57
- end
58
- if opts[:hide_blocks_by_name]
59
- filtered_blocks.reject { |block| hide_block_given_options opts, block }
60
- else
61
- filtered_blocks
62
- end.map do |block|
63
- block
64
- end
65
- end
66
-
67
- def required_blocks(reqs)
68
- return [] unless reqs
69
-
70
- remaining = reqs
71
- collected = []
72
- while remaining.count.positive?
73
- remaining = remaining.map do |req|
74
- next if collected.include? req
75
-
76
- collected += [req]
77
- get_block(req).fetch(:reqs, [])
78
- end
79
- .compact
80
- .flatten(1)
81
- end
82
- collected
83
- end
84
-
85
- # Helper method to process block code
86
- def process_block_code(block)
87
- body = block[:body].join("\n")
88
-
89
- if block[:cann]
90
- xcall = block[:cann][1..-2]
91
- mstdin = xcall.match(/<(?<type>\$)?(?<name>[A-Za-z_\-.\w]+)/)
92
- mstdout = xcall.match(/>(?<type>\$)?(?<name>[A-Za-z_\-.\w]+)/)
93
-
94
- yqcmd = if mstdin[:type]
95
- "echo \"$#{mstdin[:name]}\" | yq '#{body}'"
96
- else
97
- "yq e '#{body}' '#{mstdin[:name]}'"
98
- end
99
- if mstdout[:type]
100
- "export #{mstdout[:name]}=$(#{yqcmd})"
101
- else
102
- "#{yqcmd} > '#{mstdout[:name]}'"
103
- end
104
- elsif block[:stdout]
105
- stdout = block[:stdout]
106
- body = block[:body].join("\n")
107
- if stdout[:type]
108
- %(export #{stdout[:name]}=$(cat <<"EOF"\n#{body}\nEOF\n))
109
- else
110
- "cat > '#{stdout[:name]}' <<\"EOF\"\n" \
111
- "#{body}\n" \
112
- "EOF\n"
113
- end
114
- else
115
- block[:body]
116
- end
117
- end
118
-
119
- # Helper method to process block references
120
- def process_block_references(block)
121
- if (call = block[:call])
122
- [get_block("[#{call.match(/^%\((\S+) |\)/)[1]}]")
123
- .merge({ cann: call })]
124
- else
125
- []
126
- end + [block]
127
- end
128
- end
129
- end
130
-
131
- if $PROGRAM_NAME == __FILE__
132
- # require 'bundler/setup'
133
- # Bundler.require(:default)
134
-
135
- require 'minitest/autorun'
136
-
137
- require_relative 'tap'
138
- include Tap
139
-
140
- module MarkdownExec
141
- class TestMDoc < Minitest::Test
142
- def setup
143
- @table = [
144
- { name: 'block1', body: ['code for block1'], reqs: ['block2'] },
145
- { name: 'block2', body: ['code for block2'], reqs: nil },
146
- { name: 'block3', body: ['code for block3'], reqs: ['block1'] }
147
- ]
148
- @doc = MDoc.new(@table)
149
- end
150
-
151
- def test_collect_recursively_required_code
152
- result = @doc.collect_recursively_required_code('block1')
153
- expected_result = @table[0][:body] + @table[1][:body]
154
- assert_equal expected_result, result
155
- end
156
-
157
- def test_get_block_by_name
158
- result = @doc.get_block_by_name('block1')
159
- assert_equal @table[0], result
160
-
161
- result_missing = @doc.get_block_by_name('missing_block')
162
- assert_equal({}, result_missing)
163
- end
164
-
165
- def test_get_required_blocks
166
- result = @doc.get_required_blocks('block3')
167
- expected_result = [@table[0], @table[1], @table[2]]
168
- assert_equal expected_result, result
169
-
170
- assert_raises(RuntimeError) { @doc.get_required_blocks('missing_block') }
171
- end
172
-
173
- def test_hide_menu_block_per_options
174
- opts = { hide_blocks_by_name: true, block_name_hidden_match: 'block1' }
175
- block = { name: 'block1' }
176
- result = @doc.hide_menu_block_per_options(opts, block)
177
- assert result # this should be true based on the given logic
178
- end
179
-
180
- def test_fcbs_per_options
181
- opts = { hide_blocks_by_name: true, block_name_hidden_match: 'block1' }
182
- result = @doc.fcbs_per_options(opts)
183
- assert_equal [@table[1], @table[2]], result
184
- end
185
-
186
- def test_recursively_required
187
- result = @doc.recursively_required(['block3'])
188
- assert_equal %w[block3 block1 block2], result
189
-
190
- result_no_reqs = @doc.recursively_required(nil)
191
- assert_equal [], result_no_reqs
192
- end
193
- end
194
- end
195
- end
data/lib/menu_options.rb DELETED
File without changes
data/lib/menu_options.yml DELETED
File without changes