brigadier 0.1.1

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.
@@ -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