ivanvc-choice 0.1.3.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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