diff --git a/Library/Homebrew/extend/array.rb b/Library/Homebrew/extend/array.rb new file mode 100644 index 0000000000..1d91c99b52 --- /dev/null +++ b/Library/Homebrew/extend/array.rb @@ -0,0 +1,42 @@ +# typed: true +# frozen_string_literal: true + +class Array + # Converts the array to a comma-separated sentence where the last element is + # joined by the connector word. + # + # You can pass the following kwargs to change the default behavior: + # + # * :words_connector - The sign or word used to join all but the last + # element in arrays with three or more elements (default: ", "). + # * :last_word_connector - The sign or word used to join the last element + # in arrays with three or more elements (default: ", and "). + # * :two_words_connector - The sign or word used to join the elements + # in arrays with two elements (default: " and "). + # + # ==== Examples + # + # [].to_sentence # => "" + # ['one'].to_sentence # => "one" + # ['one', 'two'].to_sentence # => "one and two" + # ['one', 'two', 'three'].to_sentence # => "one, two, and three" + # ['one', 'two'].to_sentence(two_words_connector: '-') + # # => "one-two" + # + # ['one', 'two', 'three'].to_sentence(words_connector: ' or ', last_word_connector: ' or at least ') + # # => "one or two or at least three" + # @see https://github.com/rails/rails/blob/v7.0.4.2/activesupport/lib/active_support/core_ext/array/conversions.rb#L8-L84 + # ActiveSupport Array#to_sentence monkey-patch + def to_sentence(words_connector: ", ", two_words_connector: " and ", last_word_connector: ", and ") + case length + when 0 + +"" + when 1 + +(self[0]).to_s + when 2 + +"#{self[0]}#{two_words_connector}#{self[1]}" + else + +"#{self[0...-1].join(words_connector)}#{last_word_connector}#{self[-1]}" + end + end +end diff --git a/Library/Homebrew/global.rb b/Library/Homebrew/global.rb index fb3d785efa..9666251ced 100644 --- a/Library/Homebrew/global.rb +++ b/Library/Homebrew/global.rb @@ -133,6 +133,7 @@ module Homebrew end require "context" +require "extend/array" require "extend/git_repository" require "extend/pathname" require "extend/predicable" diff --git a/Library/Homebrew/rubocops/all.rb b/Library/Homebrew/rubocops/all.rb index ba9442d61c..ec0fe92957 100644 --- a/Library/Homebrew/rubocops/all.rb +++ b/Library/Homebrew/rubocops/all.rb @@ -1,9 +1,7 @@ # typed: strict # frozen_string_literal: true -# TODO: remove this (and avoid further active support in rubocops) -require "active_support/core_ext/array/conversions" - +require_relative "../extend/array" require_relative "io_read" require_relative "move_to_extend_os" require_relative "shell_commands" diff --git a/Library/Homebrew/test/extend/array_spec.rb b/Library/Homebrew/test/extend/array_spec.rb new file mode 100644 index 0000000000..6654b23a69 --- /dev/null +++ b/Library/Homebrew/test/extend/array_spec.rb @@ -0,0 +1,51 @@ +# typed: false +# frozen_string_literal: true + +require "extend/array" + +describe Array do + describe ".to_sentence" do + it "converts a plain array to a sentence" do + expect([].to_sentence).to eq("") + expect(["one"].to_sentence).to eq("one") + expect(["one", "two"].to_sentence).to eq("one and two") + expect(["one", "two", "three"].to_sentence).to eq("one, two, and three") + end + + it "converts an array to a sentence with a custom connector" do + expect(["one", "two", "three"].to_sentence(words_connector: " ")).to eq("one two, and three") + expect(["one", "two", "three"].to_sentence(words_connector: " & ")).to eq("one & two, and three") + end + + it "converts an array to a sentence with a custom last word connector" do + expect(["one", "two", "three"].to_sentence(last_word_connector: ", and also ")) + .to eq("one, two, and also three") + expect(["one", "two", "three"].to_sentence(last_word_connector: " ")).to eq("one, two three") + expect(["one", "two", "three"].to_sentence(last_word_connector: " and ")).to eq("one, two and three") + end + + it "converts an array to a sentence with a custom two word connector" do + expect(["one", "two"].to_sentence(two_words_connector: " ")).to eq("one two") + end + + it "creates a new string" do + elements = ["one"] + expect(elements.to_sentence.object_id).not_to eq(elements[0].object_id) + end + + it "converts a non-String to a sentence" do + expect([1].to_sentence).to eq("1") + end + + it "converts an array with blank elements to a sentence" do + expect([nil, "one", "", "two", "three"].to_sentence).to eq(", one, , two, and three") + end + + it "does not return a frozen string" do + expect([""].to_sentence).not_to be_frozen + expect(["one"].to_sentence).not_to be_frozen + expect(["one", "two"].to_sentence).not_to be_frozen + expect(["one", "two", "three"].to_sentence).not_to be_frozen + end + end +end diff --git a/Library/Homebrew/test/utils_spec.rb b/Library/Homebrew/test/utils_spec.rb index 551f7d9c78..c75d21bed8 100644 --- a/Library/Homebrew/test/utils_spec.rb +++ b/Library/Homebrew/test/utils_spec.rb @@ -58,51 +58,4 @@ describe Utils do expect(described_class.pluralize("foo", 2, singular: "o", plural: "es")).to eq("fooes") end end - - describe ".to_sentence" do - it "converts a plain array to a sentence" do - expect(described_class.to_sentence([])).to eq("") - expect(described_class.to_sentence(["one"])).to eq("one") - expect(described_class.to_sentence(["one", "two"])).to eq("one and two") - expect(described_class.to_sentence(["one", "two", "three"])).to eq("one, two, and three") - end - - it "converts an array to a sentence with a custom connector" do - expect(described_class.to_sentence(["one", "two", "three"], words_connector: " ")).to eq("one two, and three") - expect(described_class.to_sentence(["one", "two", "three"], - words_connector: " & ")).to eq("one & two, and three") - end - - it "converts an array to a sentence with a custom last word connector" do - expect(described_class.to_sentence(["one", "two", "three"], - last_word_connector: ", and also ")).to eq("one, two, and also three") - expect(described_class.to_sentence(["one", "two", "three"], last_word_connector: " ")).to eq("one, two three") - expect(described_class.to_sentence(["one", "two", "three"], - last_word_connector: " and ")).to eq("one, two and three") - end - - it "converts an array to a sentence with a custom two word connector" do - expect(described_class.to_sentence(["one", "two"], two_words_connector: " ")).to eq("one two") - end - - it "creates a new string" do - elements = ["one"] - expect(described_class.to_sentence(elements).object_id).not_to eq(elements[0].object_id) - end - - it "converts a non-String to a sentence" do - expect(described_class.to_sentence([1])).to eq("1") - end - - it "converts an array with blank elements to a sentence" do - expect(described_class.to_sentence([nil, "one", "", "two", "three"])).to eq(", one, , two, and three") - end - - it "does not return a frozen string" do - expect(described_class.to_sentence([])).not_to be_frozen - expect(described_class.to_sentence(["one"])).not_to be_frozen - expect(described_class.to_sentence(["one", "two"])).not_to be_frozen - expect(described_class.to_sentence(["one", "two", "three"])).not_to be_frozen - end - end end