Class: Textus::CLI::Verb
- Inherits:
-
Object
- Object
- Textus::CLI::Verb
- Defined in:
- lib/textus/cli/verb.rb,
lib/textus/cli/verb/mv.rb,
lib/textus/cli/verb/get.rb,
lib/textus/cli/verb/put.rb,
lib/textus/cli/verb/uid.rb,
lib/textus/cli/verb/deps.rb,
lib/textus/cli/verb/init.rb,
lib/textus/cli/verb/list.rb,
lib/textus/cli/verb/audit.rb,
lib/textus/cli/verb/blame.rb,
lib/textus/cli/verb/build.rb,
lib/textus/cli/verb/hooks.rb,
lib/textus/cli/verb/intro.rb,
lib/textus/cli/verb/rdeps.rb,
lib/textus/cli/verb/where.rb,
lib/textus/cli/verb/accept.rb,
lib/textus/cli/verb/delete.rb,
lib/textus/cli/verb/doctor.rb,
lib/textus/cli/verb/reject.rb,
lib/textus/cli/verb/schema.rb,
lib/textus/cli/verb/refresh.rb,
lib/textus/cli/verb/hook_run.rb,
lib/textus/cli/verb/freshness.rb,
lib/textus/cli/verb/published.rb,
lib/textus/cli/verb/rule_list.rb,
lib/textus/cli/verb/schema_diff.rb,
lib/textus/cli/verb/schema_init.rb,
lib/textus/cli/verb/rule_explain.rb,
lib/textus/cli/verb/refresh_stale.rb,
lib/textus/cli/verb/schema_migrate.rb
Overview
Subclasses must implement #call(store) and return an integer exit code. Use #emit(obj) for normal JSON output (returns 0). Subclasses that don’t need a Textus store (e.g. Init) override ‘.needs_store?` to return false; dispatch will pass nil instead.
Direct Known Subclasses
Group, Accept, Audit, Blame, Build, Delete, Deps, Doctor, Freshness, Get, HookRun, Hooks, Init, Intro, List, Mv, Published, Put, Rdeps, Refresh, RefreshStale, Reject, RuleExplain, RuleList, Schema, SchemaDiff, SchemaInit, SchemaMigrate, Uid, Where
Defined Under Namespace
Classes: Accept, Audit, Blame, Build, Delete, Deps, Doctor, Freshness, Get, HookRun, Hooks, Init, Intro, List, Mv, Published, Put, Rdeps, Refresh, RefreshStale, Reject, RuleExplain, RuleList, Schema, SchemaDiff, SchemaInit, SchemaMigrate, Uid, Where
Instance Attribute Summary collapse
-
#positional ⇒ Object
readonly
Returns the value of attribute positional.
Class Method Summary collapse
-
.command_name(name = nil) ⇒ Object
Declarative CLI name.
-
.descendants ⇒ Object
Recursive subclass enumeration.
- .inherited(subclass) ⇒ Object
- .needs_store? ⇒ Boolean
- .option(name, optspec) ⇒ Object
- .options ⇒ Object
-
.parent_group(group_klass = nil) ⇒ Object
Declares that this verb is a subcommand of ‘group_klass`.
Instance Method Summary collapse
-
#context_for(store) ⇒ Object
Returns an Application::Context bound to the resolved role.
-
#emit(obj, exit_code: 0) ⇒ Object
Hashes get “protocol” => PROTOCOL prepended unless they already carry one (Store envelopes do).
-
#initialize(stdin:, stdout:, stderr:, cwd: nil) ⇒ Verb
constructor
A new instance of Verb.
-
#operations_for(store) ⇒ Object
Returns an Operations instance bound to the resolved role.
- #parse(argv) ⇒ Object
-
#resolved_role(store) ⇒ Object
Resolves the active role for this invocation.
Constructor Details
#initialize(stdin:, stdout:, stderr:, cwd: nil) ⇒ Verb
Returns a new instance of Verb.
61 62 63 64 65 66 |
# File 'lib/textus/cli/verb.rb', line 61 def initialize(stdin:, stdout:, stderr:, cwd: nil) @stdin = stdin @stdout = stdout @stderr = stderr @cwd = cwd end |
Instance Attribute Details
#positional ⇒ Object (readonly)
Returns the value of attribute positional.
82 83 84 |
# File 'lib/textus/cli/verb.rb', line 82 def positional @positional end |
Class Method Details
.command_name(name = nil) ⇒ Object
Declarative CLI name. Reader returns the registered name (or nil for verbs that aren’t directly invokable, like the abstract Verb/Group base classes). Writer registers it.
28 29 30 31 32 33 34 |
# File 'lib/textus/cli/verb.rb', line 28 def command_name(name = nil) if name.nil? @command_name else @command_name = name.to_s end end |
.descendants ⇒ Object
Recursive subclass enumeration. Ruby 3.1 ships Class#subclasses but not Class#descendants, so we expand it ourselves.
56 57 58 |
# File 'lib/textus/cli/verb.rb', line 56 def descendants subclasses.flat_map { |k| [k] + k.descendants } end |
.inherited(subclass) ⇒ Object
47 48 49 50 51 52 |
# File 'lib/textus/cli/verb.rb', line 47 def inherited(subclass) super subclass.instance_variable_set(:@options, []) subclass.instance_variable_set(:@command_name, nil) subclass.instance_variable_set(:@parent_group, nil) end |
.needs_store? ⇒ Boolean
21 22 23 |
# File 'lib/textus/cli/verb.rb', line 21 def needs_store? true end |
.option(name, optspec) ⇒ Object
12 13 14 15 |
# File 'lib/textus/cli/verb.rb', line 12 def option(name, optspec) << [name, optspec] attr_accessor(name) end |
.options ⇒ Object
17 18 19 |
# File 'lib/textus/cli/verb.rb', line 17 def @options ||= [] end |
.parent_group(group_klass = nil) ⇒ Object
Declares that this verb is a subcommand of ‘group_klass`. When set, the verb is NOT a top-level CLI verb — it’s listed under the group’s subcommands instead.
39 40 41 42 43 44 45 |
# File 'lib/textus/cli/verb.rb', line 39 def parent_group(group_klass = nil) if group_klass.nil? @parent_group else @parent_group = group_klass end end |
Instance Method Details
#context_for(store) ⇒ Object
Returns an Application::Context bound to the resolved role. Convenience for verbs whose only pre-call boilerplate is resolving the role and wrapping it in a context.
102 103 104 |
# File 'lib/textus/cli/verb.rb', line 102 def context_for(store) Textus::Operations.for(store, role: resolved_role(store)).ctx end |
#emit(obj, exit_code: 0) ⇒ Object
Hashes get “protocol” => PROTOCOL prepended unless they already carry one (Store envelopes do). Caller’s value wins on collision.
86 87 88 89 90 |
# File 'lib/textus/cli/verb.rb', line 86 def emit(obj, exit_code: 0) payload = obj.is_a?(Hash) ? { "protocol" => PROTOCOL }.merge(obj) : obj @stdout.puts(JSON.generate(payload)) exit_code end |
#operations_for(store) ⇒ Object
Returns an Operations instance bound to the resolved role.
107 108 109 |
# File 'lib/textus/cli/verb.rb', line 107 def operations_for(store) Textus::Operations.for(store, role: resolved_role(store)) end |
#parse(argv) ⇒ Object
68 69 70 71 72 73 74 75 76 77 78 79 80 |
# File 'lib/textus/cli/verb.rb', line 68 def parse(argv) fmt = "json" OptionParser.new do |o| self.class..each do |name, optspec| o.on(optspec) { |v| public_send(:"#{name}=", v) } end o.on("--output=FMT") { |v| fmt = v } o.on("--format=FMT") { |_v| raise FlagRenamed.new("--format", "--output") } end.permute!(argv) raise UsageError.new("only --output=json is supported in v1") unless fmt == "json" @positional = argv.dup end |
#resolved_role(store) ⇒ Object
Resolves the active role for this invocation. Honors the verb’s ‘–as` flag if declared, then TEXTUS_ROLE, then the project default.
94 95 96 97 |
# File 'lib/textus/cli/verb.rb', line 94 def resolved_role(store) flag = respond_to?(:as_flag) ? as_flag : nil Role.resolve(flag: flag, env: ENV, root: store.root) end |