ivanvc-choice 0.1.3.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,87 @@
1
+ $:.unshift "../lib"
2
+ $:.unshift "lib"
3
+ require 'choice'
4
+
5
+ port = 21
6
+ PROGRAM_VERSION = 4
7
+
8
+ Choice.options do
9
+ #banner "Usage: ftpd.rb [options]"
10
+
11
+ header ""
12
+ header "Specific options:"
13
+
14
+ option :host do
15
+ short '-h'
16
+ long '--host=HOST'
17
+ desc "The hostname or ip of the host to bind to"
18
+ desc "(default 127.0.0.1)"
19
+ default '127.0.0.1'
20
+ end
21
+
22
+ option :port do
23
+ short '-p'
24
+ long '--port=PORT'
25
+ desc "The port to listen on (default 21)"
26
+ cast Integer
27
+ default port
28
+ end
29
+
30
+ option :clients do
31
+ short '-c'
32
+ long '--clients=NUM'
33
+ cast Integer
34
+ desc "The number of connections to allow at once (default 5)"
35
+ default 5
36
+ end
37
+
38
+ option :protocol do
39
+ short '-l'
40
+ long '--protocol=PROTOCOL'
41
+ desc "The protocol to use (default ftp)"
42
+ valid %w[ftp sftp]
43
+ default 'ftp'
44
+ end
45
+
46
+ option :yaml_cfg do
47
+ long '--config=FILE'
48
+ desc 'Load configuration from YAML file'
49
+ end
50
+
51
+ option :sample do
52
+ long '--sample'
53
+ desc "See a sample YAML config file"
54
+ action do
55
+ puts "See!"
56
+ exit
57
+ end
58
+ end
59
+
60
+ option :debug do
61
+ short '-d'
62
+ long '--debug[=LEVEL]'
63
+ desc 'Turn on debugging mode'
64
+ end
65
+
66
+ separator ''
67
+ separator 'Common options: '
68
+
69
+ option :help do
70
+ long '--help'
71
+ desc 'Show this message'
72
+ end
73
+
74
+ option :version do
75
+ short '-v'
76
+ long '--version'
77
+ desc 'Show version'
78
+ action do
79
+ puts "ftpd.rb FTP server v#{PROGRAM_VERSION}"
80
+ exit
81
+ end
82
+ end
83
+
84
+ end
85
+
86
+ print "Choices: "
87
+ puts Choice.choices.inspect
@@ -0,0 +1,42 @@
1
+ $:.unshift "../lib"
2
+ $:.unshift "lib"
3
+ require 'choice'
4
+
5
+ suits = %w[clubs diamonds spades hearts]
6
+ stringed_numerics = (1..13).to_a.map { |a| a.to_s }
7
+ valid_cards = stringed_numerics + %w[jack queen king ace]
8
+ cards = {}
9
+ stringed_numerics.each { |n| cards[n] = n }
10
+ cards.merge!('1' => 'ace', '11' => 'jack', '12' => 'queen', '13' => 'king')
11
+
12
+ Choice.options do
13
+ header "Gambling is fun again! Pick a card and a suit (or two), then see if you win!"
14
+ header ""
15
+ header "Options:"
16
+
17
+ option :suit, :required => true do
18
+ short '-s'
19
+ long '--suit *SUITS'
20
+ desc "The suit you wish to choose. Required. You can pass in more than one, even."
21
+ desc " Valid suits: #{suits * ' '}"
22
+ valid suits
23
+ end
24
+
25
+ separator ''
26
+
27
+ option :card, :required => true do
28
+ short '-c'
29
+ long '--card CARD'
30
+ desc "The card you wish to gamble on. Required. Only one, please."
31
+ desc " Valid cards: 1 - 13, jack, queen, king, ace"
32
+ valid valid_cards
33
+ cast String
34
+ end
35
+ end
36
+
37
+ suit = suits[rand(suits.size)]
38
+ card = cards[(rand(13)+1).to_s]
39
+
40
+ puts "I drew the #{card} of #{suit}."
41
+ puts "You picked the #{Choice.choices.card} of #{Choice.choices.suit * ' or '}."
42
+ puts "You " << (Choice.choices.suit.include?(suit) && card == cards[Choice.choices.card] ? 'win!' : 'lose :(')
@@ -0,0 +1,166 @@
1
+ $:.unshift File.dirname(__FILE__)
2
+ require 'choice/option'
3
+ require 'choice/parser'
4
+ require 'choice/writer'
5
+ require 'choice/lazyhash'
6
+
7
+ #
8
+ # Usage of this module is lovingly detailed in the README file.
9
+ #
10
+ module Choice
11
+ extend self
12
+
13
+ # The main method, which defines the options
14
+ def options(hash = {}, &block)
15
+ # if we are passing in a hash to define our options, use that straight
16
+ options_from_hash(hash) unless hash.empty?
17
+
18
+ # Setup all instance variables
19
+ reset! if hash.empty?
20
+ @@args ||= ARGV
21
+
22
+ # Eval the passed block to define the options.
23
+ instance_eval(&block) if block_given?
24
+
25
+ # Parse what we've got.
26
+ parse unless parsed?
27
+ end
28
+
29
+ # Set options from a hash, shorthand style
30
+ def options_from_hash(options_hash)
31
+ options_hash.each do |name, definition|
32
+ option = Option.new
33
+ definition.each do |key, value|
34
+ Array(value).each { |hit| option.send(key, hit) }
35
+ end
36
+ @@options << [name.to_s, option]
37
+ end
38
+ end
39
+
40
+ # Return an array representing the rest of the command line arguments
41
+ def rest
42
+ @@rest
43
+ end
44
+
45
+ # Returns a hash representing options passed in via the command line.
46
+ def choices
47
+ @@choices
48
+ end
49
+
50
+ # Shortcut access to Choice.choices
51
+ def [](choice)
52
+ choices[choice]
53
+ end
54
+
55
+ # Defines an option.
56
+ def option(opt, options = {}, &block)
57
+ # Notice: options is maintained as an array of arrays, the first element
58
+ # the option name and the second the option object.
59
+ @@options << [opt.to_s, Option.new(options, &block)]
60
+ end
61
+
62
+ # Separators are text displayed by --help within the options block.
63
+ def separator(str)
64
+ # We store separators as simple strings in the options array to maintain
65
+ # order. They are ignored by the parser.
66
+ @@options << str
67
+ end
68
+
69
+ # Define the banner, header, footer methods. All are just getters/setters
70
+ # of class variables.
71
+ %w[banner header footer].each do |method|
72
+ define_method(method) do |string|
73
+ variable = "@@#{method}"
74
+ return class_variable_get(variable) if string.nil?
75
+ val = class_variable_get(variable) || ''
76
+ class_variable_set(variable, val << string)
77
+ end
78
+ end
79
+
80
+
81
+ # Parse the provided args against the defined options.
82
+ def parse #:nodoc:
83
+ # Do nothing if options are not defined.
84
+ return unless @@options.size > 0
85
+
86
+ # Show help if it's anywhere in the argument list.
87
+ if @@args.include?('--help')
88
+ help
89
+ else
90
+ begin
91
+ # Delegate parsing to our parser class, passing it our defined
92
+ # options and the passed arguments.
93
+ @@choices, @@rest = Parser.parse(@@options, @@args)
94
+ @@choices = LazyHash.new(@@choices)
95
+ rescue Choice::Parser::ParseError
96
+ # If we get an expected exception, show the help file.
97
+ help
98
+ end
99
+ end
100
+ end
101
+
102
+ # Did we already parse the arguments?
103
+ def parsed? #:nodoc:
104
+ @@choices ||= false
105
+ end
106
+
107
+ # Print the help screen by calling our Writer object
108
+ def help #:nodoc:
109
+ Writer.help( { :banner => @@banner, :header => @@header,
110
+ :options => @@options, :footer => @@footer },
111
+ output_to, exit_on_help? )
112
+ end
113
+
114
+ # Set the args, potentially to something other than ARGV.
115
+ def args=(args) #:nodoc:
116
+ @@args = args.dup.map { |a| a + '' }
117
+ parse if parsed?
118
+ end
119
+
120
+ # Return the args.
121
+ def args #:nodoc:
122
+ @@args
123
+ end
124
+
125
+ # Returns the arguments that follow an argument
126
+ def args_of(opt)
127
+ args_of_opt = []
128
+
129
+ # Return an array of the arguments between opt and the next option,
130
+ # which all start with "-"
131
+ @@args.slice(@@args.index(opt)+1, @@args.length).select do |arg|
132
+ if arg[0].chr != "-"
133
+ args_of_opt << arg
134
+ else
135
+ break
136
+ end
137
+ end
138
+ args_of_opt
139
+ end
140
+
141
+ # You can choose to not kill the script after the help screen is printed.
142
+ def dont_exit_on_help=(val) #:nodoc:
143
+ @@exit = true
144
+ end
145
+
146
+ # Do we want to exit on help?
147
+ def exit_on_help? #:nodoc:
148
+ @@exit rescue false
149
+ end
150
+
151
+ # If we want to write to somewhere other than STDOUT.
152
+ def output_to(target = nil) #:nodoc:
153
+ @@output_to ||= STDOUT
154
+ return @@output_to if target.nil?
155
+ @@output_to = target
156
+ end
157
+
158
+ # Reset all the class variables.
159
+ def reset! #:nodoc:
160
+ @@args = false
161
+ @@banner = false
162
+ @@header = Array.new
163
+ @@options = Array.new
164
+ @@footer = Array.new
165
+ end
166
+ end
@@ -0,0 +1,67 @@
1
+ module Choice
2
+
3
+ # This class lets us get away with really bad, horrible, lazy hash accessing.
4
+ # Like so:
5
+ # hash = LazyHash.new
6
+ # hash[:someplace] = "somewhere"
7
+ # puts hash[:someplace]
8
+ # puts hash['someplace']
9
+ # puts hash.someplace
10
+ #
11
+ # If you'd like, you can pass in a current hash when initializing to convert
12
+ # it into a lazyhash. Or you can use the .to_lazyhash method attached to the
13
+ # Hash object (evil!).
14
+ class LazyHash < Hash
15
+
16
+ # Keep the old methods around.
17
+ alias_method :old_store, :store
18
+ alias_method :old_fetch, :fetch
19
+
20
+ # You can pass in a normal hash to convert it to a LazyHash.
21
+ def initialize(hash = nil)
22
+ hash.each { |key, value| self[key] = value } if !hash.nil? && hash.is_a?(Hash)
23
+ end
24
+
25
+ # Wrapper for []
26
+ def store(key, value)
27
+ self[key] = value
28
+ end
29
+
30
+ # Wrapper for []=
31
+ def fetch(key)
32
+ self[key]
33
+ end
34
+
35
+ # Store every key as a string.
36
+ def []=(key, value)
37
+ key = key.to_s if key.is_a? Symbol
38
+ self.old_store(key, value)
39
+ end
40
+
41
+ # Every key is stored as a string. Like a normal hash, nil is returned if
42
+ # the key does not exist.
43
+ def [](key)
44
+ key = key.to_s if key.is_a? Symbol
45
+ self.old_fetch(key) rescue return nil
46
+ end
47
+
48
+ # You can use hash.something or hash.something = 'thing' since this is
49
+ # truly a lazy hash.
50
+ def method_missing(meth, *args)
51
+ meth = meth.to_s
52
+ if meth =~ /=/
53
+ self[meth.sub('=','')] = args.first
54
+ else
55
+ self[meth]
56
+ end
57
+ end
58
+
59
+ end
60
+ end
61
+
62
+ # Really ugly, horrible, extremely fun hack.
63
+ class Hash #:nodoc:
64
+ def to_lazyhash
65
+ return Choice::LazyHash.new(self)
66
+ end
67
+ end
@@ -0,0 +1,90 @@
1
+ module Choice
2
+
3
+ # The Option class parses and stores all the information about a specific
4
+ # option.
5
+ class Option #:nodoc: all
6
+
7
+ # Since we define getters/setters on the fly, we need a white list of
8
+ # which to accept. Here's the list.
9
+ CHOICES = %w[short long desc default filter action cast validate valid]
10
+
11
+ # You can instantiate an option on its own or by passing it a name and
12
+ # a block. If you give it a block, it will eval() the block and set itself
13
+ # up nicely.
14
+ def initialize(options = {}, &block)
15
+ # Here we store the definitions this option contains, to make to_a and
16
+ # to_h easier.
17
+ @choices = []
18
+
19
+ # If we got a block, eval it and set everything up.
20
+ instance_eval(&block) if block_given?
21
+
22
+ # Is this option required?
23
+ @required = options[:required] || false
24
+ @choices << 'required'
25
+ end
26
+
27
+ # This is the catch all for the getter/setter choices defined in CHOICES.
28
+ # It also gives us choice? methods.
29
+ def method_missing(method, *args, &block)
30
+ # Get the name of the choice we want, as a class variable string.
31
+ var = "@#{method.to_s.sub('?','')}"
32
+
33
+ # To string, for regex purposes.
34
+ method = method.to_s
35
+
36
+ # Don't let in any choices not defined in our white list array.
37
+ raise ParseError, "I don't know `#{method}'" unless CHOICES.include? method.sub('?','')
38
+
39
+ # If we're asking a question, give an answer. Like 'short?'.
40
+ return !!instance_variable_get(var) if method =~ /\?/
41
+
42
+ # If we were called with no arguments, we want a get.
43
+ return instance_variable_get(var) unless args[0] || block_given?
44
+
45
+ # If we were given a block or an argument, save it.
46
+ instance_variable_set(var, args[0]) if args[0]
47
+ instance_variable_set(var, block) if block_given?
48
+
49
+ # Add the choice to the @choices array if we're setting it for the first
50
+ # time.
51
+ @choices << method if args[0] || block_given? unless @choices.index(method)
52
+ end
53
+
54
+ # The desc method is slightly special: it stores itself as an array and
55
+ # each subsequent call adds to that array, rather than overwriting it.
56
+ # This is so we can do multi-line descriptions easily.
57
+ def desc(string = nil)
58
+ return @desc if string.nil?
59
+
60
+ @desc ||= []
61
+ @desc.push(string)
62
+
63
+ # Only add to @choices array if it's not already present.
64
+ @choices << 'desc' unless @choices.index('desc')
65
+ end
66
+
67
+ # Simple, desc question method.
68
+ def desc?() !!@desc end
69
+
70
+ # Returns Option converted to an array.
71
+ def to_a
72
+ @choices.inject([]) do |array, choice|
73
+ return array unless @choices.include? choice
74
+ array + [instance_variable_get("@#{choice}")]
75
+ end
76
+ end
77
+
78
+ # Returns Option converted to a hash.
79
+ def to_h
80
+ @choices.inject({}) do |hash, choice|
81
+ return hash unless @choices.include? choice
82
+ hash.merge choice => instance_variable_get("@#{choice}")
83
+ end
84
+ end
85
+
86
+ # In case someone tries to use a method we don't know about in their
87
+ # option block.
88
+ class ParseError < Exception; end
89
+ end
90
+ end