Class: Brut::CLI::App
- Inherits:
-
Object
- Object
- Brut::CLI::App
- Includes:
- ExecutionResults, I18n::ForCLI
- Defined in:
- lib/brut/cli/app.rb
Overview
Base class for all Brut-powered CLI Apps. Your subclass will call or override methods to declare the UI of your CLI app, including
the commands it provides and options it recognizes. These mostly help to provide command-line documentation for your app, but also
provide basic help with accessing the command line arguments and options. Internally, this uses Ruby's OptionParser
.
The types of CLIs this framework supports are command suites where a single CLI app has several subcommands, similar to git
. As
such, the CLI has several parts that you can configure:
cli_app [global options] «subcommand» [command options] [arguments]
- Global options appear between the CLI app's executable and the name of the subcommand. These affect any command. A common example is
--log-level
. These are configured with on or App.option_parser. - Subcommand is a single string representing the command to execute. The available commands are returned by App.commands although it's more conventional to declare inner classes of your app that extend Command.
- Command options appear after the subcommand and apply only to that sub command. They are declared with Command.on or Command.opts.
- Arguments are any additional values present on the command line. They are defined per-command and can be documented via Command.args.
Direct Known Subclasses
Brut::CLI::Apps::BuildAssets, Brut::CLI::Apps::DB, Brut::CLI::Apps::DeployBase, Brut::CLI::Apps::Scaffold, Brut::CLI::Apps::Test
Class Method Summary collapse
-
.commands ⇒ Object
Returns a list of Command classes that each represent the subcommands your CLI app accepts.
-
.configure_only! ⇒ Object
Call this if your app must operate before the Brut framework starts up.
-
.configure_only? ⇒ Boolean
-
.default_command(new_command_name = nil) ⇒ Object
Specify the default command to use when no subcommand is given.
-
.default_env ⇒ Object
Returns the default project env, based on the logic described in App.requires_project_env.
-
.description(new_description = nil) ⇒ String
Call this to set the one-line description of your command line app.
-
.env_var(var_name, purpose:) ⇒ Object
Call this for each environment variable your app responds to.
-
.option_parser ⇒ OptionParser
Returns the configured
OptionParser
used to parse global portion of the command line. -
.opts ⇒ OptionParser
Provides access to an
OptionParser
you can use to declare flags and switches that should be accepted globally. -
.requires_project_env(default: "development") ⇒ Object
Call this if your CLI requires a project environment as context for what it does.
-
.requires_project_env? ⇒ Boolean
Returns true if this app requires a project env.
Instance Method Summary collapse
-
#after_bootstrap(app:) ⇒ Object
Called after all setup has been executed.
-
#before_execute ⇒ Object
Called before anything else happens.
-
#execute!(command, project_root:) ⇒ Object
Executes the command.
-
#initialize(global_options:, out:, err:, executor:) ⇒ App
constructor
Create the App.
Methods included from I18n::ForCLI
Methods included from I18n::BaseMethods
#l, #t, #t_direct, #this_field_value
Methods included from ExecutionResults
#abort_execution, #as_execution_result, #cli_usage_error, #continue_execution, #show_cli_usage, #stop_execution
Constructor Details
#initialize(global_options:, out:, err:, executor:) ⇒ App
Create the App. This is called by Brut::CLI::AppRunner.
145 146 147 148 149 150 151 152 153 |
# File 'lib/brut/cli/app.rb', line 145 def initialize(global_options:,out:,err:,executor:) @global_options = @out = out @err = err @executor = executor if self.class.default_env @global_options.set_default(:env,self.class.default_env) end end |
Class Method Details
.commands ⇒ Object
Returns a list of Command classes that each represent the subcommands your CLI app accepts. By default, this will look for all internal classes that extend Command and use them as your subcommands. This means that you don't need to override this method and can instead define classes inside your app subclass.
26 27 28 29 30 31 32 |
# File 'lib/brut/cli/app.rb', line 26 def self.commands self.constants.map { |name| self.const_get(name) }.select { |constant| constant.kind_of?(Class) && constant.ancestors.include?(Brut::CLI::Command) && constant.instance_methods.include?(:execute) } end |
.configure_only! ⇒ Object
Call this if your app must operate before the Brut framework starts up.
134 135 136 |
# File 'lib/brut/cli/app.rb', line 134 def self.configure_only! @configure_only = true end |
.configure_only? ⇒ Boolean
137 |
# File 'lib/brut/cli/app.rb', line 137 def self.configure_only? = !!@configure_only |
.default_command(new_command_name = nil) ⇒ Object
Specify the default command to use when no subcommand is given.
66 67 68 69 70 71 72 |
# File 'lib/brut/cli/app.rb', line 66 def self.default_command(new_command_name=nil) if new_command_name.nil? return @default_command || "help" else @default_command = new_command_name.to_s end end |
.default_env ⇒ Object
Returns the default project env, based on the logic described in requires_project_env
129 130 |
# File 'lib/brut/cli/app.rb', line 129 def self.default_env = @default_env # Returns true if this app requires a project env |
.description(new_description = nil) ⇒ String
Call this to set the one-line description of your command line app.
38 39 40 41 42 43 44 |
# File 'lib/brut/cli/app.rb', line 38 def self.description(new_description=nil) if new_description.nil? return @description.to_s else @description = new_description end end |
.env_var(var_name, purpose:) ⇒ Object
Call this for each environment variable your app responds to. These would be variables that affect any of the subcommands. For command-specific environment variables, see Command.env_var.
51 52 53 |
# File 'lib/brut/cli/app.rb', line 51 def self.env_var(var_name,purpose:) env_vars[var_name] = purpose end |
.option_parser ⇒ OptionParser
Returns the configured OptionParser
used to parse global portion of the command line.
If you don't want to call opts, you can create and return
a fully-formed OptionParser
by overriding this method. By default, it will create one with a conventional banner.
97 98 99 100 101 |
# File 'lib/brut/cli/app.rb', line 97 def self.option_parser @option_parser ||= OptionParser.new do |opts| opts. = "%{app} %{global_options} commands [command options] [args]" end end |
.opts ⇒ OptionParser
Provides access to an OptionParser
you can use to declare flags and switches that should be accepted globally. The way to use
this is to call .on
and provide a description for an option as you would to OptionParser
. The only difference is that you
should not pass a block to this. When the command line is parsed, the results will be placed into a Options
instance made available to your command.
88 89 90 |
# File 'lib/brut/cli/app.rb', line 88 def self.opts self.option_parser end |
.requires_project_env(default: "development") ⇒ Object
Call this if your CLI requires a project environment as context for what it does. For example, a command to analyze the database needs to know if it should operate on development, test, or production. When called, this will do a few things:
- Your app will recognize
--env=ENVIRONMENT
as a global option - Your app will recognize the
RACK_ENV
environment variable.
When your app executes, the project environment will be determined as follows:
- If
--env
was on the command line, that is the environment used - If
RACK_ENV
is set in the environment, that is used - Otherwise the value given to the
default:
parameter of this method is used.
116 117 118 119 120 121 122 123 124 125 126 |
# File 'lib/brut/cli/app.rb', line 116 def self.requires_project_env(default: "development") = if default.nil? "" else " (default '#{default}')" end opts.on("--env=ENVIRONMENT","Project environment#{}") @default_env = ENV["RACK_ENV"] || default @requires_project_env = true self.env_var("RACK_ENV",purpose: "default project environment when --env is omitted") end |
.requires_project_env? ⇒ Boolean
Returns true if this app requires a project env
131 |
# File 'lib/brut/cli/app.rb', line 131 def self.requires_project_env? = @requires_project_env |
Instance Method Details
#after_bootstrap(app:) ⇒ Object
Called after all setup has been executed. Brut will have been started/loaded. This will not be called if anything caused execution to be aborted.
184 185 |
# File 'lib/brut/cli/app.rb', line 184 def after_bootstrap(app:) end |
#before_execute ⇒ Object
Called before anything else happens. You can override this to perform any setup or other checking before Brut is started up.
177 178 |
# File 'lib/brut/cli/app.rb', line 177 def before_execute end |
#execute!(command, project_root:) ⇒ Object
Executes the command. Called by Brut::CLI::AppRunner.
191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 |
# File 'lib/brut/cli/app.rb', line 191 def execute!(command,project_root:) before_execute set_env_if_needed command.set_env_if_needed load_env(project_root:) command.before_execute app = nil bootstrap_result = begin require "#{project_root}/app/bootstrap" bootstrap = Bootstrap.new if self.class.configure_only? bootstrap.configure_only! else bootstrap.bootstrap! end app = bootstrap.app continue_execution rescue => ex as_execution_result(command.handle_bootstrap_exception(ex)) end if bootstrap_result.stop? return bootstrap_result end after_bootstrap(app:) command.after_bootstrap(app:) if self.class.configure_only? as_execution_result(command.execute) else result = Brut.container.instrumentation.span("CLI #{$0}", prefix: "brut.cli", class: self.class.name) do |span| as_execution_result(command.execute) end result end rescue Brut::CLI::Error => ex abort_execution(ex.) end |