From 6561ef9c6054e5b997602bc95b96bc5be6961634 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 25 Nov 2024 03:02:32 +0000 Subject: [PATCH 01/41] Bump rubygems/release-gem Bumps [rubygems/release-gem](https://github.com/rubygems/release-gem) from 612653d273a73bdae1df8453e090060bb4db5f31 to 9e85cb11501bebc2ae661c1500176316d3987059. - [Release notes](https://github.com/rubygems/release-gem/releases) - [Commits](https://github.com/rubygems/release-gem/compare/612653d273a73bdae1df8453e090060bb4db5f31...9e85cb11501bebc2ae661c1500176316d3987059) --- updated-dependencies: - dependency-name: rubygems/release-gem dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- .github/workflows/push_gem.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/push_gem.yml b/.github/workflows/push_gem.yml index 91c6864..4c04fb0 100644 --- a/.github/workflows/push_gem.yml +++ b/.github/workflows/push_gem.yml @@ -36,7 +36,7 @@ jobs: ruby-version: ruby - name: Publish to RubyGems - uses: rubygems/release-gem@612653d273a73bdae1df8453e090060bb4db5f31 # v1 + uses: rubygems/release-gem@9e85cb11501bebc2ae661c1500176316d3987059 # v1 - name: Create GitHub release run: | From b33139c1358e37ae0204d4763e0cdb9576db8118 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Mon, 25 Nov 2024 12:33:45 +0900 Subject: [PATCH 02/41] Fixed version number of rubygems/release-gem --- .github/workflows/push_gem.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/push_gem.yml b/.github/workflows/push_gem.yml index 4c04fb0..64b710d 100644 --- a/.github/workflows/push_gem.yml +++ b/.github/workflows/push_gem.yml @@ -36,7 +36,7 @@ jobs: ruby-version: ruby - name: Publish to RubyGems - uses: rubygems/release-gem@9e85cb11501bebc2ae661c1500176316d3987059 # v1 + uses: rubygems/release-gem@9e85cb11501bebc2ae661c1500176316d3987059 # v1.1.0 - name: Create GitHub release run: | From 2bff57ee8715296cbe668973d6e7fccd24307d09 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 25 Nov 2024 03:02:29 +0000 Subject: [PATCH 03/41] Bump step-security/harden-runner from 2.10.1 to 2.10.2 Bumps [step-security/harden-runner](https://github.com/step-security/harden-runner) from 2.10.1 to 2.10.2. - [Release notes](https://github.com/step-security/harden-runner/releases) - [Commits](https://github.com/step-security/harden-runner/compare/91182cccc01eb5e619899d80e4e971d6181294a7...0080882f6c36860b6ba35c610c98ce87d4e2f26f) --- updated-dependencies: - dependency-name: step-security/harden-runner dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/push_gem.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/push_gem.yml b/.github/workflows/push_gem.yml index 64b710d..23653c7 100644 --- a/.github/workflows/push_gem.yml +++ b/.github/workflows/push_gem.yml @@ -23,7 +23,7 @@ jobs: steps: - name: Harden Runner - uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1 + uses: step-security/harden-runner@0080882f6c36860b6ba35c610c98ce87d4e2f26f # v2.10.2 with: egress-policy: audit From d64869106f769e5ef559bac079a098a29a328981 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 23 Dec 2024 03:17:41 +0000 Subject: [PATCH 04/41] Bump rubygems/release-gem from 1.1.0 to 1.1.1 Bumps [rubygems/release-gem](https://github.com/rubygems/release-gem) from 1.1.0 to 1.1.1. - [Release notes](https://github.com/rubygems/release-gem/releases) - [Commits](https://github.com/rubygems/release-gem/compare/9e85cb11501bebc2ae661c1500176316d3987059...a25424ba2ba8b387abc8ef40807c2c85b96cbe32) --- updated-dependencies: - dependency-name: rubygems/release-gem dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/push_gem.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/push_gem.yml b/.github/workflows/push_gem.yml index 23653c7..c290a6f 100644 --- a/.github/workflows/push_gem.yml +++ b/.github/workflows/push_gem.yml @@ -36,7 +36,7 @@ jobs: ruby-version: ruby - name: Publish to RubyGems - uses: rubygems/release-gem@9e85cb11501bebc2ae661c1500176316d3987059 # v1.1.0 + uses: rubygems/release-gem@a25424ba2ba8b387abc8ef40807c2c85b96cbe32 # v1.1.1 - name: Create GitHub release run: | From 7a684dfd7fdbc12710a70bd86400c216284892c5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 14 Jan 2025 00:12:02 +0100 Subject: [PATCH 05/41] Bump step-security/harden-runner from 2.10.2 to 2.10.3 (#85) Bumps [step-security/harden-runner](https://github.com/step-security/harden-runner) from 2.10.2 to 2.10.3. - [Release notes](https://github.com/step-security/harden-runner/releases) - [Commits](https://github.com/step-security/harden-runner/compare/0080882f6c36860b6ba35c610c98ce87d4e2f26f...c95a14d0e5bab51a9f56296a4eb0e416910cd350) --- updated-dependencies: - dependency-name: step-security/harden-runner dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/push_gem.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/push_gem.yml b/.github/workflows/push_gem.yml index c290a6f..a17b546 100644 --- a/.github/workflows/push_gem.yml +++ b/.github/workflows/push_gem.yml @@ -23,7 +23,7 @@ jobs: steps: - name: Harden Runner - uses: step-security/harden-runner@0080882f6c36860b6ba35c610c98ce87d4e2f26f # v2.10.2 + uses: step-security/harden-runner@c95a14d0e5bab51a9f56296a4eb0e416910cd350 # v2.10.3 with: egress-policy: audit From 7234771de28a1a711c613ceaccd901a3776293a7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 Jan 2025 03:01:51 +0000 Subject: [PATCH 06/41] Bump step-security/harden-runner from 2.10.3 to 2.10.4 Bumps [step-security/harden-runner](https://github.com/step-security/harden-runner) from 2.10.3 to 2.10.4. - [Release notes](https://github.com/step-security/harden-runner/releases) - [Commits](https://github.com/step-security/harden-runner/compare/c95a14d0e5bab51a9f56296a4eb0e416910cd350...cb605e52c26070c328afc4562f0b4ada7618a84e) --- updated-dependencies: - dependency-name: step-security/harden-runner dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/push_gem.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/push_gem.yml b/.github/workflows/push_gem.yml index a17b546..59effeb 100644 --- a/.github/workflows/push_gem.yml +++ b/.github/workflows/push_gem.yml @@ -23,7 +23,7 @@ jobs: steps: - name: Harden Runner - uses: step-security/harden-runner@c95a14d0e5bab51a9f56296a4eb0e416910cd350 # v2.10.3 + uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4 with: egress-policy: audit From 30b6e0ef157c43aec616986930807c1dabb58185 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 17 Feb 2025 03:07:47 +0000 Subject: [PATCH 07/41] Bump step-security/harden-runner from 2.10.4 to 2.11.0 Bumps [step-security/harden-runner](https://github.com/step-security/harden-runner) from 2.10.4 to 2.11.0. - [Release notes](https://github.com/step-security/harden-runner/releases) - [Commits](https://github.com/step-security/harden-runner/compare/cb605e52c26070c328afc4562f0b4ada7618a84e...4d991eb9b905ef189e4c376166672c3f2f230481) --- updated-dependencies: - dependency-name: step-security/harden-runner dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/push_gem.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/push_gem.yml b/.github/workflows/push_gem.yml index 59effeb..e05793f 100644 --- a/.github/workflows/push_gem.yml +++ b/.github/workflows/push_gem.yml @@ -23,7 +23,7 @@ jobs: steps: - name: Harden Runner - uses: step-security/harden-runner@cb605e52c26070c328afc4562f0b4ada7618a84e # v2.10.4 + uses: step-security/harden-runner@4d991eb9b905ef189e4c376166672c3f2f230481 # v2.11.0 with: egress-policy: audit From 475ecbfc80a2c376f7038f8e7d7400adb066c044 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Sun, 9 Mar 2025 21:55:21 +0900 Subject: [PATCH 08/41] Use `git rev-list` --- rakelib/changelogs.rake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rakelib/changelogs.rake b/rakelib/changelogs.rake index 5e00c98..9be2e8a 100644 --- a/rakelib/changelogs.rake +++ b/rakelib/changelogs.rake @@ -23,7 +23,7 @@ end tags = IO.popen(%w[git tag -l v[0-9]*]).grep(/v(.*)/) {$1} unless tags.empty? tags.sort_by! {|tag| tag.scan(/\d+/).map(&:to_i)} - tags.pop if IO.popen(%W[git log --format=%H v#{tags.last}..HEAD --], &:read).empty? + tags.pop if IO.popen(%W[git rev-list --right-only --count v#{tags.last}..HEAD --], &:read).to_i == 0 tags.inject(nil) do |prev, tag| task("logs/ChangeLog-#{tag}") {|t| changelog[t.name, tag, prev]} tag From 61b4ea070439172b39eea0bca0de55435e4cccea Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Sun, 9 Mar 2025 21:56:59 +0900 Subject: [PATCH 09/41] [DOC] Manage rdoc options only in .rdoc_options file Make `rdoc .` and `rake rdoc` consistent. --- .rdoc_options | 1 + optparse.gemspec | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/.rdoc_options b/.rdoc_options index 79a8fce..24fe2d7 100644 --- a/.rdoc_options +++ b/.rdoc_options @@ -2,3 +2,4 @@ page_dir: doc main_page: README.md title: Documentation for OptionParser +op_dir: rdoc diff --git a/optparse.gemspec b/optparse.gemspec index 1aa54aa..126f71b 100644 --- a/optparse.gemspec +++ b/optparse.gemspec @@ -24,7 +24,6 @@ Gem::Specification.new do |spec| spec.files = Dir["{doc,lib,misc}/**/{*,.document}"] + %w[README.md ChangeLog COPYING .document .rdoc_options] - spec.rdoc_options = ["--main=README.md", "--op=rdoc", "--page-dir=doc"] spec.bindir = "exe" spec.executables = [] spec.require_paths = ["lib"] From a3f102981548d96f1f905dbec405d444fef7888d Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Sun, 9 Mar 2025 22:38:30 +0900 Subject: [PATCH 10/41] Use `\A` instead of `^` as the beginning of string --- lib/optparse.rb | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/optparse.rb b/lib/optparse.rb index 27e0843..ade9870 100644 --- a/lib/optparse.rb +++ b/lib/optparse.rb @@ -668,7 +668,7 @@ def compsys(sdone, ldone) # :nodoc: (sopts+lopts).each do |opt| # "(-x -c -r)-l[left justify]" - if /^--\[no-\](.+)$/ =~ opt + if /\A--\[no-\](.+)$/ =~ opt o = $1 yield("--#{o}", desc.join("")) yield("--no-#{o}", desc.join("")) @@ -1508,7 +1508,7 @@ def make_switch(opts, block = nil) raise ArgumentError, "unsupported argument type: #{o}", ParseError.filter_backtrace(caller(4)) when *ArgumentStyle.keys style = notwice(ArgumentStyle[o], style, 'style') - when /^--no-([^\[\]=\s]*)(.+)?/ + when /\A--no-([^\[\]=\s]*)(.+)?/ q, a = $1, $2 o = notwice(a ? Object : TrueClass, klass, 'type') not_pattern, not_conv = search(:atype, o) unless not_style @@ -1519,7 +1519,7 @@ def make_switch(opts, block = nil) (q = q.downcase).tr!('_', '-') long << "no-#{q}" nolong << q - when /^--\[no-\]([^\[\]=\s]*)(.+)?/ + when /\A--\[no-\]([^\[\]=\s]*)(.+)?/ q, a = $1, $2 o = notwice(a ? Object : TrueClass, klass, 'type') if a @@ -1532,7 +1532,7 @@ def make_switch(opts, block = nil) not_pattern, not_conv = search(:atype, FalseClass) unless not_style not_style = Switch::NoArgument nolong << "no-#{o}" - when /^--([^\[\]=\s]*)(.+)?/ + when /\A--([^\[\]=\s]*)(.+)?/ q, a = $1, $2 if a o = notwice(NilClass, klass, 'type') @@ -1542,7 +1542,7 @@ def make_switch(opts, block = nil) ldesc << "--#{q}" (o = q.downcase).tr!('_', '-') long << o - when /^-(\[\^?\]?(?:[^\\\]]|\\.)*\])(.+)?/ + when /\A-(\[\^?\]?(?:[^\\\]]|\\.)*\])(.+)?/ q, a = $1, $2 o = notwice(Object, klass, 'type') if a @@ -1553,7 +1553,7 @@ def make_switch(opts, block = nil) end sdesc << "-#{q}" short << Regexp.new(q) - when /^-(.)(.+)?/ + when /\A-(.)(.+)?/ q, a = $1, $2 if a o = notwice(NilClass, klass, 'type') @@ -1562,7 +1562,7 @@ def make_switch(opts, block = nil) end sdesc << "-#{q}" short << q - when /^=/ + when /\A=/ style = notwice(default_style.guess(arg = o), style, 'style') default_pattern, conv = search(:atype, Object) unless default_pattern else From 0a0e977b7c0dd2df42853e60aabdf67eef045755 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Sun, 9 Mar 2025 22:54:21 +0900 Subject: [PATCH 11/41] Add test for enum arguments --- test/optparse/test_placearg.rb | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/optparse/test_placearg.rb b/test/optparse/test_placearg.rb index a8a11e6..c6dc7ab 100644 --- a/test/optparse/test_placearg.rb +++ b/test/optparse/test_placearg.rb @@ -7,6 +7,7 @@ def setup @opt.def_option("-x [VAL]") {|x| @flag = x} @opt.def_option("--option [VAL]") {|x| @flag = x} @opt.def_option("-T [level]", /^[0-4]$/, Integer) {|x| @topt = x} + @opt.def_option("--enum [VAL]", [:Alpha, :Bravo, :Charlie]) {|x| @enum = x} @topt = nil @opt.def_option("-n") {} @opt.def_option("--regexp [REGEXP]", Regexp) {|x| @reopt = x} @@ -93,4 +94,9 @@ def test_lambda assert_equal(%w"", no_error {@opt.parse!(%w"--lambda")}) assert_equal(nil, @flag) end + + def test_enum + assert_equal([], no_error {@opt.parse!(%w"--enum=A")}) + assert_equal(:Alpha, @enum) + end end From c5ec052efc7e7dfc5f2e7c294cff3f12dfdbae6a Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Sun, 9 Mar 2025 22:39:12 +0900 Subject: [PATCH 12/41] Allow non-string enum list #79 Command line arguments are strings, convert enum list elements to strings to match. --- lib/optparse.rb | 2 +- test/optparse/test_placearg.rb | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/optparse.rb b/lib/optparse.rb index ade9870..11218fe 100644 --- a/lib/optparse.rb +++ b/lib/optparse.rb @@ -1503,7 +1503,7 @@ def make_switch(opts, block = nil) else raise ArgumentError, "argument pattern given twice" end - o.each {|pat, *v| pattern[pat] = v.fetch(0) {pat}} + o.each {|pat, *v| pattern[pat.to_s] = v.fetch(0) {pat}} when Module raise ArgumentError, "unsupported argument type: #{o}", ParseError.filter_backtrace(caller(4)) when *ArgumentStyle.keys diff --git a/test/optparse/test_placearg.rb b/test/optparse/test_placearg.rb index c6dc7ab..511541f 100644 --- a/test/optparse/test_placearg.rb +++ b/test/optparse/test_placearg.rb @@ -8,6 +8,7 @@ def setup @opt.def_option("--option [VAL]") {|x| @flag = x} @opt.def_option("-T [level]", /^[0-4]$/, Integer) {|x| @topt = x} @opt.def_option("--enum [VAL]", [:Alpha, :Bravo, :Charlie]) {|x| @enum = x} + @opt.def_option("--integer [VAL]", [1, 2, 3]) {|x| @integer = x} @topt = nil @opt.def_option("-n") {} @opt.def_option("--regexp [REGEXP]", Regexp) {|x| @reopt = x} @@ -99,4 +100,9 @@ def test_enum assert_equal([], no_error {@opt.parse!(%w"--enum=A")}) assert_equal(:Alpha, @enum) end + + def test_enum_conversion + assert_equal([], no_error {@opt.parse!(%w"--integer=1")}) + assert_equal(1, @integer) + end end From 5e71a70cb59dc612fbff33872904a458ea6eba82 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Mon, 10 Mar 2025 14:05:16 +0900 Subject: [PATCH 13/41] [DOC] Update documents to use single quotes instead of backqoutes --- doc/optparse/argument_converters.rdoc | 2 +- doc/optparse/option_params.rdoc | 29 ++++++++++++------------ doc/optparse/tutorial.rdoc | 32 +++++++++++++-------------- lib/optparse.rb | 4 ++-- 4 files changed, 34 insertions(+), 33 deletions(-) diff --git a/doc/optparse/argument_converters.rdoc b/doc/optparse/argument_converters.rdoc index 4b4b30e..5327298 100644 --- a/doc/optparse/argument_converters.rdoc +++ b/doc/optparse/argument_converters.rdoc @@ -377,4 +377,4 @@ Executions: $ ruby match_converter.rb --capitalize foo ["Foo", String] $ ruby match_converter.rb --capitalize "foo bar" - match_converter.rb:9:in `
': invalid argument: --capitalize foo bar (OptionParser::InvalidArgument) + match_converter.rb:9:in '
': invalid argument: --capitalize foo bar (OptionParser::InvalidArgument) diff --git a/doc/optparse/option_params.rdoc b/doc/optparse/option_params.rdoc index 35db8b5..48de12e 100644 --- a/doc/optparse/option_params.rdoc +++ b/doc/optparse/option_params.rdoc @@ -91,7 +91,7 @@ Executions: Usage: short_required [options] -xXXX Short name with required argument $ ruby short_required.rb -x - short_required.rb:6:in `
': missing argument: -x (OptionParser::MissingArgument) + short_required.rb:6:in '
': missing argument: -x (OptionParser::MissingArgument) $ ruby short_required.rb -x FOO ["-x", "FOO"] @@ -181,7 +181,7 @@ Executions: Usage: long_required [options] --xxx XXX Long name with required argument $ ruby long_required.rb --xxx - long_required.rb:6:in `
': missing argument: --xxx (OptionParser::MissingArgument) + long_required.rb:6:in '
': missing argument: --xxx (OptionParser::MissingArgument) $ ruby long_required.rb --xxx FOO ["--xxx", "FOO"] @@ -243,11 +243,11 @@ Usage: mixed_names [options] $ ruby mixed_names.rb --xxx ["--xxx", true] $ ruby mixed_names.rb -y - mixed_names.rb:12:in `
': missing argument: -y (OptionParser::MissingArgument) + mixed_names.rb:12:in '
': missing argument: -y (OptionParser::MissingArgument) $ ruby mixed_names.rb -y FOO ["--yyy", "FOO"] $ ruby mixed_names.rb --yyy - mixed_names.rb:12:in `
': missing argument: --yyy (OptionParser::MissingArgument) + mixed_names.rb:12:in '
': missing argument: --yyy (OptionParser::MissingArgument) $ ruby mixed_names.rb --yyy BAR ["--yyy", "BAR"] $ ruby mixed_names.rb -z @@ -279,7 +279,7 @@ Executions: Usage: argument_keywords [options] -x, --xxx Required argument $ ruby argument_styles.rb --xxx - argument_styles.rb:6:in `
': missing argument: --xxx (OptionParser::MissingArgument) + argument_styles.rb:6:in '
': missing argument: --xxx (OptionParser::MissingArgument) $ ruby argument_styles.rb --xxx FOO ["--xxx", "FOO"] @@ -298,7 +298,7 @@ Executions: Usage: argument_strings [options] -x, --xxx=XXX Required argument $ ruby argument_strings.rb --xxx - argument_strings.rb:9:in `
': missing argument: --xxx (OptionParser::MissingArgument) + argument_strings.rb:9:in '
': missing argument: --xxx (OptionParser::MissingArgument) $ ruby argument_strings.rb --xxx FOO ["--xxx", "FOO"] @@ -331,7 +331,7 @@ Executions: -xXXX Values for required argument -y [YYY] Values for optional argument $ ruby explicit_array_values.rb -x - explicit_array_values.rb:9:in `
': missing argument: -x (OptionParser::MissingArgument) + explicit_array_values.rb:9:in '
': missing argument: -x (OptionParser::MissingArgument) $ ruby explicit_array_values.rb -x foo ["-x", "foo"] $ ruby explicit_array_values.rb -x f @@ -339,9 +339,9 @@ Executions: $ ruby explicit_array_values.rb -x bar ["-x", "bar"] $ ruby explicit_array_values.rb -y ba - explicit_array_values.rb:9:in `
': ambiguous argument: -y ba (OptionParser::AmbiguousArgument) + explicit_array_values.rb:9:in '
': ambiguous argument: -y ba (OptionParser::AmbiguousArgument) $ ruby explicit_array_values.rb -x baz - explicit_array_values.rb:9:in `
': invalid argument: -x baz (OptionParser::InvalidArgument) + explicit_array_values.rb:9:in '
': invalid argument: -x baz (OptionParser::InvalidArgument) ===== Explicit Values in Hash @@ -361,7 +361,7 @@ Executions: -xXXX Values for required argument -y [YYY] Values for optional argument $ ruby explicit_hash_values.rb -x - explicit_hash_values.rb:9:in `
': missing argument: -x (OptionParser::MissingArgument) + explicit_hash_values.rb:9:in '
': missing argument: -x (OptionParser::MissingArgument) $ ruby explicit_hash_values.rb -x foo ["-x", 0] $ ruby explicit_hash_values.rb -x f @@ -369,7 +369,7 @@ Executions: $ ruby explicit_hash_values.rb -x bar ["-x", 1] $ ruby explicit_hash_values.rb -x baz - explicit_hash_values.rb:9:in `
': invalid argument: -x baz (OptionParser::InvalidArgument) + explicit_hash_values.rb:9:in '
': invalid argument: -x baz (OptionParser::InvalidArgument) $ ruby explicit_hash_values.rb -y ["-y", nil] $ ruby explicit_hash_values.rb -y baz @@ -377,14 +377,15 @@ Executions: $ ruby explicit_hash_values.rb -y bat ["-y", 3] $ ruby explicit_hash_values.rb -y ba - explicit_hash_values.rb:9:in `
': ambiguous argument: -y ba (OptionParser::AmbiguousArgument) + explicit_hash_values.rb:9:in '
': ambiguous argument: -y ba (OptionParser::AmbiguousArgument) $ ruby explicit_hash_values.rb -y bam ["-y", nil] ==== Argument Value Patterns You can restrict permissible argument values -by specifying a Regexp that the given argument must match. +by specifying a +Regexp+ that the given argument must match, +or a +Range+ or +Array+ that the converted value must be included in. File +matched_values.rb+ defines options with matched argument values. @@ -400,7 +401,7 @@ Executions: $ ruby matched_values.rb --xxx FOO ["--xxx", "FOO"] $ ruby matched_values.rb --xxx bar - matched_values.rb:6:in `
': invalid argument: --xxx bar (OptionParser::InvalidArgument) + matched_values.rb:6:in '
': invalid argument: --xxx bar (OptionParser::InvalidArgument) === Argument Converters diff --git a/doc/optparse/tutorial.rdoc b/doc/optparse/tutorial.rdoc index 6f56bbf..1134f94 100644 --- a/doc/optparse/tutorial.rdoc +++ b/doc/optparse/tutorial.rdoc @@ -111,7 +111,7 @@ Executions: ["x", true] ["input_file.txt", "output_file.txt"] $ ruby basic.rb -a - basic.rb:16:in `
': invalid option: -a (OptionParser::InvalidOption) + basic.rb:16:in '
': invalid option: -a (OptionParser::InvalidOption) === Defining Options @@ -232,11 +232,11 @@ Executions: $ ruby mixed_names.rb --xxx ["--xxx", true] $ ruby mixed_names.rb -y - mixed_names.rb:12:in `
': missing argument: -y (OptionParser::MissingArgument) + mixed_names.rb:12:in '
': missing argument: -y (OptionParser::MissingArgument) $ ruby mixed_names.rb -y FOO ["--yyy", "FOO"] $ ruby mixed_names.rb --yyy - mixed_names.rb:12:in `
': missing argument: --yyy (OptionParser::MissingArgument) + mixed_names.rb:12:in '
': missing argument: --yyy (OptionParser::MissingArgument) $ ruby mixed_names.rb --yyy BAR ["--yyy", "BAR"] $ ruby mixed_names.rb -z @@ -270,9 +270,9 @@ Executions: $ ruby name_abbrev.rb --draft ["--draft", true] $ ruby name_abbrev.rb --d - name_abbrev.rb:9:in `
': ambiguous option: --d (OptionParser::AmbiguousOption) + name_abbrev.rb:9:in '
': ambiguous option: --d (OptionParser::AmbiguousOption) $ ruby name_abbrev.rb --dr - name_abbrev.rb:9:in `
': ambiguous option: --dr (OptionParser::AmbiguousOption) + name_abbrev.rb:9:in '
': ambiguous option: --dr (OptionParser::AmbiguousOption) $ ruby name_abbrev.rb --dry ["--dry-run", true] $ ruby name_abbrev.rb --dra @@ -285,7 +285,7 @@ You can disable abbreviation using method +require_exact+. Executions: $ ruby no_abbreviation.rb --dry-ru - no_abbreviation.rb:10:in `
': invalid option: --dry-ru (OptionParser::InvalidOption) + no_abbreviation.rb:10:in '
': invalid option: --dry-ru (OptionParser::InvalidOption) $ ruby no_abbreviation.rb --dry-run ["--dry-run", true] @@ -323,7 +323,7 @@ Executions: Omitting a required argument raises an error: $ ruby required_argument.rb -x - required_argument.rb:9:in `
': missing argument: -x (OptionParser::MissingArgument) + required_argument.rb:9:in '
': missing argument: -x (OptionParser::MissingArgument) ==== Option with Optional Argument @@ -369,7 +369,7 @@ Executions: $ ruby argument_abbreviation.rb --xxx A ["--xxx", "ABC"] $ ruby argument_abbreviation.rb --xxx c - argument_abbreviation.rb:9:in `
': invalid argument: --xxx c (OptionParser::InvalidArgument) + argument_abbreviation.rb:9:in '
': invalid argument: --xxx c (OptionParser::InvalidArgument) $ ruby argument_abbreviation.rb --yyy a --yyy d ["--yyy", "XYZ"] ["--yyy", "FOO"] @@ -403,7 +403,7 @@ Executions: -xXXX Values for required argument -y [YYY] Values for optional argument $ ruby explicit_array_values.rb -x - explicit_array_values.rb:9:in `
': missing argument: -x (OptionParser::MissingArgument) + explicit_array_values.rb:9:in '
': missing argument: -x (OptionParser::MissingArgument) $ ruby explicit_array_values.rb -x foo ["-x", "foo"] $ ruby explicit_array_values.rb -x f @@ -411,9 +411,9 @@ Executions: $ ruby explicit_array_values.rb -x bar ["-x", "bar"] $ ruby explicit_array_values.rb -y ba - explicit_array_values.rb:9:in `
': ambiguous argument: -y ba (OptionParser::AmbiguousArgument) + explicit_array_values.rb:9:in '
': ambiguous argument: -y ba (OptionParser::AmbiguousArgument) $ ruby explicit_array_values.rb -x baz - explicit_array_values.rb:9:in `
': invalid argument: -x baz (OptionParser::InvalidArgument) + explicit_array_values.rb:9:in '
': invalid argument: -x baz (OptionParser::InvalidArgument) ===== Explicit Values in Hash @@ -433,7 +433,7 @@ Executions: -xXXX Values for required argument -y [YYY] Values for optional argument $ ruby explicit_hash_values.rb -x - explicit_hash_values.rb:9:in `
': missing argument: -x (OptionParser::MissingArgument) + explicit_hash_values.rb:9:in '
': missing argument: -x (OptionParser::MissingArgument) $ ruby explicit_hash_values.rb -x foo ["-x", 0] $ ruby explicit_hash_values.rb -x f @@ -441,7 +441,7 @@ Executions: $ ruby explicit_hash_values.rb -x bar ["-x", 1] $ ruby explicit_hash_values.rb -x baz - explicit_hash_values.rb:9:in `
': invalid argument: -x baz (OptionParser::InvalidArgument) + explicit_hash_values.rb:9:in '
': invalid argument: -x baz (OptionParser::InvalidArgument) $ ruby explicit_hash_values.rb -y ["-y", nil] $ ruby explicit_hash_values.rb -y baz @@ -449,7 +449,7 @@ Executions: $ ruby explicit_hash_values.rb -y bat ["-y", 3] $ ruby explicit_hash_values.rb -y ba - explicit_hash_values.rb:9:in `
': ambiguous argument: -y ba (OptionParser::AmbiguousArgument) + explicit_hash_values.rb:9:in '
': ambiguous argument: -y ba (OptionParser::AmbiguousArgument) $ ruby explicit_hash_values.rb -y bam ["-y", nil] @@ -472,7 +472,7 @@ Executions: $ ruby matched_values.rb --xxx FOO ["--xxx", "FOO"] $ ruby matched_values.rb --xxx bar - matched_values.rb:6:in `
': invalid argument: --xxx bar (OptionParser::InvalidArgument) + matched_values.rb:6:in '
': invalid argument: --xxx bar (OptionParser::InvalidArgument) === Keyword Argument +into+ @@ -524,7 +524,7 @@ Executions: -y, --yyyYYY Short and long, required argument -z, --zzz [ZZZ] Short and long, optional argument $ ruby missing_options.rb --yyy FOO - missing_options.rb:11:in `
': Missing required options: [:xxx, :zzz] (RuntimeError) + missing_options.rb:11:in '
': Missing required options: [:xxx, :zzz] (RuntimeError) ==== Default Values for Options diff --git a/lib/optparse.rb b/lib/optparse.rb index 11218fe..c0e861d 100644 --- a/lib/optparse.rb +++ b/lib/optparse.rb @@ -142,7 +142,7 @@ # Used: # # $ ruby optparse-test.rb -r -# optparse-test.rb:9:in `
': missing argument: -r (OptionParser::MissingArgument) +# optparse-test.rb:9:in '
': missing argument: -r (OptionParser::MissingArgument) # $ ruby optparse-test.rb -r my-library # You required my-library! # @@ -235,7 +235,7 @@ # $ ruby optparse-test.rb --user 2 # # # $ ruby optparse-test.rb --user 3 -# optparse-test.rb:15:in `block in find_user': No User Found for id 3 (RuntimeError) +# optparse-test.rb:15:in 'block in find_user': No User Found for id 3 (RuntimeError) # # === Store options to a Hash # From d7dec6808f908ad616add62891c6660fe8042295 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Mon, 10 Mar 2025 17:01:34 +0900 Subject: [PATCH 14/41] Remove extra blank lines [ci skip] --- lib/optparse.rb | 3 --- 1 file changed, 3 deletions(-) diff --git a/lib/optparse.rb b/lib/optparse.rb index c0e861d..a53b1d1 100644 --- a/lib/optparse.rb +++ b/lib/optparse.rb @@ -496,7 +496,6 @@ def convert(opt = nil, val = nil, *) end end - # # Map from option/keyword string to object with completion. # @@ -504,7 +503,6 @@ class OptionMap < Hash include Completion end - # # Individual switch class. Not important to the user. # @@ -1032,7 +1030,6 @@ def match(key) DefaultList.short['-'] = Switch::NoArgument.new {} DefaultList.long[''] = Switch::NoArgument.new {throw :terminate} - COMPSYS_HEADER = <<'XXX' # :nodoc: typeset -A opt_args From 71e2b31824cf768a01a5aa4a969d45d2834c7d91 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Mon, 10 Mar 2025 17:02:43 +0900 Subject: [PATCH 15/41] Update argument check with save navigation operator --- lib/optparse.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/optparse.rb b/lib/optparse.rb index a53b1d1..a45d99d 100644 --- a/lib/optparse.rb +++ b/lib/optparse.rb @@ -780,7 +780,7 @@ class PlacedArgument < self # Returns nil if argument is not present or begins with '-' and is not '-'. # def parse(arg, argv, &error) - if !(val = arg) and (argv.empty? or /\A-./ =~ (val = argv[0])) + if !(val = arg) and !(val = argv[0])&.match?(/\A(?!-.)/) return nil, block end opt = (val = parse_arg(val, &error))[1] From 050a87d02915400ee67ca6650dbaa131732f7c73 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Mon, 10 Mar 2025 13:12:34 +0900 Subject: [PATCH 16/41] Add post-check of value Fix #80 --- lib/optparse.rb | 38 +++++++++++++++++++++++++++------- test/optparse/test_placearg.rb | 9 +++++++- 2 files changed, 38 insertions(+), 9 deletions(-) diff --git a/lib/optparse.rb b/lib/optparse.rb index a45d99d..731d9bd 100644 --- a/lib/optparse.rb +++ b/lib/optparse.rb @@ -461,6 +461,10 @@ def self.candidate(key, icase = false, pat = nil, &block) candidates end + def self.completable?(key) + String.try_convert(key) or defined?(key.id2name) + end + def candidate(key, icase = false, pat = nil, &_) Completion.candidate(key, icase, pat, &method(:each)) end @@ -544,11 +548,11 @@ def self.pattern def initialize(pattern = nil, conv = nil, short = nil, long = nil, arg = nil, - desc = ([] if short or long), block = nil, &_block) + desc = ([] if short or long), block = nil, values = nil, &_block) raise if Array === pattern block ||= _block - @pattern, @conv, @short, @long, @arg, @desc, @block = - pattern, conv, short, long, arg, desc, block + @pattern, @conv, @short, @long, @arg, @desc, @block, @values = + pattern, conv, short, long, arg, desc, block, values end # @@ -581,11 +585,15 @@ def parse_arg(arg) # :nodoc: # exception. # def conv_arg(arg, val = []) # :nodoc: + v, = *val if conv val = conv.call(*val) else val = proc {|v| v}.call(*val) end + if @values + @values.include?(val) or raise InvalidArgument, v + end return arg, block, val end private :conv_arg @@ -780,7 +788,7 @@ class PlacedArgument < self # Returns nil if argument is not present or begins with '-' and is not '-'. # def parse(arg, argv, &error) - if !(val = arg) and !(val = argv[0])&.match?(/\A(?!-.)/) + if !(val = arg) and (argv.empty? or /\A-./ =~ (val = argv[0])) return nil, block end opt = (val = parse_arg(val, &error))[1] @@ -1464,6 +1472,7 @@ def make_switch(opts, block = nil) klass = nil q, a = nil has_arg = false + values = nil opts.each do |o| # argument class @@ -1477,7 +1486,7 @@ def make_switch(opts, block = nil) end # directly specified pattern(any object possible to match) - if (!(String === o || Symbol === o)) and o.respond_to?(:match) + if !Completion.completable?(o) and o.respond_to?(:match) pattern = notwice(o, pattern, 'pattern') if pattern.respond_to?(:convert) conv = pattern.method(:convert).to_proc @@ -1492,6 +1501,11 @@ def make_switch(opts, block = nil) when Proc, Method block = notwice(o, block, 'block') when Array, Hash + if Array === o + o, v = o.partition {|v| Completion.completable?(v)} + values = notwice(v, values, 'values') unless v.empty? + next if o.empty? + end case pattern when CompletingHash when nil @@ -1500,7 +1514,9 @@ def make_switch(opts, block = nil) else raise ArgumentError, "argument pattern given twice" end - o.each {|pat, *v| pattern[pat.to_s] = v.fetch(0) {pat}} + o.each {|pat, *v| pattern[pat] = v.fetch(0) {pat}} + when Range + values = notwice(o, values, 'values') when Module raise ArgumentError, "unsupported argument type: #{o}", ParseError.filter_backtrace(caller(4)) when *ArgumentStyle.keys @@ -1568,12 +1584,18 @@ def make_switch(opts, block = nil) end default_pattern, conv = search(:atype, default_style.pattern) unless default_pattern + if Range === values and klass + unless (!values.begin or klass === values.begin) and + (!values.end or klass === values.end) + raise ArgumentError, "range does not match class" + end + end if !(short.empty? and long.empty?) if has_arg and default_style == Switch::NoArgument default_style = Switch::RequiredArgument end s = (style || default_style).new(pattern || default_pattern, - conv, sdesc, ldesc, arg, desc, block) + conv, sdesc, ldesc, arg, desc, block, values) elsif !block if style or pattern raise ArgumentError, "no switch given", ParseError.filter_backtrace(caller) @@ -1582,7 +1604,7 @@ def make_switch(opts, block = nil) else short << pattern s = (style || default_style).new(pattern, - conv, nil, nil, arg, desc, block) + conv, nil, nil, arg, desc, block, values) end return s, short, long, (not_style.new(not_pattern, not_conv, sdesc, ldesc, nil, desc, block) if not_style), diff --git a/test/optparse/test_placearg.rb b/test/optparse/test_placearg.rb index 511541f..36edf40 100644 --- a/test/optparse/test_placearg.rb +++ b/test/optparse/test_placearg.rb @@ -8,7 +8,8 @@ def setup @opt.def_option("--option [VAL]") {|x| @flag = x} @opt.def_option("-T [level]", /^[0-4]$/, Integer) {|x| @topt = x} @opt.def_option("--enum [VAL]", [:Alpha, :Bravo, :Charlie]) {|x| @enum = x} - @opt.def_option("--integer [VAL]", [1, 2, 3]) {|x| @integer = x} + @opt.def_option("--integer [VAL]", Integer, [1, 2, 3]) {|x| @integer = x} + @opt.def_option("--range [VAL]", Integer, 1..3) {|x| @range = x} @topt = nil @opt.def_option("-n") {} @opt.def_option("--regexp [REGEXP]", Regexp) {|x| @reopt = x} @@ -105,4 +106,10 @@ def test_enum_conversion assert_equal([], no_error {@opt.parse!(%w"--integer=1")}) assert_equal(1, @integer) end + + def test_enum_range + assert_equal([], no_error {@opt.parse!(%w"--range=1")}) + assert_equal(1, @range) + assert_raise(OptionParser::InvalidArgument) {@opt.parse!(%w"--range=4")} + end end From e1957d7392bfe9083ca6c0c1779e4f3074859f5b Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Mon, 10 Mar 2025 16:53:16 +0900 Subject: [PATCH 17/41] [DOC] Mention about post-check --- doc/optparse/option_params.rdoc | 12 +++++++++++- doc/optparse/ruby/matched_values.rb | 6 ++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/doc/optparse/option_params.rdoc b/doc/optparse/option_params.rdoc index 48de12e..575ee66 100644 --- a/doc/optparse/option_params.rdoc +++ b/doc/optparse/option_params.rdoc @@ -396,12 +396,22 @@ Executions: $ ruby matched_values.rb --help Usage: matched_values [options] --xxx XXX Matched values + --yyy YYY Check by range + --zzz ZZZ Check by list $ ruby matched_values.rb --xxx foo ["--xxx", "foo"] $ ruby matched_values.rb --xxx FOO ["--xxx", "FOO"] $ ruby matched_values.rb --xxx bar - matched_values.rb:6:in '
': invalid argument: --xxx bar (OptionParser::InvalidArgument) + matched_values.rb:12:in '
': invalid argument: --xxx bar (OptionParser::InvalidArgument) + $ ruby matched_values.rb --yyy 1 + ["--yyy", 1] + $ ruby matched_values.rb --yyy 4 + matched_values.rb:12:in '
': invalid argument: --yyy 4 (OptionParser::InvalidArgument) + $ ruby matched_values.rb --zzz 1 + ["--zzz", 1] + $ ruby matched_values.rb --zzz 2 + matched_values.rb:12:in '
': invalid argument: --zzz 2 (OptionParser::InvalidArgument) === Argument Converters diff --git a/doc/optparse/ruby/matched_values.rb b/doc/optparse/ruby/matched_values.rb index f184ca8..a1aba14 100644 --- a/doc/optparse/ruby/matched_values.rb +++ b/doc/optparse/ruby/matched_values.rb @@ -3,4 +3,10 @@ parser.on('--xxx XXX', /foo/i, 'Matched values') do |value| p ['--xxx', value] end +parser.on('--yyy YYY', Integer, 'Check by range', 1..3) do |value| + p ['--yyy', value] +end +parser.on('--zzz ZZZ', Integer, 'Check by list', [1, 3, 4]) do |value| + p ['--zzz', value] +end parser.parse! From 262cf6f9ac9b94df4b649a670163121fd0335b80 Mon Sep 17 00:00:00 2001 From: Koichi ITO Date: Sun, 2 Feb 2025 16:17:37 +0900 Subject: [PATCH 18/41] Make the result of `tty?` obtainable with flexible stdout In mock testing for stdout, `StringIO.new` is sometimes used to redirect the output. In such cases, the assignment is done with `$stdout = StringIO.new`, not the constant `STDOUT`. e.g., https://github.com/rubocop/rubocop/blob/v1.71.1/lib/rubocop/rspec/shared_contexts.rb#L154-L164 After assigning `StringIO.new`, `$stdout.tty?` returns `false`, allowing the standard output destination to be switched during test execution. ```ruby STDOUT.tty? # => true StringIO.new.tty? # => false ``` However, since `STDOUT.tty?` returns `true`, a failure occurred in environments where the environment variables `RUBY_PAGER` or `PAGER` are set. e.g., https://github.com/rubocop/rubocop/pull/13784 To address this, `STDOUT` has been updated to `$stdout` so that the result of `tty?` can be flexibly overridden. A potential concern is that `$stdout`, unlike `STDOUT`, does not always represent the standard output at the time the Ruby process started. However, no concrete examples of issues related to this have been identified. `STDOUT.tty?` is the logic of optparse introduced in https://github.com/ruby/optparse/pull/70. This PR replaces `STDOUT` with `$stdout` throughout, based on the assumption that `$stdout` is sufficient for use with optparse. --- lib/optparse.rb | 6 +++--- test/optparse/test_optparse.rb | 5 ++--- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/lib/optparse.rb b/lib/optparse.rb index 731d9bd..f849a9c 100644 --- a/lib/optparse.rb +++ b/lib/optparse.rb @@ -1056,7 +1056,7 @@ def compsys(to, name = File.basename($0)) # :nodoc: end def help_exit - if STDOUT.tty? && (pager = ENV.values_at(*%w[RUBY_PAGER PAGER]).find {|e| e && !e.empty?}) + if $stdout.tty? && (pager = ENV.values_at(*%w[RUBY_PAGER PAGER]).find {|e| e && !e.empty?}) less = ENV["LESS"] args = [{"LESS" => "#{!less || less.empty? ? '-' : less}Fe"}, pager, "w"] print = proc do |f| @@ -1065,7 +1065,7 @@ def help_exit # pager terminated end if Process.respond_to?(:fork) and false - IO.popen("-") {|f| f ? Process.exec(*args, in: f) : print.call(STDOUT)} + IO.popen("-") {|f| f ? Process.exec(*args, in: f) : print.call($stdout)} # unreachable end IO.popen(*args, &print) @@ -1107,7 +1107,7 @@ def help_exit # Officious['*-completion-zsh'] = proc do |parser| Switch::OptionalArgument.new do |arg| - parser.compsys(STDOUT, arg) + parser.compsys($stdout, arg) exit end end diff --git a/test/optparse/test_optparse.rb b/test/optparse/test_optparse.rb index 7f35cb4..d50203b 100644 --- a/test/optparse/test_optparse.rb +++ b/test/optparse/test_optparse.rb @@ -184,10 +184,9 @@ def test_help_pager File.open(File.join(dir, "options.rb"), "w") do |f| f.puts "#{<<~"begin;"}\n#{<<~'end;'}" begin; - stdout = STDOUT.dup + stdout = $stdout.dup def stdout.tty?; true; end - Object.__send__(:remove_const, :STDOUT) - STDOUT = stdout + $stdout = stdout ARGV.options do |opt| end; 100.times {|i| f.puts " opt.on('--opt-#{i}') {}"} From 30571f91d3dca33f2244883127cb1785694aa4d4 Mon Sep 17 00:00:00 2001 From: Kouhei Yanagita Date: Thu, 9 Jan 2025 11:00:54 +0900 Subject: [PATCH 19/41] Fix LESS environment variable setup in OptionParser#help_exit If the original value of LESS ends with an option starting with "--", simply appending "Fe" would result in an invalid option string. --- lib/optparse.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/optparse.rb b/lib/optparse.rb index f849a9c..f32edc5 100644 --- a/lib/optparse.rb +++ b/lib/optparse.rb @@ -1058,7 +1058,7 @@ def compsys(to, name = File.basename($0)) # :nodoc: def help_exit if $stdout.tty? && (pager = ENV.values_at(*%w[RUBY_PAGER PAGER]).find {|e| e && !e.empty?}) less = ENV["LESS"] - args = [{"LESS" => "#{!less || less.empty? ? '-' : less}Fe"}, pager, "w"] + args = [{"LESS" => "#{less} -Fe"}, pager, "w"] print = proc do |f| f.puts help rescue Errno::EPIPE From 83e8c23d68b70e32e816b9c1c755f0479a63762c Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Fri, 26 Apr 2024 19:32:29 +0900 Subject: [PATCH 20/41] [DOC] Extract description from README --- optparse.gemspec | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/optparse.gemspec b/optparse.gemspec index 126f71b..8589f18 100644 --- a/optparse.gemspec +++ b/optparse.gemspec @@ -14,7 +14,10 @@ Gem::Specification.new do |spec| spec.email = ["nobu@ruby-lang.org"] spec.summary = %q{OptionParser is a class for command-line option analysis.} - spec.description = %q{OptionParser is a class for command-line option analysis.} + spec.description = File.open(File.join(__dir__, "README.md")) do |readme| + readme.gets("") # heading + readme.gets("").chomp + end rescue spec.summary spec.homepage = "https://github.com/ruby/optparse" spec.required_ruby_version = Gem::Requirement.new(">= 2.5.0") spec.licenses = ["Ruby", "BSD-2-Clause"] From f4d64b0b17af329b774181db220a5daa806d8061 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Mon, 10 Mar 2025 20:06:00 +0900 Subject: [PATCH 21/41] bump up to 0.7.0.dev.1 [ci skip] --- lib/optparse.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/optparse.rb b/lib/optparse.rb index f32edc5..fca5663 100644 --- a/lib/optparse.rb +++ b/lib/optparse.rb @@ -425,7 +425,7 @@ # class OptionParser # The version string - OptionParser::Version = "0.6.0" + OptionParser::Version = "0.7.0.dev.1" # :stopdoc: NoArgument = [NO_ARGUMENT = :NONE, nil].freeze From a8d0ba8dac609c815a3dcdeb3203574192c9c41d Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Mon, 17 Mar 2025 19:13:47 +0900 Subject: [PATCH 22/41] Fix completion of key-value pairs array Enum array may be the list of pairs of key and value. Check if only key is completable, not pair. Fix #93 Fix #94 --- lib/optparse.rb | 2 +- test/optparse/test_placearg.rb | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/optparse.rb b/lib/optparse.rb index fca5663..c9caf32 100644 --- a/lib/optparse.rb +++ b/lib/optparse.rb @@ -1502,7 +1502,7 @@ def make_switch(opts, block = nil) block = notwice(o, block, 'block') when Array, Hash if Array === o - o, v = o.partition {|v| Completion.completable?(v)} + o, v = o.partition {|v,| Completion.completable?(v)} values = notwice(v, values, 'values') unless v.empty? next if o.empty? end diff --git a/test/optparse/test_placearg.rb b/test/optparse/test_placearg.rb index 36edf40..d5be5a6 100644 --- a/test/optparse/test_placearg.rb +++ b/test/optparse/test_placearg.rb @@ -8,6 +8,7 @@ def setup @opt.def_option("--option [VAL]") {|x| @flag = x} @opt.def_option("-T [level]", /^[0-4]$/, Integer) {|x| @topt = x} @opt.def_option("--enum [VAL]", [:Alpha, :Bravo, :Charlie]) {|x| @enum = x} + @opt.def_option("--enumval [VAL]", [[:Alpha, 1], [:Bravo, 2], [:Charlie, 3]]) {|x| @enum = x} @opt.def_option("--integer [VAL]", Integer, [1, 2, 3]) {|x| @integer = x} @opt.def_option("--range [VAL]", Integer, 1..3) {|x| @range = x} @topt = nil @@ -102,6 +103,11 @@ def test_enum assert_equal(:Alpha, @enum) end + def test_enum_pair + assert_equal([], no_error {@opt.parse!(%w"--enumval=A")}) + assert_equal(1, @enum) + end + def test_enum_conversion assert_equal([], no_error {@opt.parse!(%w"--integer=1")}) assert_equal(1, @integer) From ba649b1f7300dde001d68ab75da69e43c34ff10d Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Wed, 19 Mar 2025 16:57:01 +0900 Subject: [PATCH 23/41] bump:dev task --- rakelib/version.rake | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/rakelib/version.rake b/rakelib/version.rake index eb430b0..583530d 100644 --- a/rakelib/version.rake +++ b/rakelib/version.rake @@ -28,9 +28,21 @@ class << (helper = Bundler::GemHelper.instance) def bump(major, minor = 0, teeny = 0, pre: nil) self.version = [major, minor, teeny, pre].compact.join(".") end + + def next_prerelease(*prefix, num) + if num + [*prefix, num.succ] + else + "dev.1" + end + end end -major, minor, teeny = helper.gemspec.version.segments +major, minor, teeny, *prerelease = helper.gemspec.version.segments + +task "bump:dev", [:pre] do |t, pre: helper.next_prerelease(*prerelease)| + helper.bump(major, minor, teeny, pre: pre) +end task "bump:teeny", [:pre] do |t, pre: nil| helper.bump(major, minor, teeny+1, pre: pre) From 8c2c7a490343bff6b131d40e2e06d325fa9e47f7 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Wed, 19 Mar 2025 16:57:11 +0900 Subject: [PATCH 24/41] bump up to 0.7.0.dev.2 --- lib/optparse.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/optparse.rb b/lib/optparse.rb index c9caf32..e1069b3 100644 --- a/lib/optparse.rb +++ b/lib/optparse.rb @@ -425,7 +425,7 @@ # class OptionParser # The version string - OptionParser::Version = "0.7.0.dev.1" + OptionParser::Version = "0.7.0.dev.2" # :stopdoc: NoArgument = [NO_ARGUMENT = :NONE, nil].freeze From 24bce42a5c88b078eb0cb9da2bf17cc1102733d0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 7 Apr 2025 03:44:44 +0000 Subject: [PATCH 25/41] Bump step-security/harden-runner from 2.11.0 to 2.11.1 Bumps [step-security/harden-runner](https://github.com/step-security/harden-runner) from 2.11.0 to 2.11.1. - [Release notes](https://github.com/step-security/harden-runner/releases) - [Commits](https://github.com/step-security/harden-runner/compare/4d991eb9b905ef189e4c376166672c3f2f230481...c6295a65d1254861815972266d5933fd6e532bdf) --- updated-dependencies: - dependency-name: step-security/harden-runner dependency-version: 2.11.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/push_gem.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/push_gem.yml b/.github/workflows/push_gem.yml index e05793f..0a72cfd 100644 --- a/.github/workflows/push_gem.yml +++ b/.github/workflows/push_gem.yml @@ -23,7 +23,7 @@ jobs: steps: - name: Harden Runner - uses: step-security/harden-runner@4d991eb9b905ef189e4c376166672c3f2f230481 # v2.11.0 + uses: step-security/harden-runner@c6295a65d1254861815972266d5933fd6e532bdf # v2.11.1 with: egress-policy: audit From 541e99d4aadac96c42dbdaed7863cc91a15d6336 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 28 Apr 2025 03:35:10 +0000 Subject: [PATCH 26/41] Bump step-security/harden-runner from 2.11.1 to 2.12.0 Bumps [step-security/harden-runner](https://github.com/step-security/harden-runner) from 2.11.1 to 2.12.0. - [Release notes](https://github.com/step-security/harden-runner/releases) - [Commits](https://github.com/step-security/harden-runner/compare/c6295a65d1254861815972266d5933fd6e532bdf...0634a2670c59f64b4a01f0f96f84700a4088b9f0) --- updated-dependencies: - dependency-name: step-security/harden-runner dependency-version: 2.12.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/push_gem.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/push_gem.yml b/.github/workflows/push_gem.yml index 0a72cfd..4e02df3 100644 --- a/.github/workflows/push_gem.yml +++ b/.github/workflows/push_gem.yml @@ -23,7 +23,7 @@ jobs: steps: - name: Harden Runner - uses: step-security/harden-runner@c6295a65d1254861815972266d5933fd6e532bdf # v2.11.1 + uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0 with: egress-policy: audit From 87466f01233ff3421f4efa2c6491e33e99a6189d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Jun 2025 03:17:14 +0000 Subject: [PATCH 27/41] Bump step-security/harden-runner from 2.12.0 to 2.12.1 Bumps [step-security/harden-runner](https://github.com/step-security/harden-runner) from 2.12.0 to 2.12.1. - [Release notes](https://github.com/step-security/harden-runner/releases) - [Commits](https://github.com/step-security/harden-runner/compare/0634a2670c59f64b4a01f0f96f84700a4088b9f0...002fdce3c6a235733a90a27c80493a3241e56863) --- updated-dependencies: - dependency-name: step-security/harden-runner dependency-version: 2.12.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/push_gem.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/push_gem.yml b/.github/workflows/push_gem.yml index 4e02df3..a417ef9 100644 --- a/.github/workflows/push_gem.yml +++ b/.github/workflows/push_gem.yml @@ -23,7 +23,7 @@ jobs: steps: - name: Harden Runner - uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0 + uses: step-security/harden-runner@002fdce3c6a235733a90a27c80493a3241e56863 # v2.12.1 with: egress-policy: audit From 7b1362bcd70c300bfbb52fb8007aa90d031ae81e Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Fri, 20 Jun 2025 13:26:09 +0900 Subject: [PATCH 28/41] Use GITHUB_TOKEN instead of admin credential --- .github/workflows/push_gem.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/push_gem.yml b/.github/workflows/push_gem.yml index a417ef9..95ba55a 100644 --- a/.github/workflows/push_gem.yml +++ b/.github/workflows/push_gem.yml @@ -43,4 +43,4 @@ jobs: tag_name="$(git describe --tags --abbrev=0)" gh release create "${tag_name}" --verify-tag --generate-notes env: - GITHUB_TOKEN: ${{ secrets.MATZBOT_GITHUB_WORKFLOW_TOKEN }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} From 3869000e987337dca2c95af0094e6750ffdc152b Mon Sep 17 00:00:00 2001 From: kwatch Date: Sun, 29 Jun 2025 16:30:50 +0900 Subject: [PATCH 29/41] Enhance to support 'Set' object as an enum (#76) * Enhance to support 'Set' object as an enum * Add test script for '#make_swithc()' --------- Co-authored-by: Nobuyoshi Nakada --- lib/optparse.rb | 3 ++- test/optparse/test_switch.rb | 50 ++++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 1 deletion(-) create mode 100644 test/optparse/test_switch.rb diff --git a/lib/optparse.rb b/lib/optparse.rb index e1069b3..9cbd377 100644 --- a/lib/optparse.rb +++ b/lib/optparse.rb @@ -7,6 +7,7 @@ # # See OptionParser for documentation. # +require 'set' unless defined?(Set) #-- # == Developer Documentation (not for RDoc output) @@ -1500,7 +1501,7 @@ def make_switch(opts, block = nil) case o when Proc, Method block = notwice(o, block, 'block') - when Array, Hash + when Array, Hash, Set if Array === o o, v = o.partition {|v,| Completion.completable?(v)} values = notwice(v, values, 'values') unless v.empty? diff --git a/test/optparse/test_switch.rb b/test/optparse/test_switch.rb new file mode 100644 index 0000000..b06f4e3 --- /dev/null +++ b/test/optparse/test_switch.rb @@ -0,0 +1,50 @@ +# frozen_string_literal: false + +require 'test/unit' +require 'optparse' + + +class TestOptionParserSwitch < Test::Unit::TestCase + + def setup + @parser = OptionParser.new + end + + def assert_invalidarg_error(msg, &block) + exc = assert_raise(OptionParser::InvalidArgument) do + yield + end + assert_equal "invalid argument: #{msg}", exc.message + end + + def test_make_switch__enum_array + p = @parser + p.on("--enum=", ["aa", "bb", "cc"]) + p.permute(["--enum=bb"], into: (opts={})) + assert_equal({:enum=>"bb"}, opts) + assert_invalidarg_error("--enum=dd") do + p.permute(["--enum=dd"], into: (opts={})) + end + end + + def test_make_switch__enum_hash + p = @parser + p.on("--hash=", {"aa"=>"AA", "bb"=>"BB"}) + p.permute(["--hash=bb"], into: (opts={})) + assert_equal({:hash=>"BB"}, opts) + assert_invalidarg_error("--hash=dd") do + p.permute(["--hash=dd"], into: (opts={})) + end + end + + def test_make_switch__enum_set + p = @parser + p.on("--set=", Set.new(["aa", "bb", "cc"])) + p.permute(["--set=bb"], into: (opts={})) + assert_equal({:set=>"bb"}, opts) + assert_invalidarg_error("--set=dd") do + p.permute(["--set=dd"], into: (opts={})) + end + end + +end From 740ffa76c05b9627d8be481e2a7b5869c7b0c46a Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Sun, 29 Jun 2025 16:07:07 +0900 Subject: [PATCH 30/41] Fix OptionParser#program_name not to strip suffix unexpectedly --- lib/optparse.rb | 10 +++++++++- test/optparse/test_optparse.rb | 12 ++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/lib/optparse.rb b/lib/optparse.rb index 9cbd377..7838af7 100644 --- a/lib/optparse.rb +++ b/lib/optparse.rb @@ -1294,7 +1294,15 @@ def banner # to $0. # def program_name - @program_name || File.basename($0, '.*') + @program_name || strip_ext(File.basename($0)) + end + + private def strip_ext(name) # :nodoc: + exts = /#{ + require "rbconfig" + Regexp.union(RbConfig::CONFIG["EXECUTABLE_EXTS"]) + }\z/o + name.sub(exts, "") end # for experimental cascading :-) diff --git a/test/optparse/test_optparse.rb b/test/optparse/test_optparse.rb index d50203b..ae12ae5 100644 --- a/test/optparse/test_optparse.rb +++ b/test/optparse/test_optparse.rb @@ -216,4 +216,16 @@ def stdout.tty?; true; end end end end + + def test_program_name + program = $0 + $0 = "rdbg3.5" + assert_equal "rdbg3.5", OptionParser.new.program_name + RbConfig::CONFIG["EXECUTABLE_EXTS"].split(" ") do |ext| + $0 = "rdbg3.5" + ext + assert_equal "rdbg3.5", OptionParser.new.program_name + end + ensure + $0 = program + end end From 15b2f00b6bed354bf66a98a4759626ed41aedd4b Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Sun, 29 Jun 2025 16:50:09 +0900 Subject: [PATCH 31/41] JRuby does not have EXECUTABLE_EXTS in RbConfg::CONFIG --- lib/optparse.rb | 2 +- test/optparse/test_optparse.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/optparse.rb b/lib/optparse.rb index 7838af7..332aea2 100644 --- a/lib/optparse.rb +++ b/lib/optparse.rb @@ -1300,7 +1300,7 @@ def program_name private def strip_ext(name) # :nodoc: exts = /#{ require "rbconfig" - Regexp.union(RbConfig::CONFIG["EXECUTABLE_EXTS"]) + Regexp.union(*RbConfig::CONFIG["EXECUTABLE_EXTS"]&.split(" ")) }\z/o name.sub(exts, "") end diff --git a/test/optparse/test_optparse.rb b/test/optparse/test_optparse.rb index ae12ae5..ff33400 100644 --- a/test/optparse/test_optparse.rb +++ b/test/optparse/test_optparse.rb @@ -221,7 +221,7 @@ def test_program_name program = $0 $0 = "rdbg3.5" assert_equal "rdbg3.5", OptionParser.new.program_name - RbConfig::CONFIG["EXECUTABLE_EXTS"].split(" ") do |ext| + RbConfig::CONFIG["EXECUTABLE_EXTS"]&.split(" ") do |ext| $0 = "rdbg3.5" + ext assert_equal "rdbg3.5", OptionParser.new.program_name end From 24374b42d31194c2a19d284949dcda236049fa69 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Tue, 1 Jul 2025 09:47:20 +0900 Subject: [PATCH 32/41] Use Dir.glob and base keyword arg for the installer of Ruby package --- optparse.gemspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/optparse.gemspec b/optparse.gemspec index 8589f18..cd29267 100644 --- a/optparse.gemspec +++ b/optparse.gemspec @@ -25,7 +25,7 @@ Gem::Specification.new do |spec| spec.metadata["homepage_uri"] = spec.homepage spec.metadata["source_code_uri"] = spec.homepage - spec.files = Dir["{doc,lib,misc}/**/{*,.document}"] + + spec.files = Dir.glob("{doc,lib,misc}/**/{*,.document}", base: File.expand_path("..", __FILE__)) + %w[README.md ChangeLog COPYING .document .rdoc_options] spec.bindir = "exe" spec.executables = [] From 55d9a7a886b9a9df4b1e30633c42e3e43cfde26e Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Tue, 1 Jul 2025 10:44:07 +0900 Subject: [PATCH 33/41] Use git ls-files instead of Dir.glob because optparse has optionparser.rb that is outside of lib/optparse directory Co-authored-by: Nobuyoshi Nakada --- optparse.gemspec | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/optparse.gemspec b/optparse.gemspec index cd29267..6ea6b88 100644 --- a/optparse.gemspec +++ b/optparse.gemspec @@ -25,8 +25,9 @@ Gem::Specification.new do |spec| spec.metadata["homepage_uri"] = spec.homepage spec.metadata["source_code_uri"] = spec.homepage - spec.files = Dir.glob("{doc,lib,misc}/**/{*,.document}", base: File.expand_path("..", __FILE__)) + - %w[README.md ChangeLog COPYING .document .rdoc_options] + dir, gemspec = File.split(__FILE__) + excludes = %W[#{gemspec} rakelib test/ Gemfile Rakefile .git* .editor*].map {|n| ":^"+n} + spec.files = IO.popen(%w[git ls-files -z --] + excludes, chdir: dir, &:read).split("\x0") spec.bindir = "exe" spec.executables = [] spec.require_paths = ["lib"] From 214d75240607a21d39e09c490a71510cfcd5fa99 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 7 Jul 2025 06:55:52 +0200 Subject: [PATCH 34/41] Bump step-security/harden-runner from 2.12.1 to 2.12.2 (#102) Bumps [step-security/harden-runner](https://github.com/step-security/harden-runner) from 2.12.1 to 2.12.2. - [Release notes](https://github.com/step-security/harden-runner/releases) - [Commits](https://github.com/step-security/harden-runner/compare/002fdce3c6a235733a90a27c80493a3241e56863...6c439dc8bdf85cadbbce9ed30d1c7b959517bc49) --- updated-dependencies: - dependency-name: step-security/harden-runner dependency-version: 2.12.2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/push_gem.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/push_gem.yml b/.github/workflows/push_gem.yml index 95ba55a..b7fc386 100644 --- a/.github/workflows/push_gem.yml +++ b/.github/workflows/push_gem.yml @@ -23,7 +23,7 @@ jobs: steps: - name: Harden Runner - uses: step-security/harden-runner@002fdce3c6a235733a90a27c80493a3241e56863 # v2.12.1 + uses: step-security/harden-runner@6c439dc8bdf85cadbbce9ed30d1c7b959517bc49 # v2.12.2 with: egress-policy: audit From 2fe7555cfd48b69ab91eac292198f011025fc510 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 21 Jul 2025 06:41:48 +0200 Subject: [PATCH 35/41] Bump step-security/harden-runner from 2.12.2 to 2.13.0 (#103) Bumps [step-security/harden-runner](https://github.com/step-security/harden-runner) from 2.12.2 to 2.13.0. - [Release notes](https://github.com/step-security/harden-runner/releases) - [Commits](https://github.com/step-security/harden-runner/compare/6c439dc8bdf85cadbbce9ed30d1c7b959517bc49...ec9f2d5744a09debf3a187a3f4f675c53b671911) --- updated-dependencies: - dependency-name: step-security/harden-runner dependency-version: 2.13.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/push_gem.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/push_gem.yml b/.github/workflows/push_gem.yml index b7fc386..25ea710 100644 --- a/.github/workflows/push_gem.yml +++ b/.github/workflows/push_gem.yml @@ -23,7 +23,7 @@ jobs: steps: - name: Harden Runner - uses: step-security/harden-runner@6c439dc8bdf85cadbbce9ed30d1c7b959517bc49 # v2.12.2 + uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0 with: egress-policy: audit From e0fdabf94697f38a9971019106c1dac070e98461 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Sun, 3 Aug 2025 22:37:53 +0900 Subject: [PATCH 36/41] Fallback HOME --- test/optparse/test_load.rb | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/test/optparse/test_load.rb b/test/optparse/test_load.rb index 0ebe855..b8b76a3 100644 --- a/test/optparse/test_load.rb +++ b/test/optparse/test_load.rb @@ -31,7 +31,13 @@ def assert_load(result) assert_equal({test: result}, into) end + def assert_load_nothing + assert !new_parser.load + assert_nil @result + end + def setup_options(env, dir, suffix = nil) + env.update({'HOME'=>@tmpdir}) optdir = File.join(@tmpdir, dir) FileUtils.mkdir_p(optdir) file = File.join(optdir, [@basename, suffix].join("")) @@ -50,7 +56,7 @@ def setup_options(env, dir, suffix = nil) end def setup_options_home(&block) - setup_options({'HOME'=>@tmpdir}, ".options", &block) + setup_options({}, ".options", &block) end def setup_options_xdg_config_home(&block) @@ -58,7 +64,7 @@ def setup_options_xdg_config_home(&block) end def setup_options_home_config(&block) - setup_options({'HOME'=>@tmpdir}, ".config", ".options", &block) + setup_options({}, ".config", ".options", &block) end def setup_options_xdg_config_dirs(&block) @@ -66,7 +72,7 @@ def setup_options_xdg_config_dirs(&block) end def setup_options_home_config_settings(&block) - setup_options({'HOME'=>@tmpdir}, "config/settings", ".options", &block) + setup_options({}, "config/settings", ".options", &block) end def test_load_home_options @@ -135,7 +141,8 @@ def test_load_home_config_settings end def test_load_nothing - assert !new_parser.load - assert_nil @result + setup_options({}, "") do + assert_load_nothing + end end end From 181752391ca392240eab450fc47dcaea7d5ed4b5 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Sun, 3 Aug 2025 22:41:21 +0900 Subject: [PATCH 37/41] Expand literal home paths only Paths in environment variables should already be expanded. The base name of the program is also not subject to expansion. --- lib/optparse.rb | 12 +++++++----- test/optparse/test_load.rb | 30 ++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 5 deletions(-) diff --git a/lib/optparse.rb b/lib/optparse.rb index 332aea2..23b4844 100644 --- a/lib/optparse.rb +++ b/lib/optparse.rb @@ -2047,19 +2047,21 @@ def candidate(word) def load(filename = nil, **keywords) unless filename basename = File.basename($0, '.*') - return true if load(File.expand_path(basename, '~/.options'), **keywords) rescue nil + return true if load(File.expand_path("~/.options/#{basename}"), **keywords) rescue nil basename << ".options" return [ # XDG ENV['XDG_CONFIG_HOME'], - '~/.config', + ['~/.config', true], *ENV['XDG_CONFIG_DIRS']&.split(File::PATH_SEPARATOR), # Haiku - '~/config/settings', - ].any? {|dir| + ['~/config/settings', true], + ].any? {|dir, expand| next if !dir or dir.empty? - load(File.expand_path(basename, dir), **keywords) rescue nil + filename = File.join(dir, basename) + filename = File.expand_path(filename) if expand + load(filename, **keywords) rescue nil } end begin diff --git a/test/optparse/test_load.rb b/test/optparse/test_load.rb index b8b76a3..8c83503 100644 --- a/test/optparse/test_load.rb +++ b/test/optparse/test_load.rb @@ -75,6 +75,10 @@ def setup_options_home_config_settings(&block) setup_options({}, "config/settings", ".options", &block) end + def setup_options_home_options(envname, &block) + setup_options({envname => '~/options'}, "options", ".options", &block) + end + def test_load_home_options result, = setup_options_home assert_load(result) @@ -145,4 +149,30 @@ def test_load_nothing assert_load_nothing end end + + def test_not_expand_path_basename + basename = @basename + @basename = "~" + $test_optparse_basename = "/" + @basename + alias $test_optparse_prog $0 + alias $0 $test_optparse_basename + setup_options({'HOME'=>@tmpdir+"/~options"}, "", "options") do + assert_load_nothing + end + ensure + alias $0 $test_optparse_prog + @basename = basename + end + + def test_not_expand_path_xdg_config_home + setup_options_home_options('XDG_CONFIG_HOME') do + assert_load_nothing + end + end + + def test_not_expand_path_xdg_config_dirs + setup_options_home_options('XDG_CONFIG_DIRS') do + assert_load_nothing + end + end end From 2f9c7500a337a03c059c8ef68886b91e9ab4da68 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Fri, 8 Aug 2025 19:33:00 +0900 Subject: [PATCH 38/41] Use `~/.config` only if `$XDG_CONFIG_HOME` is unset or empty --- lib/optparse.rb | 12 +++++++++--- test/optparse/test_load.rb | 14 ++++++++++++-- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/lib/optparse.rb b/lib/optparse.rb index 23b4844..06e33db 100644 --- a/lib/optparse.rb +++ b/lib/optparse.rb @@ -2049,10 +2049,16 @@ def load(filename = nil, **keywords) basename = File.basename($0, '.*') return true if load(File.expand_path("~/.options/#{basename}"), **keywords) rescue nil basename << ".options" + if !(xdg = ENV['XDG_CONFIG_HOME']) or xdg.empty? + # https://specifications.freedesktop.org/basedir-spec/latest/#variables + # + # If $XDG_CONFIG_HOME is either not set or empty, a default + # equal to $HOME/.config should be used. + xdg = ['~/.config', true] + end return [ - # XDG - ENV['XDG_CONFIG_HOME'], - ['~/.config', true], + xdg, + *ENV['XDG_CONFIG_DIRS']&.split(File::PATH_SEPARATOR), # Haiku diff --git a/test/optparse/test_load.rb b/test/optparse/test_load.rb index 8c83503..f664cfb 100644 --- a/test/optparse/test_load.rb +++ b/test/optparse/test_load.rb @@ -47,7 +47,7 @@ def setup_options(env, dir, suffix = nil) begin yield dir, optdir ensure - File.unlink(file) + File.unlink(file) rescue nil Dir.rmdir(optdir) rescue nil end else @@ -101,7 +101,7 @@ def test_load_home_options end def test_load_xdg_config_home - result, = setup_options_xdg_config_home + result, dir = setup_options_xdg_config_home assert_load(result) setup_options_home_config do @@ -115,6 +115,11 @@ def test_load_xdg_config_home setup_options_home_config_settings do assert_load(result) end + + File.unlink("#{dir}/#{@basename}.options") + setup_options_home_config do + assert_load_nothing + end end def test_load_home_config @@ -128,6 +133,11 @@ def test_load_home_config setup_options_home_config_settings do assert_load(result) end + + setup_options_xdg_config_home do |_, dir| + File.unlink("#{dir}/#{@basename}.options") + assert_load_nothing + end end def test_load_xdg_config_dirs From de76dbfdc4a5b8e0daef2460c6fc615c5249b492 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 18 Aug 2025 04:32:53 +0000 Subject: [PATCH 39/41] Bump actions/checkout from 4 to 5 Bumps [actions/checkout](https://github.com/actions/checkout) from 4 to 5. - [Release notes](https://github.com/actions/checkout/releases) - [Commits](https://github.com/actions/checkout/compare/v4...v5) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: '5' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/codeql.yml | 2 +- .github/workflows/push_gem.yml | 2 +- .github/workflows/test.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index ee28f6b..065e78a 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -48,7 +48,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@v5 # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL diff --git a/.github/workflows/push_gem.yml b/.github/workflows/push_gem.yml index 25ea710..764dcab 100644 --- a/.github/workflows/push_gem.yml +++ b/.github/workflows/push_gem.yml @@ -27,7 +27,7 @@ jobs: with: egress-policy: audit - - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 + - uses: actions/checkout@ff7abcd0c3c05ccf6adc123a8cd1fd4fb30fb493 # v4.1.4 - name: Set up Ruby uses: ruby/setup-ruby@a6e6f86333f0a2523ece813039b8b4be04560854 # v1.190.0 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 2736e12..250d3f1 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -28,7 +28,7 @@ jobs: - { os: windows-latest, ruby: jruby } runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Set up Ruby uses: ruby/setup-ruby@v1 with: From d2a27069580f80841809801a0ee53a3d9592fc5b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 15 Sep 2025 03:01:53 +0000 Subject: [PATCH 40/41] Bump step-security/harden-runner from 2.13.0 to 2.13.1 Bumps [step-security/harden-runner](https://github.com/step-security/harden-runner) from 2.13.0 to 2.13.1. - [Release notes](https://github.com/step-security/harden-runner/releases) - [Commits](https://github.com/step-security/harden-runner/compare/ec9f2d5744a09debf3a187a3f4f675c53b671911...f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a) --- updated-dependencies: - dependency-name: step-security/harden-runner dependency-version: 2.13.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/push_gem.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/push_gem.yml b/.github/workflows/push_gem.yml index 764dcab..ceaa5d0 100644 --- a/.github/workflows/push_gem.yml +++ b/.github/workflows/push_gem.yml @@ -23,7 +23,7 @@ jobs: steps: - name: Harden Runner - uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0 + uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1 with: egress-policy: audit From 9ec5d1d582109f31a3a6c2b8afa84b3349d9352e Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Mon, 15 Sep 2025 22:10:14 +0900 Subject: [PATCH 41/41] Prefer `Proc` over `Method` The performances are: block > proc > method object. --- lib/optparse.rb | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/lib/optparse.rb b/lib/optparse.rb index 06e33db..ea6844b 100644 --- a/lib/optparse.rb +++ b/lib/optparse.rb @@ -1855,7 +1855,7 @@ def permute(*argv, **keywords) # def permute!(argv = default_argv, **keywords) nonopts = [] - order!(argv, **keywords, &nonopts.method(:<<)) + order!(argv, **keywords) {|nonopt| nonopts << nonopt} argv[0, 0] = nonopts argv end @@ -1908,13 +1908,16 @@ def getopts(*args, symbolize_names: false, **keywords) single_options, *long_options = *args result = {} + setter = (symbolize_names ? + ->(name, val) {result[name.to_sym] = val} + : ->(name, val) {result[name] = val}) single_options.scan(/(.)(:)?/) do |opt, val| if val - result[opt] = nil + setter[opt, nil] define("-#{opt} VAL") else - result[opt] = false + setter[opt, false] define("-#{opt}") end end if single_options @@ -1923,16 +1926,16 @@ def getopts(*args, symbolize_names: false, **keywords) arg, desc = arg.split(';', 2) opt, val = arg.split(':', 2) if val - result[opt] = val.empty? ? nil : val + setter[opt, (val unless val.empty?)] define("--#{opt}=#{result[opt] || "VAL"}", *[desc].compact) else - result[opt] = false + setter[opt, false] define("--#{opt}", *[desc].compact) end end - parse_in_order(argv, result.method(:[]=), **keywords) - symbolize_names ? result.transform_keys(&:to_sym) : result + parse_in_order(argv, setter, **keywords) + result end # @@ -1982,7 +1985,7 @@ def complete(typ, opt, icase = false, *pat) # :nodoc: visit(:complete, typ, opt, icase, *pat) {|o, *sw| return sw} } exc = ambiguous ? AmbiguousOption : InvalidOption - raise exc.new(opt, additional: self.method(:additional_message).curry[typ]) + raise exc.new(opt, additional: proc {|o| additional_message(typ, o)}) end private :complete @@ -2273,9 +2276,10 @@ def recover(argv) argv end + DIR = File.join(__dir__, '') def self.filter_backtrace(array) unless $DEBUG - array.delete_if(&%r"\A#{Regexp.quote(__FILE__)}:"o.method(:=~)) + array.delete_if {|bt| bt.start_with?(DIR)} end array end