thor_enhance 0.4.0 → 0.5.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/Gemfile +2 -1
- data/Gemfile.lock +36 -8
- data/README.md +4 -2
- data/bin/thor_enhance +22 -0
- data/docs/autogenerate/Readme.md +152 -0
- data/lib/thor_enhance/autogenerate/command.rb +240 -0
- data/lib/thor_enhance/autogenerate/configuration.rb +72 -0
- data/lib/thor_enhance/autogenerate/option.rb +44 -0
- data/lib/thor_enhance/autogenerate/templates/aggregate_options.rb.erb +12 -0
- data/lib/thor_enhance/autogenerate/templates/command.rb.erb +49 -0
- data/lib/thor_enhance/autogenerate/templates/footer.rb.erb +3 -0
- data/lib/thor_enhance/autogenerate/templates/option.rb.erb +14 -0
- data/lib/thor_enhance/autogenerate/templates/root.rb.erb +9 -0
- data/lib/thor_enhance/autogenerate/validate.rb +95 -0
- data/lib/thor_enhance/autogenerate.rb +78 -0
- data/lib/thor_enhance/command_method.rb +35 -5
- data/lib/thor_enhance/configuration.rb +47 -4
- data/lib/thor_enhance/option.rb +0 -2
- data/lib/thor_enhance/sample.rb +40 -0
- data/lib/thor_enhance/thor_auto_generate_inject.rb +64 -0
- data/lib/thor_enhance/tree.rb +4 -2
- data/lib/thor_enhance/version.rb +1 -1
- data/lib/thor_enhance.rb +12 -4
- data/thor_enhance.gemspec +1 -0
- metadata +30 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8bd2c2b70158e1ab7a387dddfefde9c88c27c1809278ee05608dfca0f7de6484
|
4
|
+
data.tar.gz: eb3ed82f1b26e2239130ff9383971c7167975ac685815e08d48de42cf7eea74c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 52f31daa639f2db023690b1c5b67ae261f0de382a1e03c9ad0a4801162e2ddef4127a942d8b57ad9a2dd72392a17953e63ad9ebfa913bf3e6a70d753bc668617
|
7
|
+
data.tar.gz: b504a6e6087671967755adf851386e0ad499d568a9f66ae561b2aee44b77a2b84c882ace9656136a10f2ed91ce77101023ee8e1ee9b2136d79f02dc428c1e63b
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,18 +1,39 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
thor_enhance (0.
|
4
|
+
thor_enhance (0.5.0)
|
5
|
+
activesupport (>= 6)
|
5
6
|
thor (~> 1.3)
|
6
7
|
|
7
8
|
GEM
|
8
9
|
remote: https://rubygems.org/
|
9
10
|
specs:
|
11
|
+
activesupport (7.1.2)
|
12
|
+
base64
|
13
|
+
bigdecimal
|
14
|
+
concurrent-ruby (~> 1.0, >= 1.0.2)
|
15
|
+
connection_pool (>= 2.2.5)
|
16
|
+
drb
|
17
|
+
i18n (>= 1.6, < 2)
|
18
|
+
minitest (>= 5.1)
|
19
|
+
mutex_m
|
20
|
+
tzinfo (~> 2.0)
|
21
|
+
base64 (0.2.0)
|
22
|
+
bigdecimal (3.1.4)
|
10
23
|
byebug (11.1.3)
|
11
24
|
coderay (1.1.3)
|
25
|
+
concurrent-ruby (1.2.2)
|
26
|
+
connection_pool (2.4.1)
|
12
27
|
diff-lcs (1.5.0)
|
13
28
|
docile (1.4.0)
|
14
|
-
|
29
|
+
drb (2.2.0)
|
30
|
+
ruby2_keywords
|
31
|
+
i18n (1.14.1)
|
32
|
+
concurrent-ruby (~> 1.0)
|
33
|
+
ice_age (0.2.0)
|
15
34
|
method_source (1.0.0)
|
35
|
+
minitest (5.20.0)
|
36
|
+
mutex_m (0.2.0)
|
16
37
|
pry (0.14.2)
|
17
38
|
coderay (~> 1.1)
|
18
39
|
method_source (~> 1.0)
|
@@ -34,23 +55,30 @@ GEM
|
|
34
55
|
rspec-support (3.12.1)
|
35
56
|
rspec_junit_formatter (0.6.0)
|
36
57
|
rspec-core (>= 2, < 4, != 2.12.0)
|
37
|
-
|
58
|
+
ruby2_keywords (0.0.5)
|
59
|
+
simplecov (0.22.0)
|
38
60
|
docile (~> 1.1)
|
39
|
-
|
40
|
-
|
41
|
-
simplecov-html (0.
|
61
|
+
simplecov-html (~> 0.11)
|
62
|
+
simplecov_json_formatter (~> 0.1)
|
63
|
+
simplecov-html (0.12.3)
|
64
|
+
simplecov_json_formatter (0.1.4)
|
42
65
|
thor (1.3.0)
|
66
|
+
tzinfo (2.0.6)
|
67
|
+
concurrent-ruby (~> 1.0)
|
43
68
|
|
44
69
|
PLATFORMS
|
45
70
|
aarch64-linux
|
71
|
+
arm64-darwin-22
|
72
|
+
arm64-darwin-23
|
46
73
|
|
47
74
|
DEPENDENCIES
|
75
|
+
ice_age
|
48
76
|
pry
|
49
77
|
pry-byebug
|
50
78
|
rspec (~> 3.0)
|
51
79
|
rspec_junit_formatter
|
52
|
-
simplecov
|
80
|
+
simplecov
|
53
81
|
thor_enhance!
|
54
82
|
|
55
83
|
BUNDLED WITH
|
56
|
-
2.
|
84
|
+
2.5.1
|
data/README.md
CHANGED
@@ -31,10 +31,12 @@ Command option injection is very powerful. This allows add low level documentati
|
|
31
31
|
|
32
32
|
[Command option documentation](docs/command.md)
|
33
33
|
|
34
|
-
###
|
34
|
+
### Automatic ReadMe Generation
|
35
35
|
The beauty of ThorEnhance is that it forces all your documentation to live with the code. As your code changes, the documentation naturally changes with it.
|
36
36
|
|
37
|
-
|
37
|
+
ThorEnhance can automatically generate your code bases Readme for you.
|
38
|
+
|
39
|
+
[Autogenerate Readme](docs/autogenerate/Readme.md)
|
38
40
|
|
39
41
|
|
40
42
|
### Initialization
|
data/bin/thor_enhance
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "rubygems"
|
4
|
+
require "bundler/setup"
|
5
|
+
require "pry"
|
6
|
+
|
7
|
+
require "thor_enhance"
|
8
|
+
|
9
|
+
ThorEnhance.configure do |c|
|
10
|
+
c.readme_enhance!(required: true) do |r|
|
11
|
+
r.custom_header(:how_does_this_help, repeatable: true)
|
12
|
+
r.custom_header(:when_should_i_use_this, required: true, question: true)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
require "thor_enhance/sample"
|
17
|
+
|
18
|
+
begin
|
19
|
+
ThorEnhance::Sample.start
|
20
|
+
rescue Interrupt => e
|
21
|
+
$stdout.puts "\nThanks for using Better Dependabot 👋\n"
|
22
|
+
end
|
@@ -0,0 +1,152 @@
|
|
1
|
+
# Autogenerate Readme
|
2
|
+
|
3
|
+
A core component of `ThorEnhance` is the ability to autogenerate Readmes for your thor commands. This allows the code and the readme to be in lockstep without the worry of the Readme getting out of date.
|
4
|
+
|
5
|
+
## How does this work?
|
6
|
+
By building on top of [Command Method Injection](../command.md) and [Method Option Injection](../method_option.md), ThorEnhance allows Readme's to get autogenerated based on the description of the command and the methods.
|
7
|
+
|
8
|
+
## How to use
|
9
|
+
|
10
|
+
```ruby
|
11
|
+
# thor_enhance_config.rb
|
12
|
+
ThorEnhance.configure do |c|
|
13
|
+
c.readme_enhance!
|
14
|
+
end
|
15
|
+
```
|
16
|
+
|
17
|
+
## Default capabilities
|
18
|
+
|
19
|
+
### Example Command Option
|
20
|
+
When `readme_enhance` is enabled, by default the `example`ew command option is available on for every command.
|
21
|
+
|
22
|
+
```ruby
|
23
|
+
desc "sample", "This Sample command"
|
24
|
+
example "sample", desc: "Basic invocation of the useless command"
|
25
|
+
example "sample --boolean", desc: "Basic invocation of the useless command with a flag"
|
26
|
+
method_option :boolean, type: :boolean, desc: "Just a normal boolean"
|
27
|
+
def sample;end;
|
28
|
+
```
|
29
|
+
|
30
|
+
The example command takes signature expects:
|
31
|
+
```ruby
|
32
|
+
# remove basename and any submodules from command execution
|
33
|
+
example "command execution", desc: "Description of what the command does"
|
34
|
+
```
|
35
|
+
|
36
|
+
By default, `example` is not required for every command. To make example required for every command, modify the configuration to
|
37
|
+
```ruby
|
38
|
+
ThorEnhance.configure do |c|
|
39
|
+
c.readme_enhance! do |r|
|
40
|
+
r.example(required: true)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
```
|
44
|
+
|
45
|
+
### Header Command Option
|
46
|
+
When `readme_enhance` is enabled, by default a the `header` option is available on every command.
|
47
|
+
|
48
|
+
```ruby
|
49
|
+
desc "sample", "This Sample command"
|
50
|
+
header name: "When should I use this?", desc: "To add additional commentary to your command"
|
51
|
+
header name: "I can have many headers", desc: "Headers can be different per command"
|
52
|
+
def sample;end;
|
53
|
+
```
|
54
|
+
|
55
|
+
By default, `header` is not required for every command. It is an additive command that is customizable per command
|
56
|
+
|
57
|
+
### Title Command Option
|
58
|
+
When `readme_enhance` is enabled, by default a the `title` option is available on every command.
|
59
|
+
|
60
|
+
This optional command option gets used for the Readme title. Otherwise, the method name gets used
|
61
|
+
|
62
|
+
```ruby
|
63
|
+
desc "sample", "This Sample command"
|
64
|
+
title ""
|
65
|
+
def sample;end;
|
66
|
+
```
|
67
|
+
|
68
|
+
By default, `title` is not required for every command. To make example required for every command, modify the configuration to
|
69
|
+
```ruby
|
70
|
+
ThorEnhance.configure do |c|
|
71
|
+
c.readme_enhance! do |r|
|
72
|
+
r.title(required: true)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
```
|
76
|
+
|
77
|
+
### Readme Method Option
|
78
|
+
|
79
|
+
When `readme_enhance` is enabled, by default `readme` flag is available on every option.
|
80
|
+
|
81
|
+
```ruby
|
82
|
+
desc "sample", "This Sample command"
|
83
|
+
method_option :boolean, type: :boolean, desc: "Just a normal boolean", readme: :important
|
84
|
+
def sample;end;
|
85
|
+
```
|
86
|
+
|
87
|
+
The Default options for the value of `:readme` are [`:important`, `:advanced`, `:skip`].
|
88
|
+
|
89
|
+
All methods flagged with `:important` will show up higher in the readme. Anything labled with `:skip`, will not show up on the readme.
|
90
|
+
|
91
|
+
|
92
|
+
By default, `readme` is not required for every method.
|
93
|
+
|
94
|
+
```ruby
|
95
|
+
# This will require all method_options to have the `readme` flag
|
96
|
+
ThorEnhance.configure do |c|
|
97
|
+
c.readme_enhance! do |r|
|
98
|
+
r.readme(required: true)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
```
|
102
|
+
|
103
|
+
```ruby
|
104
|
+
# This will options without the `readme` flag to a group of :empty on the readme
|
105
|
+
ThorEnhance.configure do |c|
|
106
|
+
c.readme_enhance! do |r|
|
107
|
+
r.readme(empty_group: :empty)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
```
|
111
|
+
|
112
|
+
```ruby
|
113
|
+
# Setting enums will override the default readme groups
|
114
|
+
# Only these values will be allowed as readme values
|
115
|
+
# The order of the arry determines the order the group will be ouputted in the Readme
|
116
|
+
ThorEnhance.configure do |c|
|
117
|
+
c.readme_enhance! do |r|
|
118
|
+
r.readme(enums: ["cool", :features, "live", "here".to_sym])
|
119
|
+
end
|
120
|
+
end
|
121
|
+
```
|
122
|
+
|
123
|
+
### Custom Header Command Option
|
124
|
+
|
125
|
+
Custom Headers must get manually added to the configuration.
|
126
|
+
|
127
|
+
```ruby
|
128
|
+
ThorEnhance.configure do |c|
|
129
|
+
c.readme_enhance! do |r|
|
130
|
+
# how_does_this_help will be required on every command
|
131
|
+
r.custom_header("how_does_this_help", required: true)
|
132
|
+
# when_should_i_use_this is a repeatable command
|
133
|
+
r.custom_header("when_should_i_use_this", repeatable: true)
|
134
|
+
# is_this_important is now a question. On the readme, `?` gets appened to the header
|
135
|
+
r.custom_header("is_this_important", question: true)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
```
|
139
|
+
|
140
|
+
The configuration enumerated above allows the ability to do the following:
|
141
|
+
|
142
|
+
|
143
|
+
```ruby
|
144
|
+
desc "sample", "This Sample command"
|
145
|
+
how_does_this_help "This command will help enable additional configuration for each command. This will get appended to the Readme in the order it appears as originally configured", tag: "h4"
|
146
|
+
when_should_i_use_this "Use this whenever you like"
|
147
|
+
when_should_i_use_this "Or you dont ever have to use this", tag: "h2"
|
148
|
+
is_this_important "Yes this is imporant. It even has a custom tag", tag: 1
|
149
|
+
def sample;end;
|
150
|
+
```
|
151
|
+
|
152
|
+
Take special not of the `tag` option on the custom header. By default, header will output as an <h2> header tag. To change, this you can use numeric `1|2|3|4` or you can use string `h[1234]`
|
@@ -0,0 +1,240 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/core_ext/string/inflections"
|
4
|
+
require "thor_enhance/autogenerate/option"
|
5
|
+
require "erb"
|
6
|
+
|
7
|
+
module ThorEnhance
|
8
|
+
module Autogenerate
|
9
|
+
class Command
|
10
|
+
COMMAND_ERB = "#{File.dirname(__FILE__)}/templates/command.rb.erb"
|
11
|
+
COMMAND_TEMPLATE = ERB.new(File.read(COMMAND_ERB))
|
12
|
+
|
13
|
+
AGGREGATE_OPTIONS_ERB = "#{File.dirname(__FILE__)}/templates/aggregate_options.rb.erb"
|
14
|
+
AGGREGATE_OPTIONS_TEMPLATE = ERB.new(File.read(AGGREGATE_OPTIONS_ERB))
|
15
|
+
|
16
|
+
FOOTER_ERB = "#{File.dirname(__FILE__)}/templates/footer.rb.erb"
|
17
|
+
FOOTER_TEMPLATE = ERB.new(File.read(FOOTER_ERB))
|
18
|
+
|
19
|
+
attr_reader :leaf, :name, :basename, :child_commands, :parent
|
20
|
+
|
21
|
+
def initialize(leaf:, name:, basename:, parent: nil)
|
22
|
+
@leaf = leaf
|
23
|
+
@name = name
|
24
|
+
@basename = basename
|
25
|
+
@child_commands = []
|
26
|
+
@parent = parent
|
27
|
+
initialize_children!
|
28
|
+
end
|
29
|
+
|
30
|
+
def initialize_children!
|
31
|
+
return unless children?
|
32
|
+
|
33
|
+
@child_commands = leaf.children.map do |name, child_leaf|
|
34
|
+
self.class.new(leaf: child_leaf, name: name, basename: basename, parent: self)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def method_options
|
39
|
+
@method_options ||= begin
|
40
|
+
_options = options.map { |name, option| Option.new(name: name, option: option) }
|
41
|
+
|
42
|
+
_options.group_by { _1.readme_type }
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def command_erb
|
47
|
+
@command_erb ||= begin
|
48
|
+
params = {
|
49
|
+
basename_string: basename_string,
|
50
|
+
children_descriptors: children_descriptors,
|
51
|
+
command: command,
|
52
|
+
custom_headers: custom_headers,
|
53
|
+
description: description,
|
54
|
+
drawn_out_examples: drawn_out_examples,
|
55
|
+
footer_erb: footer_erb,
|
56
|
+
headers: headers,
|
57
|
+
method_options_erb: method_options_erb,
|
58
|
+
parent_basename_string: parent_basename_string,
|
59
|
+
title: title,
|
60
|
+
}
|
61
|
+
COMMAND_TEMPLATE.result_with_hash(params)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def footer_erb
|
66
|
+
@footer_erb ||= begin
|
67
|
+
regenerate_single_command = "#{parent_basename_string} thor_enhance_autogenerate --command #{command.usage} --apply"
|
68
|
+
regenerate_thor_command = "#{basename} thor_enhance_autogenerate --apply"
|
69
|
+
FOOTER_TEMPLATE.result_with_hash({ regenerate_single_command: regenerate_single_command, regenerate_thor_command: regenerate_thor_command })
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def drawn_out_examples(with_desc: true)
|
74
|
+
case command.example
|
75
|
+
when nil
|
76
|
+
when Array
|
77
|
+
command.example.map do |example|
|
78
|
+
value = []
|
79
|
+
value << "# #{example[:arguments][:kwargs][:desc]}" if with_desc
|
80
|
+
value << "#{parent_basename_string} #{example[:input]}"
|
81
|
+
value.join("\n")
|
82
|
+
end
|
83
|
+
else
|
84
|
+
value = []
|
85
|
+
value << "# #{example[:arguments][:kwargs][:desc]}" if with_desc
|
86
|
+
value << "#{parent_basename_string} #{example[:input]}"
|
87
|
+
[value.join("\n")]
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def method_options_erb
|
92
|
+
@method_options_erb ||= AGGREGATE_OPTIONS_TEMPLATE.result_with_hash({ method_options: method_options })
|
93
|
+
end
|
94
|
+
|
95
|
+
def basename_string
|
96
|
+
"#{parent_basename_string} #{command.usage}"
|
97
|
+
end
|
98
|
+
|
99
|
+
def parent_basename_string
|
100
|
+
parent_names = [basename]
|
101
|
+
temp_leaf = leaf
|
102
|
+
while parent = temp_leaf.parent
|
103
|
+
temp_leaf = parent
|
104
|
+
parent_names << parent.command.usage
|
105
|
+
end
|
106
|
+
parent_names.join(" ")
|
107
|
+
end
|
108
|
+
|
109
|
+
def parent_root
|
110
|
+
if parent
|
111
|
+
# Remove the last index of parent because that will be the Readme.md file
|
112
|
+
# We just want the directory of the parent file
|
113
|
+
parent.relative_readme_path[0..-2]
|
114
|
+
else
|
115
|
+
[]
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
def relative_readme_path
|
120
|
+
if children?
|
121
|
+
# If children exist, this is a subcommand and needs to be a root ReadMe
|
122
|
+
[*parent_root, name, "Readme.md"]
|
123
|
+
else
|
124
|
+
[*parent_root, "#{name}.md"]
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
# this only returns children and its children
|
129
|
+
# Call this on top most parent to retreive family tree for subcommands
|
130
|
+
def flatten_children
|
131
|
+
return [] if child_commands.empty?
|
132
|
+
|
133
|
+
child_commands.map do |child|
|
134
|
+
[child, child.flatten_children]
|
135
|
+
end.flatten
|
136
|
+
end
|
137
|
+
|
138
|
+
def save_self!(root:, apply:)
|
139
|
+
absolute_path = "#{root}/#{relative_readme_path.join("/")}"
|
140
|
+
pathname = Pathname.new(absolute_path)
|
141
|
+
FileUtils.mkdir_p(pathname.dirname)
|
142
|
+
if File.exist?(absolute_path)
|
143
|
+
content = File.read(absolute_path)
|
144
|
+
diff = command_erb == content ? :same : :overwite
|
145
|
+
else
|
146
|
+
diff = :new
|
147
|
+
end
|
148
|
+
|
149
|
+
if apply
|
150
|
+
File.write(absolute_path, command_erb)
|
151
|
+
end
|
152
|
+
|
153
|
+
{ path: absolute_path, diff: diff, apply: apply, self_for_root: self_for_root }
|
154
|
+
end
|
155
|
+
|
156
|
+
def description
|
157
|
+
command.long_description || command.description
|
158
|
+
end
|
159
|
+
|
160
|
+
def title
|
161
|
+
command.title || command.usage
|
162
|
+
end
|
163
|
+
|
164
|
+
def self_for_root
|
165
|
+
params_for_child(self)
|
166
|
+
end
|
167
|
+
|
168
|
+
private
|
169
|
+
|
170
|
+
def custom_headers
|
171
|
+
ThorEnhance.configuration.autogenerated_config.custom_headers.map do |header|
|
172
|
+
next unless command.respond_to?(header.to_sym)
|
173
|
+
|
174
|
+
header_value = command.public_send(header.to_sym)
|
175
|
+
next if header_value.nil?
|
176
|
+
case header_value
|
177
|
+
when Array
|
178
|
+
header_value.map { header_string(_1, header) }
|
179
|
+
else
|
180
|
+
header_string(header_value, header)
|
181
|
+
end
|
182
|
+
|
183
|
+
end.compact.flatten.join("\n\n")
|
184
|
+
end
|
185
|
+
|
186
|
+
def header_string(header_value, header)
|
187
|
+
header_name = header.to_s.gsub(/[_-]/, " ").titlecase
|
188
|
+
header_name += "?" if ThorEnhance.configuration.autogenerated_config.question_headers.include?(header)
|
189
|
+
header_tag = decipher_header_tag(header_value[:arguments][:kwargs][:tag])
|
190
|
+
header_input = header_value[:input]
|
191
|
+
"#{header_tag} #{header_name}\n\n#{header_input}"
|
192
|
+
end
|
193
|
+
|
194
|
+
def decipher_header_tag(input)
|
195
|
+
case input
|
196
|
+
when String
|
197
|
+
begin
|
198
|
+
input[0..1][-1].to_i.to_s == input[0..1][-1] ? "#" * input[0..1][-1].to_i : "##"
|
199
|
+
rescue
|
200
|
+
"##"
|
201
|
+
end
|
202
|
+
when Integer
|
203
|
+
"#" * input
|
204
|
+
else
|
205
|
+
"##"
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
def children_descriptors
|
210
|
+
child_commands.map { params_for_child(_1) }
|
211
|
+
end
|
212
|
+
|
213
|
+
def params_for_child(child)
|
214
|
+
{
|
215
|
+
title: child.title,
|
216
|
+
link: child.relative_readme_path[-1],
|
217
|
+
description: child.description,
|
218
|
+
basename_string: child.basename_string,
|
219
|
+
examples: child.drawn_out_examples(with_desc: false) || [],
|
220
|
+
}
|
221
|
+
end
|
222
|
+
|
223
|
+
def headers
|
224
|
+
(command.header || []).map { _1[:arguments][:kwargs] }
|
225
|
+
end
|
226
|
+
|
227
|
+
def children?
|
228
|
+
leaf.children?
|
229
|
+
end
|
230
|
+
|
231
|
+
def command
|
232
|
+
leaf.command
|
233
|
+
end
|
234
|
+
|
235
|
+
def options
|
236
|
+
command.options
|
237
|
+
end
|
238
|
+
end
|
239
|
+
end
|
240
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ThorEnhance
|
4
|
+
module Autogenerate
|
5
|
+
class Configuration
|
6
|
+
attr_reader :question_headers, :custom_headers, :configuration, :readme_empty_group, :readme_skip_key, :readme_enums
|
7
|
+
|
8
|
+
DEFAULT_SKIP_KEY = :skip
|
9
|
+
|
10
|
+
def initialize(required: false)
|
11
|
+
@required = required
|
12
|
+
@configuration = { add_option_enhance: {}, add_command_method_enhance: {} }
|
13
|
+
@readme_enums = []
|
14
|
+
@custom_headers = []
|
15
|
+
@question_headers = []
|
16
|
+
end
|
17
|
+
|
18
|
+
def set_default_required(value)
|
19
|
+
@required = value
|
20
|
+
end
|
21
|
+
|
22
|
+
def default
|
23
|
+
ThorEnhance::Configuration.allow_changes?
|
24
|
+
|
25
|
+
example
|
26
|
+
header
|
27
|
+
title
|
28
|
+
readme
|
29
|
+
end
|
30
|
+
|
31
|
+
def title(required: false)
|
32
|
+
ThorEnhance::Configuration.allow_changes?
|
33
|
+
|
34
|
+
required = required.nil? ? @required : required
|
35
|
+
configuration[:add_command_method_enhance][:title] = { repeatable: false, required: required }
|
36
|
+
end
|
37
|
+
|
38
|
+
def example(required: nil, repeatable: true)
|
39
|
+
ThorEnhance::Configuration.allow_changes?
|
40
|
+
|
41
|
+
required = required.nil? ? @required : required
|
42
|
+
configuration[:add_command_method_enhance][:example] = { repeatable: repeatable, required: required, required_kwargs: [:desc] }
|
43
|
+
end
|
44
|
+
|
45
|
+
def header
|
46
|
+
ThorEnhance::Configuration.allow_changes?
|
47
|
+
|
48
|
+
configuration[:add_command_method_enhance][:header] = { repeatable: true, required: false, required_kwargs: [:name, :desc], optional_kwargs: [:tag] }
|
49
|
+
end
|
50
|
+
|
51
|
+
def custom_header(name, question: false, repeatable: false, required: false)
|
52
|
+
ThorEnhance::Configuration.allow_changes?
|
53
|
+
|
54
|
+
raise ArgumentError, "Custom Header name must be unique. #{name} is already defined as a custom header. " if custom_headers.include?(name.to_sym)
|
55
|
+
|
56
|
+
custom_headers << name.to_sym
|
57
|
+
question_headers << name.to_sym if question
|
58
|
+
configuration[:add_command_method_enhance][name.to_sym] = { repeatable: repeatable, required: required, optional_kwargs: [:tag] }
|
59
|
+
end
|
60
|
+
|
61
|
+
def readme(required: nil, empty_group: :unassigned, skip_key: DEFAULT_SKIP_KEY, enums: [:important, :advanced, skip_key.to_sym].compact)
|
62
|
+
ThorEnhance::Configuration.allow_changes?
|
63
|
+
|
64
|
+
@readme_empty_group = empty_group
|
65
|
+
@readme_skip_key = skip_key
|
66
|
+
@readme_enums = enums.map(&:to_sym)
|
67
|
+
required = required.nil? ? @required : required
|
68
|
+
configuration[:add_option_enhance][:readme] = { enums: enums, required: required }
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "erb"
|
4
|
+
|
5
|
+
module ThorEnhance
|
6
|
+
module Autogenerate
|
7
|
+
class Option
|
8
|
+
TEMPLATE_ERB = "#{File.dirname(__FILE__)}/templates/option.rb.erb"
|
9
|
+
OPTION_TEMPLATE = ERB.new(File.read(TEMPLATE_ERB))
|
10
|
+
|
11
|
+
attr_reader :name, :option
|
12
|
+
|
13
|
+
def initialize(name:, option:)
|
14
|
+
@name = name
|
15
|
+
@option = option
|
16
|
+
end
|
17
|
+
|
18
|
+
def template_text
|
19
|
+
text = []
|
20
|
+
text << "# What: #{option.description}"
|
21
|
+
text << "# Type: #{option.type}"
|
22
|
+
text << "# Required: #{option.required}"
|
23
|
+
text << "# Allowed Inputs: #{option.enum}" if option.enum
|
24
|
+
text << invocations.map { "#{_1}"}.join(" | ")
|
25
|
+
|
26
|
+
text.join("\n")
|
27
|
+
end
|
28
|
+
|
29
|
+
def invocations
|
30
|
+
base = [option.switch_name] + option.aliases
|
31
|
+
if option.type == :boolean
|
32
|
+
counter = option.switch_name.sub("--", "--no-")
|
33
|
+
base << counter
|
34
|
+
end
|
35
|
+
|
36
|
+
base
|
37
|
+
end
|
38
|
+
|
39
|
+
def readme_type
|
40
|
+
option.readme || ThorEnhance.configuration.autogenerated_config.readme_empty_group
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
<% ThorEnhance.configuration.autogenerated_config.readme_enums.each_with_index do |group_name, index| %>
|
2
|
+
<% next if method_options[group_name].nil? %>
|
3
|
+
<details <%= "open" if index == 0 %>>
|
4
|
+
<summary> <h3> <%= group_name.to_s.titlecase %> options </h3> </summary>
|
5
|
+
|
6
|
+
```bash
|
7
|
+
<%= method_options[group_name].map { _1.template_text }.join("\n") %>
|
8
|
+
```
|
9
|
+
|
10
|
+
</details>
|
11
|
+
|
12
|
+
<% end %>
|