diff --git a/Library/Homebrew/cask/cmd/abstract_command.rb b/Library/Homebrew/cask/cmd/abstract_command.rb index 6690ae55a3..23e972087c 100644 --- a/Library/Homebrew/cask/cmd/abstract_command.rb +++ b/Library/Homebrew/cask/cmd/abstract_command.rb @@ -12,8 +12,6 @@ module Cask extend T::Sig extend T::Helpers - include Homebrew::Search - OPTIONS = [ [:switch, "--[no-]binaries", { description: "Disable/enable linking of helper executables (default: enabled).", @@ -87,7 +85,7 @@ module Cask end def suggestion_message(cask_token) - matches = search_casks(cask_token) + matches = Homebrew::Search.search_casks(cask_token) if matches.one? "Did you mean '#{matches.first}'?" diff --git a/Library/Homebrew/cmd/desc.rb b/Library/Homebrew/cmd/desc.rb index 46fff56915..b38a8ae11f 100644 --- a/Library/Homebrew/cmd/desc.rb +++ b/Library/Homebrew/cmd/desc.rb @@ -11,8 +11,6 @@ module Homebrew module_function - extend Search - sig { returns(CLI::Parser) } def desc_args Homebrew::CLI::Parser.new do @@ -71,23 +69,8 @@ module Homebrew Descriptions.new(desc).print else query = args.named.join(" ") - string_or_regex = query_regexp(query) - eval_all = args.eval_all? || Homebrew::EnvConfig.eval_all? - unless args.cask? - ohai "Formulae" - CacheStoreDatabase.use(:descriptions) do |db| - cache_store = DescriptionCacheStore.new(db) - Descriptions.search(string_or_regex, search_type, cache_store, eval_all).print - end - end - unless args.formula? - puts unless args.cask? - ohai "Casks" - CacheStoreDatabase.use(:cask_descriptions) do |db| - cache_store = CaskDescriptionCacheStore.new(db) - Descriptions.search(string_or_regex, search_type, cache_store, eval_all).print - end - end + string_or_regex = Search.query_regexp(query) + Search.search_descriptions(string_or_regex, args, search_type: search_type) end end end diff --git a/Library/Homebrew/cmd/install.rb b/Library/Homebrew/cmd/install.rb index 8dc6251c46..8a67db1249 100644 --- a/Library/Homebrew/cmd/install.rb +++ b/Library/Homebrew/cmd/install.rb @@ -8,7 +8,6 @@ require "missing_formula" require "formula_installer" require "development_tools" require "install" -require "search" require "cleanup" require "cli/parser" require "upgrade" @@ -16,8 +15,6 @@ require "upgrade" module Homebrew extend T::Sig - extend Search - module_function sig { returns(CLI::Parser) } @@ -299,11 +296,12 @@ module Homebrew # so we might as well return early. return if name.include?("/") + require "search" ohai "Searching for similarly named formulae and casks..." # Don't treat formula/cask name as a regex query = string_or_regex = name - all_formulae, all_casks = search_names(query, string_or_regex, args) + all_formulae, all_casks = Search.search_names(query, string_or_regex, args) if all_formulae.any? ohai "Formulae", Formatter.columns(all_formulae) diff --git a/Library/Homebrew/cmd/search.rb b/Library/Homebrew/cmd/search.rb index bc0e6d01b1..ba56e35d74 100644 --- a/Library/Homebrew/cmd/search.rb +++ b/Library/Homebrew/cmd/search.rb @@ -12,8 +12,6 @@ module Homebrew module_function - extend Search - PACKAGE_MANAGERS = { repology: ->(query) { "https://repology.org/projects/?search=#{query}" }, macports: ->(query) { "https://ports.macports.org/search/?q=#{query}" }, @@ -76,17 +74,17 @@ module Homebrew return if search_package_manager(args) query = args.named.join(" ") - string_or_regex = query_regexp(query) + string_or_regex = Search.query_regexp(query) if args.desc? if !args.eval_all? && !Homebrew::EnvConfig.eval_all? odeprecated "brew search --desc", "brew search --desc --eval-all or HOMEBREW_EVAL_ALL" end - search_descriptions(string_or_regex, args) + Search.search_descriptions(string_or_regex, args) elsif args.pull_request? search_pull_requests(query, args) else - formulae, casks = search_names(query, string_or_regex, args) + formulae, casks = Search.search_names(query, string_or_regex, args) print_results(formulae, casks, query) end diff --git a/Library/Homebrew/descriptions.rb b/Library/Homebrew/descriptions.rb index 9382bc2107..ff252b5798 100644 --- a/Library/Homebrew/descriptions.rb +++ b/Library/Homebrew/descriptions.rb @@ -3,15 +3,12 @@ require "formula" require "formula_versions" -require "search" require "searchable" # Helper class for printing and searching descriptions. # # @api private class Descriptions - extend Homebrew::Search - # Given a regex, find all formulae whose specified fields contain a match. def self.search(string_or_regex, field, cache_store, eval_all = Homebrew::EnvConfig.eval_all?) cache_store.populate_if_empty!(eval_all: eval_all) diff --git a/Library/Homebrew/extend/os/mac/search.rb b/Library/Homebrew/extend/os/mac/search.rb deleted file mode 100644 index 5901ac74ba..0000000000 --- a/Library/Homebrew/extend/os/mac/search.rb +++ /dev/null @@ -1,56 +0,0 @@ -# typed: false -# frozen_string_literal: true - -require "cask/cask" -require "cask/cask_loader" - -module Homebrew - module Search - module Extension - def search_descriptions(string_or_regex, args) - super - - return if args.formula? - - puts unless args.cask? - ohai "Casks" - CacheStoreDatabase.use(:cask_descriptions) do |db| - cache_store = CaskDescriptionCacheStore.new(db) - eval_all = args.eval_all? || Homebrew::EnvConfig.eval_all? - Descriptions.search(string_or_regex, :desc, cache_store, eval_all).print - end - end - - def search_casks(string_or_regex) - if string_or_regex.is_a?(String) && string_or_regex.match?(HOMEBREW_TAP_CASK_REGEX) - return begin - [Cask::CaskLoader.load(string_or_regex).token] - rescue Cask::CaskUnavailableError - [] - end - end - - cask_tokens = Tap.flat_map(&:cask_tokens).map do |c| - c.sub(%r{^homebrew/cask.*/}, "") - end - - results = cask_tokens.extend(Searchable) - .search(string_or_regex) - - results += DidYouMean::SpellChecker.new(dictionary: cask_tokens) - .correct(string_or_regex) - - results.sort.map do |name| - cask = Cask::CaskLoader.load(name) - if cask.installed? - pretty_installed(cask.full_name) - else - cask.full_name - end - end.uniq - end - end - - prepend Extension - end -end diff --git a/Library/Homebrew/extend/os/search.rb b/Library/Homebrew/extend/os/search.rb deleted file mode 100644 index 96e7ff28ec..0000000000 --- a/Library/Homebrew/extend/os/search.rb +++ /dev/null @@ -1,4 +0,0 @@ -# typed: strict -# frozen_string_literal: true - -require "extend/os/mac/search" if OS.mac? diff --git a/Library/Homebrew/search.rb b/Library/Homebrew/search.rb index 674e956b40..632ab6e3c2 100644 --- a/Library/Homebrew/search.rb +++ b/Library/Homebrew/search.rb @@ -9,6 +9,8 @@ module Homebrew # # @api private module Search + module_function + def query_regexp(query) if (m = query.match(%r{^/(.*)/$})) Regexp.new(m[1]) @@ -19,14 +21,25 @@ module Homebrew raise "#{query} is not a valid regex." end - def search_descriptions(string_or_regex, args) - return if args.cask? + def search_descriptions(string_or_regex, args, search_type: :desc) + both = !args.formula? && !args.cask? + eval_all = args.eval_all? || Homebrew::EnvConfig.eval_all? - ohai "Formulae" - CacheStoreDatabase.use(:descriptions) do |db| - cache_store = DescriptionCacheStore.new(db) - eval_all = args.eval_all? || Homebrew::EnvConfig.eval_all? - Descriptions.search(string_or_regex, :desc, cache_store, eval_all).print + if args.formula? || both + ohai "Formulae" + CacheStoreDatabase.use(:descriptions) do |db| + cache_store = DescriptionCacheStore.new(db) + Descriptions.search(string_or_regex, search_type, cache_store, eval_all).print + end + end + return if !args.cask? && !both + + puts if both + + ohai "Casks" + CacheStoreDatabase.use(:cask_descriptions) do |db| + cache_store = CaskDescriptionCacheStore.new(db) + Descriptions.search(string_or_regex, search_type, cache_store, eval_all).print end end @@ -111,8 +124,33 @@ module Homebrew end.compact end - def search_casks(_string_or_regex) - [] + def search_casks(string_or_regex) + if string_or_regex.is_a?(String) && string_or_regex.match?(HOMEBREW_TAP_CASK_REGEX) + return begin + [Cask::CaskLoader.load(string_or_regex).token] + rescue Cask::CaskUnavailableError + [] + end + end + + cask_tokens = Tap.flat_map(&:cask_tokens).map do |c| + c.sub(%r{^homebrew/cask.*/}, "") + end + + results = cask_tokens.extend(Searchable) + .search(string_or_regex) + + results += DidYouMean::SpellChecker.new(dictionary: cask_tokens) + .correct(string_or_regex) + + results.sort.map do |name| + cask = Cask::CaskLoader.load(name) + if cask.installed? + pretty_installed(cask.full_name) + else + cask.full_name + end + end.uniq end def search_names(query, string_or_regex, args) @@ -136,5 +174,3 @@ module Homebrew end end end - -require "extend/os/search" diff --git a/Library/Homebrew/test/search_spec.rb b/Library/Homebrew/test/search_spec.rb index 56949f2340..ef3f383919 100644 --- a/Library/Homebrew/test/search_spec.rb +++ b/Library/Homebrew/test/search_spec.rb @@ -4,12 +4,6 @@ require "search" describe Homebrew::Search do - subject(:mod) { Object.new } - - before do - mod.extend(described_class) - end - describe "#search_taps" do before do ENV.delete("HOMEBREW_NO_GITHUB_API") @@ -17,13 +11,13 @@ describe Homebrew::Search do it "does not raise if `HOMEBREW_NO_GITHUB_API` is set" do ENV["HOMEBREW_NO_GITHUB_API"] = "1" - expect(mod.search_taps("some-formula")).to match(formulae: [], casks: []) + expect(described_class.search_taps("some-formula")).to match(formulae: [], casks: []) end it "does not raise if the network fails" do allow(GitHub::API).to receive(:open_rest).and_raise(GitHub::API::Error) - expect(mod.search_taps("some-formula")) + expect(described_class.search_taps("some-formula")) .to match(formulae: [], casks: []) end @@ -47,22 +41,22 @@ describe Homebrew::Search do allow(GitHub::API).to receive(:open_rest).and_yield(json_response) - expect(mod.search_taps("some-formula")) + expect(described_class.search_taps("some-formula")) .to match(formulae: ["homebrew/foo/some-formula"], casks: ["homebrew/bar/some-cask"]) end end describe "#query_regexp" do it "correctly parses a regex query" do - expect(mod.query_regexp("/^query$/")).to eq(/^query$/) + expect(described_class.query_regexp("/^query$/")).to eq(/^query$/) end it "returns the original string if it is not a regex query" do - expect(mod.query_regexp("query")).to eq("query") + expect(described_class.query_regexp("query")).to eq("query") end it "raises an error if the query is an invalid regex" do - expect { mod.query_regexp("/+/") }.to raise_error(/not a valid regex/) + expect { described_class.query_regexp("/+/") }.to raise_error(/not a valid regex/) end end end