climate 0.5.0 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -7,6 +7,11 @@ structure.
7
7
 
8
8
  Designed for both simple and more complex cases.
9
9
 
10
+ - Embed a CLI in to your application
11
+ - Builds on trollop, a refreshingly sane option parsing library
12
+ - N-levels of subcommands
13
+ - Nice help output
14
+
10
15
  # Easy
11
16
 
12
17
  Useful for one-shot scripts:
@@ -29,14 +34,13 @@ Useful for one-shot scripts:
29
34
 
30
35
  This style is intended for embedding a CLI in to your existing application.
31
36
 
32
- class Parent < Climate::Command
33
- name 'thing'
37
+ class Parent < Climate::Command('thing')
34
38
  description "App that does it all, yet without fuss"
35
39
  opt :log, "Whether to log to stdout" :default => false
36
40
  end
37
41
 
38
42
  class Arbitrary < Climate::Command
39
- name 'arbitrary'
43
+ set_name 'arbitrary'
40
44
  subcommand_of, Parent
41
45
  description "Do something arbitrary to a file"
42
46
  arg :path "Path to input file"
@@ -131,7 +131,7 @@ module Climate
131
131
  command_name, *arguments = parent.leftovers
132
132
 
133
133
  if command_name.nil?
134
- raise MissingArgumentError.new("command #{parent.class.command_name}" +
134
+ raise MissingSubcommandError.new("command #{parent.class.command_name}" +
135
135
  " expects a subcommand as an argument", parent)
136
136
  end
137
137
 
@@ -50,6 +50,7 @@ module Climate
50
50
 
51
51
  # Raised when a {Command} is run with insufficient arguments
52
52
  class MissingArgumentError < ParsingError ; end
53
+ class MissingSubcommandError < MissingArgumentError ; end
53
54
 
54
55
  # Raised when two or more options conflict
55
56
  class ConflictingOptionError < ParsingError ; end
@@ -10,7 +10,11 @@ module Climate
10
10
  @included = true
11
11
  at_exit do
12
12
  Climate.with_standard_exception_handling do
13
- othermodule.send(:parse_argv)
13
+ begin
14
+ othermodule.send(:parse_argv)
15
+ rescue Trollop::HelpNeeded => e
16
+ raise HelpNeeded.new(othermodule)
17
+ end
14
18
  othermodule.send(:run)
15
19
  end
16
20
  end
@@ -35,7 +39,7 @@ module Climate
35
39
  attr_reader :arguments, :options, :leftovers
36
40
 
37
41
  def ancestors ; [self] ; end
38
- def name ; File.basename($CLIMATE_PROGRAM_NAME || $PROGRAM_NAME) ; end
42
+ def command_name ; File.basename($CLIMATE_PROGRAM_NAME || $PROGRAM_NAME) ; end
39
43
 
40
44
  def has_subcommands? ; false ; end
41
45
 
@@ -1,3 +1,3 @@
1
1
  module Climate
2
- VERSION = '0.5.0'
2
+ VERSION = '0.6.0'
3
3
  end
data/lib/climate.rb CHANGED
@@ -2,38 +2,59 @@ require 'trollop'
2
2
 
3
3
  module Climate
4
4
 
5
- def self.with_standard_exception_handling(options={}, &block)
5
+ def self.error_messages
6
6
  error_messages = {
7
- UnexpectedArgumentError => 'Unknown argument',
8
- UnknownCommandError => 'Unknown command',
9
- MissingArgumentError => 'Missing argument',
10
- ConflictingOptionError => 'Conflicting options given'
7
+ UnexpectedArgumentError =>
8
+ proc {|e| "Unknown argument: #{e}" },
9
+ UnknownCommandError =>
10
+ proc {|e| "Unknown command '#{e}': #{e.command_class.ancestors.map(&:command_name).join(' ')} expects one of: #{e.command_class.subcommands.map(&:command_name).join(' ')}" },
11
+ MissingArgumentError =>
12
+ proc {|e| "Missing argument: #{e.message}" },
13
+ MissingSubcommandError =>
14
+ proc {|e| "Missing argument: #{e.command_class.ancestors.map(&:command_name).join(' ')} expects one of: #{e.command_class.subcommands.map(&:command_name).join(' ')}" },
15
+ ConflictingOptionError =>
16
+ proc {|e| "Conflicting options given: #{e}" }
11
17
  }
18
+ end
12
19
 
20
+ def self.with_standard_exception_handling(options={}, &block)
13
21
  begin
14
22
  yield
15
- rescue ExitException => e
16
- # exit silently if there is no error message to print out
17
- $stderr.puts(e.message) if e.has_message?
18
- exit(e.exit_code)
19
- rescue HelpNeeded => e
20
- print_usage(e.command_class, options)
21
- exit(0)
22
- rescue ParsingError => e
23
- $stderr.puts(error_messages[e.class] + ": #{e.message}")
24
- print_usage(e.command_class, options)
25
- exit(1)
26
23
  rescue => e
27
- $stderr.puts("Unexpected error: #{e.class.name} - #{e.message}")
28
- $stderr.puts(e.backtrace)
29
- exit(2)
24
+ exit handle_error(e, options)
30
25
  end
31
26
  end
32
27
 
33
- def self.print_usage(command_class, options={})
34
- help = Help.new(command_class)
28
+ # extracted for stubbing/overriding without having to do it globally
29
+ def self.stderr ; $stderr ; end
30
+ def self.stdout ; $stdout ; end
31
+
32
+ def self.handle_error(e, options)
33
+ case e
34
+ when ExitException
35
+ # exit silently if there is no error message to print out
36
+ stderr.puts(e.message) if e.has_message?
37
+ e.exit_code
38
+ when HelpNeeded
39
+ help(e.command_class).print(options)
40
+ 0
41
+ when ParsingError
42
+ stderr.puts(error_messages[e.class].call(e))
43
+ help(e.command_class).print_usage
44
+ 1
45
+ else
46
+ stderr.puts("Unexpected error: #{e.class.name} - #{e.message}")
47
+ stderr.puts(e.backtrace)
48
+ 2
49
+ end
50
+ end
35
51
 
36
- help.print(options)
52
+ def self.help(command_class)
53
+ Help.new(command_class)
54
+ end
55
+
56
+ def self.print_usage(command_class, options={})
57
+ help(command_class).print_usage(options)
37
58
  end
38
59
 
39
60
  def run(&block)
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: climate
3
3
  version: !ruby/object:Gem::Version
4
- hash: 11
4
+ hash: 7
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
- - 5
8
+ - 6
9
9
  - 0
10
- version: 0.5.0
10
+ version: 0.6.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Nick Griffiths
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2012-10-05 00:00:00 Z
18
+ date: 2013-02-18 00:00:00 Z
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
21
  name: trollop
@@ -84,15 +84,15 @@ extensions: []
84
84
  extra_rdoc_files: []
85
85
 
86
86
  files:
87
- - lib/climate.rb
88
- - lib/climate/help.rb
89
- - lib/climate/command_compat.rb
90
87
  - lib/climate/version.rb
91
- - lib/climate/script.rb
92
- - lib/climate/errors.rb
93
- - lib/climate/parser.rb
94
- - lib/climate/command.rb
95
88
  - lib/climate/help/man.rb
89
+ - lib/climate/command_compat.rb
90
+ - lib/climate/command.rb
91
+ - lib/climate/parser.rb
92
+ - lib/climate/errors.rb
93
+ - lib/climate/script.rb
94
+ - lib/climate/help.rb
95
+ - lib/climate.rb
96
96
  - README.md
97
97
  - bin/climate
98
98
  homepage:
@@ -124,9 +124,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
124
124
  requirements: []
125
125
 
126
126
  rubyforge_project:
127
- rubygems_version: 1.8.24
127
+ rubygems_version: 1.8.10
128
128
  signing_key:
129
129
  specification_version: 3
130
130
  summary: Library for building command line interfaces
131
131
  test_files: []
132
132
 
133
+ has_rdoc: