markdown_exec 1.3.7 → 1.3.9

Sign up to get free protection for your applications and to get access to all the features.
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