climate 0.5.0 → 0.6.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.
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: