Repository: JEG2/highline (ruby)

Issue:
`::add_to_color_scheme` improvement
Hi, thanks for the useful gem.
I've been using the following extension for a while, and if you like it too, I could make it into a PR or something.
```ruby
class HighLine
  class << self
    def add_to_color_scheme(hash)
      old_hash = (color_scheme || {}).to_hash
      fail "Overlapping color schemes: #{old_hash.keys & hash.keys}"  unless
        (old_hash.keys & hash.keys).empty?
      self.color_scheme = ColorScheme.new(old_hash.merge hash)
    end
  end
end
```


Discussion:
I think this addition doesn't change any previous behavior. So I would welcome a PR as it sounds a good idea. Could you please add tests along the PR? I can help you with any doubt in the code base. Sorry for taking so long to answer.

Patch:
diff --git a/.rubocop.yml b/.rubocop.yml
--- a/.rubocop.yml
+++ b/.rubocop.yml
@@ -4,7 +4,8 @@
 # https://github.com/bbatsov/rubocop/tree/master/config
 
 AllCops:
-  TargetRubyVersion: 2.1
+  TargetRubyVersion: 3.3
+  NewCops: enable
 
 # General
 
@@ -58,7 +59,7 @@ Style/OptionalArguments:
     - 'lib/highline/list_renderer.rb'
 
 # TemplateRenderer should never fail on method missing.
-Style/MethodMissing:
+Style/MissingRespondToMissing:
   Exclude:
     - 'lib/highline/template_renderer.rb'
 
@@ -73,7 +74,7 @@ Style/SymbolArray:
 # Cop supports --auto-correct.
 # Configuration parameters: EnforcedStyle, SupportedStyles.
 # SupportedStyles: auto_detection, squiggly, active_support, powerpack, unindent
-Layout/IndentHeredoc:
+Layout/HeredocIndentation:
   Exclude:
     - 'examples/page_and_wrap.rb'
     - 'highline.gemspec'
diff --git a/Changelog.md b/Changelog.md
--- a/Changelog.md
+++ b/Changelog.md
@@ -2,6 +2,11 @@
 
 Below is a complete listing of changes for each revision of HighLine.
 
+### 3.1.1 / 2024-08-18
+* PR #274 / I #273 (@costa)
+  * Add Highline#add_to_color_scheme
+  * Dockerize the test environment. Just run `bin/test` and voilá!
+
 ### 3.1.0 / 2024-07-15
 * PR #272 / I #271 - Readline is now completed deprecated over Reline (@abinoam, issue by @64kramsystem)
 * PR #269 - Provide a 'Changelog' link on rubygems.org/gems/highline (@mark-young-atg)
diff --git a/Gemfile b/Gemfile
--- a/Gemfile
+++ b/Gemfile
@@ -13,6 +13,7 @@ group :code_quality do
   gem "flog", require: false
   gem "pronto", require: false, platform: :ruby
   gem "pronto-flay", require: false, platform: :ruby
+  gem "path_expander", "1.1.1", require: false # Remove this lock when path_expander > 1.1.2 and flay > 2.13.3 is released.
   # gem "pronto-poper", require: false, platform: :ruby
   gem "pronto-reek", require: false, platform: :ruby
   gem "pronto-rubocop", require: false, platform: :ruby
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -206,6 +206,9 @@ Contributing
   - ```rake acceptance```
   - ```pronto run```
 
+  Alternatively, if you're in a [Docker](https://www.docker.com)ised environment,
+  don't care about installing anything locally -- just run `bin/test` instead.
+
 8. Commit your changes
   - ```git commit -am "Your commit message"```
 
diff --git a/lib/highline.rb b/lib/highline.rb
--- a/lib/highline.rb
+++ b/lib/highline.rb
@@ -61,6 +61,14 @@ def using_color_scheme?
       true if @color_scheme
     end
 
+    # Pass a +Hash+ to add +new+ colors to the current scheme.
+    def add_to_color_scheme(hash)
+      old_hash = (color_scheme || {}).to_hash
+      fail "Overlapping color schemes: #{old_hash.keys & hash.keys}"  unless
+        (old_hash.keys & hash.keys).empty?
+      self.color_scheme = ColorScheme.new(old_hash.merge hash)
+    end
+
     # Reset color scheme to default (+nil+)
     def reset_color_scheme
       self.color_scheme = nil
diff --git a/lib/highline/version.rb b/lib/highline/version.rb
--- a/lib/highline/version.rb
+++ b/lib/highline/version.rb
@@ -2,5 +2,5 @@
 
 class HighLine
   # The version of the installed library.
-  VERSION = "3.1.0".freeze
+  VERSION = "3.1.1".freeze
 end


Test patch:
diff --git a/bin/test b/bin/test
new file mode 100755
--- /dev/null
+++ b/bin/test
@@ -0,0 +1,11 @@
+#!/bin/bash -e
+test "$#" -ne 0 && echo "Unsupported args: $@" >&2 && exit 145
+cd "$( dirname "${BASH_SOURCE[0]}" )"/..
+
+export COMPOSE_FILE=test/docker-compose.yml
+export COMPOSE_PROJECT_NAME=highline_dev
+
+docker compose rm -svf
+docker compose build --force-rm
+
+docker compose run --rm tester && docker compose rm -svf || ( docker compose logs && exit 1 )
diff --git a/test/Dockerfile b/test/Dockerfile
new file mode 100644
--- /dev/null
+++ b/test/Dockerfile
@@ -0,0 +1,15 @@
+FROM ruby
+
+WORKDIR /highline
+
+
+RUN bash -ec 'apt update; apt -y install cmake'
+
+ADD Gemfile highline.gemspec .git* ./
+ADD lib/highline/version.rb ./lib/highline/version.rb
+RUN bundle install
+
+ADD . .
+
+ENTRYPOINT ["bundle", "exec"]
+CMD ["bash", "-ec", "rake test; rake acceptance; pronto run"]
diff --git a/test/docker-compose.yml b/test/docker-compose.yml
new file mode 100644
--- /dev/null
+++ b/test/docker-compose.yml
@@ -0,0 +1,5 @@
+services:
+  tester:
+    build:
+      context: ..
+      dockerfile: test/Dockerfile
diff --git a/test/test_color_scheme.rb b/test/test_color_scheme.rb
--- a/test/test_color_scheme.rb
+++ b/test/test_color_scheme.rb
@@ -51,6 +51,8 @@ def test_scheme
                     info debug row_even row_odd].sort,
                  HighLine.color_scheme.keys.sort
 
+    HighLine.add_to_color_scheme calming: [:blue]
+
     # Color scheme doesn't care if we use symbols or strings.
     # And it isn't case-sensitive
     warning1 = HighLine.color_scheme[:warning]
@@ -64,6 +66,7 @@ def test_scheme
     assert_equal warning1, warning2
     assert_equal warning1, warning3
     assert_equal warning1, warning4
+    assert_instance_of HighLine::Style, HighLine.color_scheme[:calming]
 
     # Nonexistent keys return nil
     assert_nil HighLine.color_scheme[:nonexistent]
@@ -81,18 +84,23 @@ def test_scheme
     assert_equal [:bold, :yellow], defn2
     assert_equal [:bold, :yellow], defn3
     assert_equal [:bold, :yellow], defn4
+    assert_equal [:blue], HighLine.color_scheme.definition(:calming)
     assert_nil HighLine.color_scheme.definition(:nonexistent)
 
     color_scheme_hash = HighLine.color_scheme.to_hash
     assert_instance_of Hash, color_scheme_hash
-    assert_equal %w[critical error warning notice
+    assert_equal %w[calming critical error warning notice
                     info debug row_even row_odd].sort,
                  color_scheme_hash.keys.sort
-    assert_instance_of Array, HighLine.color_scheme.definition(:warning)
-    assert_equal [:bold, :yellow], HighLine.color_scheme.definition(:warning)
+
+    # adding a color already present should raise an exception
+    assert_raises(StandardError) do
+      HighLine.add_to_color_scheme :critical, [:black]
+    end
 
     # turn it back off, should raise an exception
-    HighLine.color_scheme = nil
+    HighLine.reset_color_scheme
+    assert_nil HighLine.color_scheme
     assert_raises(NameError) do
       @terminal.say("This should be <%= color('nothing at all', :error) %>.")
     end