clamp 1.2.1 → 1.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +12 -4
- data/.travis.yml +4 -6
- data/CHANGES.md +7 -0
- data/Gemfile +8 -6
- data/Guardfile +3 -1
- data/Rakefile +8 -0
- data/clamp.gemspec +8 -6
- data/examples/admin +3 -2
- data/examples/defaulted +4 -3
- data/examples/flipflop +1 -0
- data/examples/fubar +1 -0
- data/examples/gitdown +2 -1
- data/examples/scoop +3 -2
- data/examples/speak +3 -2
- data/examples/subcommand_missing +1 -0
- data/examples/word +1 -0
- data/lib/clamp.rb +3 -1
- data/lib/clamp/attribute/declaration.rb +5 -0
- data/lib/clamp/attribute/definition.rb +15 -12
- data/lib/clamp/attribute/instance.rb +5 -3
- data/lib/clamp/command.rb +9 -1
- data/lib/clamp/errors.rb +7 -3
- data/lib/clamp/help.rb +8 -6
- data/lib/clamp/messages.rb +21 -14
- data/lib/clamp/option/declaration.rb +4 -0
- data/lib/clamp/option/definition.rb +9 -3
- data/lib/clamp/option/parsing.rb +37 -32
- data/lib/clamp/parameter/declaration.rb +4 -0
- data/lib/clamp/parameter/definition.rb +9 -3
- data/lib/clamp/parameter/parsing.rb +5 -1
- data/lib/clamp/subcommand/declaration.rb +15 -13
- data/lib/clamp/subcommand/definition.rb +2 -0
- data/lib/clamp/subcommand/execution.rb +11 -0
- data/lib/clamp/subcommand/parsing.rb +4 -0
- data/lib/clamp/truthy.rb +4 -2
- data/lib/clamp/version.rb +3 -1
- data/spec/clamp/command_group_spec.rb +27 -9
- data/spec/clamp/command_spec.rb +84 -49
- data/spec/clamp/messages_spec.rb +5 -4
- data/spec/clamp/option/definition_spec.rb +13 -11
- data/spec/clamp/option_module_spec.rb +3 -1
- data/spec/clamp/option_reordering_spec.rb +6 -4
- data/spec/clamp/parameter/definition_spec.rb +14 -12
- data/spec/spec_helper.rb +3 -3
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a8365dad9e1c1555dfddea4d47c063438af94be5
|
4
|
+
data.tar.gz: b618f175a72f08180fb77315cc1a4ceafbbb134e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2bec2151d2344efc7fbcd37709646904d20e7456fa83365484aacfa318bb23207a8e3ae9e813457d26d791f56b8c890eb863ccb59a85724a53b542193af26384
|
7
|
+
data.tar.gz: 0be7bb668484292023495887a581e8e887e0d3f10f2fac89353f6e6a6d091a2f3e9a308902a3f8548c169dd138c0aec7a90e28fac950e36999f9524b1ffab886
|
data/.rubocop.yml
CHANGED
@@ -1,3 +1,6 @@
|
|
1
|
+
AllCops:
|
2
|
+
TargetRubyVersion: 2.1
|
3
|
+
|
1
4
|
Eval:
|
2
5
|
Exclude:
|
3
6
|
- "Rakefile"
|
@@ -14,6 +17,10 @@ Layout/EmptyLinesAroundModuleBody:
|
|
14
17
|
Metrics/AbcSize:
|
15
18
|
Enabled: false
|
16
19
|
|
20
|
+
Metrics/BlockLength:
|
21
|
+
Exclude:
|
22
|
+
- "spec/**/*"
|
23
|
+
|
17
24
|
Metrics/LineLength:
|
18
25
|
Max: 120
|
19
26
|
|
@@ -27,6 +34,9 @@ Naming/FileName:
|
|
27
34
|
Exclude:
|
28
35
|
- "bin/*"
|
29
36
|
|
37
|
+
Naming/PredicateName:
|
38
|
+
Enabled: false
|
39
|
+
|
30
40
|
Style/ClassAndModuleChildren:
|
31
41
|
EnforcedStyle: nested
|
32
42
|
Exclude:
|
@@ -35,21 +45,19 @@ Style/ClassAndModuleChildren:
|
|
35
45
|
Style/Documentation:
|
36
46
|
Exclude:
|
37
47
|
- "lib/**/version.rb"
|
48
|
+
- "examples/*"
|
38
49
|
- "spec/**/*"
|
39
50
|
|
40
51
|
Style/Encoding:
|
41
52
|
Enabled: true
|
42
53
|
|
43
|
-
Style/HashSyntax:
|
44
|
-
EnforcedStyle: hash_rockets
|
45
|
-
|
46
54
|
Style/Lambda:
|
47
55
|
Enabled: false
|
48
56
|
|
49
57
|
Style/NumericLiterals:
|
50
58
|
Enabled: false
|
51
59
|
|
52
|
-
|
60
|
+
Style/StderrPuts:
|
53
61
|
Enabled: false
|
54
62
|
|
55
63
|
Style/StringLiterals:
|
data/.travis.yml
CHANGED
data/CHANGES.md
CHANGED
@@ -1,5 +1,12 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## 1.3.0 (2018-06-17)
|
4
|
+
|
5
|
+
* Add `.execute` DSL method.
|
6
|
+
* Append '(required)' to the description of required options.
|
7
|
+
* Fix issue#75: don't generate `default_XXX` method unless a default is specified.
|
8
|
+
* Fix issue#90: allow required options to be provided after subcommands.
|
9
|
+
|
3
10
|
## 1.2.0 (2018-02-12)
|
4
11
|
|
5
12
|
* Add option to `Clamp.allow_options_after_parameters`.
|
data/Gemfile
CHANGED
@@ -1,15 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
source "http://rubygems.org"
|
2
4
|
|
3
5
|
gemspec
|
4
6
|
|
5
7
|
group :development do
|
6
|
-
gem "guard-rspec", "~> 4.
|
7
|
-
gem "
|
8
|
-
gem "
|
9
|
-
gem "
|
8
|
+
gem "guard-rspec", "~> 4.7", require: false
|
9
|
+
gem "highline"
|
10
|
+
gem "listen", "~> 3.0"
|
11
|
+
gem "rake", "~> 12.3"
|
12
|
+
gem "rubocop", require: false
|
10
13
|
end
|
11
14
|
|
12
15
|
group :test do
|
13
|
-
gem "rspec", "~> 3.
|
14
|
-
gem "rr", "~> 1.2.0"
|
16
|
+
gem "rspec", "~> 3.7"
|
15
17
|
end
|
data/Guardfile
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# A sample Guardfile
|
2
4
|
# More info at https://github.com/guard/guard#readme
|
3
5
|
|
@@ -24,7 +26,7 @@
|
|
24
26
|
# * zeus: 'zeus rspec' (requires the server to be started separately)
|
25
27
|
# * 'just' rspec: 'rspec'
|
26
28
|
|
27
|
-
guard :rspec, :
|
29
|
+
guard :rspec, cmd: "bundle exec rspec" do
|
28
30
|
require "guard/rspec/dsl"
|
29
31
|
dsl = Guard::RSpec::Dsl.new(self)
|
30
32
|
|
data/Rakefile
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "bundler"
|
2
4
|
|
3
5
|
Bundler::GemHelper.install_tasks
|
@@ -10,3 +12,9 @@ RSpec::Core::RakeTask.new do |t|
|
|
10
12
|
t.pattern = "spec/**/*_spec.rb"
|
11
13
|
t.rspec_opts = ["--colour", "--format", "documentation"]
|
12
14
|
end
|
15
|
+
|
16
|
+
require "rubocop/rake_task"
|
17
|
+
|
18
|
+
RuboCop::RakeTask.new
|
19
|
+
|
20
|
+
task "default" => "rubocop"
|
data/clamp.gemspec
CHANGED
@@ -1,4 +1,6 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
$LOAD_PATH.push File.expand_path("lib", __dir__)
|
2
4
|
require "clamp/version"
|
3
5
|
|
4
6
|
Gem::Specification.new do |s|
|
@@ -8,15 +10,15 @@ Gem::Specification.new do |s|
|
|
8
10
|
s.platform = Gem::Platform::RUBY
|
9
11
|
s.authors = ["Mike Williams"]
|
10
12
|
s.email = "mdub@dogbiscuit.org"
|
11
|
-
s.homepage = "
|
13
|
+
s.homepage = "https://github.com/mdub/clamp"
|
12
14
|
|
13
15
|
s.license = "MIT"
|
14
16
|
|
15
17
|
s.summary = "a minimal framework for command-line utilities"
|
16
|
-
s.description =
|
17
|
-
Clamp provides an object-model for command-line utilities.
|
18
|
-
It handles parsing of command-line options, and generation of usage help.
|
19
|
-
|
18
|
+
s.description = <<-TEXT.gsub(/^\s+/, "")
|
19
|
+
Clamp provides an object-model for command-line utilities.
|
20
|
+
It handles parsing of command-line options, and generation of usage help.
|
21
|
+
TEXT
|
20
22
|
|
21
23
|
s.files = `git ls-files`.split("\n")
|
22
24
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
data/examples/admin
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
#! /usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
2
3
|
|
3
4
|
# An example of options and parameters
|
4
5
|
|
@@ -6,12 +7,12 @@ require "clamp"
|
|
6
7
|
|
7
8
|
Clamp do
|
8
9
|
|
9
|
-
option "--timeout", "SECONDS", "connection timeout", :
|
10
|
+
option "--timeout", "SECONDS", "connection timeout", default: 5, environment_variable: "MYAPP_TIMEOUT" do |x|
|
10
11
|
Integer(x)
|
11
12
|
end
|
12
13
|
|
13
14
|
parameter "HOST", "server address"
|
14
|
-
parameter "[PORT]", "server port", :
|
15
|
+
parameter "[PORT]", "server port", default: 80, environment_variable: "MYAPP_PORT"
|
15
16
|
|
16
17
|
def execute
|
17
18
|
puts "trying to connect to #{host} on port #{port} (waiting up to #{timeout} seconds)"
|
data/examples/defaulted
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
#! /usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
2
3
|
|
3
4
|
# An example of default values and methods
|
4
5
|
|
@@ -8,10 +9,10 @@ require "highline"
|
|
8
9
|
Clamp do
|
9
10
|
|
10
11
|
option ["-U", "--user"], "USER", "user name",
|
11
|
-
:
|
12
|
-
:
|
12
|
+
environment_variable: "THE_USER",
|
13
|
+
default: "bob"
|
13
14
|
option ["-P", "--password"], "PASSWORD", "password",
|
14
|
-
:
|
15
|
+
environment_variable: "THE_PASSWORD"
|
15
16
|
|
16
17
|
def execute
|
17
18
|
puts "User: #{user}, Password: #{password}"
|
data/examples/flipflop
CHANGED
data/examples/fubar
CHANGED
data/examples/gitdown
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
#! /usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
2
3
|
|
3
4
|
# Demonstrate how subcommands can be declared as classes
|
4
5
|
|
@@ -25,7 +26,7 @@ module GitDown
|
|
25
26
|
class CloneCommand < AbstractCommand
|
26
27
|
|
27
28
|
parameter "REPOSITORY", "repository to clone"
|
28
|
-
parameter "[DIR]", "working directory", :
|
29
|
+
parameter "[DIR]", "working directory", default: "."
|
29
30
|
|
30
31
|
def execute
|
31
32
|
say "cloning to #{dir}"
|
data/examples/scoop
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
#! /usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
2
3
|
|
3
4
|
# An example of multi-valued options
|
4
5
|
|
@@ -7,8 +8,8 @@ require "clamp"
|
|
7
8
|
Clamp do
|
8
9
|
|
9
10
|
option ["-f", "--flavour"], "FLAVOUR", "flavour",
|
10
|
-
:
|
11
|
-
:
|
11
|
+
multivalued: true, default: ["chocolate"],
|
12
|
+
attribute_name: :flavours
|
12
13
|
|
13
14
|
def execute
|
14
15
|
puts "one #{flavours.join(' and ')} ice-cream"
|
data/examples/speak
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
#! /usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
2
3
|
|
3
4
|
# A simple Clamp command, with options and parameters
|
4
5
|
|
@@ -11,11 +12,11 @@ Clamp do
|
|
11
12
|
)
|
12
13
|
|
13
14
|
option "--loud", :flag, "say it loud"
|
14
|
-
option ["-n", "--iterations"], "N", "say it N times", :
|
15
|
+
option ["-n", "--iterations"], "N", "say it N times", default: 1 do |s|
|
15
16
|
Integer(s)
|
16
17
|
end
|
17
18
|
|
18
|
-
parameter "WORDS ...", "the thing to say", :
|
19
|
+
parameter "WORDS ...", "the thing to say", attribute_name: :words
|
19
20
|
|
20
21
|
def execute
|
21
22
|
the_truth = words.join(" ")
|
data/examples/subcommand_missing
CHANGED
data/examples/word
CHANGED
data/lib/clamp.rb
CHANGED
@@ -1,6 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Clamp
|
2
4
|
module Attribute
|
3
5
|
|
6
|
+
# Methods to generate attribute accessors.
|
7
|
+
#
|
4
8
|
module Declaration
|
5
9
|
|
6
10
|
protected
|
@@ -25,6 +29,7 @@ module Clamp
|
|
25
29
|
end
|
26
30
|
|
27
31
|
def define_default_for(attribute)
|
32
|
+
return false if attribute.default_value.nil?
|
28
33
|
define_method(attribute.default_method) do
|
29
34
|
attribute.default_value
|
30
35
|
end
|
@@ -1,25 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "clamp/attribute/instance"
|
2
4
|
|
3
5
|
module Clamp
|
4
6
|
module Attribute
|
5
7
|
|
8
|
+
# Represents an attribute of a Clamp::Command class.
|
9
|
+
#
|
6
10
|
class Definition
|
7
11
|
|
8
12
|
def initialize(options)
|
9
|
-
if options.key?(:attribute_name)
|
10
|
-
@attribute_name = options[:attribute_name].to_s
|
11
|
-
end
|
13
|
+
@attribute_name = options[:attribute_name].to_s if options.key?(:attribute_name)
|
12
14
|
@default_value = options[:default] if options.key?(:default)
|
13
|
-
if options.key?(:environment_variable)
|
14
|
-
@environment_variable = options[:environment_variable]
|
15
|
-
end
|
15
|
+
@environment_variable = options[:environment_variable] if options.key?(:environment_variable)
|
16
16
|
@hidden = options[:hidden] if options.key?(:hidden)
|
17
17
|
end
|
18
18
|
|
19
19
|
attr_reader :description, :environment_variable
|
20
20
|
|
21
21
|
def help_rhs
|
22
|
-
|
22
|
+
rhs = description
|
23
|
+
comments = required_indicator || default_description
|
24
|
+
rhs += " (#{comments})" if comments
|
25
|
+
rhs
|
23
26
|
end
|
24
27
|
|
25
28
|
def help
|
@@ -77,11 +80,11 @@ module Clamp
|
|
77
80
|
def option_missing_message
|
78
81
|
if environment_variable
|
79
82
|
Clamp.message(:option_or_env_required,
|
80
|
-
:
|
81
|
-
:
|
83
|
+
option: switches.first,
|
84
|
+
env: environment_variable)
|
82
85
|
else
|
83
86
|
Clamp.message(:option_required,
|
84
|
-
:
|
87
|
+
option: switches.first)
|
85
88
|
end
|
86
89
|
end
|
87
90
|
|
@@ -92,8 +95,8 @@ module Clamp
|
|
92
95
|
("$#{@environment_variable}" if defined?(@environment_variable)),
|
93
96
|
(@default_value.inspect if defined?(@default_value))
|
94
97
|
].compact
|
95
|
-
return
|
96
|
-
"
|
98
|
+
return nil if default_sources.empty?
|
99
|
+
"#{Clamp.message(:default)}: " + default_sources.join(", #{Clamp.message(:or)} ")
|
97
100
|
end
|
98
101
|
|
99
102
|
end
|
@@ -1,7 +1,9 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Clamp
|
2
4
|
module Attribute
|
3
5
|
|
4
|
-
# Represents an
|
6
|
+
# Represents an attribute of a Clamp::Command instance.
|
5
7
|
#
|
6
8
|
class Instance
|
7
9
|
|
@@ -27,7 +29,7 @@ module Clamp
|
|
27
29
|
end
|
28
30
|
|
29
31
|
def default
|
30
|
-
command.send(attribute.default_method)
|
32
|
+
command.send(attribute.default_method) if command.respond_to?(attribute.default_method, true)
|
31
33
|
end
|
32
34
|
|
33
35
|
# default implementation of read_method
|
@@ -73,7 +75,7 @@ module Clamp
|
|
73
75
|
begin
|
74
76
|
take(value)
|
75
77
|
rescue ArgumentError => e
|
76
|
-
signal_usage_error Clamp.message(:env_argument_error, :
|
78
|
+
signal_usage_error Clamp.message(:env_argument_error, env: attribute.environment_variable, message: e.message)
|
77
79
|
end
|
78
80
|
end
|
79
81
|
|
data/lib/clamp/command.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "clamp/messages"
|
2
4
|
require "clamp/errors"
|
3
5
|
require "clamp/help"
|
@@ -48,6 +50,7 @@ module Clamp
|
|
48
50
|
parse_options
|
49
51
|
parse_parameters
|
50
52
|
parse_subcommand
|
53
|
+
verify_required_options_are_set
|
51
54
|
handle_remaining_arguments
|
52
55
|
end
|
53
56
|
|
@@ -81,7 +84,7 @@ module Clamp
|
|
81
84
|
#
|
82
85
|
# @ param [String] name subcommand_name
|
83
86
|
def subcommand_missing(name)
|
84
|
-
signal_usage_error(Clamp.message(:no_such_subcommand, :
|
87
|
+
signal_usage_error(Clamp.message(:no_such_subcommand, name: name))
|
85
88
|
end
|
86
89
|
|
87
90
|
include Clamp::Option::Parsing
|
@@ -122,6 +125,11 @@ module Clamp
|
|
122
125
|
include Clamp::Subcommand::Declaration
|
123
126
|
include Help
|
124
127
|
|
128
|
+
# An alternative to "def execute"
|
129
|
+
def execute(&block)
|
130
|
+
define_method(:execute, &block)
|
131
|
+
end
|
132
|
+
|
125
133
|
# Create an instance of this command class, and run it.
|
126
134
|
#
|
127
135
|
# @param [String] invocation_path the path used to invoke the command
|