desc, search: also search cask descriptions

This commit is contained in:
EricFromCanada 2022-03-23 00:03:11 -04:00
parent 663c0a713a
commit 2fdc70c3bf
No known key found for this signature in database
GPG Key ID: 179D9CDDDB814168
17 changed files with 174 additions and 34 deletions

View File

@ -30,10 +30,14 @@ module Homebrew
switch "-d", "--description",
description: "Search just descriptions for <text>. If <text> is flanked by slashes, "\
"it is interpreted as a regular expression."
switch "--formula", "--formulae",
description: "Treat all named arguments as formulae."
switch "--cask", "--casks",
description: "Treat all named arguments as casks."
conflicts "--search", "--name", "--description"
named_args [:formula, :text_or_regex], min: 1
named_args [:formula, :cask, :text_or_regex], min: 1
end
end
@ -48,19 +52,35 @@ module Homebrew
:desc
end
results = if search_type.nil?
if search_type.blank?
desc = {}
args.named.to_formulae.each { |f| desc[f.full_name] = f.desc }
Descriptions.new(desc)
args.named.to_formulae_and_casks.each do |formula_or_cask|
if formula_or_cask.is_a? Formula
desc[formula_or_cask.full_name] = formula_or_cask.desc
else
description = formula_or_cask.desc.presence || Formatter.warning("[no description]")
desc[formula_or_cask.full_name] = "(#{formula_or_cask.name.join(", ")}) #{description}"
end
end
Descriptions.new(desc).print
else
query = args.named.join(" ")
string_or_regex = query_regexp(query)
CacheStoreDatabase.use(:descriptions) do |db|
cache_store = DescriptionCacheStore.new(db)
Descriptions.search(string_or_regex, search_type, cache_store)
unless args.cask?
ohai "Formulae"
CacheStoreDatabase.use(:descriptions) do |db|
cache_store = DescriptionCacheStore.new(db)
Descriptions.search(string_or_regex, search_type, cache_store).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).print
end
end
end
results.print
end
end

View File

@ -43,7 +43,7 @@ module Homebrew
description: "Search online and locally for casks."
switch "--desc",
description: "Search for formulae with a description matching <text> and casks with "\
"a name matching <text>."
"a name or description matching <text>."
switch "--pull-request",
description: "Search for GitHub pull requests containing <text>."
switch "--open",

View File

@ -197,6 +197,10 @@ module Homebrew
DescriptionCacheStore.new(db)
.update_from_report!(hub)
end
CacheStoreDatabase.use(:cask_descriptions) do |db|
CaskDescriptionCacheStore.new(db)
.update_from_report!(hub)
end
if !args.preinstall? && !args.quiet?
outdated_formulae = Formula.installed.count(&:outdated?)

View File

@ -6,8 +6,8 @@ require "cache_store"
require "searchable"
#
# {DescriptionCacheStore} provides methods to fetch and mutate linkage-specific data used
# by the `brew linkage` command.
# {DescriptionCacheStore} provides methods to fetch and mutate formula descriptions used
# by the `brew desc` and `brew search` commands.
#
class DescriptionCacheStore < CacheStore
include Searchable
@ -81,6 +81,7 @@ class DescriptionCacheStore < CacheStore
formula_names.each(&method(:delete!))
end
alias delete_from_cask_tokens! delete_from_formula_names!
private
@ -89,3 +90,49 @@ class DescriptionCacheStore < CacheStore
database.select(&block)
end
end
#
# {CaskDescriptionCacheStore} provides methods to fetch and mutate cask descriptions used
# by the `brew desc` and `brew search` commands.
#
class CaskDescriptionCacheStore < DescriptionCacheStore
# If the database is empty `update!` it with all known casks.
#
# @return [nil]
def populate_if_empty!
return unless database.empty?
# TODO: 3.6.0: consider if we want to actually read all contents of all casks or odeprecate.
Cask::Cask.all.each { |c| update!(c.full_name, [c.name.join(", "), c.desc.presence]) }
end
# Use an update report to update the {CaskDescriptionCacheStore}.
#
# @param report [Report] an update report generated by cmd/update.rb
# @return [nil]
def update_from_report!(report)
return populate_if_empty! if database.empty?
return if report.empty?
alterations = report.select_formula(:AC) +
report.select_formula(:MC)
update_from_cask_tokens!(alterations)
delete_from_cask_tokens!(report.select_formula(:DC))
end
# Use an array of cask tokens to update the {CaskDescriptionCacheStore}.
#
# @param cask_tokens [Array] the casks to update
# @return [nil]
def update_from_cask_tokens!(cask_tokens)
return populate_if_empty! if database.empty?
cask_tokens.each do |token|
c = Cask::CaskLoader.load(token)
update!(c.full_name, [c.name.join(", "), c.desc.presence])
rescue Cask::CaskUnavailableError, *FormulaVersions::IGNORED_EXCEPTIONS
delete!(c.full_name) if c.present?
end
end
end

View File

@ -45,7 +45,13 @@ class Descriptions
full_name
end
description = @descriptions[full_name] || blank
puts "#{Tty.bold}#{printed_name}:#{Tty.reset} #{description}"
if description.is_a?(Array)
names = description[0]
description = description[1] || blank
puts "#{Tty.bold}#{printed_name}:#{Tty.reset} (#{names}) #{description}"
else
puts "#{Tty.bold}#{printed_name}:#{Tty.reset} #{description}"
end
end
end

View File

@ -10,15 +10,13 @@ module Homebrew
def search_descriptions(string_or_regex, args)
super
puts
return if args.formula?
puts unless args.cask?
ohai "Casks"
Cask::Cask.all.extend(Searchable)
.search(string_or_regex, &:name)
.each do |cask|
puts "#{Tty.bold}#{cask.token}:#{Tty.reset} #{cask.name.join(", ")}"
CacheStoreDatabase.use(:cask_descriptions) do |db|
cache_store = CaskDescriptionCacheStore.new(db)
Descriptions.search(string_or_regex, :desc, cache_store).print
end
end
@ -42,9 +40,9 @@ module Homebrew
results.sort.map do |name|
cask = Cask::CaskLoader.load(name)
if cask.installed?
pretty_installed(cask.token)
pretty_installed(cask.full_name)
else
cask.token
cask.full_name
end
end
end

View File

@ -1759,7 +1759,7 @@ class Formula
@aliases ||= (core_aliases + tap_aliases.map { |name| name.split("/").last }).uniq.sort
end
# an array of all aliases, , which the tap formulae have the fully-qualified name
# an array of all aliases as fully-qualified names
# @private
def self.alias_full_names
@alias_full_names ||= core_aliases + tap_aliases

View File

@ -89,7 +89,7 @@ module Homebrew
.search(string_or_regex)
.sort
results |= Formula.fuzzy_search(string_or_regex)
results |= Formula.fuzzy_search(string_or_regex).map { |n| Formulary.factory(n).full_name }
results.map do |name|
formula, canonical_full_name = begin

View File

@ -32,7 +32,7 @@ module Searchable
simplified_string = simplify_string(string)
select do |*args|
args = yield(*args) if block_given?
args = Array(args).compact
args = Array(args).flatten.compact
args.any? { |arg| simplify_string(arg).include?(simplified_string) }
end
end

View File

@ -330,6 +330,10 @@ class Tap
DescriptionCacheStore.new(db)
.update_from_formula_names!(formula_names)
end
CacheStoreDatabase.use(:cask_descriptions) do |db|
CaskDescriptionCacheStore.new(db)
.update_from_cask_tokens!(cask_tokens)
end
if official?
untapped = self.class.untapped_official_taps
@ -411,6 +415,10 @@ class Tap
DescriptionCacheStore.new(db)
.delete_from_formula_names!(formula_names)
end
CacheStoreDatabase.use(:cask_descriptions) do |db|
CaskDescriptionCacheStore.new(db)
.delete_from_cask_tokens!(cask_tokens)
end
Utils::Link.unlink_manpages(path)
Utils::Link.unlink_completions(path)
path.rmtree

View File

@ -53,4 +53,34 @@ describe DescriptionCacheStore do
cache_store.delete_from_formula_names!([formula_name])
end
end
describe CaskDescriptionCacheStore do
subject(:cache_store) { described_class.new(database) }
let(:database) { double("database") }
describe "#update_from_report!" do
let(:report) { double(select_formula: [], empty?: false) }
it "reads from the report" do
expect(database).to receive(:empty?).at_least(:once).and_return(false)
cache_store.update_from_report!(report)
end
end
describe "#update_from_cask_tokens!" do
it "sets the cask descriptions" do
c = Cask::Cask.new("cask-names-desc") do
url "url-1"
name "Name 1"
name "Name 2"
desc "description"
end
expect(Cask::CaskLoader).to receive(:load).with("cask-names-desc", any_args).and_return(c)
expect(database).to receive(:empty?).and_return(false)
expect(database).to receive(:set).with(c.full_name, [c.name.join(", "), c.desc.presence])
cache_store.update_from_cask_tokens!([c.token])
end
end
end
end

View File

@ -43,4 +43,9 @@ describe Descriptions do
EOS
).to_stdout
end
it "can print description for a cask" do
descriptions_hash["homebrew/cask/foo"] = ["Foo", "Cask foo"]
expect { descriptions.print }.to output("foo: (Foo) Cask foo\n").to_stdout
end
end

View File

@ -741,8 +741,10 @@ _brew_desc() {
case "${cur}" in
-*)
__brewcomp "
--cask
--debug
--description
--formula
--help
--name
--quiet
@ -754,6 +756,7 @@ _brew_desc() {
*)
esac
__brew_complete_formulae
__brew_complete_casks
}
_brew_developer() {

View File

@ -279,7 +279,7 @@ __fish_brew_complete_arg '-S' -l cask -d 'Search online and locally for casks'
__fish_brew_complete_arg '-S' -l closed -d 'Search for only closed GitHub pull requests'
__fish_brew_complete_arg '-S' -l debian -d 'Search for text in the given database'
__fish_brew_complete_arg '-S' -l debug -d 'Display any debugging information'
__fish_brew_complete_arg '-S' -l desc -d 'Search for formulae with a description matching text and casks with a name matching text'
__fish_brew_complete_arg '-S' -l desc -d 'Search for formulae with a description matching text and casks with a name or description matching text'
__fish_brew_complete_arg '-S' -l fedora -d 'Search for text in the given database'
__fish_brew_complete_arg '-S' -l fink -d 'Search for text in the given database'
__fish_brew_complete_arg '-S' -l formula -d 'Search online and locally for formulae'
@ -578,14 +578,17 @@ __fish_brew_complete_arg 'deps; and not __fish_seen_argument -l formula -l formu
__fish_brew_complete_cmd 'desc' 'Display formula\'s name and one-line description'
__fish_brew_complete_arg 'desc' -l cask -d 'Treat all named arguments as casks'
__fish_brew_complete_arg 'desc' -l debug -d 'Display any debugging information'
__fish_brew_complete_arg 'desc' -l description -d 'Search just descriptions for text. If text is flanked by slashes, it is interpreted as a regular expression'
__fish_brew_complete_arg 'desc' -l formula -d 'Treat all named arguments as formulae'
__fish_brew_complete_arg 'desc' -l help -d 'Show this message'
__fish_brew_complete_arg 'desc' -l name -d 'Search just names for text. If text is flanked by slashes, it is interpreted as a regular expression'
__fish_brew_complete_arg 'desc' -l quiet -d 'Make some output more quiet'
__fish_brew_complete_arg 'desc' -l search -d 'Search both names and descriptions for text. If text is flanked by slashes, it is interpreted as a regular expression'
__fish_brew_complete_arg 'desc' -l verbose -d 'Make some output more verbose'
__fish_brew_complete_arg 'desc' -a '(__fish_brew_suggest_formulae_all)'
__fish_brew_complete_arg 'desc; and not __fish_seen_argument -l cask -l casks' -a '(__fish_brew_suggest_formulae_all)'
__fish_brew_complete_arg 'desc; and not __fish_seen_argument -l formula -l formulae' -a '(__fish_brew_suggest_casks_all)'
__fish_brew_complete_cmd 'developer' 'Control Homebrew\'s developer mode'
@ -1240,7 +1243,7 @@ __fish_brew_complete_arg 'search' -l cask -d 'Search online and locally for cask
__fish_brew_complete_arg 'search' -l closed -d 'Search for only closed GitHub pull requests'
__fish_brew_complete_arg 'search' -l debian -d 'Search for text in the given database'
__fish_brew_complete_arg 'search' -l debug -d 'Display any debugging information'
__fish_brew_complete_arg 'search' -l desc -d 'Search for formulae with a description matching text and casks with a name matching text'
__fish_brew_complete_arg 'search' -l desc -d 'Search for formulae with a description matching text and casks with a name or description matching text'
__fish_brew_complete_arg 'search' -l fedora -d 'Search for text in the given database'
__fish_brew_complete_arg 'search' -l fink -d 'Search for text in the given database'
__fish_brew_complete_arg 'search' -l formula -d 'Search online and locally for formulae'

View File

@ -354,7 +354,7 @@ _brew__s() {
'(--open)--closed[Search for only closed GitHub pull requests]' \
'(--repology --macports --fink --opensuse --fedora --archlinux --ubuntu)--debian[Search for text in the given database]' \
'--debug[Display any debugging information]' \
'(--pull-request)--desc[Search for formulae with a description matching text and casks with a name matching text]' \
'(--pull-request)--desc[Search for formulae with a description matching text and casks with a name or description matching text]' \
'(--repology --macports --fink --opensuse --archlinux --debian --ubuntu)--fedora[Search for text in the given database]' \
'(--repology --macports --opensuse --fedora --archlinux --debian --ubuntu)--fink[Search for text in the given database]' \
'--formula[Search online and locally for formulae]' \
@ -717,7 +717,11 @@ _brew_desc() {
'(--name --description)--search[Search both names and descriptions for text. If text is flanked by slashes, it is interpreted as a regular expression]' \
'--verbose[Make some output more verbose]' \
- formula \
'*::formula:__brew_formulae'
'--formula[Treat all named arguments as formulae]' \
'*::formula:__brew_formulae' \
- cask \
'--cask[Treat all named arguments as casks]' \
'*::cask:__brew_casks'
}
# brew developer
@ -1513,7 +1517,7 @@ _brew_search() {
'(--open)--closed[Search for only closed GitHub pull requests]' \
'(--repology --macports --fink --opensuse --fedora --archlinux --ubuntu)--debian[Search for text in the given database]' \
'--debug[Display any debugging information]' \
'(--pull-request)--desc[Search for formulae with a description matching text and casks with a name matching text]' \
'(--pull-request)--desc[Search for formulae with a description matching text and casks with a name or description matching text]' \
'(--repology --macports --fink --opensuse --archlinux --debian --ubuntu)--fedora[Search for text in the given database]' \
'(--repology --macports --opensuse --fedora --archlinux --debian --ubuntu)--fink[Search for text in the given database]' \
'--formula[Search online and locally for formulae]' \

View File

@ -177,7 +177,7 @@ show the intersection of dependencies for each formula.
* `--cask`:
Treat all named arguments as casks.
### `desc` [*`options`*] *`formula`*|*`text`*|`/`*`regex`*`/` [...]
### `desc` [*`options`*] *`formula`*|*`cask`*|*`text`*|`/`*`regex`*`/` [...]
Display *`formula`*'s name and one-line description.
Formula descriptions are cached; the cache is created on the
@ -189,6 +189,10 @@ first search, making that search slower than subsequent ones.
Search just names for *`text`*. If *`text`* is flanked by slashes, it is interpreted as a regular expression.
* `-d`, `--description`:
Search just descriptions for *`text`*. If *`text`* is flanked by slashes, it is interpreted as a regular expression.
* `--formula`:
Treat all named arguments as formulae.
* `--cask`:
Treat all named arguments as casks.
### `developer` [*`subcommand`*]
@ -563,7 +567,7 @@ The search for *`text`* is extended online to `homebrew/core` and `homebrew/cask
* `--cask`:
Search online and locally for casks.
* `--desc`:
Search for formulae with a description matching *`text`* and casks with a name matching *`text`*.
Search for formulae with a description matching *`text`* and casks with a name or description matching *`text`*.
* `--pull-request`:
Search for GitHub pull requests containing *`text`*.
* `--open`:

View File

@ -225,7 +225,7 @@ Treat all named arguments as formulae\.
\fB\-\-cask\fR
Treat all named arguments as casks\.
.
.SS "\fBdesc\fR [\fIoptions\fR] \fIformula\fR|\fItext\fR|\fB/\fR\fIregex\fR\fB/\fR [\.\.\.]"
.SS "\fBdesc\fR [\fIoptions\fR] \fIformula\fR|\fIcask\fR|\fItext\fR|\fB/\fR\fIregex\fR\fB/\fR [\.\.\.]"
Display \fIformula\fR\'s name and one\-line description\. Formula descriptions are cached; the cache is created on the first search, making that search slower than subsequent ones\.
.
.TP
@ -240,6 +240,14 @@ Search just names for \fItext\fR\. If \fItext\fR is flanked by slashes, it is in
\fB\-d\fR, \fB\-\-description\fR
Search just descriptions for \fItext\fR\. If \fItext\fR is flanked by slashes, it is interpreted as a regular expression\.
.
.TP
\fB\-\-formula\fR
Treat all named arguments as formulae\.
.
.TP
\fB\-\-cask\fR
Treat all named arguments as casks\.
.
.SS "\fBdeveloper\fR [\fIsubcommand\fR]"
Control Homebrew\'s developer mode\. When developer mode is enabled, \fBbrew update\fR will update Homebrew to the latest commit on the \fBmaster\fR branch instead of the latest stable version along with some other behaviour changes\.
.
@ -778,7 +786,7 @@ Search online and locally for casks\.
.
.TP
\fB\-\-desc\fR
Search for formulae with a description matching \fItext\fR and casks with a name matching \fItext\fR\.
Search for formulae with a description matching \fItext\fR and casks with a name or description matching \fItext\fR\.
.
.TP
\fB\-\-pull\-request\fR