brigadier 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,55 @@
1
+ module Brigadier
2
+ module Helper
3
+ def display_help_for(item, label)
4
+ opts = item.values.uniq(&:name)
5
+ return if opts.empty?
6
+ $stderr.puts label
7
+ opts.each do |opt|
8
+ next if opt.hidden?
9
+ $stderr.puts '%s %-28s %s' % [ indent, opt.display_name, opt.display_description ]
10
+ end
11
+ $stderr.puts
12
+ end
13
+
14
+ def help_requested?(args)
15
+ !(%w( --help -help -h ) & args).empty?
16
+ end
17
+
18
+ def display_help_if_requested(klasses, args)
19
+ return false unless help_requested?(args)
20
+ $stderr.puts
21
+ help(klasses)
22
+ true
23
+ end
24
+
25
+ def help(klasses)
26
+ klasses = [ *klasses ]
27
+ display_help_for(available_params_for(klasses, :toggles), 'Toggle(s)')
28
+ display_help_for(available_params_for(klasses, :options), 'Option(s)')
29
+ display_help_for(available_params_for(klasses, :arguments), 'Argument(s)')
30
+ display_help_for(available_params_for(klasses, :sub_commands), 'Subcommand(s)') unless sub_command?
31
+ end
32
+
33
+ def available_params_for(klasses, param)
34
+ klasses.each_with_object({}) { |k, a| a.merge!(k.public_send(param)) }
35
+ end
36
+
37
+ def inverse_toggle_arg?(arg)
38
+ arg =~ /^-{1,}no.+$/ ? true : false
39
+ end
40
+
41
+ def sub_command?
42
+ is_a?(Brigadier::Commands::SubCommand)
43
+ end
44
+
45
+ def option_or_toggle?(arg)
46
+ arg.match(/^-[-\w+]/)
47
+ end
48
+
49
+ private
50
+
51
+ def indent
52
+ @indent ||= (' ' * 2)
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,57 @@
1
+ module Brigadier
2
+ module Parameters
3
+ class Argument
4
+ include Base
5
+
6
+ def initialize(name, description, args, block)
7
+ @name = name
8
+ @description = description
9
+ @args = args
10
+ @value = nil
11
+ @block = block
12
+ assign_value_from_env_variable
13
+ end
14
+
15
+ def display_name
16
+ name
17
+ end
18
+
19
+ def display_description
20
+ opts = []
21
+ opts << 'valid_values: %s' % [ valid_values.inspect ] if valid_values?
22
+ opts << 'current: %s' % [ value.inspect ]
23
+ '%s (%s)' % [ description, opts.join(', ') ]
24
+ end
25
+
26
+ def valid_values
27
+ args.fetch(:valid_values, [])
28
+ end
29
+
30
+ def validate!
31
+ validate_presence! if required?
32
+ validate_valid_value! if valid_values?
33
+ validate_using_klass! if validator_klasses
34
+ end
35
+
36
+ def required?
37
+ true
38
+ end
39
+
40
+ def valid_values?
41
+ !valid_values.empty?
42
+ end
43
+
44
+ private
45
+
46
+ attr_reader :args
47
+
48
+ def validate_valid_value!
49
+ raise Exceptions::ValueInvalid.new(self), 'Value is invalid. Valid values are %s' % [ valid_values] if valid_values? && !valid_values.include?(value)
50
+ end
51
+
52
+ def validate_presence!
53
+ raise Exceptions::ValueMissing.new(self), 'Value is empty' if [ nil, '' ].include?(value)
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,75 @@
1
+ module Brigadier
2
+ module Parameters
3
+ module Base
4
+ attr_reader :name, :description, :value
5
+
6
+ def forbidden_parameters
7
+ [ :name, :description, :value ]
8
+ end
9
+
10
+ def value=(value)
11
+ @value = block_defined? ? block.call(value) : value
12
+ ENV[env_variable_value_key_name] = @value.to_s
13
+ end
14
+
15
+ def normalised_attribute_name
16
+ attribute_name.gsub(/[ -]/, '_')
17
+ end
18
+
19
+ def attribute_name
20
+ @attribute_name ||= args.fetch(:attribute_name, name).to_s
21
+ end
22
+
23
+ def hidden?
24
+ args.fetch(:hidden, false)
25
+ end
26
+
27
+ def value?
28
+ !value.nil?
29
+ end
30
+
31
+ def valid?
32
+ validate! && true
33
+ rescue Exceptions::Base
34
+ false
35
+ end
36
+
37
+ def required?
38
+ args.fetch(:required, false)
39
+ end
40
+
41
+ def block_defined?
42
+ !block.nil?
43
+ end
44
+
45
+ private
46
+
47
+ attr_reader :block
48
+
49
+ def default_value
50
+ nil
51
+ end
52
+
53
+ def validate_using_klass!
54
+ validator_klasses.each { |klass| klass.new(self).validate! }
55
+ end
56
+
57
+ def validator_klasses
58
+ args.fetch(:validators, nil)
59
+ end
60
+
61
+ def assign_value_from_env_variable
62
+ value = ENV.fetch(env_variable_value_key_name, default_value)
63
+ self.value = value if value
64
+ end
65
+
66
+ def normalised_name
67
+ name.gsub(/[ -]/, '_')
68
+ end
69
+
70
+ def env_variable_value_key_name
71
+ normalised_name.upcase
72
+ end
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,51 @@
1
+ module Brigadier
2
+ module Parameters
3
+ class Option
4
+ include Base
5
+
6
+ def initialize(name, description, args, block)
7
+ @name = name
8
+ @description = description
9
+ @args = args
10
+ @value = default_value
11
+ @block = block
12
+ assign_value_from_env_variable
13
+ end
14
+
15
+ def display_name
16
+ str = [ "--#{name}" ]
17
+ str << (required? ? '<value>' : '[<value>]')
18
+ str.join(' ')
19
+ end
20
+
21
+ def display_description
22
+ opts = []
23
+ opts << 'default: %s' % [ default_value ] if default_value
24
+ opts << 'required: %s' % [ required? ]
25
+ opts << 'current: %s' % [ value.inspect ]
26
+ '%s (%s)' % [ description, opts.join(', ') ]
27
+ end
28
+
29
+ def validate!
30
+ validate_presence! if required?
31
+ validate_using_klass! if validator_klasses
32
+ end
33
+
34
+ private
35
+
36
+ attr_reader :args
37
+
38
+ def aliases
39
+ args.fetch(:aliases, [])
40
+ end
41
+
42
+ def default_value
43
+ args.fetch(:default, nil)
44
+ end
45
+
46
+ def validate_presence!
47
+ raise Exceptions::ValueMissing.new(self), 'Value is empty' if [ nil, '' ].include?(value)
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,63 @@
1
+ module Brigadier
2
+ module Parameters
3
+ class Toggle
4
+ include Base
5
+
6
+ def initialize(name, description, args, block)
7
+ @name = name
8
+ @description = description
9
+ @args = args
10
+ @block = block
11
+ @value = default_value
12
+ assign_value_from_env_variable
13
+ end
14
+
15
+ def display_name
16
+ "--#{name}"
17
+ end
18
+
19
+ def display_description
20
+ '%s (%s)' % [ description, description_detail ]
21
+ end
22
+
23
+ def enable!
24
+ assign_value(true)
25
+ end
26
+
27
+ def disable!
28
+ assign_value(false)
29
+ end
30
+
31
+ private
32
+
33
+ attr_reader :args
34
+
35
+ def value_set?
36
+ value != default_value
37
+ end
38
+
39
+ def description_detail
40
+ detail = [ 'default: %s' % [ default_value ] ]
41
+ detail << 'current: %s' % [ value ] if value_set?
42
+ detail.join(', ')
43
+ end
44
+
45
+ def aliases
46
+ args.fetch(:aliases, [])
47
+ end
48
+
49
+ def klass_only
50
+ self.class.to_s.to_s.gsub(/^.*::/, '')
51
+ end
52
+
53
+ def default_value
54
+ args.fetch(:default, false)
55
+ end
56
+
57
+ def assign_value(value)
58
+ @value = value
59
+ ENV[env_variable_value_key_name] = value.to_s.downcase
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,9 @@
1
+ require 'brigadier/parameters/base'
2
+ require 'brigadier/parameters/argument'
3
+ require 'brigadier/parameters/option'
4
+ require 'brigadier/parameters/toggle'
5
+
6
+ module Brigadier
7
+ module Parameters
8
+ end
9
+ end
@@ -0,0 +1,71 @@
1
+ require 'ostruct'
2
+
3
+ module Brigadier
4
+ class Runner
5
+ include Helper
6
+
7
+ def initialize(args)
8
+ @args = args
9
+ end
10
+
11
+ def run(*klasses)
12
+ remaining_args = []
13
+ args_to_process = []
14
+ sub_command_to_execute = false
15
+ full_args = args.dup
16
+
17
+ collect_execute_blocks(klasses)
18
+
19
+ klasses.each do |klass|
20
+ remaining_args = args.dup
21
+
22
+ until remaining_args.empty?
23
+ arg = remaining_args.shift
24
+
25
+ klass.sub_commands.each do |names, sub_command|
26
+ next unless names.include?(arg)
27
+ sub_command_to_execute = sub_command
28
+ break
29
+ end
30
+
31
+ break if sub_command_to_execute
32
+
33
+ args_to_process << arg
34
+ end
35
+
36
+ break if sub_command_to_execute
37
+ end
38
+
39
+ if sub_command_to_execute
40
+ args_to_process += remaining_args
41
+ sub_command_to_execute.execute(args_to_process, full_args)
42
+ elsif default_command
43
+ default_command.execute(args, full_args, klasses)
44
+ elsif help_requested?(args)
45
+ $stderr.puts
46
+ help(klasses)
47
+ else
48
+ raise Exceptions::ExecuteBlockMissing.new(self), 'There is no execute {} block defined'
49
+ end
50
+ rescue Exceptions::ExecuteBlockMissing, Exceptions::Base => e
51
+ $stderr.puts "ERROR: #{e.message}"
52
+ exit(Exceptions::ERROR_EXIT_CODE)
53
+ end
54
+
55
+ private
56
+
57
+ attr_reader :args
58
+
59
+ def default_command
60
+ Brigadier.default_command
61
+ end
62
+
63
+ def collect_execute_blocks(klasses)
64
+ klasses.each do |klass|
65
+ execute_proc = klass.instance_variable_get('@execute_proc')
66
+ next unless execute_proc
67
+ Brigadier.set_default_command(klass, execute_proc)
68
+ end
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,25 @@
1
+ module Brigadier
2
+ module Validators
3
+ module Base
4
+ def initialize(obj)
5
+ @obj = obj
6
+ end
7
+
8
+ def validate!
9
+ raise Brigadier::Exceptions::Base.new(obj), failure_message unless valid?
10
+ end
11
+
12
+ private
13
+
14
+ attr_reader :obj
15
+
16
+ def value
17
+ @value ||= obj.value
18
+ end
19
+
20
+ def valid?
21
+ !obj.value.match(/poop/i)
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,15 @@
1
+ module Brigadier
2
+ module Validators
3
+ class Email
4
+ include Base
5
+
6
+ def failure_message
7
+ %('%s' is not a valid email address.) % [ value ]
8
+ end
9
+
10
+ def valid?
11
+ value.match(/\A([\w+\-].?)+@[a-z\d\-]+(\.[a-z]+)*\.[a-z]+\z/i)
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,7 @@
1
+ require 'brigadier/validators/base'
2
+ require 'brigadier/validators/email'
3
+
4
+ module Brigadier
5
+ module Validators
6
+ end
7
+ end
@@ -0,0 +1,3 @@
1
+ module Brigadier
2
+ VERSION = '0.1.1'.freeze
3
+ end
data/lib/brigadier.rb ADDED
@@ -0,0 +1,123 @@
1
+ require 'brigadier/version'
2
+ require 'brigadier/exceptions'
3
+ require 'brigadier/validators'
4
+ require 'brigadier/helper'
5
+ require 'brigadier/parameters'
6
+ require 'brigadier/commands'
7
+ require 'brigadier/runner'
8
+
9
+ module Brigadier
10
+ @@arguments = {}
11
+ @@options = {}
12
+ @@toggles = {}
13
+ @@sub_commands = {}
14
+ @@default_command = nil
15
+
16
+ class << self
17
+ def arguments
18
+ @@arguments
19
+ end
20
+
21
+ def options
22
+ @@options
23
+ end
24
+
25
+ def toggles
26
+ @@toggles
27
+ end
28
+
29
+ def sub_commands
30
+ @@sub_commands
31
+ end
32
+
33
+ def default_command
34
+ @@default_command
35
+ end
36
+
37
+ def set_default_command(klass, block)
38
+ @@default_command = Commands::Command.new(klass, block)
39
+ end
40
+ end
41
+
42
+ def options
43
+ @options ||= {}
44
+ end
45
+
46
+ def toggles
47
+ @toggles ||= {}
48
+ end
49
+
50
+ def arguments
51
+ @arguments ||= {}
52
+ end
53
+
54
+ def sub_commands
55
+ @sub_commands ||= {}
56
+ end
57
+
58
+ def execute(&block)
59
+ @execute_proc = block
60
+ end
61
+
62
+ def sub_command?
63
+ @sub_command || false
64
+ end
65
+
66
+ def sub_command(name, description, args = {}, &block)
67
+ @sub_command = true
68
+ instance = args.fetch(:instance, new)
69
+ aliases = args.fetch(:aliases, [])
70
+ all_aliases = ([ *name ] + aliases).uniq
71
+ args[:aliases] = all_aliases
72
+
73
+ sub_commands[all_aliases] = Commands::SubCommand.new(name, description, instance, args, block)
74
+ end
75
+
76
+ def argument(name, description, args = {}, &block)
77
+ arguments[name] = Parameters::Argument.new(name, description, args, block)
78
+ end
79
+
80
+ def option(name, description, args = {}, &block)
81
+ new_aliases = []
82
+ aliases = args.fetch(:aliases, [])
83
+
84
+ ([ *name ] + aliases).each do |n|
85
+ new_aliases << "--#{n}"
86
+ new_aliases << "-#{n}"
87
+ end
88
+
89
+ new_aliases.uniq!
90
+ args[:aliases] = new_aliases
91
+ options[new_aliases] = Parameters::Option.new(name, description, args, block)
92
+ end
93
+
94
+ def toggle(name, description, args = {}, &block)
95
+ new_aliases = []
96
+ new_inverse_aliases = []
97
+ aliases = args.fetch(:aliases, [])
98
+ modifiers = %w( -- - )
99
+ inverse_modifiers = %w( -no- --no- -not- --not- -no_ --no_ -not_ --not_ )
100
+
101
+ ([ *name ] + aliases).each do |n|
102
+ alt_name = n.gsub(/[ -]/, '_')
103
+
104
+ modifiers.each do |modifier|
105
+ new_aliases << '%s%s' % [ modifier, n]
106
+ new_aliases << '%s%s' % [ modifier, alt_name ]
107
+ end
108
+
109
+ inverse_modifiers.each do |modifier|
110
+ new_inverse_aliases << '%s%s' % [ modifier, n]
111
+ new_inverse_aliases << '%s%s' % [ modifier, alt_name ]
112
+ end
113
+ end
114
+
115
+ new_aliases.uniq!
116
+ new_inverse_aliases.uniq!
117
+ all_aliases = [ new_aliases + new_inverse_aliases ].uniq.flatten
118
+ args[:aliases] = new_aliases
119
+ args[:inverse_aliases] = new_inverse_aliases
120
+
121
+ toggles[all_aliases] = Parameters::Toggle.new(name, description, args, block)
122
+ end
123
+ end