mirror of
https://github.com/Homebrew/brew.git
synced 2025-07-14 16:09:03 +08:00

Modify parser.rb to add a colon between each term and the line break, which `ronn` converts into a definition list. The <br> that follows ensures each term description is on a new line in the manpage output, and also replaces the double trailing space for generating the hard return that follows each term in the HTML output. Also modify man.rb to print environment variables with list markup matching the cask commands, and then drop trailing colons from both lists of terms (cask commands, env vars) and non-list terms (analytics, bundle, services; a <br> is added here because it would prevent the term description from being indented in the manpage output). https://docs.brew.sh/Manpage#cask-command-options-cask
269 lines
6.5 KiB
Ruby
269 lines
6.5 KiB
Ruby
# typed: false
|
|
# frozen_string_literal: true
|
|
|
|
require "optparse"
|
|
require "shellwords"
|
|
|
|
require "cli/parser"
|
|
require "extend/optparse"
|
|
|
|
require "cask/config"
|
|
|
|
require "cask/cmd/abstract_command"
|
|
require "cask/cmd/--cache"
|
|
require "cask/cmd/audit"
|
|
require "cask/cmd/cat"
|
|
require "cask/cmd/create"
|
|
require "cask/cmd/doctor"
|
|
require "cask/cmd/edit"
|
|
require "cask/cmd/fetch"
|
|
require "cask/cmd/help"
|
|
require "cask/cmd/home"
|
|
require "cask/cmd/info"
|
|
require "cask/cmd/install"
|
|
require "cask/cmd/list"
|
|
require "cask/cmd/outdated"
|
|
require "cask/cmd/reinstall"
|
|
require "cask/cmd/style"
|
|
require "cask/cmd/uninstall"
|
|
require "cask/cmd/upgrade"
|
|
require "cask/cmd/zap"
|
|
|
|
require "cask/cmd/abstract_internal_command"
|
|
require "cask/cmd/internal_help"
|
|
require "cask/cmd/internal_stanza"
|
|
|
|
module Cask
|
|
# Implementation of the `brew cask` command-line interface.
|
|
#
|
|
# @api private
|
|
class Cmd
|
|
extend T::Sig
|
|
|
|
include Context
|
|
|
|
ALIASES = {
|
|
"ls" => "list",
|
|
"homepage" => "home",
|
|
"instal" => "install", # gem does the same
|
|
"uninstal" => "uninstall",
|
|
"rm" => "uninstall",
|
|
"remove" => "uninstall",
|
|
"abv" => "info",
|
|
"dr" => "doctor",
|
|
}.freeze
|
|
|
|
DEPRECATED_COMMANDS = {
|
|
Cmd::Cache => "brew --cache --cask",
|
|
Cmd::Doctor => "brew doctor --verbose",
|
|
Cmd::Home => "brew home",
|
|
Cmd::List => "brew list --cask",
|
|
Cmd::Outdated => "brew outdated --cask",
|
|
Cmd::Reinstall => "brew reinstall",
|
|
Cmd::Upgrade => "brew upgrade --cask",
|
|
}.freeze
|
|
|
|
sig { returns(String) }
|
|
def self.description
|
|
max_command_length = Cmd.commands.map(&:length).max
|
|
|
|
command_lines = Cmd.command_classes
|
|
.select(&:visible?)
|
|
.map do |klass|
|
|
" - #{"`#{klass.command_name}`".ljust(max_command_length + 2)} #{klass.short_description}\n"
|
|
end
|
|
|
|
<<~EOS
|
|
Homebrew Cask provides a friendly CLI workflow for the administration of macOS applications distributed as binaries.
|
|
|
|
Commands:
|
|
#{command_lines.join}
|
|
See also: `man brew`
|
|
EOS
|
|
end
|
|
|
|
def self.parser(&block)
|
|
Homebrew::CLI::Parser.new do
|
|
if block_given?
|
|
instance_eval(&block)
|
|
else
|
|
usage_banner <<~EOS
|
|
`cask` <command> [<options>] [<cask>]
|
|
|
|
#{Cmd.description}
|
|
EOS
|
|
end
|
|
|
|
cask_options
|
|
end
|
|
end
|
|
|
|
def self.command_classes
|
|
@command_classes ||= constants.map(&method(:const_get))
|
|
.select { |klass| klass.is_a?(Class) && klass < AbstractCommand }
|
|
.reject(&:abstract?)
|
|
.sort_by(&:command_name)
|
|
end
|
|
|
|
def self.commands
|
|
@commands ||= command_classes.map(&:command_name)
|
|
end
|
|
|
|
def self.lookup_command(command_name)
|
|
@lookup ||= Hash[commands.zip(command_classes)]
|
|
command_name = ALIASES.fetch(command_name, command_name)
|
|
@lookup.fetch(command_name, nil)
|
|
end
|
|
|
|
def self.aliases
|
|
ALIASES
|
|
end
|
|
|
|
def self.run(*args)
|
|
new(*args).run
|
|
end
|
|
|
|
def initialize(*args)
|
|
@argv = args
|
|
end
|
|
|
|
def find_external_command(command)
|
|
@tap_cmd_directories ||= Tap.cmd_directories
|
|
@path ||= PATH.new(@tap_cmd_directories, ENV["HOMEBREW_PATH"])
|
|
|
|
external_ruby_cmd = @tap_cmd_directories.map { |d| d/"brewcask-#{command}.rb" }
|
|
.find(&:file?)
|
|
external_ruby_cmd ||= which("brewcask-#{command}.rb", @path)
|
|
|
|
if external_ruby_cmd
|
|
ExternalRubyCommand.new(command, external_ruby_cmd)
|
|
elsif external_command = which("brewcask-#{command}", @path)
|
|
ExternalCommand.new(external_command)
|
|
end
|
|
end
|
|
|
|
def detect_internal_command(*args)
|
|
args.each_with_index do |arg, i|
|
|
if command = self.class.lookup_command(arg)
|
|
args.delete_at(i)
|
|
return [command, args]
|
|
elsif !arg.start_with?("-")
|
|
break
|
|
end
|
|
end
|
|
|
|
nil
|
|
end
|
|
|
|
def detect_external_command(*args)
|
|
args.each_with_index do |arg, i|
|
|
if command = find_external_command(arg)
|
|
args.delete_at(i)
|
|
return [command, args]
|
|
elsif !arg.start_with?("-")
|
|
break
|
|
end
|
|
end
|
|
|
|
nil
|
|
end
|
|
|
|
def run
|
|
argv = @argv
|
|
|
|
args = self.class.parser.parse(argv, ignore_invalid_options: true)
|
|
|
|
Tap.default_cask_tap.install unless Tap.default_cask_tap.installed?
|
|
|
|
command, argv = detect_internal_command(*argv) ||
|
|
detect_external_command(*argv) ||
|
|
[args.remaining.empty? ? NullCommand : UnknownSubcommand.new(args.remaining.first), argv]
|
|
|
|
if (replacement = DEPRECATED_COMMANDS[command])
|
|
odeprecated "brew cask #{command.command_name}", replacement
|
|
end
|
|
|
|
if args.help?
|
|
puts command.help
|
|
else
|
|
command.run(*argv)
|
|
end
|
|
rescue CaskError, MethodDeprecatedError, ArgumentError => e
|
|
onoe e.message
|
|
$stderr.puts e.backtrace if args.debug?
|
|
exit 1
|
|
end
|
|
|
|
# Wrapper class for running an external Ruby command.
|
|
class ExternalRubyCommand
|
|
def initialize(command, path)
|
|
@command_name = command.to_s.capitalize.to_sym
|
|
@path = path
|
|
end
|
|
|
|
def run(*args)
|
|
command_class&.run(*args)
|
|
end
|
|
|
|
def help
|
|
command_class&.help
|
|
end
|
|
|
|
private
|
|
|
|
def command_class
|
|
return @command_class if defined?(@command_class)
|
|
|
|
require @path
|
|
|
|
@command_class = begin
|
|
Cmd.const_get(@command_name)
|
|
rescue NameError
|
|
nil
|
|
end
|
|
end
|
|
end
|
|
|
|
# Wrapper class for running an external command.
|
|
class ExternalCommand
|
|
def initialize(path)
|
|
@path = path
|
|
end
|
|
|
|
def run(*argv)
|
|
exec @path, *argv
|
|
end
|
|
|
|
def help
|
|
exec @path, "--help"
|
|
end
|
|
end
|
|
|
|
# Helper class for showing help for unknown subcommands.
|
|
class UnknownSubcommand
|
|
def initialize(command_name)
|
|
@command_name = command_name
|
|
end
|
|
|
|
def run(*)
|
|
raise UsageError, "Subcommand `#{@command_name}` does not exist."
|
|
end
|
|
|
|
def help
|
|
run
|
|
end
|
|
end
|
|
|
|
# Helper class for showing help when no subcommand is given.
|
|
class NullCommand
|
|
def self.run(*)
|
|
raise UsageError, "No subcommand given."
|
|
end
|
|
|
|
def self.help
|
|
Cmd.parser.generate_help_text
|
|
end
|
|
end
|
|
end
|
|
end
|