markdown_exec 1.3.9 → 1.4
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/.pryrc +11 -0
- data/.rubocop.yml +15 -1
- data/Gemfile.lock +1 -1
- data/bin/bmde +11 -0
- data/bin/tab_completion.sh +2 -2
- data/examples/linked1.md +13 -13
- data/examples/linked2.md +15 -14
- data/examples/linked3.md +12 -0
- data/lib/block_types.rb +2 -0
- data/lib/colorize.rb +52 -55
- data/lib/filter.rb +3 -3
- data/lib/markdown_exec/version.rb +1 -1
- data/lib/markdown_exec.rb +873 -614
- data/lib/mdoc.rb +53 -51
- data/lib/menu.src.yml +19 -1
- data/lib/menu.yml +20 -2
- data/lib/method_sorter.rb +76 -0
- data/lib/sort_yaml_gpt4.rb +32 -0
- metadata +7 -2
data/lib/mdoc.rb
CHANGED
@@ -25,6 +25,44 @@ module MarkdownExec
|
|
25
25
|
@table = table
|
26
26
|
end
|
27
27
|
|
28
|
+
def collect_block_code_cann(fcb)
|
29
|
+
body = fcb[:body].join("\n")
|
30
|
+
xcall = fcb[:cann][1..-2]
|
31
|
+
mstdin = xcall.match(/<(?<type>\$)?(?<name>[A-Za-z_\-.\w]+)/)
|
32
|
+
mstdout = xcall.match(/>(?<type>\$)?(?<name>[A-Za-z_\-.\w]+)/)
|
33
|
+
|
34
|
+
yqcmd = if mstdin[:type]
|
35
|
+
"echo \"$#{mstdin[:name]}\" | yq '#{body}'"
|
36
|
+
else
|
37
|
+
"yq e '#{body}' '#{mstdin[:name]}'"
|
38
|
+
end
|
39
|
+
if mstdout[:type]
|
40
|
+
"export #{mstdout[:name]}=$(#{yqcmd})"
|
41
|
+
else
|
42
|
+
"#{yqcmd} > '#{mstdout[:name]}'"
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def collect_block_code_shell(fcb)
|
47
|
+
# write named variables to block at top of script
|
48
|
+
#
|
49
|
+
fcb[:body].join(' ').split.compact.map do |key|
|
50
|
+
format(opts[:block_type_port_set_format], { key: key, value: ENV.fetch(key, nil) })
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def collect_block_code_stdout(fcb)
|
55
|
+
stdout = fcb[:stdout]
|
56
|
+
body = fcb[:body].join("\n")
|
57
|
+
if stdout[:type]
|
58
|
+
%(export #{stdout[:name]}=$(cat <<"EOF"\n#{body}\nEOF\n))
|
59
|
+
else
|
60
|
+
"cat > '#{stdout[:name]}' <<\"EOF\"\n" \
|
61
|
+
"#{body}\n" \
|
62
|
+
"EOF\n"
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
28
66
|
# Retrieves code blocks that are required by a specified code block.
|
29
67
|
#
|
30
68
|
# @param name [String] The name of the code block to start the retrieval from.
|
@@ -56,49 +94,18 @@ module MarkdownExec
|
|
56
94
|
# @param name [String] The name of the code block to start the collection from.
|
57
95
|
# @return [Array<String>] An array of strings containing the collected code blocks.
|
58
96
|
#
|
59
|
-
def collect_recursively_required_code(name)
|
97
|
+
def collect_recursively_required_code(name, opts: {})
|
60
98
|
code = collect_wrapped_blocks(
|
61
99
|
blocks = collect_recursively_required_blocks(name)
|
62
100
|
).map do |fcb|
|
63
|
-
body = fcb[:body].join("\n")
|
64
|
-
|
65
101
|
if fcb[:cann]
|
66
|
-
|
67
|
-
mstdin = xcall.match(/<(?<type>\$)?(?<name>[A-Za-z_\-.\w]+)/)
|
68
|
-
mstdout = xcall.match(/>(?<type>\$)?(?<name>[A-Za-z_\-.\w]+)/)
|
69
|
-
|
70
|
-
yqcmd = if mstdin[:type]
|
71
|
-
"echo \"$#{mstdin[:name]}\" | yq '#{body}'"
|
72
|
-
else
|
73
|
-
"yq e '#{body}' '#{mstdin[:name]}'"
|
74
|
-
end
|
75
|
-
if mstdout[:type]
|
76
|
-
"export #{mstdout[:name]}=$(#{yqcmd})"
|
77
|
-
else
|
78
|
-
"#{yqcmd} > '#{mstdout[:name]}'"
|
79
|
-
end
|
102
|
+
collect_block_code_cann(fcb)
|
80
103
|
elsif fcb[:stdout]
|
81
|
-
|
82
|
-
|
83
|
-
if stdout[:type]
|
84
|
-
%(export #{stdout[:name]}=$(cat <<"EOF"\n#{body}\nEOF\n))
|
85
|
-
else
|
86
|
-
"cat > '#{stdout[:name]}' <<\"EOF\"\n" \
|
87
|
-
"#{body}\n" \
|
88
|
-
"EOF\n"
|
89
|
-
end
|
90
|
-
# elsif fcb[:shell] == 'opts' || fcb[:shell] == 'vars'
|
91
|
-
elsif [BLOCK_TYPE_OPTS, BLOCK_TYPE_VARS].include? fcb[:shell]
|
104
|
+
collect_block_code_stdout(fcb)
|
105
|
+
elsif [BLOCK_TYPE_LINK, BLOCK_TYPE_OPTS, BLOCK_TYPE_VARS].include? fcb[:shell]
|
92
106
|
nil
|
93
107
|
elsif fcb[:shell] == BLOCK_TYPE_PORT
|
94
|
-
|
95
|
-
# write named variables to block at top of script
|
96
|
-
#
|
97
|
-
fcb[:body].join(' ').split(' ').compact.map do |key|
|
98
|
-
# format(opts[:block_type_include_vars_set_format],
|
99
|
-
format(': ${%{key}:=%{value}}', { key: key, value: ENV[key] })
|
100
|
-
end
|
101
|
-
### end
|
108
|
+
collect_block_code_shell(fcb)
|
102
109
|
else
|
103
110
|
fcb[:body]
|
104
111
|
end
|
@@ -285,29 +292,25 @@ if $PROGRAM_NAME == __FILE__
|
|
285
292
|
|
286
293
|
def test_collect_wrapped_blocks
|
287
294
|
# Test case 1: blocks with wraps
|
288
|
-
|
295
|
+
OpenStruct.new(oname: 'block1')
|
289
296
|
|
290
297
|
assert_equal(%w[{wrap1} a],
|
291
298
|
@mdoc.collect_wrapped_blocks(
|
292
299
|
[OpenStruct.new(oname: 'a',
|
293
|
-
|
294
|
-
).map
|
295
|
-
block.oname
|
296
|
-
end)
|
300
|
+
wraps: ['{wrap1}'])]
|
301
|
+
).map(&:oname))
|
297
302
|
|
298
303
|
assert_equal(%w[{wrap2-before} {wrap2} b {wrap2-after}],
|
299
304
|
@mdoc.collect_wrapped_blocks(
|
300
305
|
[OpenStruct.new(oname: 'b',
|
301
|
-
|
302
|
-
).map
|
303
|
-
block.oname
|
304
|
-
end)
|
306
|
+
wraps: ['{wrap2}'])]
|
307
|
+
).map(&:oname))
|
305
308
|
|
306
309
|
assert_equal(%w[{wrap2-before} {wrap2} {wrap3-before} {wrap3} c {wrap3-after} {wrap2-after}],
|
307
310
|
@mdoc.collect_wrapped_blocks(
|
308
|
-
[OpenStruct.new(
|
309
|
-
|
310
|
-
).map
|
311
|
+
[OpenStruct.new(oname: 'c',
|
312
|
+
wraps: %w[{wrap2} {wrap3}])]
|
313
|
+
).map(&:oname))
|
311
314
|
|
312
315
|
# Test case 2: blocks with no wraps
|
313
316
|
blocks = @mdoc.collect_wrapped_blocks([])
|
@@ -316,9 +319,8 @@ if $PROGRAM_NAME == __FILE__
|
|
316
319
|
# Test case 3: blocks with missing wraps
|
317
320
|
assert_equal(
|
318
321
|
%w[block4],
|
319
|
-
@mdoc.collect_wrapped_blocks([OpenStruct.new(oname: 'block4',
|
320
|
-
|
321
|
-
end
|
322
|
+
@mdoc.collect_wrapped_blocks([OpenStruct.new(oname: 'block4',
|
323
|
+
wraps: ['wrap4'])]).map(&:oname)
|
322
324
|
)
|
323
325
|
end
|
324
326
|
end
|
data/lib/menu.src.yml
CHANGED
@@ -51,6 +51,10 @@
|
|
51
51
|
:env_var: MDE_BLOCK_STDOUT_SCAN
|
52
52
|
:opt_name: block_stdout_scan
|
53
53
|
:procname: val_as_str
|
54
|
+
- :default: ": ${%{key}:=%{value}}"
|
55
|
+
:env_var: MDE_BLOCK_TYPE_PORT_SET_FORMAT
|
56
|
+
:opt_name: block_type_port_set_format
|
57
|
+
:procname: val_as_str
|
54
58
|
- :arg_name: PATH
|
55
59
|
:default: "."
|
56
60
|
:description: Read configuration file
|
@@ -129,10 +133,14 @@
|
|
129
133
|
:env_var: MDE_HIDE_BLOCKS_BY_NAME
|
130
134
|
:opt_name: hide_blocks_by_name
|
131
135
|
:procname: val_as_bool
|
132
|
-
- :default: "
|
136
|
+
- :default: "|"
|
133
137
|
:env_var: MDE_HISTORY_DOCUMENT_SEPARATOR
|
134
138
|
:opt_name: history_document_separator
|
135
139
|
:procname: val_as_str
|
140
|
+
- :default: "&"
|
141
|
+
:env_var: MDE_HISTORY_PROPERTY_SEPARATOR
|
142
|
+
:opt_name: history_property_separator
|
143
|
+
:procname: val_as_str
|
136
144
|
- :default: "^ *@import (.+)$"
|
137
145
|
:env_var: MDE_IMPORT_PATTERN
|
138
146
|
:opt_name: import_pattern
|
@@ -244,6 +252,16 @@
|
|
244
252
|
:env_var: MDE_MENU_LINK_COLOR
|
245
253
|
:opt_name: menu_link_color
|
246
254
|
:procname: val_as_str
|
255
|
+
- :default: "* Back"
|
256
|
+
:description: Text for Back option
|
257
|
+
:env_var: MDE_MENU_OPTION_BACK_NAME
|
258
|
+
:opt_name: menu_option_back_name
|
259
|
+
:procname: val_as_str
|
260
|
+
- :default: "* Exit"
|
261
|
+
:description: Text for Exit option
|
262
|
+
:env_var: MDE_MENU_OPTION_EXIT_NAME
|
263
|
+
:opt_name: menu_option_exit_name
|
264
|
+
:procname: val_as_str
|
247
265
|
- :default: blue
|
248
266
|
:description: Color of menu opts
|
249
267
|
:env_var: MDE_MENU_OPTS_COLOR
|
data/lib/menu.yml
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# MDE - Markdown Executor (1.
|
1
|
+
# MDE - Markdown Executor (1.4)
|
2
2
|
---
|
3
3
|
- :description: Show current configuration values
|
4
4
|
:procname: show_config
|
@@ -52,6 +52,10 @@
|
|
52
52
|
:env_var: MDE_BLOCK_STDOUT_SCAN
|
53
53
|
:opt_name: block_stdout_scan
|
54
54
|
:procname: val_as_str
|
55
|
+
- :default: ": ${%{key}:=%{value}}"
|
56
|
+
:env_var: MDE_BLOCK_TYPE_PORT_SET_FORMAT
|
57
|
+
:opt_name: block_type_port_set_format
|
58
|
+
:procname: val_as_str
|
55
59
|
- :arg_name: PATH
|
56
60
|
:default: "."
|
57
61
|
:description: Read configuration file
|
@@ -130,10 +134,14 @@
|
|
130
134
|
:env_var: MDE_HIDE_BLOCKS_BY_NAME
|
131
135
|
:opt_name: hide_blocks_by_name
|
132
136
|
:procname: val_as_bool
|
133
|
-
- :default: "
|
137
|
+
- :default: "|"
|
134
138
|
:env_var: MDE_HISTORY_DOCUMENT_SEPARATOR
|
135
139
|
:opt_name: history_document_separator
|
136
140
|
:procname: val_as_str
|
141
|
+
- :default: "&"
|
142
|
+
:env_var: MDE_HISTORY_PROPERTY_SEPARATOR
|
143
|
+
:opt_name: history_property_separator
|
144
|
+
:procname: val_as_str
|
137
145
|
- :default: "^ *@import (.+)$"
|
138
146
|
:env_var: MDE_IMPORT_PATTERN
|
139
147
|
:opt_name: import_pattern
|
@@ -245,6 +253,16 @@
|
|
245
253
|
:env_var: MDE_MENU_LINK_COLOR
|
246
254
|
:opt_name: menu_link_color
|
247
255
|
:procname: val_as_str
|
256
|
+
- :default: "* Back"
|
257
|
+
:description: Text for Back option
|
258
|
+
:env_var: MDE_MENU_OPTION_BACK_NAME
|
259
|
+
:opt_name: menu_option_back_name
|
260
|
+
:procname: val_as_str
|
261
|
+
- :default: "* Exit"
|
262
|
+
:description: Text for Exit option
|
263
|
+
:env_var: MDE_MENU_OPTION_EXIT_NAME
|
264
|
+
:opt_name: menu_option_exit_name
|
265
|
+
:procname: val_as_str
|
248
266
|
- :default: blue
|
249
267
|
:description: Color of menu opts
|
250
268
|
:env_var: MDE_MENU_OPTS_COLOR
|
@@ -0,0 +1,76 @@
|
|
1
|
+
require 'ripper'
|
2
|
+
require 'parser/current'
|
3
|
+
|
4
|
+
class MethodSorter
|
5
|
+
def initialize(file_path)
|
6
|
+
@file_path = file_path
|
7
|
+
end
|
8
|
+
|
9
|
+
def sort
|
10
|
+
file_contents = File.read(@file_path)
|
11
|
+
|
12
|
+
ast = Parser::CurrentRuby.parse(file_contents)
|
13
|
+
|
14
|
+
# Find the class node
|
15
|
+
class_node = ast.children.find { |node| node.type == :class }
|
16
|
+
|
17
|
+
method_nodes = []
|
18
|
+
|
19
|
+
# Look for method def nodes within each child node
|
20
|
+
class_node.children.compact.each do |child|
|
21
|
+
if child.type == :begin
|
22
|
+
method_nodes += child.children.select {|n| n.type == :def}
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# Sort and process method nodes
|
27
|
+
# class_node = ast.children.find { |node| node.type == :class }
|
28
|
+
# unless class_node
|
29
|
+
# puts "No class node found in #{@file_path}"
|
30
|
+
# return
|
31
|
+
# end
|
32
|
+
|
33
|
+
# method_nodes = class_node.children.compact.select { |node|
|
34
|
+
# node.type == :def
|
35
|
+
# }
|
36
|
+
|
37
|
+
sorted_methods = method_nodes.sort_by{ |n| n.children[0].to_s }
|
38
|
+
ripper = Ripper.sexp(file_contents)
|
39
|
+
lines = ripper.each_with_index.map{|sexp, index| [sexp, index] }
|
40
|
+
|
41
|
+
method_ranges = get_method_ranges(lines, method_nodes)
|
42
|
+
|
43
|
+
result = replace_method_ranges(lines, method_ranges, sorted_methods)
|
44
|
+
|
45
|
+
puts result.compact.select{|v|v.is_a? String}.join("\n")
|
46
|
+
# File.write(@file_path, result.join)
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
def get_method_ranges(lines, method_nodes)
|
52
|
+
method_nodes.map do |method_node|
|
53
|
+
start_line = method_node.loc.line - 1
|
54
|
+
end_line = start_line
|
55
|
+
|
56
|
+
while end_line < lines.size && lines[end_line][0] !~ /^end/
|
57
|
+
end_line += 1
|
58
|
+
end
|
59
|
+
|
60
|
+
(start_line..end_line)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def replace_method_ranges(lines, ranges, sorted_methods)
|
65
|
+
result = lines.dup
|
66
|
+
|
67
|
+
ranges.each_with_index do |range, index|
|
68
|
+
result[range] = sorted_methods[index].loc.expression.source.split("\n")
|
69
|
+
end
|
70
|
+
|
71
|
+
result
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
sorter = MethodSorter.new(ARGV[0])
|
76
|
+
sorter.sort
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'yaml'
|
4
|
+
|
5
|
+
def sort_yaml(input_yaml)
|
6
|
+
# Parse the input YAML
|
7
|
+
data = YAML.load(input_yaml)
|
8
|
+
|
9
|
+
# Ensure data is an array of hashes
|
10
|
+
unless data.is_a?(Array) && data.all? { |item| item.is_a?(Hash) }
|
11
|
+
raise ArgumentError, 'Input YAML must be an array of hashes.'
|
12
|
+
end
|
13
|
+
|
14
|
+
# Sort items by 'opt_name' values
|
15
|
+
sorted_data = data.sort_by do |item|
|
16
|
+
(item[:opt_name] || item[:long_name] || item[:short_name]).to_s
|
17
|
+
end
|
18
|
+
|
19
|
+
# Sort keys in each item
|
20
|
+
sorted_data.each do |item|
|
21
|
+
item.replace(item.sort.to_h)
|
22
|
+
end
|
23
|
+
|
24
|
+
# Convert the sorted data back to YAML and write to stdout
|
25
|
+
puts YAML.dump(sorted_data).gsub("\n-", "\n\n-")
|
26
|
+
end
|
27
|
+
|
28
|
+
# Read YAML from stdin
|
29
|
+
input_yaml = $stdin.read
|
30
|
+
|
31
|
+
# Call the function with input YAML
|
32
|
+
sort_yaml(input_yaml)
|
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.
|
4
|
+
version: '1.4'
|
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-
|
11
|
+
date: 2023-10-31 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: clipboard
|
@@ -91,6 +91,7 @@ executables:
|
|
91
91
|
extensions: []
|
92
92
|
extra_rdoc_files: []
|
93
93
|
files:
|
94
|
+
- ".pryrc"
|
94
95
|
- ".reek"
|
95
96
|
- ".rubocop.yml"
|
96
97
|
- CHANGELOG.md
|
@@ -105,6 +106,7 @@ files:
|
|
105
106
|
- assets/output_of_execution.png
|
106
107
|
- assets/select_a_block.png
|
107
108
|
- assets/select_a_file.png
|
109
|
+
- bin/bmde
|
108
110
|
- bin/colorize_env_vars.sh
|
109
111
|
- bin/console
|
110
112
|
- bin/mde
|
@@ -118,6 +120,7 @@ files:
|
|
118
120
|
- examples/infile_config.md
|
119
121
|
- examples/linked1.md
|
120
122
|
- examples/linked2.md
|
123
|
+
- examples/linked3.md
|
121
124
|
- examples/opts.md
|
122
125
|
- examples/pass-through.md
|
123
126
|
- examples/plant.md
|
@@ -138,6 +141,7 @@ files:
|
|
138
141
|
- lib/mdoc.rb
|
139
142
|
- lib/menu.src.yml
|
140
143
|
- lib/menu.yml
|
144
|
+
- lib/method_sorter.rb
|
141
145
|
- lib/object_present.rb
|
142
146
|
- lib/option_value.rb
|
143
147
|
- lib/regexp.rb
|
@@ -145,6 +149,7 @@ files:
|
|
145
149
|
- lib/saved_assets.rb
|
146
150
|
- lib/saved_files_matcher.rb
|
147
151
|
- lib/shared.rb
|
152
|
+
- lib/sort_yaml_gpt4.rb
|
148
153
|
- lib/tap.rb
|
149
154
|
homepage: https://rubygems.org/gems/markdown_exec
|
150
155
|
licenses:
|