clamp 1.3.2 → 1.3.3

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
  SHA256:
3
- metadata.gz: c164c63137c57502ad15e11ab471b2607661868298e5330a8a4961dfea629537
4
- data.tar.gz: 297e0abb1ead811d567eea7e668a91ba7c99654657a358016abb5cdbfd13168d
3
+ metadata.gz: 43f15a863374d1abf2505c8b102de45e94f05146649728354c3d5593ff8f3a01
4
+ data.tar.gz: 5e9d629fa2e5947ba0060dfb831198ffa4a313a5faa7318b4efb4fd651bbb158
5
5
  SHA512:
6
- metadata.gz: 3773151ffa64b908d26c569877bb27704bf68efe658d9b6ebd48c009bcbc1a4d0a3fce2c4f16a02ed379e126dd436ef018ff1eac56334fcc8f467402fad6c995
7
- data.tar.gz: 8104ea9b1d9a42669234cb0d82cc441efd7a6f94ed5cba542a502ae1cb2797d977530a07bbe649d98dab551e9078b434711e091e9d0b3716799522c04436d8c9
6
+ metadata.gz: 8e68d1317f82da6b7275eb56ad1ef5be9b34fd2390e8819efd488558424c20e550ea4e625d90fa0d5d1303decd0ecd68e11138c4fc505fa66c876a00bd2de107
7
+ data.tar.gz: f16d43d5234ac429d1839f822177f55d1aee7e1d4eb94c49c6bcd2585c5a9049099a4bd426df01d2c8f409e7957d44c84a34c83adcc6a3710f62efcd11421d7e
data/.editorconfig CHANGED
@@ -7,3 +7,4 @@ end_of_line = lf
7
7
  charset = utf-8
8
8
  trim_trailing_whitespace = true
9
9
  insert_final_newline = true
10
+ max_line_length = 120
data/.gitignore CHANGED
@@ -2,6 +2,7 @@
2
2
  .bundle
3
3
  .markdownlint*
4
4
  .rvmrc
5
+ .ruby-version
5
6
  .yardoc
6
7
  doc
7
8
  pkg/*
data/.rubocop.yml CHANGED
@@ -1,9 +1,13 @@
1
+ plugins:
2
+ - rubocop-rake
3
+ - rubocop-rspec
4
+
1
5
  AllCops:
2
- TargetRubyVersion: 2.1
6
+ TargetRubyVersion: 2.5
7
+ NewCops: enable
3
8
 
4
- Eval:
5
- Exclude:
6
- - "Rakefile"
9
+ Layout/LineLength:
10
+ Max: 120
7
11
 
8
12
  Layout/EmptyLinesAroundBlockBody:
9
13
  Enabled: false
@@ -21,9 +25,6 @@ Metrics/BlockLength:
21
25
  Exclude:
22
26
  - "spec/**/*"
23
27
 
24
- Metrics/LineLength:
25
- Max: 120
26
-
27
28
  Metrics/MethodLength:
28
29
  Max: 30
29
30
 
@@ -34,7 +35,7 @@ Naming/FileName:
34
35
  Exclude:
35
36
  - "bin/*"
36
37
 
37
- Naming/PredicateName:
38
+ Naming/PredicatePrefix:
38
39
  Enabled: false
39
40
 
40
41
  Style/ClassAndModuleChildren:
@@ -65,3 +66,6 @@ Style/StringLiterals:
65
66
 
66
67
  Style/WordArray:
67
68
  Enabled: false
69
+
70
+ RSpec/NestedGroups:
71
+ Enabled: false
data/.travis.yml CHANGED
@@ -1,5 +1,6 @@
1
1
  language: ruby
2
2
  rvm:
3
- - 2.3
4
3
  - 2.5
5
4
  - 2.6
5
+ - 2.7
6
+ - 3.0
data/CHANGES.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.3.3 (2025-07-31)
4
+
5
+ * Raise an error if no value is provided for a non-flag switch.
6
+
3
7
  ## 1.3.2 (2020-08-20)
4
8
 
5
9
  * Fix Ruby warnings.
data/CODEOWNERS ADDED
@@ -0,0 +1 @@
1
+ * @mdub
data/Gemfile CHANGED
@@ -1,17 +1,20 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- source "http://rubygems.org"
3
+ source "https://rubygems.org"
4
4
 
5
5
  gemspec
6
6
 
7
7
  group :development do
8
8
  gem "guard-rspec", "~> 4.7", require: false
9
9
  gem "highline"
10
- gem "listen", "~> 3.0"
11
- gem "rake", "~> 12.3"
12
- gem "rubocop", "~> 0.57.2", "<= 0.58", require: false
10
+ gem "listen", "~> 3.9"
11
+ gem "pry-byebug", "~> 3.11"
12
+ gem "rake", "~> 13.3"
13
+ gem "rubocop", "~> 1.79.0", require: false
14
+ gem "rubocop-rake", "~> 0.7.1", require: false
15
+ gem "rubocop-rspec", "~> 3.6.0", require: false
13
16
  end
14
17
 
15
18
  group :test do
16
- gem "rspec", "~> 3.7"
19
+ gem "rspec", "~> 3.13"
17
20
  end
data/Guardfile CHANGED
@@ -7,7 +7,7 @@
7
7
  # directories %w(app lib config test spec features) \
8
8
  # .select{|d| Dir.exists?(d) ? d : UI.warning("Directory #{d} does not exist")}
9
9
 
10
- ## Note: if you are using the `directories` clause above and you are not
10
+ ## NOTE: if you are using the `directories` clause above and you are not
11
11
  ## watching the project directory ('.'), then you will want to move
12
12
  ## the Guardfile to a watched dir and symlink it back, e.g.
13
13
  #
@@ -17,7 +17,7 @@
17
17
  #
18
18
  # and, you'll have to watch "config/Guardfile" instead of "Guardfile"
19
19
 
20
- # Note: The cmd option is now required due to the increasing number of ways
20
+ # NOTE: The cmd option is now required due to the increasing number of ways
21
21
  # rspec may be run, below are examples of the most common uses.
22
22
  # * bundler: 'bundle exec rspec'
23
23
  # * bundler binstubs: 'bin/rspec'
data/Rakefile CHANGED
@@ -6,8 +6,6 @@ Bundler::GemHelper.install_tasks
6
6
 
7
7
  require "rspec/core/rake_task"
8
8
 
9
- task "default" => "spec"
10
-
11
9
  RSpec::Core::RakeTask.new do |t|
12
10
  t.pattern = "spec/**/*_spec.rb"
13
11
  t.rspec_opts = ["--colour", "--format", "documentation"]
@@ -17,4 +15,4 @@ require "rubocop/rake_task"
17
15
 
18
16
  RuboCop::RakeTask.new
19
17
 
20
- task "default" => "rubocop"
18
+ task "default" => ["spec", "rubocop"]
data/clamp.gemspec CHANGED
@@ -21,7 +21,8 @@ Gem::Specification.new do |s|
21
21
  TEXT
22
22
 
23
23
  s.files = `git ls-files`.split("\n")
24
- s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
25
24
  s.require_paths = ["lib"]
26
25
 
26
+ s.required_ruby_version = ">= 2.5", "< 4"
27
+ s.metadata["rubygems_mfa_required"] = "true"
27
28
  end
@@ -30,6 +30,7 @@ module Clamp
30
30
 
31
31
  def define_default_for(attribute)
32
32
  return false if attribute.default_value.nil?
33
+
33
34
  define_method(attribute.default_method) do
34
35
  attribute.default_value
35
36
  end
@@ -20,8 +20,8 @@ module Clamp
20
20
 
21
21
  def help_rhs
22
22
  rhs = description
23
- comments = required_indicator || default_description
24
- rhs += " (#{comments})" if comments
23
+ comments = [required_indicator, default_description].compact
24
+ rhs += " (#{comments.join(', ')})" unless comments.empty?
25
25
  rhs
26
26
  end
27
27
 
@@ -95,7 +95,9 @@ module Clamp
95
95
  ("$#{@environment_variable}" if defined?(@environment_variable)),
96
96
  (@default_value.inspect if defined?(@default_value))
97
97
  ].compact
98
+
98
99
  return nil if default_sources.empty?
100
+
99
101
  "#{Clamp.message(:default)}: " + default_sources.join(", #{Clamp.message(:or)} ")
100
102
  end
101
103
 
@@ -70,8 +70,9 @@ module Clamp
70
70
  return if self.defined?
71
71
  return if attribute.environment_variable.nil?
72
72
  return unless ENV.key?(attribute.environment_variable)
73
+
73
74
  # Set the parameter value if it's environment variable is present
74
- value = ENV[attribute.environment_variable]
75
+ value = ENV.fetch(attribute.environment_variable, nil)
75
76
  begin
76
77
  take(value)
77
78
  rescue ArgumentError => e
data/lib/clamp/help.rb CHANGED
@@ -14,7 +14,7 @@ module Clamp
14
14
  @declared_usage_descriptions << usage
15
15
  end
16
16
 
17
- attr_reader :declared_usage_descriptions
17
+ attr_reader :declared_usage_descriptions, :description
18
18
 
19
19
  def description=(description)
20
20
  @description = description.dup
@@ -29,8 +29,6 @@ module Clamp
29
29
  self.description = description
30
30
  end
31
31
 
32
- attr_reader :description
33
-
34
32
  def derived_usage_description
35
33
  parts = ["[OPTIONS]"]
36
34
  parts += parameters.map(&:name)
@@ -84,7 +82,7 @@ module Clamp
84
82
  end
85
83
 
86
84
  def add_usage(invocation_path, usage_descriptions)
87
- line Clamp.message(:usage_heading) + ":"
85
+ line "#{Clamp.message(:usage_heading)}:"
88
86
  usage_descriptions.each do |usage|
89
87
  line " #{invocation_path} #{usage}".rstrip
90
88
  end
@@ -92,11 +90,12 @@ module Clamp
92
90
 
93
91
  def add_description(description)
94
92
  return unless description
93
+
95
94
  line
96
95
  line description.gsub(/^/, " ")
97
96
  end
98
97
 
99
- DETAIL_FORMAT = " %-29s %s".freeze
98
+ DETAIL_FORMAT = " %-29s %s"
100
99
 
101
100
  def add_list(heading, items)
102
101
  line
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Clamp #:nodoc:
3
+ module Clamp # :nodoc:
4
4
 
5
5
  # Message lookup, to allow localization.
6
6
  #
@@ -21,8 +21,6 @@ module Clamp #:nodoc:
21
21
  init_default_messages
22
22
  end
23
23
 
24
- private
25
-
26
24
  DEFAULTS = {
27
25
  too_many_arguments: "too many arguments",
28
26
  option_required: "option '%<option>s' is required",
@@ -42,6 +40,8 @@ module Clamp #:nodoc:
42
40
  options_heading: "Options"
43
41
  }.freeze
44
42
 
43
+ private
44
+
45
45
  def messages
46
46
  init_default_messages unless defined?(@messages)
47
47
  @messages
@@ -40,6 +40,7 @@ module Clamp
40
40
 
41
41
  def declare_implicit_help_option
42
42
  return false if effective_options.find { |o| o.handles?("--help") }
43
+
43
44
  help_switches = ["--help"]
44
45
  help_switches.unshift("-h") unless effective_options.find { |o| o.handles?("-h") }
45
46
  option help_switches, :flag, "print help" do
@@ -55,6 +56,7 @@ module Clamp
55
56
 
56
57
  def options_declared_on(ancestor)
57
58
  return [] unless ancestor.is_a?(Clamp::Option::Declaration)
59
+
58
60
  ancestor.declared_options
59
61
  end
60
62
 
@@ -16,7 +16,9 @@ module Clamp
16
16
  @description = description
17
17
  super(options)
18
18
  @multivalued = options[:multivalued]
19
+
19
20
  return unless options.key?(:required)
21
+
20
22
  @required = options[:required]
21
23
  # Do some light validation for conflicting settings.
22
24
  raise ArgumentError, "Specifying a :default value with :required doesn't make sense" if options.key?(:default)
@@ -37,13 +39,13 @@ module Clamp
37
39
  @type == :flag
38
40
  end
39
41
 
40
- def flag_value(switch)
41
- !(switch =~ /^--no-(.*)/ && switches.member?("--\[no-\]#{Regexp.last_match(1)}"))
42
+ def flag_set?(switch)
43
+ !(switch =~ /^--no-(.*)/ && switches.member?("--[no-]#{Regexp.last_match(1)}"))
42
44
  end
43
45
 
44
46
  def read_method
45
47
  if flag?
46
- super + "?"
48
+ "#{super}?"
47
49
  else
48
50
  super
49
51
  end
@@ -51,8 +53,10 @@ module Clamp
51
53
 
52
54
  def extract_value(switch, arguments)
53
55
  if flag?
54
- flag_value(switch)
56
+ flag_set?(switch)
55
57
  else
58
+ raise ArgumentError, Clamp.message(:no_value_provided) if arguments.empty?
59
+
56
60
  arguments.shift
57
61
  end
58
62
  end
@@ -63,7 +67,7 @@ module Clamp
63
67
 
64
68
  def help_lhs
65
69
  lhs = switches.join(", ")
66
- lhs += " " + type unless flag?
70
+ lhs += " #{type}" unless flag?
67
71
  lhs
68
72
  end
69
73
 
@@ -81,6 +85,7 @@ module Clamp
81
85
 
82
86
  def infer_attribute_name
83
87
  raise Clamp::DeclarationError, "You must specify either a long-switch or an :attribute_value" unless long_switch
88
+
84
89
  inferred_name = long_switch.sub(/^--(\[no-\])?/, "").tr("-", "_")
85
90
  inferred_name += "_list" if multivalued?
86
91
  inferred_name
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Clamp #:nodoc:
3
+ module Clamp # :nodoc:
4
4
 
5
5
  class << self
6
6
 
@@ -29,11 +29,16 @@ module Clamp #:nodoc:
29
29
  until remaining_arguments.empty?
30
30
  unless remaining_arguments.first.start_with?("-")
31
31
  break unless argument_buffer.size < argument_buffer_limit
32
+
32
33
  argument_buffer << remaining_arguments.shift
34
+
33
35
  next
34
36
  end
37
+
35
38
  switch = remaining_arguments.shift
39
+
36
40
  break if switch == "--"
41
+
37
42
  handle_switch(switch)
38
43
  end
39
44
  remaining_arguments.unshift(*argument_buffer)
@@ -42,8 +47,8 @@ module Clamp #:nodoc:
42
47
  def handle_switch(switch)
43
48
  switch = split_trailing_switches(switch)
44
49
  option = find_option(switch)
45
- value = option.extract_value(switch, remaining_arguments)
46
50
  begin
51
+ value = option.extract_value(switch, remaining_arguments)
47
52
  option.of(self).take(value)
48
53
  rescue ArgumentError => e
49
54
  signal_usage_error Clamp.message(:option_argument_error, switch: switch, message: e.message)
@@ -55,7 +60,7 @@ module Clamp #:nodoc:
55
60
  when /\A(-\w)(.+)\z/m # combined short options
56
61
  switch = Regexp.last_match(1)
57
62
  if find_option(switch).flag?
58
- remaining_arguments.unshift("-" + Regexp.last_match(2))
63
+ remaining_arguments.unshift("-#{Regexp.last_match(2)}")
59
64
  else
60
65
  remaining_arguments.unshift(Regexp.last_match(2))
61
66
  end
@@ -33,7 +33,9 @@ module Clamp
33
33
 
34
34
  def parameter_buffer_limit
35
35
  return 0 unless Clamp.allow_options_after_parameters
36
+
36
37
  return Float::INFINITY if inheritable_parameters.any?(&:multivalued?)
38
+
37
39
  inheritable_parameters.size
38
40
  end
39
41
 
@@ -41,6 +43,7 @@ module Clamp
41
43
 
42
44
  def superclass_inheritable_parameters
43
45
  return [] unless superclass.respond_to?(:inheritable_parameters, true)
46
+
44
47
  superclass.inheritable_parameters
45
48
  end
46
49
 
@@ -32,19 +32,22 @@ module Clamp
32
32
 
33
33
  def consume(arguments)
34
34
  raise ArgumentError, Clamp.message(:no_value_provided) if required? && arguments.empty?
35
+
35
36
  arguments.shift(multivalued? ? arguments.length : 1)
36
37
  end
37
38
 
38
- private
39
+ ELLIPSIS_SUFFIX = / \.\.\.$/.freeze
40
+ OPTIONAL = /^\[(.*)\]/.freeze
39
41
 
40
- ELLIPSIS_SUFFIX = / \.\.\.$/
41
- OPTIONAL = /^\[(.*)\]/
42
+ VALID_ATTRIBUTE_NAME = /^[a-z0-9_]+$/.freeze
42
43
 
43
- VALID_ATTRIBUTE_NAME = /^[a-z0-9_]+$/
44
+ private
44
45
 
45
46
  def infer_attribute_name
46
47
  inferred_name = name.downcase.tr("-", "_").sub(ELLIPSIS_SUFFIX, "").sub(OPTIONAL) { Regexp.last_match(1) }
47
- raise "cannot infer attribute_name from #{name.inspect}" unless inferred_name =~ VALID_ATTRIBUTE_NAME
48
+
49
+ raise "cannot infer attribute_name from #{name.inspect}" unless inferred_name.match? VALID_ATTRIBUTE_NAME
50
+
48
51
  inferred_name += "_list" if multivalued?
49
52
  inferred_name
50
53
  end
@@ -18,13 +18,11 @@ module Clamp
18
18
 
19
19
  def set_parameters_from_command_line
20
20
  self.class.parameters.each do |parameter|
21
- begin
22
- parameter.consume(remaining_arguments).each do |value|
23
- parameter.of(self).take(value)
24
- end
25
- rescue ArgumentError => e
26
- signal_usage_error Clamp.message(:parameter_argument_error, param: parameter.name, message: e.message)
21
+ parameter.consume(remaining_arguments).each do |value|
22
+ parameter.of(self).take(value)
27
23
  end
24
+ rescue ArgumentError => e
25
+ signal_usage_error Clamp.message(:parameter_argument_error, param: parameter.name, message: e.message)
28
26
  end
29
27
  end
30
28
 
@@ -31,8 +31,9 @@ module Clamp
31
31
  def find_subcommand_class(*names)
32
32
  names.inject(self) do |command_class, name|
33
33
  return nil unless command_class
34
+
34
35
  subcommand = command_class.find_subcommand(name)
35
- subcommand.subcommand_class if subcommand
36
+ subcommand&.subcommand_class
36
37
  end
37
38
  end
38
39
 
@@ -42,6 +43,7 @@ module Clamp
42
43
 
43
44
  def default_subcommand=(name)
44
45
  raise Clamp::DeclarationError, "default_subcommand must be defined before subcommands" if has_subcommands?
46
+
45
47
  @default_subcommand = name
46
48
  end
47
49
 
@@ -25,6 +25,7 @@ module Clamp
25
25
  subcommand = subcommand_class.new(invocation_path_for(name), context)
26
26
  self.class.inheritable_attributes.each do |attribute|
27
27
  next unless attribute.of(self).defined?
28
+
28
29
  attribute.of(subcommand).set(attribute.of(self).get)
29
30
  end
30
31
  subcommand
@@ -38,6 +39,7 @@ module Clamp
38
39
  def find_subcommand_class(name)
39
40
  subcommand_def = self.class.find_subcommand(name)
40
41
  return subcommand_def.subcommand_class if subcommand_def
42
+
41
43
  subcommand_missing(name)
42
44
  end
43
45
 
@@ -13,6 +13,7 @@ module Clamp
13
13
 
14
14
  def parse_subcommand
15
15
  return false unless self.class.has_subcommands?
16
+
16
17
  extend(Subcommand::Execution)
17
18
  end
18
19
 
data/lib/clamp/truthy.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Clamp #:nodoc:
3
+ module Clamp # :nodoc:
4
4
 
5
5
  TRUTHY_VALUES = %w[1 yes enable on true].freeze
6
6
 
data/lib/clamp/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Clamp
4
- VERSION = "1.3.2".freeze
4
+ VERSION = "1.3.3"
5
5
  end