diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index b2dcbef..bfcb268 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -18,7 +18,7 @@ jobs: strategy: matrix: ruby: - - '3.3.0' + - '4.0.1' steps: - uses: actions/checkout@v4 @@ -28,4 +28,4 @@ jobs: ruby-version: ${{ matrix.ruby }} bundler-cache: true - name: Run the tests - run: rspec \ No newline at end of file + run: bundle exec rspec \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 211f2ce..eef4294 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,25 @@ # Rbcli Changelog +## 0.4.4 (Mar 19, 2026) + +### Improvements + +* Updated minimum required Ruby version to 3.4.0 +* Switched all dependency version constraints to open-ended (`>=`) and updated minimum versions +* Added `base64` as an explicit dependency +* Removed redundant `.select` filter in parser on a collection that was already filtered +* Refactored engine priority check to avoid running the same `select` query twice +* Simplified `File.expand_path(File.dirname(__FILE__))` to `__dir__` in `rbcli.rb` +* Added missing `# frozen_string_literal: true` magic comment to `parser.rb` +* Fixed typo "Compatiblity" → "Compatibility" in helptext banner + +### Bugfixes + +* Fixed logger method definitions generated by a `%w()` list with commas, which produced invalid method names like `:"debug,"` instead of `:debug` +* Fixed `!=` comparison being used instead of `+=` concatenation in the parser's interactive prompt, causing the default value hint never to be displayed +* Fixed command name validation regex not being anchored, which allowed invalid names containing special characters to pass validation +* Fixed test assertion in `gem_spec.rb` using `.equal?` as a bare method call (a no-op) instead of a proper RSpec `eq` matcher + ## 0.4.3 (Oct 22, 2025) ### Improvements diff --git a/lib/rbcli.rb b/lib/rbcli.rb index 64a42b8..14ee87c 100644 --- a/lib/rbcli.rb +++ b/lib/rbcli.rb @@ -3,8 +3,8 @@ # Rbcli -- A framework for developing command line applications in Ruby # # Copyright (C) 2024 Andrew Khoury # ################################################################################## -RBCLI_LIBDIR = File.join(File.expand_path(File.dirname(__FILE__)), 'rbcli') -RBCLI_TOOLDIR = File.join(File.expand_path(File.dirname(__FILE__)), 'rbcli-tool') +RBCLI_LIBDIR = File.join(__dir__, 'rbcli') +RBCLI_TOOLDIR = File.join(__dir__, 'rbcli-tool') EXECUTABLE = File.basename($0).gsub(/\.[^.]+$/, '') # Prerequisites for anything else to run diff --git a/lib/rbcli/components/commands/command.rb b/lib/rbcli/components/commands/command.rb index fac43d0..5eaf449 100644 --- a/lib/rbcli/components/commands/command.rb +++ b/lib/rbcli/components/commands/command.rb @@ -5,7 +5,7 @@ ################################################################################## class Rbcli::Command def initialize name - raise Rbcli::CommandError.new "Command name can only contain the characters [A-Za-z0-9_]+" unless /[A-Za-z0-9_]+/.match?(name) + raise Rbcli::CommandError.new "Command name can only contain the characters [A-Za-z0-9_]+" unless /\A[A-Za-z0-9_]+\z/.match?(name.to_s) @name = name.to_s.downcase @default = false @description = nil diff --git a/lib/rbcli/components/core/engine.rb b/lib/rbcli/components/core/engine.rb index 2dc2815..8bb3116 100644 --- a/lib/rbcli/components/core/engine.rb +++ b/lib/rbcli/components/core/engine.rb @@ -7,8 +7,9 @@ module Rbcli::Engine @operations = [] def self.register_operation operation, name: nil, priority: nil - if @operations.select { |op| op[:priority] == priority }.count != 0 - raise Rbcli::Error.new "The Rbcli engine can not have two operations defined with the same priority: #{name}, #{@operations.select { |op| op[:priority] == priority }.join(", ")}" + conflicts = @operations.select { |op| op[:priority] == priority } + unless conflicts.empty? + raise Rbcli::Error, "The Rbcli engine can not have two operations defined with the same priority: #{name}, #{conflicts.join(", ")}" end @operations << { operation: operation, name: name, priority: priority } end diff --git a/lib/rbcli/components/logger/logger.rb b/lib/rbcli/components/logger/logger.rb index be34298..544348c 100644 --- a/lib/rbcli/components/logger/logger.rb +++ b/lib/rbcli/components/logger/logger.rb @@ -98,12 +98,6 @@ def unknown message, progname = nil, &block self.add(Logger::UNKNOWN, message, progname, &block) end - %w(debug, info, warn, error, fatal, unknown).each do |l| - self.define_method(l.to_sym) do |message, progname = nil, &block| - self.send(:add, l.to_sym, message, progname, &block) - end - end - private def self.colorlevel level diff --git a/lib/rbcli/components/parser/parser.rb b/lib/rbcli/components/parser/parser.rb index 7a9f0f6..0c0fb08 100644 --- a/lib/rbcli/components/parser/parser.rb +++ b/lib/rbcli/components/parser/parser.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true ################################################################################## # Rbcli -- A framework for developing command line applications in Ruby # # Copyright (C) 2024 Andrew Khoury # @@ -24,7 +25,7 @@ def self.parse bannerstr += "\n" end unless appinfo[:compatibility].nil? || appinfo[:compatibility].empty? - bannerstr += "Compatiblity: " + bannerstr += "Compatibility: " if appinfo[:compatibility].length == 2 bannerstr += appinfo[:compatibility].join(' and ') + "\n" else @@ -46,7 +47,7 @@ def self.parse @parser.synopsis bannerstr (Rbcli::Warehouse.get(:opts, :unparsedopts) || []).each { |args| @parser.opt *args } - @parser.stop_on(non_default_commands.select { |_name, cmd| !cmd.default? }.keys) + @parser.stop_on(non_default_commands.keys) begin opts = @parser.parse @@ -148,7 +149,7 @@ def self.prompt_for_missing prompt_string += ' (' + (param_value ? 'Y' : 'y') + '/' + (param_value ? 'n' : 'N') + ')' opt[:default] = param_value if opt[:default].nil? elsif !opt[:default].nil? - prompt_string != " (default: #{opt[:default]})" + prompt_string += " (default: #{opt[:default]})" end prompt_string += ':' unless %w(. ? ! :).include?(opt[:prompt][-1]) prompt_string += ' ' diff --git a/rbcli.gemspec b/rbcli.gemspec index 33d31d7..3c17fec 100644 --- a/rbcli.gemspec +++ b/rbcli.gemspec @@ -34,23 +34,24 @@ Gem::Specification.new do |spec| spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) } spec.require_paths = ["lib"] - spec.required_ruby_version = ">= 2.6.10" - - spec.add_development_dependency "rake", "~> 13.0" - spec.add_development_dependency "rspec", "~> 3.0" - - spec.add_dependency "colorize", "~> 1.1" - spec.add_dependency "octokit", "~> 8.1" - spec.add_dependency "faraday-retry", "~> 2.2" # Required for octokit - spec.add_dependency "json-schema", "~> 4.3" - spec.add_dependency "bigdecimal", "~> 3.1" # Required for json-schema - spec.add_dependency "erb", "~> 4.0" - spec.add_dependency "deep_merge", "~> 1.2" - spec.add_dependency "paint", "~> 2.3" - spec.add_dependency "erubis", "~> 2.7" - spec.add_dependency "rest-client", "~> 2.1" - spec.add_dependency "toml", "~> 0.3" + spec.required_ruby_version = ">= 3.4.0" + + spec.add_development_dependency "rake", '~> 13.3' + spec.add_development_dependency "rspec", '~> 3.13' + + spec.add_dependency "colorize", '>= 1.1' + spec.add_dependency "octokit", '>= 8.1' + spec.add_dependency "faraday-retry", '>= 2.4' # Required for octokit + spec.add_dependency "json-schema", '>= 4.3' + spec.add_dependency "bigdecimal", '>= 3.3' # Required for json-schema + spec.add_dependency "erb", '>= 4.0' + spec.add_dependency "deep_merge", '>= 1.2' + spec.add_dependency "paint", '>= 2.3' + spec.add_dependency "erubis", '>= 2.7' + spec.add_dependency "rest-client", '>= 2.1' + spec.add_dependency "toml", '>= 0.3' + spec.add_dependency "base64", '>= 0.3' # For more information and examples about making a new gem, check out our # guide at: https://bundler.io/guides/creating_gem.html -end \ No newline at end of file +end diff --git a/spec/gem_spec.rb b/spec/gem_spec.rb index 23b1359..fca792b 100644 --- a/spec/gem_spec.rb +++ b/spec/gem_spec.rb @@ -13,6 +13,6 @@ it "pulls the version number from a file" do version = File.read("VERSION") - expect(Rbcli::VERSION).equal? version + expect(Rbcli::VERSION).to eq(version.chomp.strip) end end \ No newline at end of file