optopus 0.1.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.
Files changed (3) hide show
  1. data/README +49 -0
  2. data/lib/optopus.rb +189 -0
  3. metadata +68 -0
data/README ADDED
@@ -0,0 +1,49 @@
1
+ = optopus
2
+
3
+ == Description
4
+
5
+ Enhanced option parser.
6
+
7
+ == Install
8
+
9
+ gem install optopus
10
+
11
+ == Example
12
+
13
+ require 'rubygems'
14
+ require 'optopus'
15
+
16
+ opts = optopus do
17
+ desc 'print lots of debugging information'
18
+ option :debug, '-d', '--debug'
19
+
20
+ desc 'log messages to FILE.'
21
+ option :output_file, '-o', '--output-file FILE', :default => '/var/log/xxx.log'
22
+
23
+ desc 'set number of retries to NUMBER (0 unlimits)'
24
+ option :tries, '-t', '--tries NUMBER', :type => Integer, :default => 0 do
25
+ # custom validation
26
+ invalid_argument if @value < 0
27
+ end
28
+
29
+ desc 'comma-separated list of accepted extensions'
30
+ option :accept, '-A', '--accept LIST', :type => Array, :default => []
31
+
32
+ desc 'access timestamp'
33
+ option :timestamp, '-T', '--timestamp TIME', :type => Time
34
+
35
+ # read yaml config file and overwrite options
36
+ file '-c', '--config-file FILE'
37
+
38
+ after do
39
+ # postprocessing
40
+ # @options.each { ... }
41
+ end
42
+
43
+ exception do |e|
44
+ $stderr.puts e.message
45
+ exit 1
46
+ end
47
+ end
48
+
49
+ p opts
data/lib/optopus.rb ADDED
@@ -0,0 +1,189 @@
1
+ require 'optparse'
2
+ require 'optparse/date'
3
+ require 'optparse/shellwords'
4
+ require 'optparse/time'
5
+ require 'optparse/uri'
6
+ require 'yaml'
7
+
8
+ module Optopus
9
+ class DefinerContext
10
+ def self.evaluate(opts, &block)
11
+ self.new(opts).instance_eval(&block)
12
+ end
13
+
14
+ def initialize(opts)
15
+ @opts = opts
16
+ end
17
+
18
+ def desc(str)
19
+ @desc = str
20
+ end
21
+
22
+ def option(name, args_hd, *args_tl, &block)
23
+ @opts.add(name, [args_hd] + args_tl, @desc, block)
24
+ @desc = nil
25
+ end
26
+
27
+ def file(args_hd, *args_tl)
28
+ @desc ||= 'reading config file'
29
+ @opts.add_file([args_hd] + args_tl, @desc)
30
+ @desc = nil
31
+ end
32
+
33
+ def after(&block)
34
+ @opts.add_after(block)
35
+ end
36
+
37
+ def exception(&block)
38
+ @opts.add_exception(block)
39
+ end
40
+ end # DefinerContext
41
+
42
+ class CheckerContext
43
+ def self.evaluate(args, vars = {}, &block)
44
+ self.new(args, vars).instance_eval(&block)
45
+ end
46
+
47
+ def initialize(value, vars = {})
48
+ @args = value ? [value] : []
49
+
50
+ vars.each do |name, value|
51
+ instance_variable_set("@#{name}", value)
52
+ end
53
+ end
54
+
55
+ def parse_error(reason)
56
+ e = OptionParser::ParseError.new(*@args)
57
+ e.reason = reason
58
+ raise e
59
+ end
60
+
61
+ def ambiguous_option
62
+ raise OptionParser::AmbiguousOption.new(*@args)
63
+ end
64
+
65
+ def needless_argument
66
+ raise OptionParser::NeedlessArgument.new(*@args)
67
+ end
68
+
69
+ def missing_argument
70
+ raise OptionParser::MissingArgument.new(*@args)
71
+ end
72
+
73
+ def invalid_option
74
+ raise OptionParser::InvalidOption.new(*@args)
75
+ end
76
+
77
+ def invalid_argument
78
+ raise OptionParser::InvalidArgument.new(*@args)
79
+ end
80
+
81
+ def ambiguous_argument
82
+ raise OptionParser::AmbiguousArgument.new(*@args)
83
+ end
84
+ end # CheckerContext
85
+
86
+ class Options
87
+ def initialize
88
+ @opts_args = []
89
+ end
90
+
91
+ def add(name, args, desc, block)
92
+ args, defval = fix_args(args, desc)
93
+ @opts_args << [name.to_sym, args, defval, block]
94
+ end
95
+
96
+ def add_file(args, desc)
97
+ args, defval = fix_args(args, desc)
98
+ @file_args = args
99
+ end
100
+
101
+ def add_after(block)
102
+ @on_after = block
103
+ end
104
+
105
+ def add_exception(block)
106
+ @on_exception = block
107
+ end
108
+
109
+ def parse!
110
+ parser = OptionParser.new
111
+ options = {}
112
+ has_arg_h = false
113
+
114
+ @opts_args.each do |name, args, defval, block|
115
+ options[name] = defval
116
+ has_arg_h = (args.first == '-h')
117
+
118
+ parser.on(*args) do |*v|
119
+ value = v.first || true
120
+ options[name] = value
121
+ CheckerContext.evaluate(v, {:value => value}, &block) if block
122
+ end
123
+ end
124
+
125
+ if @file_args
126
+ parser.on(*@file_args) do |v|
127
+ config = YAML.load_file(v)
128
+
129
+ @opts_args.each do |name, args, defval, block|
130
+ value = config[name] || config[name.to_s]
131
+
132
+ next unless value
133
+
134
+ value = value.to_s
135
+ type = args.find {|i| i.kind_of?(Class) }
136
+ pat, conv = OptionParser::DefaultList.atype[type]
137
+
138
+ if pat and pat !~ value
139
+ raise OptionParser::InvalidArgument.new("(#{name}: #{value})")
140
+ end
141
+
142
+ value = conv.call(value) if conv
143
+
144
+ options[name] = value
145
+ end
146
+ end
147
+ end
148
+
149
+ unless has_arg_h
150
+ parser.on_tail('-h', '--help', 'Show this message') do
151
+ puts parser.help
152
+ exit
153
+ end
154
+ end
155
+
156
+ parser.parse!(ARGV)
157
+ CheckerContext.evaluate([], {:options => options},&@on_after) if @on_after
158
+
159
+ return options
160
+ rescue => e
161
+ if @on_exception
162
+ @on_exception.call(e)
163
+ else
164
+ raise e
165
+ end
166
+ end
167
+
168
+ private
169
+ def fix_args(args, desc)
170
+ defval = nil
171
+
172
+ if args.last.kind_of?(Hash)
173
+ hash = args.pop
174
+ args = (args.slice(0, 2) + [hash[:type], hash[:desc] || desc]).select {|i| i }
175
+ defval = hash[:default]
176
+ elsif desc
177
+ args = args + [desc]
178
+ end
179
+
180
+ return [args, defval]
181
+ end
182
+ end # Options
183
+ end # Optopus
184
+
185
+ def optopus(&block)
186
+ opts = Optopus::Options.new
187
+ Optopus::DefinerContext.evaluate(opts, &block)
188
+ opts.parse!
189
+ end
metadata ADDED
@@ -0,0 +1,68 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: optopus
3
+ version: !ruby/object:Gem::Version
4
+ hash: 27
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 0
10
+ version: 0.1.0
11
+ platform: ruby
12
+ authors:
13
+ - winebarrel
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-05-31 00:00:00 +09:00
19
+ default_executable:
20
+ dependencies: []
21
+
22
+ description:
23
+ email: sgwr_dts@yahoo.co.jp
24
+ executables: []
25
+
26
+ extensions: []
27
+
28
+ extra_rdoc_files: []
29
+
30
+ files:
31
+ - README
32
+ - lib/optopus.rb
33
+ has_rdoc: true
34
+ homepage: https://bitbucket.org/winebarrel/optopus
35
+ licenses: []
36
+
37
+ post_install_message:
38
+ rdoc_options: []
39
+
40
+ require_paths:
41
+ - lib
42
+ required_ruby_version: !ruby/object:Gem::Requirement
43
+ none: false
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ hash: 3
48
+ segments:
49
+ - 0
50
+ version: "0"
51
+ required_rubygems_version: !ruby/object:Gem::Requirement
52
+ none: false
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ hash: 3
57
+ segments:
58
+ - 0
59
+ version: "0"
60
+ requirements: []
61
+
62
+ rubyforge_project:
63
+ rubygems_version: 1.4.2
64
+ signing_key:
65
+ specification_version: 3
66
+ summary: Enhanced option parser.
67
+ test_files: []
68
+