ergane 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 6f27bb356ea374b87bf0a12ad73bc945e518dee66aa18797b5f9b06a197de896
4
+ data.tar.gz: 2de58095dd7014c321d13fcac71f9d16019db72cd6feb0896bafea5f9ae19d6e
5
+ SHA512:
6
+ metadata.gz: 3a3431e9dd63b745dc3765a83c98c0d3ed3d60837373d12b69371f1df05e5718be8b2fd5007808e4383ba8d77c0fd6997ba7dc867e317b5b598fc80921429161
7
+ data.tar.gz: fa7972b5a4019cff455ca2f0631181cb3ce49192a56ee01eb549c22827fbc8d41b77cc86d089178d04e2b63474626faab18dd3acbe45be12aedaec5a37254955
data/CHANGELOG.md ADDED
@@ -0,0 +1,5 @@
1
+ ## [Unreleased]
2
+
3
+ ## [0.1.0] - 2023-04-26
4
+
5
+ - Initial release
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2023 Dale Stevens
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,18 @@
1
+ # Ergane
2
+ **The patron goddess of craftsmen and artisans**
3
+
4
+ Library for creating lightweight, yet powerful CLI tools in Ruby.
5
+ Emphasis and priority on load speed and flexibility.
6
+
7
+ ## Requirements
8
+ Ruby 2.7+
9
+
10
+ May work with older versions.
11
+
12
+ ## Contributing
13
+
14
+ 1. Fork it ( https://github.com/TwilightCoders/ergane/fork )
15
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
16
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
17
+ 4. Push to the branch (`git push origin my-new-feature`)
18
+ 5. Create a new Pull Request
@@ -0,0 +1,22 @@
1
+ define :console do
2
+
3
+ description "Jump into an interactive REPL console"
4
+
5
+ requirements inherit: true do
6
+ require 'colorize'
7
+
8
+ end
9
+
10
+ switches(inherit: false) do
11
+ # option(:help, description: "display help")
12
+ end
13
+
14
+ run do
15
+ Pry.config.prompt_name = "#{Process.argv0.split('/').last.capitalize} #{label} ".light_blue
16
+ Pry.start
17
+ end
18
+
19
+ def support_method
20
+
21
+ end
22
+ end
data/bin/ergane ADDED
@@ -0,0 +1,24 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ profile = nil
4
+ if ARGV.include?('--profile')
5
+ require 'ruby-prof'
6
+ profile = RubyProf::Profile.new
7
+ profile.exclude_common_methods!
8
+ profile.start
9
+ end
10
+
11
+ require 'bundler/setup'
12
+ require 'ergane'
13
+ require 'ergane/tool'
14
+
15
+ tool = Ergane::Tool.new :ergane, 'lib/ergane/commands/**/*.rb', 'app/**/commands/**/*.rb'
16
+ tool.run
17
+
18
+ if profile
19
+ result = profile.stop
20
+ File.open "profile-graph.html", 'w+' do |file|
21
+ # RubyProf::GraphHtmlPrinter.new(results).print(file)
22
+ RubyProf::CallStackPrinter.new(result).print(file)
23
+ end
24
+ end
@@ -0,0 +1,15 @@
1
+ class OptionParser
2
+
3
+ # Like order!, but leave any unrecognized --switches alone
4
+ def order_recognized!(args)
5
+ extra_opts = []
6
+ begin
7
+ order!(args) { |a| extra_opts << a }
8
+ rescue OptionParser::InvalidOption => e
9
+ extra_opts << e.args[0]
10
+ retry
11
+ end
12
+ args[0, 0] = extra_opts
13
+ end
14
+
15
+ end
@@ -0,0 +1,176 @@
1
+ # IDEA: "switches" are just "inline commands".
2
+ # They share a similar structure to a command.
3
+ # They have a label, description, and optionally a "run block"
4
+
5
+ require 'pry'
6
+ require 'helpers/hashall'
7
+ require 'switch_definition'
8
+
9
+ module Ergane
10
+
11
+ class CommandDefinition < Hashall
12
+
13
+ attr_reader :label
14
+ attr_reader :chain
15
+ attr_reader :description
16
+ attr_reader :switch_definitions
17
+ attr_reader :switch_parser
18
+ attr_reader :requirements_block
19
+ attr_reader :run_block
20
+
21
+ def pretty_print(q)
22
+ q.text "#{self.class.name} (#{label})"
23
+ q.text "\n\tCommands:"
24
+ q.group(1, " {", "}") do
25
+ self.each_pair do |key, value|
26
+ q.breakable
27
+ q.text "#{key}: #{value}"
28
+ end
29
+ end
30
+ end
31
+
32
+ def run(*args)
33
+ if run_block
34
+ instance_exec(&requirements_block) if requirements_block
35
+ instance_exec(*args, &run_block) if run_block
36
+ else
37
+ puts "show help for this command"
38
+ end
39
+ end
40
+
41
+ def self.define(label, chain: [], &block)
42
+ new(label, *chain).tap do |c|
43
+ c.define(chain: chain, &block)
44
+ end
45
+ end
46
+
47
+ def define(chain: [], &block)
48
+ dsl_parse(&block)
49
+ end
50
+
51
+ def commands
52
+ self.to_h
53
+ end
54
+
55
+ def arguments
56
+ if commands.any?
57
+ commands.keys
58
+ else
59
+ instance_method(:run).parameters.map { |arg| arg[1] }
60
+ end
61
+ end
62
+
63
+ def default_switches
64
+ @default_switches ||= switch_definitions.inject({}) do |collector, (label, switch)|
65
+ collector[label] = switch.default
66
+ collector
67
+ end
68
+ @default_switches.dup
69
+ end
70
+
71
+ def parse_args(args, path = [])
72
+ if args.any? && args.first.match(/\A(\w+)\z/) && word = args.first.to_sym
73
+ case command = self[word]
74
+ when CommandDefinition
75
+ path << args.shift
76
+ command.parse_args(args, path)
77
+ else
78
+ puts "no such subcommand #{word} for #{self}"
79
+ end
80
+ else
81
+ # These are args for this command now.
82
+ Ergane.logger.debug "Now, process these args #{args} for #{label}"
83
+ switch_parser.order_recognized!(args)
84
+ [self, args || []]
85
+ end
86
+ end
87
+
88
+ protected
89
+
90
+ def dsl_parse(&block)
91
+ dsl = DSL.new.tap do |dsl|
92
+ dsl.instance_eval(&block)
93
+ end
94
+ @switch_definitions.merge!(dsl.config.delete(:switch_definitions))
95
+ dsl.config.each do |k, v|
96
+ begin
97
+ instance_variable_set("@#{k}", v)
98
+ rescue
99
+ binding.pry
100
+ end
101
+ end
102
+
103
+ switches = default_switches
104
+ switch_definitions.values.each do |o|
105
+ o.attach(@switch_parser, self) do |value|
106
+ value = case o.kind
107
+ when TrueClass
108
+ true
109
+ when FalseClass
110
+ false
111
+ else
112
+ value.nil? ? true : value
113
+ end
114
+ Ergane.logger.debug "Setting switches[#{o.label}] = #{value.inspect}"
115
+ switches[o.label] = value
116
+ end
117
+ end
118
+ end
119
+
120
+ private
121
+
122
+ def initialize(label, *chain)
123
+ super()
124
+ @chain = chain
125
+ @label = label
126
+ @switch_definitions = {}
127
+ @requirement_options = {
128
+ inherit: true
129
+ }
130
+ @run_options = {
131
+ inherit: true
132
+ }
133
+ @switch_parser = OptionParser.new
134
+ end
135
+
136
+ class DSL
137
+ attr_reader :config
138
+
139
+ def initialize
140
+ @config = {
141
+ switch_definitions: {},
142
+ run_block: nil,
143
+ requirements_block: nil
144
+ }
145
+ end
146
+
147
+ def method_missing(k, v)
148
+ @config[k] = v
149
+ end
150
+
151
+ def switches(inherit: true, drop: [], &block)
152
+ def option(label, short: nil, kind: nil, description: nil, default: nil, &block)
153
+ label, argument = case label
154
+ when Hash
155
+ [label.keys.first, "=#{label.values.first}"]
156
+ else
157
+ [label, nil]
158
+ end
159
+ warn "Warning! #{label.inspect} option is being redefined.".red if @config[:switch_definitions][label]
160
+ @config[:switch_definitions][label] = SwitchDefinition.new(label, argument: argument, short: short, kind: kind, description: description, default: default, &block)
161
+ end
162
+ block.call if block_given?
163
+ @config[:switch_definitions]
164
+ end
165
+
166
+ def requirements(options, &block)
167
+ @config[:requirements_block] = block
168
+ end
169
+
170
+ def run(&block)
171
+ # puts "setting run_block"
172
+ @config[:run_block] = block
173
+ end
174
+ end
175
+ end
176
+ end
@@ -0,0 +1,75 @@
1
+ module Ergane
2
+ module Debug
3
+
4
+ class << self
5
+
6
+ @nl = false
7
+
8
+ def enable_break!
9
+ class << self
10
+ define_method(:break, &binding.method(:pry))
11
+ end
12
+ end
13
+
14
+ def suppress
15
+ original_stdout, original_stderr = $stdout.clone, $stderr.clone
16
+ $stderr.reopen File.new('/dev/null', 'w')
17
+ $stdout.reopen File.new('/dev/null', 'w')
18
+ yield
19
+ ensure
20
+ $stdout.reopen original_stdout
21
+ $stderr.reopen original_stderr
22
+ end
23
+
24
+ def break
25
+ puts "Breakpoints Not Enabled"
26
+ end
27
+
28
+ def format_print(m)
29
+ case m
30
+ when String
31
+ format_print(m.split("\n"))
32
+ when Array
33
+ m.join("\n\t")
34
+ else
35
+ m
36
+ end
37
+ end
38
+
39
+ def puts(m=nil, prefix: false, &block)
40
+ prefix ||= $debug ? 'DEBUG' : false
41
+ if (prefix)
42
+ if @nl || m.blank?
43
+ $stdout.puts format_print(m)
44
+ else
45
+ $stdout.print "[#{prefix.upcase.light_magenta}] " unless prefix.blank?
46
+ $stdout.puts format_print(m)
47
+ end
48
+ else
49
+ yield if block_given?
50
+ end
51
+ @nl = false
52
+ end
53
+
54
+ def print(m=nil, prefix: false, &block)
55
+ @nl = true
56
+ prefix ||= $debug ? 'DEBUG' : false
57
+ if (prefix)
58
+ if (m.blank?)
59
+ $stdout.print format_print(m)
60
+ else
61
+ $stdout.print "[#{prefix.upcase.light_magenta}] " unless prefix.blank?
62
+ $stdout.print format_print(m)
63
+ end
64
+ else
65
+ yield if block_given?
66
+ end
67
+ end
68
+
69
+ end
70
+
71
+ enable_break! if $debug
72
+
73
+ end
74
+
75
+ end
@@ -0,0 +1,8 @@
1
+ module Ergane
2
+ class Hashall < Hash
3
+ def initialize(*args)
4
+ super()
5
+ self.default_proc = -> (h, k) { h[k] = self.class.new(*args) }
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,49 @@
1
+ module Ergane
2
+ class NamedBlock
3
+ def self.new(*args, &block)
4
+ Class.new do
5
+ args.each do |arg|
6
+ attr_reader arg.to_sym
7
+ end
8
+
9
+ def initialize(label, args)
10
+ @label = label.to_sym
11
+ args.each do |arg, value|
12
+ instance_variable_set("@#{args}", value)
13
+ end
14
+ end
15
+ end
16
+ end
17
+ private :initialize
18
+ end
19
+
20
+ class SwitchDefinition < NamedBlock.new(:short, :kind, :argument, :description, :default)
21
+ attr_reader :label
22
+ attr_reader :short
23
+ attr_reader :kind
24
+ attr_reader :argument
25
+ attr_reader :description
26
+ attr_reader :default
27
+ attr_reader :run_block
28
+
29
+ def initialize(label, short: nil, argument: nil, kind: nil, description: nil, default: nil, &block)
30
+ @label, @short, @argument, @kind, @description, @default = label.to_sym, short, argument, kind, description, default
31
+ @run_block = block if block_given?
32
+ end
33
+
34
+ def attach(option_parser, command, &block)
35
+ flag_arg = argument ? "=#{argument}" : ""
36
+ args = []
37
+ args << "-#{short}#{flag_arg}" if short
38
+ args << "--#{label.to_s.gsub(/_/, '-')}#{flag_arg}"
39
+ args << kind if kind
40
+ args << description if description
41
+
42
+ option_parser.on(*args, Proc.new { |value|
43
+ command.instance_exec(value, &block) if block_given?
44
+ command.instance_exec(value, &run_block) if run_block
45
+ })
46
+ end
47
+
48
+ end
49
+ end
@@ -0,0 +1,116 @@
1
+ module Ergane
2
+ class Tool < CommandDefinition
3
+ attr_reader :title #capitalized :label
4
+ attr_reader :version
5
+
6
+ def initialize(label, *paths)
7
+ super(label)
8
+
9
+ @title = label.capitalize
10
+ @version = VERSION
11
+
12
+ # Dogfood-ing
13
+ define do
14
+ description "Basic CLI Tool"
15
+ switches do
16
+ switch :help, default: false, kind: TrueClass, description: "Display this help block" do
17
+ raise Help
18
+ end
19
+ switch :version, default: false, kind: TrueClass, description: "Display the version" do
20
+ # TODO: Push ARGV into a variable at the command level that can be manipulated by flags/switches
21
+ # NOTE: This would allow a --version to morph into a version command and we could push all this logic to that.
22
+ # Additional logic for --version would be -1 or --short etc.
23
+ puts "#{@title} Version: #{Ergane::VERSION}"
24
+ exit
25
+ end
26
+ # switch verbose: FalseClass, short: :v, "Turn on verbose logging"
27
+ end
28
+
29
+ run do
30
+ begin
31
+ command, args = self, []
32
+ Process.setproctitle(label.to_s)
33
+ command, args = self.parse_args(ARGV.dup)
34
+
35
+ command.run(*args)
36
+ puts "Finished running #{label}"
37
+ rescue Interrupt
38
+ puts "\nOkay. Aborting."
39
+ rescue RuntimeError
40
+ puts "RuntimeError"
41
+ binding.pry
42
+ rescue Help
43
+ puts help(command, args)
44
+ ensure
45
+ system "printf '\033]0;\007'"
46
+ end
47
+ end
48
+ end
49
+
50
+ Pry.config.prompt_name = "#{title} ".light_blue
51
+
52
+ load_commands(paths)
53
+ end
54
+
55
+ def help(command, args=[])
56
+ missing_args = command.arguments.product([false]).to_h.merge(args.product([true]).to_h).map do |arg, is_missing|
57
+ a = arg.to_s.light_black.underline.tap do |b|
58
+ b.blink if is_missing
59
+ end
60
+ end.join(' ')
61
+
62
+ command.switch_parser.banner = [].tap do |text|
63
+ text << "About: #{description}"
64
+ text << "Version: #{version.to_s.light_blue}"
65
+ text << "Usage: #{([label] + chain).join(' ').light_red} #{'[options]'.light_cyan} "
66
+ if commands.any?
67
+ text.last << "[subcommand]".light_black.underline
68
+ text << (" ┌" + ("─" * (text.last.uncolorize.length - 12)) + "┘").light_black
69
+ commands.each do |key, command|
70
+ # text << " ├─┐".light_black + " #{(klass.terms.join(', ')).ljust(24, ' ')} ".send(Athena::Util.next_color) + klass.description.light_black
71
+ text << " ├─┐".light_black + " #{key.to_s.ljust(24, ' ')} " + command.description.light_black
72
+ end
73
+ text << (" └" + "─" * 64).light_black
74
+ else
75
+ # text.last << command.arguments(missing_args.keys)
76
+ end
77
+ # text << list_examples if examples.any?
78
+ text << "Options:".light_cyan
79
+ end.join("\n")
80
+ switch_parser
81
+ end
82
+
83
+ def self.define(label, chain: [], &block)
84
+ c = CommandDefinition.define(label, chain: chain, &block)
85
+
86
+ parent_command = if chain.any?
87
+ Ergane.active_tool.dig(*chain)
88
+ else
89
+ Ergane.active_tool
90
+ end
91
+
92
+ parent_command[label] = c
93
+ end
94
+
95
+ def load_commands(paths)
96
+ activate_tool do
97
+ Ergane.logger.debug "Loading paths:"
98
+ Array.wrap(paths).each do |path|
99
+ Ergane.logger.debug " - #{path}"
100
+ Dir[path].each do |path|
101
+ file = path.split('/').last
102
+ Ergane.logger.debug " - loading #{path.split('/').last(4).join('/')}"
103
+ instance_eval(File.read(path), file)
104
+ end
105
+ end
106
+ end
107
+ end
108
+
109
+ private
110
+
111
+ def activate_tool(&block)
112
+ Ergane.activate_tool(self, &block)
113
+ end
114
+
115
+ end
116
+ end
@@ -0,0 +1,77 @@
1
+ module Ergane
2
+ module Util
3
+
4
+ def self.colors
5
+ # @colors = [:red, :yellow, :green, :blue, :cyan, :magenta].cycle
6
+ @colors ||= [:light_red, :light_yellow, :light_green, :light_blue, :light_cyan, :light_magenta].cycle
7
+ end
8
+
9
+ def self.color_array(array)
10
+ array.collect do |a|
11
+ a.to_s.send(colors.next.to_sym).underline
12
+ end
13
+ end
14
+
15
+ def self.color_array!(array)
16
+ colors.rewind
17
+ array.collect do |a|
18
+ a.to_s.send(colors.next.to_sym).underline
19
+ end
20
+ end
21
+
22
+ def self.rainbow(string, delimeter=' ')
23
+ rainbow_a(string.split(delimeter)).join(delimeter)
24
+ end
25
+
26
+ def self.rainbow!(string, delimeter=' ')
27
+ rainbow_a!(string.split(delimeter)).join(delimeter)
28
+ end
29
+
30
+ def self.rainbow_a(array)
31
+ array.collect do |a|
32
+ a.to_s.send(next_color).underline
33
+ end
34
+ end
35
+
36
+ def self.rainbow_a!(array)
37
+ rainbow_colors.rewind
38
+ array.collect do |a|
39
+ a.to_s.send(next_color).underline
40
+ end
41
+ end
42
+
43
+ def self.next_color
44
+ colors.next
45
+ end
46
+
47
+ def self.rainbow_colors
48
+ @rainbow_colors = [:light_red, :light_yellow, :light_green, :light_blue, :light_cyan, :light_magenta].cycle
49
+ end
50
+
51
+ def self.next_rainbow_color
52
+ rainbow_colors.cycle
53
+ end
54
+
55
+ def self.full_name
56
+ @full_name ||= `finger \`whoami\` | grep Name | awk -F 'Name: ' '{print $2}'`.chomp
57
+ end
58
+
59
+ def self.last_name
60
+ @last_name || begin
61
+ split_names.last
62
+ end
63
+ end
64
+
65
+ def self.first_name
66
+ @first_name || begin
67
+ split_names.first
68
+ end
69
+ end
70
+
71
+ private
72
+
73
+ def self.split_names
74
+ @first_name, @last_name = ful_name.split(' ')
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,3 @@
1
+ module Ergane
2
+ VERSION = '0.0.1'
3
+ end
data/lib/ergane.rb ADDED
@@ -0,0 +1,85 @@
1
+ require 'active_support'
2
+ require 'active_support/core_ext'
3
+ require 'active_support/dependencies'
4
+ require 'optparse'
5
+ require 'colorize'
6
+ require 'notifier'
7
+ require 'pry-byebug'
8
+
9
+ $LOAD_PATH.unshift File.expand_path("#{__dir__}/ergane")
10
+
11
+ require 'ergane/version'
12
+ require 'ergane/command_definition'
13
+ require 'ergane/tool'
14
+
15
+ module Ergane
16
+
17
+ Help = Class.new(StandardError)
18
+ Interrupt = Class.new(StandardError)
19
+
20
+ class << self
21
+ attr_reader :logger
22
+
23
+ def root(*args)
24
+ (@root ||= Pathname.new(File.expand_path('../', __dir__))).join(*args)
25
+ end
26
+
27
+ def logger
28
+ @logger ||= Logger.new($stdout).tap do |log|
29
+ log.progname = @@active_tool&.title || self.name
30
+ log.level = :warn
31
+ end
32
+ end
33
+
34
+ # def debug(string)
35
+ # old_level = logger.level
36
+ # logger.level = :debug if $debug
37
+ # logger.debug(string)
38
+ # ensure
39
+ # logger.level = old_level
40
+ # end
41
+
42
+ @@active_tool = nil
43
+
44
+ def active_tool
45
+ @@active_tool
46
+ end
47
+
48
+ def activate_tool(tool)
49
+ previous_tool = @@active_tool
50
+ @@active_tool = tool
51
+ yield if block_given?
52
+ ensure
53
+ @@active_tool = previous_tool
54
+ end
55
+
56
+ def notify(message, title: nil, sound: nil, icon: nil, group: nil)
57
+ cmd = ['terminal-notifier']
58
+ cmd << "-group #{Process.pid}#{group}"
59
+ cmd << "-title #{active_tool.label}"
60
+ cmd << "-subtitle #{title}" if title
61
+ cmd << "-appIcon 'assets/athena md-light-shadow.png'" if icon
62
+ cmd << "-message '#{message}'"
63
+ cmd << "-activate 'com.apple.Terminal'" # if macos
64
+ cmd << "-sound #{sound}" if sound
65
+ Thread.new { `afplay /System/Library/Sounds/#{sound == true ? 'Blow' : sound}.aiff` } unless sound == false
66
+
67
+ `#{cmd.join(' ')}`
68
+ # Notifier.notify(title: title, message: message, image: 'assets/athena md-light-shadow.png')
69
+ end
70
+
71
+ # Show a list of available extensions to use
72
+ def extensions
73
+ Extension.library
74
+ end
75
+ end
76
+ end
77
+
78
+ if ARGV.include?('--debug')
79
+ $debug = true
80
+ Ergane.logger.level = :debug
81
+ end
82
+
83
+ Dir[Ergane.root('lib', 'core_ext', "*.rb")].each do |path|
84
+ require path
85
+ end
metadata ADDED
@@ -0,0 +1,201 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ergane
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Dale Stevens
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2023-05-08 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activesupport
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: colorize
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: terminal-notifier
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: notifier
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: pry-byebug
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: bundler
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: ruby-prof
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: rspec
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: pry-byebug
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ - !ruby/object:Gem::Dependency
140
+ name: rake
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
153
+ description: |
154
+ Library for creating lightweight, yet powerful CLI tools in Ruby.
155
+ Emphasis and priority on load speed and flexibility.
156
+ email:
157
+ - dale@twilightcoders.net
158
+ executables:
159
+ - ergane
160
+ extensions: []
161
+ extra_rdoc_files: []
162
+ files:
163
+ - CHANGELOG.md
164
+ - LICENSE
165
+ - README.md
166
+ - app/commands/ergane/console.rb
167
+ - bin/ergane
168
+ - lib/core_ext/option_parser.rb
169
+ - lib/ergane.rb
170
+ - lib/ergane/command_definition.rb
171
+ - lib/ergane/debug.rb
172
+ - lib/ergane/helpers/hashall.rb
173
+ - lib/ergane/switch_definition.rb
174
+ - lib/ergane/tool.rb
175
+ - lib/ergane/util.rb
176
+ - lib/ergane/version.rb
177
+ homepage: https://github.com/TwilightCoders/ergane
178
+ licenses:
179
+ - MIT
180
+ metadata:
181
+ allowed_push_host: https://rubygems.org
182
+ post_install_message:
183
+ rdoc_options: []
184
+ require_paths:
185
+ - lib
186
+ required_ruby_version: !ruby/object:Gem::Requirement
187
+ requirements:
188
+ - - ">="
189
+ - !ruby/object:Gem::Version
190
+ version: '2.7'
191
+ required_rubygems_version: !ruby/object:Gem::Requirement
192
+ requirements:
193
+ - - ">="
194
+ - !ruby/object:Gem::Version
195
+ version: '0'
196
+ requirements: []
197
+ rubygems_version: 3.1.6
198
+ signing_key:
199
+ specification_version: 4
200
+ summary: Ergane — The patron goddess of craftsmen and artisans
201
+ test_files: []