brew/Library/Homebrew/abstract_command.rb

50 lines
1.6 KiB
Ruby
Raw Normal View History

2024-03-03 15:32:30 -08:00
# typed: strong
# frozen_string_literal: true
module Homebrew
2024-03-05 10:40:02 -08:00
# Subclass this to implement a `brew` command. This is preferred to declaring a named function in the `Homebrew`
# module, because:
# - Each Command lives in an isolated namespace.
# - Each Command implements a defined interface.
#
# To subclass, implement a `run` method and provide a `cmd_args` block to document the command and its allowed args.
2024-03-15 12:51:03 -07:00
# To generate method signatures for command args, run `brew typecheck --update`.
2024-03-03 15:32:30 -08:00
class AbstractCommand
extend T::Helpers
abstract!
class << self
2024-03-15 12:58:59 -07:00
sig { returns(T.nilable(CLI::Parser)) }
attr_reader :parser
2024-03-05 10:40:02 -08:00
sig { returns(String) }
def command_name = T.must(name).split("::").fetch(-1).downcase
# @return the AbstractCommand subclass associated with the brew CLI command name.
sig { params(name: String).returns(T.nilable(T.class_of(AbstractCommand))) }
def command(name) = subclasses.find { _1.command_name == name }
2024-03-05 10:40:02 -08:00
private
sig { params(block: T.nilable(T.proc.bind(CLI::Parser).void)).void }
def cmd_args(&block)
2024-03-15 12:58:59 -07:00
@parser = T.let(CLI::Parser.new(&block), T.nilable(CLI::Parser))
2024-03-05 10:40:02 -08:00
end
2024-03-03 15:32:30 -08:00
end
# @note because `Args` makes use `OpenStruct`, subclasses may need to use a tapioca compiler,
# hash accessors, args.rbi, or other means to make this work with legacy commands:
2024-03-05 10:40:02 -08:00
sig { returns(CLI::Args) }
2024-03-03 15:32:30 -08:00
attr_reader :args
2024-03-06 21:12:17 -08:00
sig { params(argv: T::Array[String]).void }
def initialize(argv = ARGV.freeze)
2024-03-15 12:58:59 -07:00
@args = T.let(T.must(self.class.parser).parse(argv), CLI::Args)
2024-03-03 15:32:30 -08:00
end
sig { abstract.void }
def run; end
end
end