clamp 1.0.1 → 1.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9ea677c27d0df2e7b29b4423234f6095c1aafb8b
4
- data.tar.gz: a98836b37b03bd4d72e3fe77ac292be2dda6bb14
3
+ metadata.gz: 4bd2b8653f1a6c24e26a9ec5d84f655721cecdee
4
+ data.tar.gz: 776fa8ff95cf73971de85be5e6f30915bd40df09
5
5
  SHA512:
6
- metadata.gz: f39366b518b4705bf367f7403ff1b5837c7eb984325b96029bb14737b9c02cbcea754abe39c934fc0967de2b4e6cc46516fba66ff5ab4da9493f3627d0bb939b
7
- data.tar.gz: b75b6fcda33eb33fec53153c255d8166b3ca131afc7fae36b1a8ecf172633f8bef03583ff55d4a58913ee779f01d03e497572f6528a40410169329f3eef9814a
6
+ metadata.gz: 51397540a6660a9f10bd1fae184b16d3cac69a64ce17a5f65d4e5bc3d9f3c60140f7a16ae868393372f541c147a1459ef78eaa402a65203e77833ae829d54051
7
+ data.tar.gz: 27c409d2ebbe33d768b884cff979d33df4099008506c24dbe0080249466610928cd705b88a7f7b76dc10eb4ed7cf2fc2e5be0f2e8919ff74ce8015f2403965d1
data/.rubocop.yml ADDED
@@ -0,0 +1,60 @@
1
+ Eval:
2
+ Exclude:
3
+ - "Rakefile"
4
+
5
+ Metrics/AbcSize:
6
+ Enabled: false
7
+
8
+ Metrics/LineLength:
9
+ Max: 120
10
+
11
+ Metrics/MethodLength:
12
+ Max: 30
13
+
14
+ Style/AccessorMethodName:
15
+ Enabled: false
16
+
17
+ Style/ClassAndModuleChildren:
18
+ EnforcedStyle: nested
19
+ Exclude:
20
+ - "spec/**/*"
21
+
22
+ Style/Documentation:
23
+ Exclude:
24
+ - "lib/**/version.rb"
25
+ - "spec/**/*"
26
+
27
+ Style/EmptyLinesAroundBlockBody:
28
+ Enabled: false
29
+
30
+ Style/EmptyLinesAroundClassBody:
31
+ EnforcedStyle: empty_lines
32
+
33
+ Style/EmptyLinesAroundModuleBody:
34
+ Enabled: false
35
+
36
+ Style/Encoding:
37
+ EnforcedStyle: when_needed
38
+ Enabled: true
39
+
40
+ Style/FileName:
41
+ Exclude:
42
+ - "bin/*"
43
+
44
+ Style/HashSyntax:
45
+ EnforcedStyle: hash_rockets
46
+
47
+ Style/Lambda:
48
+ Enabled: false
49
+
50
+ Style/NumericLiterals:
51
+ Enabled: false
52
+
53
+ Style/PredicateName:
54
+ Enabled: false
55
+
56
+ Style/StringLiterals:
57
+ EnforcedStyle: double_quotes
58
+
59
+ Style/WordArray:
60
+ Enabled: false
data/.travis.yml CHANGED
@@ -1,10 +1,8 @@
1
1
  language: ruby
2
2
  rvm:
3
- - 1.9.3
4
- - 2.0.0
5
- - 2.1.5
6
- - 2.2.0
7
- - 2.3.0
3
+ - 2.1.8
4
+ - 2.2.4
5
+ - 2.3.1
8
6
  before_install:
9
7
  - gem update --system
10
8
  - gem install bundler
data/CHANGES.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.1.0 (2016-10-17)
4
+
5
+ * Add `#subcommand_missing`.
6
+ * Fix issue#66: pass parameter values down to nested subcommands.
7
+ * Drop support for Ruby 1.9 and 2.0.
8
+
3
9
  ## 1.0.1 (2016-10-01)
4
10
 
5
11
  * Minor bug-fixes.
data/Gemfile CHANGED
@@ -6,9 +6,10 @@ group :development do
6
6
  gem "guard-rspec", "~> 4.6.5", :require => false
7
7
  gem "listen", "~> 3.0.2"
8
8
  gem "rake", "~> 10.4"
9
+ gem "rubocop", "~> 0.43.0", :require => false
9
10
  end
10
11
 
11
12
  group :test do
12
- gem "rspec", "~> 3.1.0"
13
- gem "rr", "~> 1.1.2"
13
+ gem "rspec", "~> 3.5.0"
14
+ gem "rr", "~> 1.2.0"
14
15
  end
data/Guardfile CHANGED
@@ -24,7 +24,7 @@
24
24
  # * zeus: 'zeus rspec' (requires the server to be started separately)
25
25
  # * 'just' rspec: 'rspec'
26
26
 
27
- guard :rspec, cmd: "bundle exec rspec" do
27
+ guard :rspec, :cmd => "bundle exec rspec" do
28
28
  require "guard/rspec/dsl"
29
29
  dsl = Guard::RSpec::Dsl.new(self)
30
30
 
data/README.md CHANGED
@@ -137,7 +137,7 @@ Clamp will handle both "`--force`" and "`--no-force`" options, setting the value
137
137
 
138
138
  ### Required options
139
139
 
140
- Although 'required option' is a an oxymoron, Clamp lets you mark an option as required, and will verify that a value is provided:
140
+ Although "required option" is an oxymoron, Clamp lets you mark an option as required, and will verify that a value is provided:
141
141
 
142
142
  ```ruby
143
143
  option "--password", "PASSWORD", "the secret password", :required => true
@@ -365,6 +365,19 @@ Options are inheritable, so any options declared for a command are supported by
365
365
 
366
366
  Note that, if a subcommand accepts options, they must be specified on the command-line _after_ the subcommand name.
367
367
 
368
+ You can define a `subcommand_missing` method that is called when user tries to run an unknown subcommand:
369
+
370
+ ```ruby
371
+ Clamp do
372
+ def subcommand_missing(name)
373
+ if name == "foo"
374
+ return Object.const_get(:FooPlugin) if Object.const_defined?(:FooPlugin)
375
+ abort "Subcommand 'foo' requires plugin X"
376
+ end
377
+ end
378
+ end
379
+ ```
380
+
368
381
  Getting help
369
382
  ------------
370
383
 
data/Rakefile CHANGED
@@ -1,4 +1,4 @@
1
- require 'bundler'
1
+ require "bundler"
2
2
 
3
3
  Bundler::GemHelper.install_tasks
4
4
 
@@ -7,6 +7,6 @@ require "rspec/core/rake_task"
7
7
  task "default" => "spec"
8
8
 
9
9
  RSpec::Core::RakeTask.new do |t|
10
- t.pattern = 'spec/**/*_spec.rb'
10
+ t.pattern = "spec/**/*_spec.rb"
11
11
  t.rspec_opts = ["--colour", "--format", "documentation"]
12
12
  end
data/clamp.gemspec CHANGED
@@ -1,5 +1,4 @@
1
- # -*- encoding: utf-8 -*-
2
- $:.push File.expand_path("../lib", __FILE__)
1
+ $LOAD_PATH.push File.expand_path("../lib", __FILE__)
3
2
  require "clamp/version"
4
3
 
5
4
  Gem::Specification.new do |s|
@@ -11,9 +10,9 @@ Gem::Specification.new do |s|
11
10
  s.email = "mdub@dogbiscuit.org"
12
11
  s.homepage = "http://github.com/mdub/clamp"
13
12
 
14
- s.license = 'MIT'
13
+ s.license = "MIT"
15
14
 
16
- s.summary = %q{a minimal framework for command-line utilities}
15
+ s.summary = "a minimal framework for command-line utilities"
17
16
  s.description = <<EOF
18
17
  Clamp provides an object-model for command-line utilities.
19
18
  It handles parsing of command-line options, and generation of usage help.
data/examples/defaulted CHANGED
@@ -20,7 +20,7 @@ Clamp do
20
20
  private
21
21
 
22
22
  def default_password
23
- terminal.ask("Password [#{user}]: ") { |q| q.echo = '*' }
23
+ terminal.ask("Password [#{user}]: ") { |q| q.echo = "*" }
24
24
  end
25
25
 
26
26
  def terminal
data/examples/scoop CHANGED
@@ -7,8 +7,8 @@ require "clamp"
7
7
  Clamp do
8
8
 
9
9
  option ["-f", "--flavour"], "FLAVOUR", "flavour",
10
- :multivalued => true, :default => ['chocolate'],
11
- :attribute_name => :flavours
10
+ :multivalued => true, :default => ["chocolate"],
11
+ :attribute_name => :flavours
12
12
 
13
13
  def execute
14
14
  puts "one #{flavours.join(' and ')} ice-cream"
data/examples/speak CHANGED
@@ -6,9 +6,9 @@ require "clamp"
6
6
 
7
7
  Clamp do
8
8
 
9
- banner %{
9
+ banner %(
10
10
  Say something.
11
- }
11
+ )
12
12
 
13
13
  option "--loud", :flag, "say it loud"
14
14
  option ["-n", "--iterations"], "N", "say it N times", :default => 1 do |s|
@@ -18,14 +18,12 @@ Clamp do
18
18
  parameter "WORDS ...", "the thing to say", :attribute_name => :words
19
19
 
20
20
  def execute
21
-
22
21
  the_truth = words.join(" ")
23
22
  the_truth.upcase! if loud?
24
23
 
25
24
  iterations.times do
26
25
  puts the_truth
27
26
  end
28
-
29
27
  end
30
28
 
31
29
  end
@@ -0,0 +1,18 @@
1
+ #! /usr/bin/env ruby
2
+
3
+ require "clamp"
4
+
5
+ Clamp do
6
+
7
+ subcommand "hello", "Say hello" do
8
+ def execute
9
+ puts "Hello"
10
+ end
11
+ end
12
+
13
+ def subcommand_missing(name)
14
+ abort "Install bye plugin first" if name == "bye"
15
+ super
16
+ end
17
+
18
+ end
data/lib/clamp.rb CHANGED
@@ -1,6 +1,6 @@
1
- require 'clamp/version'
1
+ require "clamp/version"
2
2
 
3
- require 'clamp/command'
3
+ require "clamp/command"
4
4
 
5
5
  def Clamp(&block)
6
6
  Class.new(Clamp::Command, &block).run
@@ -5,7 +5,7 @@ module Clamp
5
5
 
6
6
  protected
7
7
 
8
- def define_accessors_for(attribute, &block)
8
+ def declare_attribute(attribute, &block)
9
9
  define_reader_for(attribute)
10
10
  define_default_for(attribute)
11
11
  if attribute.multivalued?
@@ -16,6 +16,8 @@ module Clamp
16
16
  end
17
17
  end
18
18
 
19
+ private
20
+
19
21
  def define_reader_for(attribute)
20
22
  define_method(attribute.read_method) do
21
23
  attribute.of(self)._read
@@ -1,4 +1,4 @@
1
- require 'clamp/attribute/instance'
1
+ require "clamp/attribute/instance"
2
2
 
3
3
  module Clamp
4
4
  module Attribute
@@ -6,18 +6,14 @@ module Clamp
6
6
  class Definition
7
7
 
8
8
  def initialize(options)
9
- if options.has_key?(:attribute_name)
9
+ if options.key?(:attribute_name)
10
10
  @attribute_name = options[:attribute_name].to_s
11
11
  end
12
- if options.has_key?(:default)
13
- @default_value = options[:default]
14
- end
15
- if options.has_key?(:environment_variable)
12
+ @default_value = options[:default] if options.key?(:default)
13
+ if options.key?(:environment_variable)
16
14
  @environment_variable = options[:environment_variable]
17
15
  end
18
- if options.has_key?(:hidden)
19
- @hidden = options[:hidden]
20
- end
16
+ @hidden = options[:hidden] if options.key?(:hidden)
21
17
  end
22
18
 
23
19
  attr_reader :description, :environment_variable
@@ -47,9 +43,7 @@ module Clamp
47
43
  end
48
44
 
49
45
  def append_method
50
- if multivalued?
51
- "append_to_#{attribute_name}"
52
- end
46
+ "append_to_#{attribute_name}" if multivalued?
53
47
  end
54
48
 
55
49
  def multivalued?
@@ -63,7 +63,7 @@ module Clamp
63
63
  def default_from_environment
64
64
  return if self.defined?
65
65
  return if attribute.environment_variable.nil?
66
- return unless ENV.has_key?(attribute.environment_variable)
66
+ return unless ENV.key?(attribute.environment_variable)
67
67
  # Set the parameter value if it's environment variable is present
68
68
  value = ENV[attribute.environment_variable]
69
69
  begin
data/lib/clamp/command.rb CHANGED
@@ -1,12 +1,12 @@
1
- require 'clamp/messages'
2
- require 'clamp/errors'
3
- require 'clamp/help'
4
- require 'clamp/option/declaration'
5
- require 'clamp/option/parsing'
6
- require 'clamp/parameter/declaration'
7
- require 'clamp/parameter/parsing'
8
- require 'clamp/subcommand/declaration'
9
- require 'clamp/subcommand/parsing'
1
+ require "clamp/messages"
2
+ require "clamp/errors"
3
+ require "clamp/help"
4
+ require "clamp/option/declaration"
5
+ require "clamp/option/parsing"
6
+ require "clamp/parameter/declaration"
7
+ require "clamp/parameter/parsing"
8
+ require "clamp/subcommand/declaration"
9
+ require "clamp/subcommand/parsing"
10
10
 
11
11
  module Clamp
12
12
 
@@ -25,12 +25,9 @@ module Clamp
25
25
  # @param [String] invocation_path the path used to invoke the command
26
26
  # @param [Hash] context additional data the command may need
27
27
  #
28
- def initialize(invocation_path, context = {}, parent_attribute_values = {})
28
+ def initialize(invocation_path, context = {})
29
29
  @invocation_path = invocation_path
30
30
  @context = context
31
- parent_attribute_values.each do |attribute, value|
32
- attribute.of(self).set(value)
33
- end
34
31
  end
35
32
 
36
33
  # @return [String] the path used to invoke this command
@@ -39,9 +36,7 @@ module Clamp
39
36
 
40
37
  # @return [Array<String>] unconsumed command-line arguments
41
38
  #
42
- def remaining_arguments
43
- @remaining_arguments
44
- end
39
+ attr_reader :remaining_arguments
45
40
 
46
41
  # Parse command-line arguments.
47
42
  #
@@ -82,6 +77,13 @@ module Clamp
82
77
  self.class.help(invocation_path)
83
78
  end
84
79
 
80
+ # Abort with subcommand missing usage error
81
+ #
82
+ # @ param [String] name subcommand_name
83
+ def subcommand_missing(name)
84
+ signal_usage_error(Clamp.message(:no_such_subcommand, :name => name))
85
+ end
86
+
85
87
  include Clamp::Option::Parsing
86
88
  include Clamp::Parameter::Parsing
87
89
  include Clamp::Subcommand::Parsing
@@ -91,9 +93,7 @@ module Clamp
91
93
  attr_accessor :context
92
94
 
93
95
  def handle_remaining_arguments
94
- unless remaining_arguments.empty?
95
- signal_usage_error Clamp.message(:too_many_arguments)
96
- end
96
+ signal_usage_error Clamp.message(:too_many_arguments) unless remaining_arguments.empty?
97
97
  end
98
98
 
99
99
  private
@@ -128,22 +128,20 @@ module Clamp
128
128
  # @param [Array<String>] arguments command-line arguments
129
129
  # @param [Hash] context additional data the command may need
130
130
  #
131
- def run(invocation_path = File.basename($0), arguments = ARGV, context = {})
132
- begin
133
- new(invocation_path, context).run(arguments)
134
- rescue Clamp::UsageError => e
135
- $stderr.puts "ERROR: #{e.message}"
136
- $stderr.puts ""
137
- $stderr.puts "See: '#{e.command.invocation_path} --help'"
138
- exit(1)
139
- rescue Clamp::HelpWanted => e
140
- puts e.command.help
141
- rescue Clamp::ExecutionError => e
142
- $stderr.puts "ERROR: #{e.message}"
143
- exit(e.status)
144
- rescue SignalException => e
145
- exit(128 + e.signo)
146
- end
131
+ def run(invocation_path = File.basename($PROGRAM_NAME), arguments = ARGV, context = {})
132
+ new(invocation_path, context).run(arguments)
133
+ rescue Clamp::UsageError => e
134
+ $stderr.puts "ERROR: #{e.message}"
135
+ $stderr.puts ""
136
+ $stderr.puts "See: '#{e.command.invocation_path} --help'"
137
+ exit(1)
138
+ rescue Clamp::HelpWanted => e
139
+ puts e.command.help
140
+ rescue Clamp::ExecutionError => e
141
+ $stderr.puts "ERROR: #{e.message}"
142
+ exit(e.status)
143
+ rescue SignalException => e
144
+ exit(128 + e.signo)
147
145
  end
148
146
 
149
147
  end