Module: Magik::CLI

Defined in:
lib/magik/cli.rb

Overview

The magik command line.

Two commands work today — CLI.version and CLI.help. Every other command named in docs/idea/00-build-spec.md is listed by magik help with status planned and exits non-zero with MAGIK_COMMAND_NOT_IMPLEMENTED if you run it. That is deliberate: the CLI tells you the truth about what exists.

Both working commands support --json, so scripts and CI can consume the output without parsing prose. Errors are emitted as JSON too when --json is set, using Error#to_h.

Implemented with the stdlib OptionParser; Magik takes no third-party CLI dependency.

Examples:

Human output

$ magik version
magik 0.0.1 (spec only)

Machine output

$ magik version --json
{"name":"magik","version":"0.0.1","status":"spec only",...}

Constant Summary collapse

EXIT_SUCCESS =

Exit status for a command that did what it said.

Returns:

  • (Integer)
0
EXIT_ERROR =

Exit status for any Error — unknown command, planned command, bad option.

Returns:

  • (Integer)
1
STATUS =

Short status label reused in every output format.

Returns:

  • (String)
"spec only"
COMMANDS =

Every command the spec calls for, in the order magik help prints them.

:status is "ready" for commands that work today and "planned" for commands that only exist in docs/idea/00-build-spec.md.

Returns:

  • (Hash{String => Hash{Symbol => String}})
{
  "new" => { summary: "Generate a new Magik application", status: "planned" },
  "generate" => { summary: "Generate a model, screen, action or job", status: "planned" },
  "console" => { summary: "Open an application console", status: "planned" },
  "server" => { summary: "Run the Falcon-backed application server", status: "planned" },
  "worker" => { summary: "Run the background job worker", status: "planned" },
  "test" => { summary: "Run the application test suite", status: "planned" },
  "check" => { summary: "Lint an application against Magik's boot guardrails", status: "planned" },
  "version" => { summary: "Print the magik gem version", status: "ready" },
  "help" => { summary: "List every magik command and its status", status: "ready" }
}.freeze

Class Method Summary collapse

Class Method Details

.commands_as_dataArray<Hash{Symbol => String}>

COMMANDS flattened into an array of plain hashes, for JSON output.

Returns:

  • (Array<Hash{Symbol => String}>)


133
134
135
# File 'lib/magik/cli.rb', line 133

def commands_as_data
  COMMANDS.map { |name, meta| { name: name, summary: meta[:summary], status: meta[:status] } }
end

.help(out: $stdout, json: false) ⇒ void

This method returns an undefined value.

Print usage and every command in COMMANDS with its status.

Parameters:

  • out (IO) (defaults to: $stdout)

    stream to write to

  • json (Boolean) (defaults to: false)

    emit JSON instead of prose



105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
# File 'lib/magik/cli.rb', line 105

def help(out: $stdout, json: false)
  return out.puts(JSON.generate(usage: usage, status: STATUS, commands: commands_as_data)) if json

  out.puts usage
  out.puts
  out.puts "Commands:"
  width = COMMANDS.keys.map(&:length).max
  COMMANDS.each do |name, meta|
    out.puts format("  %-#{width}s  %-8s  %s", name, meta[:status], meta[:summary])
  end
  out.puts
  out.puts "Global options:"
  out.puts "      --json               Emit machine-readable JSON"
  out.puts "  -v, --version            Print the magik gem version"
  out.puts "  -h, --help               Show this message"
  out.puts
  out.puts "Magik is #{STATUS}: `planned` commands are specified in " \
           "docs/idea/00-build-spec.md and not implemented."
end

.start(argv = [], out: $stdout, err: $stderr) ⇒ Integer

Run the CLI.

Never raises for user error: a Error is rendered to err (or to out as JSON when --json is set) and reported as EXIT_ERROR.

Examples:

Magik::CLI.start(["version", "--json"]) # => 0

Parameters:

  • argv (Array<String>) (defaults to: [])

    the raw command line, usually ARGV

  • out (IO) (defaults to: $stdout)

    stream for command output

  • err (IO) (defaults to: $stderr)

    stream for error output

Returns:



71
72
73
74
75
76
77
78
79
# File 'lib/magik/cli.rb', line 71

def start(argv = [], out: $stdout, err: $stderr)
  options = { json: false }
  args = parse_options(Array(argv), options)
  dispatch(args, options, out)
  EXIT_SUCCESS
rescue Magik::Error => e
  report_error(e, options[:json], out, err)
  EXIT_ERROR
end

.usageString

The one-line usage banner.

Returns:

  • (String)


127
128
129
# File 'lib/magik/cli.rb', line 127

def usage
  "Usage: magik <command> [options]"
end

.version(out: $stdout, json: false) ⇒ void

This method returns an undefined value.

Print the gem version.

Parameters:

  • out (IO) (defaults to: $stdout)

    stream to write to

  • json (Boolean) (defaults to: false)

    emit JSON instead of prose



86
87
88
89
90
91
92
93
94
95
96
97
98
# File 'lib/magik/cli.rb', line 86

def version(out: $stdout, json: false)
  if json
    out.puts JSON.generate(
      name: "magik",
      version: Magik::VERSION,
      status: STATUS,
      ruby: RUBY_VERSION,
      ruby_engine: RUBY_ENGINE
    )
  else
    out.puts "magik #{Magik::VERSION} (#{STATUS})"
  end
end