optitron 0.0.8 → 0.0.9

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.
data/README.rdoc CHANGED
@@ -5,6 +5,7 @@
5
5
  You can specify lots of different commands with options
6
6
 
7
7
  @parser = Optitron.new {
8
+ help
8
9
  opt 'verbose', "Be very loud"
9
10
  cmd "install", "This installs things" do
10
11
  arg "file", "The file to install"
@@ -96,43 +97,59 @@ To use this in a file, create a parser, and tell it to dispatch to your favourit
96
97
  Now, try running it.
97
98
 
98
99
  crapbook-pro:optitron joshua$ ruby test.rb
99
- Commands
100
+ Unknown command
100
101
 
101
- show [first] <second> # This shows things
102
- install [file] # This installs things
103
- kill # This kills things
104
- -p/--pids=[ARRAY] # A list of pids to kill
105
- -P/--pid=[NUMERIC] # A pid to kill
106
- -n/--names=[HASH] # Some sort of hash
107
- join [thing1 thing2 ...] # This joins things
102
+ crapbook-pro:optitron joshua$ ruby test.rb install
103
+ File is required
108
104
 
109
- Global options
105
+ crapbook-pro:optitron joshua$ ruby test.rb install file
106
+ installing file with {"verbose"=>false}!
107
+
108
+ crapbook-pro:optitron joshua$ ruby test.rb install file --verbose
109
+ installing file with {"verbose"=>true}!
110
+
111
+ == Usage in a class
112
+
113
+ require 'optitron'
110
114
 
111
- -v/--verbose # Be very loud
115
+ class Runner
116
+ include Optitron::ClassDsl
112
117
 
113
- Errors:
114
- Unknown command
118
+ class_opt 'verbose'
119
+ use_help
115
120
 
116
- crapbook-pro:optitron joshua$ ruby test.rb install
121
+ desc "Install stuff"
122
+ opt 'force'
123
+ arg 'file'
124
+ arg 'source', :required => false
125
+ def install(file, source)
126
+ puts "install some things #{file} from #{source.inspect} #{params.inspect}"
127
+ end
128
+ end
129
+
130
+ Runner.dispatch
131
+
132
+ Running this gives you
133
+
134
+ crapbook-pro:optitron joshua$ ruby ideal.rb --help
117
135
  Commands
118
136
 
119
- show [first] <second> # This shows things
120
- install [file] # This installs things
121
- kill # This kills things
122
- -p/--pids=[ARRAY] # A list of pids to kill
123
- -P/--pid=[NUMERIC] # A pid to kill
124
- -n/--names=[HASH] # Some sort of hash
125
- join [thing1 thing2 ...] # This joins things
137
+ install [file] <source> # Install stuff
138
+ -f/--force
126
139
 
127
140
  Global options
128
141
 
129
- -v/--verbose # Be very loud
130
-
131
- Errors:
142
+ -v/--verbose
143
+ -?/--help # Print help message
144
+
145
+ crapbook-pro:optitron joshua$ ruby ideal.rb install
132
146
  File is required
133
-
134
- crapbook-pro:optitron joshua$ ruby test.rb install file
135
- installing file with {"verbose"=>false}!
136
147
 
137
- crapbook-pro:optitron joshua$ ruby test.rb install file --verbose
138
- installing file with {"verbose"=>true}!
148
+ crapbook-pro:optitron joshua$ ruby ideal.rb install file
149
+ installing file from yourmom with params: {"help"=>false, "force"=>false, "verbose"=>false}
150
+
151
+ crapbook-pro:optitron joshua$ ruby ideal.rb install file yourdad
152
+ installing file from yourdad with params: {"help"=>false, "force"=>false, "verbose"=>false}
153
+
154
+ crapbook-pro:optitron joshua$ ruby ideal.rb install file yourdad -v
155
+ installing file from yourdad with params: {"help"=>false, "force"=>false, "verbose"=>true}
data/lib/optitron.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  class Optitron
2
2
  autoload :Dsl, 'optitron/dsl'
3
+ autoload :ClassDsl, 'optitron/class_dsl'
3
4
  autoload :Tokenizer, 'optitron/tokenizer'
4
5
  autoload :Parser, 'optitron/parser'
5
6
  autoload :Response, 'optitron/response'
@@ -0,0 +1,82 @@
1
+ class Optitron
2
+ module ClassDsl
3
+
4
+ def self.included(o)
5
+ o.module_eval "
6
+ @@optitron_parser = Optitron::Parser.new
7
+ @@optitron_dsl = Optitron::Dsl.new(@@optitron_parser)
8
+ attr_accessor :params
9
+ class << self;
10
+ include ClassMethods
11
+ end"
12
+ end
13
+
14
+
15
+ module ClassMethods
16
+ def method_added(m)
17
+ last_opts = @opts
18
+ @cmds ||= []
19
+ @cmds << [m.to_s, @last_desc, @args.dup || [], @opts.dup || []]
20
+ @opts.clear if @opts
21
+ @args.clear if @args
22
+ end
23
+
24
+ def optitron_dsl
25
+ self.send(:class_variable_get, :@@optitron_dsl)
26
+ end
27
+
28
+ def optitron_parser
29
+ self.send(:class_variable_get, :@@optitron_parser)
30
+ end
31
+
32
+ def class_opt(name, desc = nil, opts = nil)
33
+ optitron_dsl.root.opt(name, desc, opts)
34
+ end
35
+
36
+ def use_help
37
+ optitron_dsl.root.help
38
+ end
39
+
40
+ def desc(desc)
41
+ @last_desc = desc
42
+ end
43
+
44
+ def arg(name, desc = nil, opts = nil)
45
+ @args ||= []
46
+ @args << [name, desc, opts]
47
+ end
48
+
49
+ def opt(name, desc = nil, opts = nil)
50
+ @opts ||= []
51
+ @opts << [name, desc, opts]
52
+ end
53
+
54
+ def build
55
+ @cmds.each do |(cmd_name, cmd_desc, args, opts)|
56
+ arity = instance_method(cmd_name).arity
57
+ optitron_dsl.root.cmd(cmd_name, cmd_desc) do
58
+ opts.each { |o| opt *o }
59
+ args.each { |a| arg *a }
60
+ end
61
+ end
62
+ optitron_dsl.configure_options
63
+ end
64
+
65
+ def dispatch
66
+ build
67
+ optitron_parser.target = new
68
+ response = optitron_parser.parse(ARGV)
69
+ if response.valid?
70
+ optitron_parser.target.params = response.params
71
+ args = response.args
72
+ while (args.size < optitron_parser.commands[response.command].args.size)
73
+ args << optitron_parser.commands[response.command].args[args.size].default
74
+ end
75
+ optitron_parser.target.send(response.command.to_sym, *response.args)
76
+ else
77
+ puts response.error_messages.join("\n")
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end
data/lib/optitron/dsl.rb CHANGED
@@ -1,23 +1,30 @@
1
1
  class Optitron
2
2
  class Dsl
3
+ attr_reader :root
3
4
 
4
5
  def initialize(parser, &blk)
5
- root = RootParserDsl.new(parser)
6
- root.configure_with(blk)
7
- root.unclaimed_opts.each do |opt_option|
6
+ @root = RootParserDsl.new(parser)
7
+ if blk
8
+ @root.configure_with(&blk)
9
+ configure_options
10
+ end
11
+ end
12
+
13
+ def configure_options
14
+ @root.unclaimed_opts.each do |opt_option|
8
15
  name = opt_option.name
9
- if !root.short_opts.key?(name[0].chr)
16
+ if !@root.short_opts.key?(name[0].chr)
10
17
  opt_option.short_name = name[0].chr
11
- root.short_opts[name[0].chr] = opt_option
12
- elsif !root.short_opts.key?(name.upcase[0].chr)
18
+ @root.short_opts[name[0].chr] = opt_option
19
+ elsif !@root.short_opts.key?(name.upcase[0].chr)
13
20
  opt_option.short_name = name.upcase[0].chr
14
- root.short_opts[name.upcase[0].chr] = opt_option
21
+ @root.short_opts[name.upcase[0].chr] = opt_option
15
22
  end
16
23
  end
17
24
  end
18
-
25
+
19
26
  class AbstractDsl
20
- def configure_with(block)
27
+ def configure_with(&block)
21
28
  instance_eval(&block)
22
29
  end
23
30
 
@@ -63,13 +70,24 @@ class Optitron
63
70
  @unclaimed_opts = []
64
71
  end
65
72
 
73
+ def help(desc = "Print help message")
74
+ configure_with {
75
+ opt 'help', desc, :short_name => '?', :run => proc{ |value, response|
76
+ if value
77
+ puts @target.help
78
+ exit(0)
79
+ end
80
+ }
81
+ }
82
+ end
83
+
66
84
  def short_opts
67
85
  @target.short_opts
68
86
  end
69
87
 
70
88
  def cmd(name, description = nil, opts = nil, &blk)
71
89
  command_option = Option::Cmd.new(name, description, opts)
72
- CmdParserDsl.new(self, command_option).configure_with(blk) if blk
90
+ CmdParserDsl.new(self, command_option).configure_with(&blk) if blk
73
91
  @target.commands[name] = command_option
74
92
  end
75
93
  end
data/lib/optitron/help.rb CHANGED
@@ -7,7 +7,7 @@ class Optitron
7
7
  def help_line_for_opt(opt)
8
8
  opt_line = ''
9
9
  opt_line << [opt.short_name ? "-#{opt.short_name}" : nil, "--#{opt.name}"].compact.join('/')
10
- opt_line << "=[#{opt.type.to_s.upcase}]" if opt.type != :boolean
10
+ opt_line << "=[#{opt.type.to_s.upcase}]" unless opt.boolean?
11
11
  [opt_line, opt.desc]
12
12
  end
13
13
 
@@ -35,6 +35,34 @@ class Optitron
35
35
  end
36
36
  end
37
37
 
38
+ def boolean?
39
+ @type == :boolean
40
+ end
41
+
42
+ def numeric?
43
+ @type == :numeric
44
+ end
45
+
46
+ def array?
47
+ @type == :array
48
+ end
49
+
50
+ def string?
51
+ @type == :string
52
+ end
53
+
54
+ def hash?
55
+ @type == :hash
56
+ end
57
+
58
+ def greedy?
59
+ @type == :greedy
60
+ end
61
+
62
+ def any?
63
+ @type.nil?
64
+ end
65
+
38
66
  def validate(val)
39
67
  validated_type = case @type
40
68
  when :boolean
@@ -61,7 +89,7 @@ class Optitron
61
89
  end
62
90
 
63
91
  class Opt < Option
64
- attr_accessor :short_name
92
+ attr_accessor :short_name, :run
65
93
  def initialize(name, desc = nil, opts = nil)
66
94
  if desc.is_a?(Hash)
67
95
  desc, opts = nil, desc
@@ -69,6 +97,7 @@ class Optitron
69
97
  @name, @desc = name, desc
70
98
  @type = opts && opts[:type] || :boolean
71
99
  self.short_name = opts[:short_name] if opts && opts[:short_name]
100
+ self.run = opts[:run] if opts && opts[:run]
72
101
  self.inclusion_test = opts[:in] if opts && opts[:in]
73
102
  self.default = opts && opts.key?(:default) ? opts[:default] : (@type == :boolean ? false : nil)
74
103
  end
@@ -137,12 +166,13 @@ class Optitron
137
166
  end
138
167
 
139
168
  class Cmd < Option
140
- attr_reader :options, :args
169
+ attr_reader :options, :args, :run
141
170
  def initialize(name, desc = nil, opts = nil)
142
171
  if desc.is_a?(Hash)
143
172
  desc, opts = nil, desc
144
173
  end
145
174
  @name, @desc = name, desc
175
+ @run = opts[:run] if opts && opts[:run]
146
176
  @options = []
147
177
  @args = []
148
178
  end
@@ -157,7 +187,8 @@ class Optitron
157
187
  end
158
188
  @name, @desc = name, desc
159
189
  self.inclusion_test = opts[:in] if opts && opts[:in]
160
- @required = opts && opts.key?(:required) ? opts[:required] : true
190
+ @default = opts && opts[:default]
191
+ @required = opts && opts.key?(:required) ? opts[:required] : @default.nil?
161
192
  @type = opts && opts[:type]
162
193
  end
163
194
 
@@ -20,7 +20,7 @@ class Optitron
20
20
  response = Response.new(self, tokens)
21
21
  options = @options
22
22
  args = @args
23
- if !@commands.empty?
23
+ unless @commands.empty?
24
24
  potential_cmd_toks = tokens.select { |t| t.respond_to?(:lit) }
25
25
  if cmd_tok = potential_cmd_toks.find { |t| @commands[t.lit] }
26
26
  tokens.delete(cmd_tok)
@@ -33,6 +33,7 @@ class Optitron
33
33
 
34
34
  def validate
35
35
  compile_params
36
+ @params_array.each { |(key, value)| key.run.call(params[key.name], self) if key.run }
36
37
  @args = @args_with_tokens.map { |(arg, tok)|
37
38
  begin
38
39
  tok.is_a?(Array) ? tok.map{ |t| arg.validate(t.lit) } : arg.validate(tok.lit)
@@ -62,8 +63,6 @@ class Optitron
62
63
  dispatch_args = params.empty? ? args : args + [params]
63
64
  @parser.target.send(command.to_sym, *dispatch_args)
64
65
  else
65
- puts @parser.help
66
- puts "\nErrors:"
67
66
  puts error_messages.join("\n")
68
67
  end
69
68
  end
@@ -14,10 +14,10 @@ class Optitron
14
14
  unless @tokens
15
15
  @tokens = @opts.map {|t|
16
16
  case t
17
- when /^--([^=]+)=([^=]+)$/ then NamedWithValue.new($1, $2)
18
- when /^--([^=]+)$/ then NamedWithValue.new($1, nil)
19
- when /^-(.*)/ then find_names_values($1)
20
- else Value.new(t)
17
+ when /^--([^-][^=]+)=([^=]+)$/ then NamedWithValue.new($1, $2)
18
+ when /^--([^-][^=]+)$/ then NamedWithValue.new($1, nil)
19
+ when /^-(.*)/ then find_names_values($1)
20
+ else Value.new(t)
21
21
  end
22
22
  }
23
23
  @tokens.flatten!
@@ -30,7 +30,7 @@ class Optitron
30
30
  while !letters.empty?
31
31
  let = letters.shift
32
32
  toks << Named.new(let)
33
- if @parser.short_opts[let] && @parser.short_opts[let].type != :boolean && !letters.empty?
33
+ if @parser.short_opts[let] && !@parser.short_opts[let].boolean? && !letters.empty?
34
34
  toks << Value.new(letters.join)
35
35
  letters.clear
36
36
  end
@@ -1,3 +1,3 @@
1
1
  class Optitron
2
- VERSION = "0.0.8"
2
+ VERSION = "0.0.9"
3
3
  end
data/spec/option_spec.rb CHANGED
@@ -79,8 +79,8 @@ describe "Optitron::Parser options" do
79
79
  }
80
80
  end
81
81
 
82
- it "should parse '-otest'" do
83
- @parser.parse(%w(-otest)).params.should == {'option' => 'test', '1' => false, '2' => false, '3' => false}
82
+ it "should parse '-123otest'" do
83
+ @parser.parse(%w(-123otest)).params.should == {'option' => 'test', '1' => true, '2' => true, '3' => true}
84
84
  end
85
85
 
86
86
  it "should parse '-123o test'" do
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: optitron
3
3
  version: !ruby/object:Gem::Version
4
- hash: 15
4
+ hash: 13
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 0
9
- - 8
10
- version: 0.0.8
9
+ - 9
10
+ version: 0.0.9
11
11
  platform: ruby
12
12
  authors:
13
13
  - Joshua Hull
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2010-08-17 00:00:00 -07:00
18
+ date: 2010-08-18 00:00:00 -07:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -51,6 +51,7 @@ files:
51
51
  - README.rdoc
52
52
  - Rakefile
53
53
  - lib/optitron.rb
54
+ - lib/optitron/class_dsl.rb
54
55
  - lib/optitron/dsl.rb
55
56
  - lib/optitron/help.rb
56
57
  - lib/optitron/option.rb