cooloptions 0.1.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/History.txt CHANGED
@@ -1,3 +1,9 @@
1
+ == 1.0.0 /
2
+
3
+ * Added test for short options specification.
4
+ * Improved the documentation.
5
+ * Re-vamped option specification completely.
6
+
1
7
  == 0.1.0 / 2006-11-30
2
8
 
3
9
  * Initial Release
data/README.txt CHANGED
@@ -8,26 +8,64 @@ CoolOptions is a simple wrapper around optparse that provides less options and m
8
8
 
9
9
  == SYNOPSYS:
10
10
 
11
+ === Declaration:
12
+
11
13
  options = CoolOptions.parse!("[options] PROJECTNAME") do |o|
12
- o.on :svk, "[no-]svk", "Use svk.", true
13
- o.on :project_path, "project-path PATH", "Root of project workspaces.", File.expand_path("~/svk")
14
- o.on :repository, "repository URL", "Remote subversion repository."
15
- o.on :repository_path, "repository-path PATH", "Remote repository path.", "/", "l"
16
- o.on :mirror_path, "mirror-path SVKPATH", "SVK mirror path.", "//"
17
- o.on :local_path, "local-path SVKPATH", "SVK local path.", "//local", "t"
18
- o.on :create_structure, "[no-]create-structure", "Create trunk/tags/branches structure.", true
19
- o.on :finish, "[no-]finish" , "Prep and commit the new project.", true
20
-
14
+ o.on "repository URL", "Remote subversion repository."
15
+ o.on "svk", "Use svk.", true
16
+ o.on "project-path PATH", "Root of project workspaces.", File.expand_path("~/svk")
17
+ o.on "l)repository-path PATH", "Remote repository path.", "/"
18
+ o.on "mirror-path SVKPATH", "SVK mirror path.", "//"
19
+ o.on "local-pa(t)h SVKPATH", "SVK local path.", "//local"
20
+ o.on "create-structure", "Create trunk/tags/branches structure.", true
21
+ o.on "finish", "Prep and commit the new project.", true
22
+
21
23
  o.after do |r|
22
24
  r.project_path = File.expand_path(r.project_path)
23
- raise "Invalid path." unless File.exist?(r.project_path)
25
+ o.error("Invalid path.") unless File.exist?(r.project_path)
24
26
  r.project_name = ARGV.shift
27
+ o.error("Project name is required.") unless r.project_name
28
+ o.error("Project name is too funky.") unless /^\w+$/ =~ r.project_name
25
29
  end
26
30
  end
31
+
32
+ === Usage:
33
+
34
+ $ ./new_rails_project --no-svk -r http://terralien.com/svn/terralien/ --no-finish
35
+
36
+ === Result:
37
+
38
+ p options.svk # => false
39
+ p options.project_path # => '/Users/ntalbott/svk'
40
+ p options.repository # => 'http://terralien.com/svn/terralien/'
41
+ p options.finish # => false
42
+ p options.create_structure # => true
43
+ p options.project_name # => 'myproject'
44
+
45
+ === Also:
46
+
47
+ $ ./new_rails_project --help
48
+ Usage: t.rb [options] PROJECTNAME
49
+ -s, --[no-]svk Use svk.
50
+ Default is: true
51
+ -p, --project-path PATH Root of project workspaces.
52
+ Default is: /Users/ntalbott/svk
53
+ -r, --repository URL Remote subversion repository.
54
+ -l, --repository-path PATH Remote repository path.
55
+ Default is: /
56
+ -m, --mirror-path SVKPATH SVK mirror path.
57
+ Default is: //
58
+ -t, --local-path SVKPATH SVK local path.
59
+ Default is: //local
60
+ -c, --[no-]create-structure Create trunk/tags/branches structure.
61
+ Default is: true
62
+ -f, --[no-]finish Prep and commit the new project.
63
+ Default is: true
64
+ -h, --help This help info.
27
65
 
28
66
  == REQUIREMENTS:
29
67
 
30
- optparse (included in Ruby stdlib)
68
+ optparse & ostruct (included in Ruby standard library).
31
69
 
32
70
  == INSTALL:
33
71
 
data/Rakefile CHANGED
@@ -5,7 +5,7 @@ require './lib/cooloptions.rb'
5
5
  Hoe.new('cooloptions', CoolOptions::VERSION) do |p|
6
6
  p.rubyforge_name = 'cooloptions'
7
7
  p.summary = p.description = 'CoolOptions is a simple wrapper around optparse that provides less options and more convenience.'
8
- p.url = 'https://rubyforge.org/projects/cooloptions/'
8
+ p.url = 'http://cooloptions.rubyforge.org/'
9
9
  p.changes = p.paragraphs_of('History.txt', 0..1).join("\n\n")
10
10
  p.author = "Nathaniel Talbott"
11
11
  p.email = "nathaniel@terralien.com"
data/lib/cooloptions.rb CHANGED
@@ -1,19 +1,30 @@
1
- # Copyright (c) 2006 Nathaniel Talbott and Terralien, Inc. All Rights Reserved.
2
- # Licensed under the RUBY license.
1
+ # Copyright:: Copyright (c) 2006 Nathaniel Talbott and Terralien, Inc. All Rights Reserved.
2
+ # License:: Licensed under the RUBY license.
3
3
 
4
4
  require 'optparse'
5
5
  require 'ostruct'
6
6
 
7
+ # For a high-level overview of using CoolOptions, see README.txt.
8
+ #
9
+ # == Usage
10
+ #
11
+ # :include:samples/literate.rb
12
+
7
13
  class CoolOptions
8
- VERSION = '0.1.0'
14
+ VERSION = '1.0.0' #:nodoc:
9
15
 
10
16
  class Error < StandardError #:nodoc:
11
17
  end
12
18
 
13
- def self.parse!(*args)
14
- o = new
19
+ # Takes an optional banner and the arguments you want to parse (defaults to
20
+ # ARGV) and yields a new CoolOptions to the supplied block. You can then
21
+ # declare your options in the block using the #on method, and do post-
22
+ # processing using #after. When processing is done, an OpenStruct
23
+ # containing the parsed options is returned.
24
+ def self.parse!(banner="[options]", argv=ARGV) #:yields: cooloptions
25
+ o = new(banner)
15
26
  yield o
16
- o.parse!(*args)
27
+ o.parse!(argv)
17
28
  rescue Error => e
18
29
  out.puts e.message
19
30
  o.help true
@@ -31,59 +42,75 @@ class CoolOptions
31
42
  @out = out
32
43
  end
33
44
 
34
- def initialize
35
- @options = []
45
+ attr_reader :parser, :result
46
+
47
+ def initialize(banner) #:nodoc:
48
+ @parser = OptionParser.new
49
+ @parser.banner = "Usage: #{File.basename($0)} #{banner}"
50
+
51
+ @required = []
52
+ @result = {}
36
53
  @after = nil
37
54
  end
38
55
 
39
- def on(key, long, message, default=nil, short=nil)
40
- unless short
41
- short = if /^\[/ =~ long
42
- long.split(/\]/).last
43
- else
44
- long
45
- end[0,1]
56
+ NO_DEFAULT = Object.new #:nodoc:
57
+
58
+ # Called on cooloptions within the #parse! block to add options to parse on.
59
+ # Long is the long option itself, description is, well, the description, and
60
+ # default is the default value for the option, if any.
61
+ def on(long, description, default=NO_DEFAULT)
62
+ if /^(.)\)(.+)$/ =~ long
63
+ short, long = $1, $2
64
+ elsif /^(.*)\((.)\)(.*)$/ =~ long
65
+ short = $2
66
+ long = $1 + $2 + $3
46
67
  end
47
- @options << [key, short, long, message, default]
68
+ short = long[0,1] unless short
69
+
70
+ key = long.split(/ /).first.gsub('-', '_').to_sym
71
+
72
+ unless long =~ / /
73
+ long = "[no-]#{long}"
74
+ end
75
+
76
+ args = ["-#{short}", "--#{long}", description]
77
+ if default == NO_DEFAULT
78
+ @required << key
79
+ else
80
+ @result[key] = default
81
+ args << "Default is: #{default}"
82
+ end
83
+
84
+ @parser.on(*args){|e| self.result[key] = e}
48
85
  end
49
86
 
50
- def parse!(banner="[options]", argv=ARGV)
51
- result = {}
52
- required = []
53
- OptionParser.new do |o|
54
- @o = o
55
- o.banner = "Usage: #{File.basename($0)} #{banner}"
87
+ def parse!(argv) #:nodoc:
88
+ @parser.on('-h', '--help', "This help info."){help}
89
+ @parser.parse!(argv)
90
+
91
+ @required.reject!{|e| @result.key?(e)}
92
+ error "Missing required options: #{@required.join(', ')}" unless @required.empty?
56
93
 
57
- @options.each do |(key, short, long, message, default)|
58
- args = ["-#{short}", "--#{long}", message]
59
- if default.nil?
60
- required << key
61
- else
62
- result[key] = default
63
- args << "Default is: #{default}"
64
- end
65
- o.on(*args){|e| result[key] = e}
66
- end
67
-
68
- o.on('-h', '--help', "This help info."){help}
69
- end.parse!(argv)
70
- required.reject!{|e| result.key?(e)}
71
- error "Missing required options: #{required.join(', ')}" unless required.empty?
72
- result = OpenStruct.new(result)
73
- @after.call(result) if @after
74
- result
94
+ r = OpenStruct.new(@result)
95
+ @after.call(r) if @after
96
+ r
75
97
  end
76
98
 
99
+ # If you want to throw an option parsing error, just call #error with a
100
+ # message and CoolOptions will bail out and display the help message.
77
101
  def error(message)
78
102
  raise Error, message, caller
79
103
  end
80
104
 
105
+ # CoolOptions only handles options parsing, and it only does rudimentary
106
+ # option validation. If you want to do more, #after is a convenient place do
107
+ # it, especially since the right thing will just happen if you call #error.
81
108
  def after(&after)
82
109
  @after = after
83
110
  end
84
111
 
85
- def help(error=false)
86
- out.puts @o
112
+ def help(error=false) #:nodoc:
113
+ out.puts @parser
87
114
  exit(error ? 1 : 0)
88
115
  end
89
116
  end
@@ -20,10 +20,10 @@ class TestCoolOptions < Test::Unit::TestCase
20
20
 
21
21
  def test_should_handle_booleans
22
22
  r = parse!(%w(-a --no-b --c)) do |o|
23
- o.on :a, '[no-]a', 'a', false
24
- o.on :b, '[no-]b', 'b', true
25
- o.on :c, '[no-]c', 'c', false
26
- o.on :d, '[no-]d', 'd', true
23
+ o.on 'a', 'a', false
24
+ o.on 'b', 'b', true
25
+ o.on 'c', 'c', false
26
+ o.on 'd', 'd', true
27
27
  end
28
28
 
29
29
  assert r.a
@@ -34,8 +34,8 @@ class TestCoolOptions < Test::Unit::TestCase
34
34
 
35
35
  def test_should_handle_strings
36
36
  r = parse!(%w(-a b --c=d)) do |o|
37
- o.on :a, 'a ARG', 'a'
38
- o.on :c, 'c ARG', 'c'
37
+ o.on 'a ARG', 'a'
38
+ o.on 'c ARG', 'c'
39
39
  end
40
40
 
41
41
  assert_equal 'b', r.a
@@ -44,7 +44,7 @@ class TestCoolOptions < Test::Unit::TestCase
44
44
 
45
45
  def test_should_ignore_non_options
46
46
  r = CoolOptions.parse!('', argv=%w(ab -c de)) do |o|
47
- o.on :c, '[no-]c', 'c'
47
+ o.on 'c', 'c'
48
48
  end
49
49
 
50
50
  assert r.c
@@ -54,7 +54,7 @@ class TestCoolOptions < Test::Unit::TestCase
54
54
  def test_should_call_after
55
55
  called = false
56
56
  r = parse!(%w(-a)) do |o|
57
- o.on :a, '[no-]a', 'a'
57
+ o.on 'a', 'a'
58
58
  o.after{|r| assert r.a; called=true}
59
59
  end
60
60
  assert called
@@ -71,7 +71,7 @@ class TestCoolOptions < Test::Unit::TestCase
71
71
  def test_should_output_help
72
72
  begin
73
73
  r = CoolOptions.parse!('details', %w(--help)) do |o|
74
- o.on :a, '[no-]a', 'aa'
74
+ o.on 'a', 'aa'
75
75
  end
76
76
  rescue SystemExit
77
77
  rescued = true
@@ -88,8 +88,39 @@ EOH
88
88
  def test_should_require_options_with_no_default
89
89
  assert_raise(SystemExit) do
90
90
  CoolOptions.parse!([]) do |o|
91
- o.on :a, 'a A', 'a'
91
+ o.on 'a A', 'a'
92
92
  end
93
93
  end
94
+ assert_nothing_raised do
95
+ CoolOptions.parse!([]) do |o|
96
+ o.on 'a A', 'a', nil
97
+ end
98
+ end
99
+ end
100
+
101
+ def test_should_allow_specification_of_alternate_short_form
102
+ r = parse!(%w(-a -b c -c d)) do |o|
103
+ o.on 'a', 'a', false
104
+ o.on 'b)aa VALUE', 'aa'
105
+ o.on 'b(c) VALUE', 'bc'
106
+ end
107
+ assert_equal true, r.a
108
+ assert_equal 'c', r.aa
109
+ assert_equal 'd', r.bc
110
+ end
111
+
112
+ def test_should_replace_dashes
113
+ r = parse!(%w(--a-b c)) do |o|
114
+ o.on 'a-b A', 'a'
115
+ end
116
+ assert_equal 'c', r.a_b
117
+ end
118
+
119
+ def test_should_provide_access_to_the_parser
120
+ called = false
121
+ r = parse!(%w(-d)) do |o|
122
+ o.parser.on('-d'){called = true}
123
+ end
124
+ assert called
94
125
  end
95
126
  end
metadata CHANGED
@@ -3,13 +3,13 @@ rubygems_version: 0.8.11
3
3
  specification_version: 1
4
4
  name: cooloptions
5
5
  version: !ruby/object:Gem::Version
6
- version: 0.1.0
7
- date: 2006-12-07 00:00:00 -05:00
6
+ version: 1.0.0
7
+ date: 2006-12-09 00:00:00 -05:00
8
8
  summary: CoolOptions is a simple wrapper around optparse that provides less options and more convenience.
9
9
  require_paths:
10
10
  - lib
11
11
  email: nathaniel@terralien.com
12
- homepage: https://rubyforge.org/projects/cooloptions/
12
+ homepage: http://cooloptions.rubyforge.org/
13
13
  rubyforge_project: cooloptions
14
14
  description: CoolOptions is a simple wrapper around optparse that provides less options and more convenience.
15
15
  autorequire: