Module: SpaceArchitect::CLI

Defined in:
lib/space_architect/cli.rb,
lib/space_architect/cli/new.rb,
lib/space_architect/cli/src.rb,
lib/space_architect/cli/use.rb,
lib/space_architect/cli/init.rb,
lib/space_architect/cli/list.rb,
lib/space_architect/cli/path.rb,
lib/space_architect/cli/repo.rb,
lib/space_architect/cli/show.rb,
lib/space_architect/cli/shell.rb,
lib/space_architect/cli/config.rb,
lib/space_architect/cli/status.rb,
lib/space_architect/cli/current.rb,
lib/space_architect/cli/helpers.rb,
lib/space_architect/cli/options.rb,
lib/space_architect/cli/architect.rb

Defined Under Namespace

Modules: Architect, Config, GlobalOptions, Helpers, Registry, Repo, Shell Classes: Current, Init, List, New, Outcome, Path, RepoProgress, Show, Status, Use

Constant Summary collapse

TOP_LEVEL_HELP =
[[], ["--help"], ["-h"], ["help"]].freeze
VERSION_REQUEST =
[["version"], ["--version"]].freeze

Class Method Summary collapse

Class Method Details

.call(argv, out = $stdout, err = $stderr) ⇒ Object



21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/space_architect/cli.rb', line 21

def self.call(argv, out = $stdout, err = $stderr)
  Thread.current[:space_architect_outcome] = nil

  if TOP_LEVEL_HELP.include?(argv)
    out.puts Dry::CLI::Usage.call(Registry.get([]))
    return 0
  end

  if VERSION_REQUEST.include?(argv)
    out.puts SpaceArchitect::VERSION
    return 0
  end

  if argv.first == "src"
    return dispatch_src(argv[1..], out, err)
  end

  Dry::CLI.new(Registry).call(arguments: normalize_args(argv), out: out, err: err)
  last_outcome&.exit_code || 0
end

.dispatch_src(rest, out = $stdout, err = $stderr) ⇒ Object

Exit-code bridge to the vendored Pristine (repo-tender) CLI engine. ‘architect src <args>` hands the raw remainder to Pristine’s own dry-cli registry and translates Pristine’s recorded Outcome into the host exit code. Pristine has its own Registry, Outcome, and :repo_tender_cli_* thread-locals; this is the seam between the two registries (NOT a re-registration). Pristine’s top-level help/version interceptors call Kernel.exit, so we reproduce that interception here against the injected IO instead of delegating to them. dry-cli’s internal exit on a bare group / unknown command propagates as SystemExit — same as the host’s own bare groups (e.g. ‘space repo`) — and is intentionally NOT rescued (accepted behavior change).



17
18
19
20
21
22
23
24
25
26
27
28
29
30
# File 'lib/space_architect/cli/src.rb', line 17

def self.dispatch_src(rest, out = $stdout, err = $stderr)
  if Pristine::CLI::TOP_LEVEL_HELP.include?(rest)
    out.puts Dry::CLI::Usage.call(Pristine::CLI::Registry.get([]))
    return 0
  end
  if Pristine::CLI::VERSION_REQUEST.include?(rest)
    out.puts SpaceArchitect::Pristine::VERSION
    return 0
  end

  Thread.current[:repo_tender_cli_outcome] = nil
  Dry::CLI.new(Pristine::CLI::Registry).call(arguments: rest, out: out, err: err)
  Pristine::CLI.last_outcome&.exit_code || 0
end

.last_outcomeObject



12
# File 'lib/space_architect/cli.rb', line 12

def self.last_outcome = Thread.current[:space_architect_outcome]

.normalize_args(argv) ⇒ Object

Move –color/–colors options to the end of the argument list so dry-cli’s command routing is not confused by options before the subcommand name.

Two passes:

1. Leading: extract two-token form (--color VALUE) and =-form from the
   front while args still look like options.
2. Non-leading: extract =-form (--color=VALUE / --colors=VALUE) from any
   position before the -- separator. The bare two-token form is ambiguous
   with a subcommand name in non-leading position and is left in place.


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
# File 'lib/space_architect/cli.rb', line 51

def self.normalize_args(argv)
  args = argv.dup
  extracted = []

  # Pass 1: leading two-token and =-form (existing behavior, unchanged)
  while (arg = args.first) && arg != "--" && arg.start_with?("-")
    if %w[--color --colors].include?(arg)
      extracted << args.shift
      extracted << args.shift if args.first && !args.first.start_with?("-")
    elsif arg.start_with?("--color=", "--colors=")
      extracted << args.shift
    else
      break
    end
  end

  # Pass 2: =-form from any non-leading position, stop at --
  sep = args.index("--")
  head = sep ? args[0, sep] : args
  tail = sep ? args[sep..] : []
  mid_color, head = head.partition { |a| a.start_with?("--color=", "--colors=") }
  extracted += mid_color
  args = head + tail

  extracted.empty? ? args : args + extracted
end

.record_outcome(o) ⇒ Object



11
# File 'lib/space_architect/cli.rb', line 11

def self.record_outcome(o) = (Thread.current[:space_architect_outcome] = o)

.run(argv, out = $stdout, err = $stderr) ⇒ Object



78
79
80
81
82
83
# File 'lib/space_architect/cli.rb', line 78

def self.run(argv, out = $stdout, err = $stderr)
  Kernel.exit(call(argv, out, err))
rescue Interrupt
  err.puts "interrupted"
  Kernel.exit(130)
end