EricFromCanada eb16624c5f manpage: reformat lists of subcommands & env vars
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
2020-11-16 07:56:50 -05:00

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