thor_enhance 0.4.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,49 @@
1
+ # <%= title.to_s.titlecase %>
2
+
3
+ ## Description
4
+ <%= command.long_description || command.description %>
5
+
6
+ ```bash
7
+ # Base command for `<%= command.usage %>`
8
+ <%= basename_string %>
9
+ ```
10
+
11
+ <%= custom_headers %>
12
+
13
+ <% headers.each do |header| %>
14
+ ## <%= header[:name] %>
15
+ <%= header[:desc]%>
16
+ <% end %>
17
+ <% if drawn_out_examples %>
18
+ ---
19
+
20
+ ## Examples
21
+ <% drawn_out_examples.each do |ex|%>
22
+ ```bash
23
+ <%= ex %>
24
+ ```
25
+ <% end %>
26
+ <% end %>
27
+ <% if !method_options_erb.strip.empty? %>
28
+ ---
29
+
30
+ <% if children_descriptors.empty? %>
31
+ ## Method Options
32
+
33
+ <%= method_options_erb %>
34
+ <% end %>
35
+ <% else %>
36
+ <% children_descriptors.each do |child| %>
37
+ ### [<%= child[:title]%>](<%= child[:link] %>)
38
+
39
+ <%= child[:description] %>
40
+
41
+ ```bash
42
+ <%= child[:basename_string]%> <options>
43
+ <%= child[:examples].map { _1 }.join("\n") %>
44
+ ```
45
+ <% end %>
46
+ <% end %>
47
+ ---
48
+
49
+ <%= footer_erb %>
@@ -0,0 +1,3 @@
1
+ > AutoGenerateted by [ThorEnhance](https://github.com/matt-taylor/thor_enhance) <br>
2
+ > Regenerate file with: <%= regenerate_single_command %> <br>
3
+ > Regenerate all files with: <%= regenerate_thor_command %>
@@ -0,0 +1,14 @@
1
+ # What: <%= option.description %>
2
+ # Type: <%= option.type %>
3
+ # Required: <%= option.required %>
4
+ # <%= "**Allowed inputs:** #{option.enum}" if option.enum %>
5
+ # <%= name.to_s.titlecase %>
6
+ <%= invocations.map { "`#{_1}`"}.join(" | ") %>
7
+
8
+ **What:** <%= option.description %><br>
9
+ **Invocation:** <br>
10
+ **Type:** <%= option.type %><br>
11
+ **Default:** <%= option.default || "none" %><br>
12
+ **Required:** <%= option.required %><br>
13
+ <%= "**Allowed inputs:** #{option.enum}" if option.enum %>
14
+
@@ -0,0 +1,9 @@
1
+ ## [<%= root_child[:title]%>](<%= root_child[:link] %>)
2
+ <%= root_child[:description] %>
3
+
4
+ ```bash
5
+ # Help Command
6
+ <%= root_child[:basename_string]%> <options>
7
+
8
+ <%= root_child[:examples].map { _1 }.join("\n") %>
9
+ ```
@@ -0,0 +1,95 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ThorEnhance
4
+ module Autogenerate
5
+ module Validate
6
+ module_function
7
+
8
+ def validate(options:, root: nil)
9
+ root_result = validate_root(options: options, root: root)
10
+ return root_result if root_result[:status] != :pass
11
+
12
+ trunk = root_result[:trunk]
13
+ constant = root_result[:constant]
14
+
15
+ subcommand_result = validate_subcommand(options: options, trunk: trunk)
16
+ return subcommand_result if subcommand_result[:status] != :pass
17
+
18
+ trunk = subcommand_result[:trunk]
19
+ command_result = validate_command(options: options, trunk: trunk, constant: constant)
20
+ return command_result if command_result[:status] != :pass
21
+ command = command_result[:command]
22
+ { command: command, trunk: trunk, constant: constant, status: :pass }
23
+ end
24
+
25
+ def validate_root(options:, root:)
26
+ begin
27
+ constant = root || Object.const_get(options.root.to_s)
28
+ rescue NameError => e
29
+ msg_array = [
30
+ "Unable to load provided --root|-r option `#{options.root}`",
31
+ "Please check the spelling and ensure the klass has loaded"
32
+ ]
33
+ return { error: e, msg_array: msg_array, status: :fail }
34
+ end
35
+
36
+ begin
37
+ trunk = ThorEnhance::Tree.tree(base: constant)
38
+ rescue TreeFailure => e
39
+ msg_array = [
40
+ "--root|-r option is not a Thor klass.",
41
+ "Please ensure that the provided klass is a child of Thor"
42
+ ]
43
+ return { error: e, msg_array: msg_array, status: :fail }
44
+ end
45
+
46
+ { trunk: trunk, constant: constant, status: :pass }
47
+ end
48
+
49
+ def validate_command(options:, trunk:, constant:)
50
+ # Return early when command is not present in the options object
51
+ command = options.command
52
+ return { status: :pass, trunk: trunk, command: nil } if command.nil?
53
+
54
+ # Return early when command is found in the tree trunk
55
+ command = trunk.children[options.command] rescue trunk[options.command]
56
+ return { status: :pass, trunk: trunk, command: command } if command
57
+
58
+ # Command option was available but command was not found in the trunk
59
+ msg_array = ["Failed to find --command|-c `#{options.command}`"]
60
+ msg_array << "Provided root command `#{constant}`"
61
+ msg_array << "With Provided subcommand `#{options.subcommand}`" if options.subcommand
62
+ msg_array << "does not have command `#{options.command}` as a child" if options.subcommand
63
+
64
+ { msg_array: msg_array, status: :fail }
65
+ end
66
+
67
+ def validate_subcommand(options:, trunk:)
68
+ subcommands = options.subcommand
69
+ return { trunk: trunk, status: :pass } if subcommands.nil?
70
+
71
+ subcommands = subcommands.dup
72
+ subcommand = subcommands.shift
73
+ temp_trunk = trunk[subcommand]
74
+ while subcommand != nil
75
+ if temp_trunk.nil? || !temp_trunk.children?
76
+ msg_array = [
77
+ "Order is important with --subcommands|-s options",
78
+ "Provided with: #{options.subcommand}",
79
+ "Subcommand `#{subcommand}` does not have any child commands",
80
+ "Every provided subcommand must have children",
81
+ "If the subcommand `#{subcommand}` is meant to be a command",
82
+ "Pass `#{subcommand}` in as `--command|-c #{subcommand}` instead",
83
+ ]
84
+ return { msg_array: msg_array, status: :fail }
85
+ end
86
+ subcommand = subcommands.shift
87
+ # Will always be in the child hash at this point if subcommand exists
88
+ temp_trunk = temp_trunk.children[subcommand] if subcommand
89
+ end
90
+
91
+ { trunk: temp_trunk, subcommands: options.subcommand, status: :pass }
92
+ end
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,78 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "thor_enhance/autogenerate/configuration"
4
+ require "thor_enhance/autogenerate/validate"
5
+ require "thor_enhance/autogenerate/option"
6
+ require "thor_enhance/autogenerate/command"
7
+
8
+ module ThorEnhance
9
+ module Autogenerate
10
+ module_function
11
+
12
+ ROOT_ERB = "#{File.dirname(__FILE__)}/autogenerate/templates/root.rb.erb"
13
+ ROOT_TEMPLATE = ERB.new(File.read(ROOT_ERB))
14
+
15
+ def execute!(options:, basename: File.basename($0), root: nil)
16
+ validate_result = Validate.validate(options: options, root: root)
17
+ return validate_result if validate_result[:status] != :pass
18
+
19
+ command = validate_result[:command]
20
+ trunk = validate_result[:trunk]
21
+ leaves =
22
+ if command
23
+ { options.command => command }
24
+ elsif Hash === trunk
25
+ # Parent trunk is a hash -- structure needs to change
26
+ trunk
27
+ else
28
+ # if not parent, grab the children
29
+ trunk.children
30
+ end
31
+
32
+ command_structure = leaves.map do |name, leaf|
33
+ parent = Command.new(name: name, leaf: leaf, basename: basename)
34
+ end
35
+
36
+ # flatten_children returns all kids, grandkids, great grandkids etc of the commands returned from the above mapping
37
+ youthful_kids = command_structure.map(&:flatten_children).flatten
38
+
39
+ # this is a flat map of the entire family tree. Each node knows where it is so we can flatten it
40
+ family_tree = command_structure + youthful_kids
41
+
42
+ save_generated_readmes!(commands: family_tree, generated_root: options.generated_root, apply: options.apply)
43
+ end
44
+
45
+ def save_generated_readmes!(commands:, generated_root:, apply:)
46
+ parent = generated_root || ENV["THOR_ENHANCE_GENERATED_ROOT_PATH"]
47
+ full_root = "#{parent}/commands"
48
+ saved_status = commands.map do |command|
49
+ command.save_self!(root: full_root, apply: apply)
50
+ end
51
+ self_for_roots = saved_status.collect { _1[:self_for_root] }
52
+ saved_status << root_savior!(apply: apply, full_root: full_root, self_for_roots: self_for_roots)
53
+
54
+ { status: :pass, saved_status: saved_status }
55
+ end
56
+
57
+ def root_savior!(full_root:, self_for_roots:, apply:)
58
+ full_path = "#{full_root}/Readme.md"
59
+ root_erb_result = self_for_roots.map do |root_child|
60
+ ROOT_TEMPLATE.result_with_hash({ root_child: root_child })
61
+ end.join("\n")
62
+
63
+ FileUtils.mkdir_p(full_root)
64
+ if File.exist?(full_path)
65
+ content = File.read(full_path)
66
+ diff = root_erb_result == content ? :same : :overwite
67
+ else
68
+ diff = :new
69
+ end
70
+
71
+ if apply
72
+ File.write(full_path, root_erb_result)
73
+ end
74
+
75
+ { path: full_path, diff: diff, apply: apply }
76
+ end
77
+ end
78
+ end
@@ -14,16 +14,18 @@ module ThorEnhance
14
14
  ThorEnhance.configuration.command_method_enhance.each do |name, object|
15
15
  # Define a new method based on the name of each enhanced command method
16
16
  # Method takes care all validation except requirment -- Requirement is done during command initialization
17
- ClassMethods.define_method("#{name}") do |input|
17
+ ClassMethods.define_method("#{name}") do |input = nil, *args, **kwargs|
18
18
  return nil unless ThorEnhance.configuration.allowed?(self)
19
19
 
20
- value = instance_variable_get("@#{name}")
21
- value ||= {}
22
20
  # Usage is nil when the `desc` has not been defined yet -- Under normal circumstance this will never happen
23
21
  if @usage.nil?
24
22
  raise ArgumentError, "Usage is not set. Please ensure `#{name}` is defined after usage is set"
25
23
  end
26
24
 
25
+ __thor_enhance_validate_arguments!(object, input, args, kwargs)
26
+ value = instance_variable_get("@#{name}")
27
+ value ||= {}
28
+
27
29
  # Required check gets done on command initialization (defined below in ClassMethods)
28
30
  if input.nil?
29
31
  # no op when it is nil
@@ -39,14 +41,14 @@ module ThorEnhance
39
41
 
40
42
  if object[:repeatable]
41
43
  value[@usage] ||= []
42
- value[@usage] << input
44
+ value[@usage] << { input: input, arguments: { kwargs: kwargs, positional: args } }
43
45
  else
44
46
  if value[@usage]
45
47
  raise ValidationFailed, "#{@usage} recieved command method `#{name}` with repeated invocations of " \
46
48
  "`#{name}`. Please remove the secondary invocation. Or set `#{name}` as a repeatable command method"
47
49
  end
48
50
 
49
- value[@usage] = input
51
+ value[@usage] = { input: input, arguments: { kwargs: kwargs, positional: args } }
50
52
  end
51
53
 
52
54
  instance_variable_set("@#{name}", value)
@@ -106,6 +108,10 @@ module ThorEnhance
106
108
  # Skip if the method is part of the ignore list
107
109
  next if ThorEnhance::Tree.ignore_commands.include?(meth.to_s)
108
110
 
111
+ # subcommands/subtasks need not require things that regular commands need
112
+ # If user wants them on the sucommand, thats cool, but we will never enforce it
113
+ next if subcommands.map(&:to_s).include?(meth.to_s)
114
+
109
115
  # At this point, the command method is missing, we are not in disable mode, and the command method was required
110
116
  # raise all hell
111
117
  raise ThorEnhance::RequiredOption, "`#{meth}` does not have required command method #{name} invoked. " \
@@ -131,6 +137,30 @@ module ThorEnhance
131
137
 
132
138
  private
133
139
 
140
+
141
+ def __thor_enhance_validate_arguments!(object, input, args, kwargs)
142
+ expected_arity = object.dig(:arity)
143
+ if args.length != expected_arity
144
+ raise ArgumentError, "Excluding #{input}, the expected arity command method `#{name}` for #{@usage} is #{expected_arity}. Provided #{args.length}"
145
+ end
146
+
147
+ # checks if there are extra kwargs present that are not expected
148
+ available_kwargs = object.dig(:kwargs).keys
149
+ extra_keys = kwargs.keys - available_kwargs
150
+ unless extra_keys.empty?
151
+ raise ArgumentError, "#{@usage} received command method `#{name}` with unknown KWargs #{extra_keys}"
152
+ end
153
+
154
+ # Checks if all the required kwargs are present
155
+ req_kwargs = object.dig(:kwargs).select { _2 }.keys
156
+ missing_required_kwargs = req_kwargs - kwargs.keys
157
+
158
+ # binding.pry if expected_arity > 0 || available_kwargs.length > 0
159
+ return if missing_required_kwargs.empty?
160
+
161
+ raise ArgumentError, "#{@usage} received command method `#{name}` with missing KWargs #{missing_required_kwargs}"
162
+ end
163
+
134
164
  def __thor_enhance_access(type:, &block)
135
165
  raise ArgumentError, "Expected to receive block. No block given" unless block_given?
136
166
 
@@ -58,6 +58,30 @@ module ThorEnhance
58
58
  self.class.disallow_changes!
59
59
  end
60
60
 
61
+ def readme_enhance!(required: false, &block)
62
+ # only inject readme things if it is required client side
63
+ require "thor_enhance/thor_auto_generate_inject"
64
+ require "thor_enhance/autogenerate"
65
+
66
+ if defined?(@autogenerated_config)
67
+ raise ValidationFailed, "ReadMe Enhance has already been initialized."
68
+ end
69
+
70
+ autogenerated_config.set_default_required(required)
71
+ autogenerated_config.default
72
+ yield(autogenerated_config) if block_given?
73
+
74
+ autogenerated_config.configuration.each do |meth, object|
75
+ object.each do |name, args|
76
+ public_send(meth, name, **args)
77
+ end
78
+ end
79
+ end
80
+
81
+ def autogenerated_config
82
+ @autogenerated_config ||= Autogenerate::Configuration.new
83
+ end
84
+
61
85
  def command_method_enhance
62
86
  @command_method_enhance ||= {}
63
87
  end
@@ -66,6 +90,14 @@ module ThorEnhance
66
90
  @klass_procs ||= []
67
91
  end
68
92
 
93
+ def basename
94
+ @basename
95
+ end
96
+
97
+ def basename=(name)
98
+ @basename = name
99
+ end
100
+
69
101
  def allowed
70
102
  @allowed ||= DEFAULT_ALLOWED
71
103
  end
@@ -92,14 +124,21 @@ module ThorEnhance
92
124
  end
93
125
 
94
126
  # Adding a new method to enhance the overall command
95
- def add_command_method_enhance(name, allowed_klasses: nil, enums: nil, required: false, repeatable: false)
127
+ def add_command_method_enhance(name, allowed_klasses: nil, enums: nil, required: false, repeatable: false, arity: 0, required_kwargs: [], optional_kwargs: [])
128
+ return if ENV["SKIP_TESTING_METHOD"]
129
+
96
130
  self.class.allow_changes?
97
131
 
98
- add_to_variable(command_method_enhance, ::Thor::Command.instance_methods, name, allowed_klasses, enums, required, repeatable)
132
+ kwargs = {}
133
+ required_kwargs.each { kwargs[_1.to_sym] = true }
134
+ optional_kwargs.each { kwargs[_1.to_sym] = false }
135
+ add_to_variable(command_method_enhance, ::Thor::Command.instance_methods, name, allowed_klasses, enums, required, repeatable, arity, kwargs)
99
136
  end
100
137
 
101
138
  # add a new flag on the command option
102
139
  def add_option_enhance(name, allowed_klasses: nil, enums: nil, required: false)
140
+ return if ENV["SKIP_TESTING_METHOD"]
141
+
103
142
  self.class.allow_changes?
104
143
 
105
144
  add_to_variable(option_enhance, ::Thor::Option.instance_methods, name, allowed_klasses, enums, required)
@@ -107,7 +146,7 @@ module ThorEnhance
107
146
 
108
147
  private
109
148
 
110
- def add_to_variable(storage, methods, name, allowed_klasses, enums, required, repeatable = false)
149
+ def add_to_variable(storage, methods, name, allowed_klasses, enums, required, repeatable = false, arity = 0, kwargs = false)
111
150
  # Reject if the name is not a Symbol or a string
112
151
  if [String, Symbol].none? { _1 === name }
113
152
  raise ArgumentError, "Invalid name type received. Received [#{name}] of type [#{name.class}]. Expected to be of type String or Symbol"
@@ -136,7 +175,11 @@ module ThorEnhance
136
175
  raise ArgumentError, "Recieved allowed_klasses with #{allowed_klasses}. When present, it is expected to be an Array"
137
176
  end
138
177
 
139
- storage[name.to_sym] = { allowed_klasses: allowed_klasses, enums: enums, required: required, repeatable: repeatable }
178
+ if arity < 0
179
+ raise ArgumentError, "Recieved arity with #{arity}. When present, it is expected to be greater than 0"
180
+ end
181
+
182
+ storage[name.to_sym] = { allowed_klasses: allowed_klasses, enums: enums, required: required, repeatable: repeatable, kwargs: kwargs, arity: arity }
140
183
  end
141
184
  end
142
185
  end
@@ -5,8 +5,6 @@ require "thor"
5
5
  module ThorEnhance
6
6
  module Option
7
7
  def self.thor_enhance_injection!
8
- return false unless ThorEnhance::Configuration.allow_changes?
9
-
10
8
  # Create getter method for the enhance instance variable
11
9
  ThorEnhance.configuration.option_enhance.each do |name, object|
12
10
  define_method(name) { instance_variable_get("@#{name}") }
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "thor_enhance"
4
+
5
+ module ThorEnhance
6
+ class Sample < Thor
7
+ thor_enhance_allow!
8
+
9
+ class SubCommand < Thor
10
+ thor_enhance_allow!
11
+
12
+ desc "innard", "Validate that a subcommand works. This description can be as long as you want it to be."
13
+ long_desc "Wow, This longer description will take precedence over the desc above. This is what will be shown in the readme autogenerated page. Try me out!"
14
+ example "innard --count 5", desc: "Innard sub command with a count of 5"
15
+ example "innard --count 35", desc: "Innard sub command with a count of 35"
16
+ header name: "Deprecation warning", desc: "This command will get deprecated in the next major version"
17
+ when_should_i_use_this "Use sub command task to validate that subocommands work as expected"
18
+ method_option :count, type: :numeric, readme: :skip
19
+ def innard;end;
20
+ end
21
+
22
+ desc "sub", "Thor sub command validation for thor enhance"
23
+ subcommand "sub", SubCommand
24
+
25
+ desc "sample", "This Sample command does a lot of nothing"
26
+ when_should_i_use_this <<~README
27
+ Have you ever wanted your code to be useless?
28
+ Well, this command does absolutely nothing.
29
+ This output is to say that this command does absolutely nothing
30
+ README
31
+ how_does_this_help "Honestly, this does not help at all", tag: "h4"
32
+ how_does_this_help "But its cool because it is a repatable command", tag: "h1"
33
+ example "sample", desc: "yo yo ma"
34
+ example "sample --boolean", desc: "yo yo ma"
35
+ method_option :boolean, aliases: "-b", type: :boolean, desc: "Just a normal boolean", readme: :important
36
+ def sample
37
+ Kernel.puts "Executed Sample method"
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ ####################
4
+ #
5
+ # Injects a method directly into the thor base class
6
+ # This allows the developer to have this convenience method
7
+ # Just by utilizing ThorEnhance
8
+ #
9
+ ####################
10
+ require "thor"
11
+
12
+ class Thor
13
+ desc "thor_enhance_autogenerate", "Auto Generate ReadMe material for your Thor commands"
14
+ method_option :subcommand, aliases: "-s", type: :string, repeatable: true, desc: "When provided, autogeneration will execute on the subcommand"
15
+ method_option :command, aliases: "-c", type: :string, desc: "When provided, autogeneration will occur only on this method. Note: When used with subcommand, method must exist on subcommand"
16
+ method_option :basename, aliases: "-b", type: :string, desc: "The name of the file that executes the Thor script"
17
+ method_option :generated_root, aliases: "-r", type: :string, default: File.expand_path("generated_readme"), desc: "The root location to store autogenerated files"
18
+ method_option :apply, aliases: "-a", type: :boolean, desc: "When comfortable with the changes made, enabling apply will save changes to generated files"
19
+
20
+ def thor_enhance_autogenerate
21
+ require "thor_enhance/autogenerate"
22
+ basename = options.basename || ThorEnhance.basename || File.basename($0)
23
+
24
+ result = ThorEnhance::Autogenerate.execute!(options: options, root: self.class, basename: basename)
25
+
26
+ if result[:status] == :pass
27
+ __auto_generate_success!(result[:saved_status])
28
+ else
29
+ __auto_generate_fail!(result[:msg_array])
30
+ end
31
+ end
32
+
33
+ no_tasks do
34
+ def __auto_generate_success!(statuses)
35
+ if statuses.all? { _1[:apply] == true }
36
+ say "Readme changes are enabled", [:green, :bold], true
37
+ else
38
+ say "Readme changes are not enabled. To apply changes, add `--apply` to the command", [:on_white, :black], true
39
+ end
40
+ statuses.each do |status|
41
+ case status[:diff]
42
+ when :new
43
+ say " Added : #{status[:path]}", [:green, :bold], true
44
+ when :same
45
+ say " No Change: #{status[:path]}", [:yellow, :bold], true
46
+ when :overwite
47
+ say " Changes : #{status[:path]}", [:cyan, :bold], true
48
+ else
49
+ say " : #{status[:path]}", [:bold], true
50
+ end
51
+ end
52
+ end
53
+
54
+ def __auto_generate_fail!(msg_array)
55
+ say_error set_color("*********************** FAILED OPERATION ***********************", :red, :bold)
56
+ say_error set_color("FAIL: Unable to continue", :red, :bold)
57
+ msg_array.each do |line|
58
+ say_error set_color("FAIL: #{line}", :red, :bold)
59
+ end
60
+ say_error set_color("*********************** FAILED OPERATION ***********************", :red, :bold)
61
+ exit 1
62
+ end
63
+ end
64
+ end
@@ -2,7 +2,7 @@
2
2
 
3
3
  module ThorEnhance
4
4
  class Tree
5
- DEFAULT_IGNORE_COMMANDS = ["help"]
5
+ DEFAULT_IGNORE_COMMANDS = ["help", "thor_enhance_autogenerate"]
6
6
 
7
7
  def self.add_ignore_commands(command)
8
8
  return false if ignore_commands.include?(command)
@@ -20,6 +20,8 @@ module ThorEnhance
20
20
  end
21
21
 
22
22
  def self.tree(base:, parent: nil)
23
+ raise TreeFailure, "#{base} does not respond to all_commands. Unable to continue" unless base.respond_to?(:all_commands)
24
+
23
25
  base.all_commands.map do |k, command|
24
26
  next if ignore_commands.include?(k)
25
27
 
@@ -36,7 +38,7 @@ module ThorEnhance
36
38
  @parent = parent
37
39
  @base = base
38
40
  @command = command
39
- @children = []
41
+ @children = {}
40
42
 
41
43
  if !base.subcommand_classes.nil? && base.subcommand_classes[command.name]
42
44
  @children = self.class.tree(parent: self, base: base.subcommand_classes[command.name])
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ThorEnhance
4
- VERSION = "0.4.0"
4
+ VERSION = "0.5.0"
5
5
  end
data/lib/thor_enhance.rb CHANGED
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "active_support"
4
+
3
5
  require "thor_enhance/base"
4
6
  require "thor_enhance/command"
5
7
  require "thor_enhance/command_hook"
@@ -10,10 +12,16 @@ require "thor_enhance/tree"
10
12
 
11
13
  module ThorEnhance
12
14
  class BaseError < StandardError; end
13
- class OptionNotAllowed < StandardError; end
14
- class ValidationFailed < StandardError; end
15
- class RequiredOption < StandardError; end
16
- class OptionDeprecated < StandardError; end
15
+ class OptionNotAllowed < BaseError; end
16
+ class ValidationFailed < BaseError; end
17
+ class RequiredOption < BaseError; end
18
+ class OptionDeprecated < BaseError; end
19
+ class TreeFailure < BaseError; end
20
+ class AutoGenerateFailure < BaseError; end
21
+
22
+ def self.basename
23
+ configuration.basename
24
+ end
17
25
 
18
26
  def self.configure
19
27
  yield configuration if block_given?
data/thor_enhance.gemspec CHANGED
@@ -30,4 +30,5 @@ Gem::Specification.new do |spec|
30
30
  spec.require_paths = ["lib"]
31
31
 
32
32
  spec.add_dependency "thor", "~> 1.3"
33
+ spec.add_dependency "activesupport", ">=6"
33
34
  end