Module: Textus::Contract::DSL

Overview

Mixed onto a use-case class via ‘extend`. Calls accumulate into ivars, frozen into a Spec on first read of `.contract`.

Instance Method Summary collapse

Instance Method Details

#arg(name, type, required: false, positional: false, session_default: nil, description: nil, wire_name: nil, default: nil, source: nil, coerce: nil, cli_default: :__unset) ⇒ Object

rubocop:disable Metrics/ParameterLists,Layout/LineLength



120
121
122
123
124
125
126
127
128
129
# File 'lib/textus/contract.rb', line 120

def arg(name, type, required: false, positional: false, session_default: nil, description: nil, wire_name: nil, default: nil, source: nil, coerce: nil, cli_default: :__unset) # rubocop:disable Metrics/ParameterLists,Layout/LineLength
  raise "contract already built; declare args before reading .contract" if defined?(@__contract) && @__contract

  (@__args ||= []) << Arg.new(
    name: name, type: type, required: required,
    positional: positional, session_default: session_default,
    description: description, wire_name: wire_name, default: default,
    source: source, coerce: coerce, cli_default: cli_default
  )
end

#around(name = nil) ⇒ Object

Declare a stateful wrapper resource (Contract::Around) to run around dispatch — e.g. ‘around :cursor` (pulse) or `around :build_lock` (build).



112
113
114
115
116
117
118
# File 'lib/textus/contract.rb', line 112

def around(name = nil)
  return @__around unless name

  raise "contract already built; declare around before reading .contract" if defined?(@__contract) && @__contract

  @__around = name
end

#cli(path = nil) ⇒ Object



100
101
102
103
104
105
106
107
108
# File 'lib/textus/contract.rb', line 100

def cli(path = nil)
  if path
    raise "contract already built; declare cli before reading .contract" if defined?(@__contract) && @__contract

    @__cli = path.to_s
  else
    @__cli
  end
end

#cli_stdin(mode = :__read) ⇒ Object

Verb-level: the CLI reads its inputs from a stdin envelope of this mode. ‘:json` parses stdin as a JSON object and distributes its keys to args by wire-name. nil means no stdin acquisition.



134
135
136
137
138
139
140
# File 'lib/textus/contract.rb', line 134

def cli_stdin(mode = :__read)
  return @__cli_stdin if mode == :__read

  raise "contract already built; declare cli_stdin before reading .contract" if defined?(@__contract) && @__contract

  @__cli_stdin = mode
end

#contractObject

rubocop:disable Naming/MemoizedInstanceVariableName (@__verb, @__args, etc.) and avoid name collision with user-defined ‘@contract`.



159
160
161
162
163
164
165
166
167
168
169
170
# File 'lib/textus/contract.rb', line 159

def contract
  @__contract ||= Spec.new(
    verb: @__verb,
    summary: @__summary,
    args: (@__args || []).freeze,
    surfaces: (@__surfaces || []).freeze,
    views: ((@__views ||= {})[:default] ||= ->(v, _i) { v }) && @__views,
    cli: @__cli,
    around: @__around,
    cli_stdin: @__cli_stdin,
  )
end

#contract?Boolean

Returns:

  • (Boolean)


152
153
154
# File 'lib/textus/contract.rb', line 152

def contract?
  !@__verb.nil?
end

#summary(text = nil) ⇒ Object



80
81
82
83
84
85
86
87
88
# File 'lib/textus/contract.rb', line 80

def summary(text = nil)
  if text
    raise "contract already built; declare summary before reading .contract" if defined?(@__contract) && @__contract

    @__summary = text
  else
    @__summary
  end
end

#surfaces(*list) ⇒ Object



90
91
92
93
94
95
96
97
98
# File 'lib/textus/contract.rb', line 90

def surfaces(*list)
  if list.empty?
    @__surfaces ||= []
  else
    raise "contract already built; declare surfaces before reading .contract" if defined?(@__contract) && @__contract

    @__surfaces = list
  end
end

#verb(name = nil) ⇒ Object



70
71
72
73
74
75
76
77
78
# File 'lib/textus/contract.rb', line 70

def verb(name = nil)
  if name
    raise "contract already built; declare verb before reading .contract" if defined?(@__contract) && @__contract

    @__verb = name
  else
    @__verb
  end
end

#view(surface = :default, &blk) ⇒ Object

Declare an output shaper. ‘view { … }` is the default (MCP + Ruby); `view(:cli) { … }` overrides for the CLI. Both receive (result, inputs).



144
145
146
147
148
149
150
# File 'lib/textus/contract.rb', line 144

def view(surface = :default, &blk)
  return (@__views ||= {})[surface] unless blk

  raise "contract already built; declare view before reading .contract" if defined?(@__contract) && @__contract

  (@__views ||= {})[surface] = blk
end