ergane 0.0.1 → 0.2.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/CHANGELOG.md +44 -1
- data/LICENSE +18 -17
- data/README.md +271 -10
- data/lib/ergane/argument_definition.rb +17 -0
- data/lib/ergane/command.rb +159 -0
- data/lib/ergane/concerns/inheritance.rb +42 -0
- data/lib/ergane/concerns/option_handling.rb +43 -0
- data/lib/ergane/core_ext/array.rb +13 -0
- data/lib/ergane/core_ext/hash.rb +10 -0
- data/lib/ergane/core_ext/object.rb +47 -0
- data/lib/ergane/core_ext/option_parser.rb +18 -0
- data/lib/ergane/core_ext/string.rb +22 -0
- data/lib/ergane/dsl/block_dsl.rb +29 -0
- data/lib/ergane/dsl/command_dsl.rb +50 -0
- data/lib/ergane/dsl/macros.rb +23 -0
- data/lib/ergane/errors.rb +51 -0
- data/lib/ergane/formatter.rb +29 -0
- data/lib/ergane/help_formatter.rb +104 -0
- data/lib/ergane/option_definition.rb +49 -0
- data/lib/ergane/path_registry.rb +50 -0
- data/lib/ergane/runner.rb +64 -0
- data/lib/ergane/tool.rb +49 -95
- data/lib/ergane/util/formatting.rb +31 -0
- data/lib/ergane/version.rb +3 -1
- data/lib/ergane.rb +32 -77
- metadata +68 -72
- data/app/commands/ergane/console.rb +0 -22
- data/bin/ergane +0 -24
- data/lib/core_ext/option_parser.rb +0 -15
- data/lib/ergane/command_definition.rb +0 -176
- data/lib/ergane/debug.rb +0 -75
- data/lib/ergane/helpers/hashall.rb +0 -8
- data/lib/ergane/switch_definition.rb +0 -49
- data/lib/ergane/util.rb +0 -77
|
@@ -1,176 +0,0 @@
|
|
|
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
|
data/lib/ergane/debug.rb
DELETED
|
@@ -1,75 +0,0 @@
|
|
|
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
|
|
@@ -1,49 +0,0 @@
|
|
|
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
|
data/lib/ergane/util.rb
DELETED
|
@@ -1,77 +0,0 @@
|
|
|
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
|