Class: Brut::CLI::AppRunner

Inherits:
Object
  • Object
show all
Includes:
ExecutionResults
Defined in:
lib/brut/cli/app_runner.rb

Overview

Manages the execution of a CLI app that extends App. Generally you won't use this class directly, but will call app.

Instance Method Summary collapse

Methods included from ExecutionResults

#abort_execution, #as_execution_result, #cli_usage_error, #continue_execution, #show_cli_usage, #stop_execution

Constructor Details

#initialize(app_klass:, project_root:) ⇒ AppRunner

Create the app runner with a class and project root

Parameters:

  • app_klass (Class)

    The class of your app that extends Brut::CLI::App

  • project_root (Pathname)

    path to the root of the project



12
13
14
15
# File 'lib/brut/cli/app_runner.rb', line 12

def initialize(app_klass:,project_root:)
  @app_klass    = app_klass
  @project_root = project_root
end

Instance Method Details

#run!Object

Runs the app, based on the CLI arguments and UNIX environment provided at the time of execution.



18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/brut/cli/app_runner.rb', line 18

def run!
  app_klass = @app_klass
  out       = Brut::CLI::Output.new(io: $stdout,prefix: "[ #{$0} ] ")
  err       = Brut::CLI::Output.new(io: $stderr,prefix: "[ #{$0} ] ")
  executor  = Brut::CLI::Executor.new(out:,err:)

  result,remaining_argv,global_options,global_option_parser = parse_global(app_klass:,out:)

  if result.stop?
    return result.to_i
  end

  result,command_klass = locate_command(remaining_argv:,app_klass:,err:,out:)

  if result.stop?
    if !result.ok?
      err.puts_no_prefix "error: #{result.message}"
      err.puts_no_prefix
      if result.show_usage?
        show_global_help(app_klass:,out:)
        err.puts_no_prefix "error: #{result.message}"
      end
    elsif result.show_usage?
      command_klass = result.command_klass
      if command_klass.nil?
        show_global_help(app_klass:,out:)
      else
        command_option_parser = command_klass.option_parser
        show_command_help(global_option_parser:,command_option_parser:,command_klass:,out:,app_klass:)
      end
    end
    return result.to_i
  end

  command_options = {}

  command_option_parser = command_klass.option_parser

  command_option_parser.on("-h", "--help", "Get help on this command") do
    show_command_help(global_option_parser:,command_option_parser:,command_klass:,out:,app_klass:)
    return 0
  end

  command_argv = remaining_argv[1..-1] || []
  begin
    args = command_option_parser.parse!(command_argv,into:command_options)
  rescue OptionParser::ParseError => ex
    raise Brut::CLI::InvalidOption.new(ex, context: command_klass)
  end

  cli_app = app_klass.new(global_options:, out:, err:, executor:)
  cmd = command_klass.new(command_options:Brut::CLI::Options.new(command_options),global_options:, args:, out:, err:, executor:)

  result = cli_app.execute!(cmd, project_root:@project_root)

  if result.message
    if !result.ok?
      err.puts "error: #{result.message}"
      if result.show_usage?
        err.puts
        show_command_help(global_option_parser:,command_option_parser:,command_klass:,out:)
      end
    else
      out.puts result.message
    end
  end
  result.to_i
rescue OptionParser::InvalidArgument => ex
  flag = ex.args.map { |_| _.gsub(/=.*$/,"") }.join(", ")
  err.puts "error: #{ex.reason} from #{flag}: value given is not one of the allowed values"
  65
rescue OptionParser::ParseError => ex
  err.puts "error: #{ex.message}"
  65
rescue => ex
  if ENV["BRUT_CLI_RAISE_ON_ERROR"] == "true"
    raise
  else
    err.puts "error: #{ex.message}"
    70
  end
end