markdown_exec 1.3.8 → 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/CHANGELOG.md +41 -2
- data/Gemfile +1 -0
- data/Gemfile.lock +5 -1
- data/Rakefile +11 -7
- data/bin/bmde +11 -0
- data/bin/colorize_env_vars.sh +7 -0
- data/bin/tab_completion.sh +19 -19
- data/examples/duplicate_block.md +10 -0
- data/examples/import0.md +8 -0
- data/examples/import1.md +10 -0
- data/examples/include.md +12 -0
- data/examples/infile_config.md +10 -0
- data/examples/linked1.md +28 -0
- data/examples/linked2.md +29 -0
- data/examples/linked3.md +12 -0
- data/examples/opts.md +13 -0
- data/examples/pass-through.md +14 -0
- data/examples/plant.md +23 -0
- data/examples/port.md +23 -0
- data/examples/vars.md +20 -0
- data/examples/wrap.md +33 -0
- data/lib/block_types.rb +7 -0
- data/lib/cached_nested_file_reader.rb +0 -1
- data/lib/colorize.rb +61 -50
- data/lib/fcb.rb +12 -30
- data/lib/filter.rb +14 -10
- data/lib/markdown_exec/version.rb +1 -1
- data/lib/markdown_exec.rb +1039 -541
- data/lib/mdoc.rb +106 -84
- data/lib/menu.src.yml +341 -267
- data/lib/menu.yml +342 -268
- data/lib/method_sorter.rb +76 -0
- data/lib/sort_yaml_gpt4.rb +32 -0
- metadata +22 -6
- data/lib/env_opts.rb +0 -242
- data/lib/markdown_block_manager.rb +0 -64
- data/lib/menu_options.rb +0 -0
- data/lib/menu_options.yml +0 -0
@@ -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,28 +106,42 @@ 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
|
110
|
+
- bin/colorize_env_vars.sh
|
108
111
|
- bin/console
|
109
112
|
- bin/mde
|
110
113
|
- bin/setup
|
111
114
|
- bin/tab_completion.sh
|
112
115
|
- bin/tab_completion.sh.erb
|
116
|
+
- examples/duplicate_block.md
|
117
|
+
- examples/import0.md
|
118
|
+
- examples/import1.md
|
119
|
+
- examples/include.md
|
120
|
+
- examples/infile_config.md
|
121
|
+
- examples/linked1.md
|
122
|
+
- examples/linked2.md
|
123
|
+
- examples/linked3.md
|
124
|
+
- examples/opts.md
|
125
|
+
- examples/pass-through.md
|
126
|
+
- examples/plant.md
|
127
|
+
- examples/port.md
|
128
|
+
- examples/vars.md
|
129
|
+
- examples/wrap.md
|
113
130
|
- lib/block_label.rb
|
131
|
+
- lib/block_types.rb
|
114
132
|
- lib/cached_nested_file_reader.rb
|
115
133
|
- lib/cli.rb
|
116
134
|
- lib/colorize.rb
|
117
135
|
- lib/env.rb
|
118
|
-
- lib/env_opts.rb
|
119
136
|
- lib/environment_opt_parse.rb
|
120
137
|
- lib/fcb.rb
|
121
138
|
- lib/filter.rb
|
122
|
-
- lib/markdown_block_manager.rb
|
123
139
|
- lib/markdown_exec.rb
|
124
140
|
- lib/markdown_exec/version.rb
|
125
141
|
- lib/mdoc.rb
|
126
142
|
- lib/menu.src.yml
|
127
143
|
- lib/menu.yml
|
128
|
-
- lib/
|
129
|
-
- lib/menu_options.yml
|
144
|
+
- lib/method_sorter.rb
|
130
145
|
- lib/object_present.rb
|
131
146
|
- lib/option_value.rb
|
132
147
|
- lib/regexp.rb
|
@@ -134,6 +149,7 @@ files:
|
|
134
149
|
- lib/saved_assets.rb
|
135
150
|
- lib/saved_files_matcher.rb
|
136
151
|
- lib/shared.rb
|
152
|
+
- lib/sort_yaml_gpt4.rb
|
137
153
|
- lib/tap.rb
|
138
154
|
homepage: https://rubygems.org/gems/markdown_exec
|
139
155
|
licenses:
|
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,64 +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
|
-
# initialize
|
20
|
-
#
|
21
|
-
# Initializes an instance of MarkdownBlockManager with the given block table.
|
22
|
-
#
|
23
|
-
# @param block_table [Array<Hash>] An array of hashes representing markdown blocks.
|
24
|
-
def initialize(block_table)
|
25
|
-
@block_table = block_table
|
26
|
-
end
|
27
|
-
|
28
|
-
# get_block
|
29
|
-
#
|
30
|
-
# Retrieves a code block by its name.
|
31
|
-
#
|
32
|
-
# @param name [String] The name of the code block to retrieve.
|
33
|
-
# @param default [Hash] The default value to return if the code block is not found.
|
34
|
-
# @return [Hash] The code block as a hash or the default value if not found.
|
35
|
-
def get_block(name, default = {})
|
36
|
-
@block_table.select { |block| block.fetch(:name, '') == name }.fetch(0, default)
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
if $PROGRAM_NAME == __FILE__
|
42
|
-
# require 'bundler/setup'
|
43
|
-
# Bundler.require(:default)
|
44
|
-
|
45
|
-
require 'minitest/autorun'
|
46
|
-
|
47
|
-
class MarkdownBlockManagerTest < Minitest::Test
|
48
|
-
def setup
|
49
|
-
@block_table = [
|
50
|
-
{ name: 'block1', reqs: ['block2'], body: ['code1'] },
|
51
|
-
{ name: 'block2', body: ['code2'] },
|
52
|
-
{ name: 'block3', body: ['code3'] }
|
53
|
-
]
|
54
|
-
@manager = MarkdownExec::MarkdownBlockManager.new(@block_table)
|
55
|
-
end
|
56
|
-
|
57
|
-
# Test the get_block method
|
58
|
-
def test_get_block
|
59
|
-
block = @manager.get_block('block2')
|
60
|
-
expected_block = { name: 'block2', body: ['code2'] }
|
61
|
-
assert_equal expected_block, block
|
62
|
-
end
|
63
|
-
end
|
64
|
-
end
|
data/lib/menu_options.rb
DELETED
File without changes
|
data/lib/menu_options.yml
DELETED
File without changes
|