ratatui_ruby-tea 0.3.1 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/AGENTS.md +42 -2
- data/CHANGELOG.md +76 -0
- data/README.md +8 -5
- data/doc/concepts/async_work.md +164 -0
- data/doc/concepts/commands.md +528 -0
- data/doc/concepts/message_processing.md +51 -0
- data/doc/contributors/WIP/decomposition_strategies_analysis.md +258 -0
- data/doc/contributors/WIP/implementation_plan.md +405 -0
- data/doc/contributors/WIP/init_callable_proposal.md +341 -0
- data/doc/contributors/WIP/mvu_tea_implementations_research.md +372 -0
- data/doc/contributors/WIP/runtime_refactoring_status.md +47 -0
- data/doc/contributors/WIP/task.md +36 -0
- data/doc/contributors/WIP/v0.4.0_todo.md +468 -0
- data/doc/contributors/design/commands_and_outlets.md +11 -1
- data/doc/contributors/priorities.md +22 -24
- data/examples/app_fractal_dashboard/app.rb +3 -7
- data/examples/app_fractal_dashboard/dashboard/base.rb +15 -16
- data/examples/app_fractal_dashboard/dashboard/update_helpers.rb +8 -8
- data/examples/app_fractal_dashboard/dashboard/update_manual.rb +11 -11
- data/examples/app_fractal_dashboard/dashboard/update_router.rb +4 -4
- data/examples/app_fractal_dashboard/{bags → fragments}/custom_shell_input.rb +8 -4
- data/examples/app_fractal_dashboard/fragments/custom_shell_modal.rb +82 -0
- data/examples/app_fractal_dashboard/{bags → fragments}/custom_shell_output.rb +8 -4
- data/examples/app_fractal_dashboard/{bags → fragments}/disk_usage.rb +13 -10
- data/examples/app_fractal_dashboard/{bags → fragments}/network_panel.rb +12 -12
- data/examples/app_fractal_dashboard/{bags → fragments}/ping.rb +12 -8
- data/examples/app_fractal_dashboard/{bags → fragments}/stats_panel.rb +12 -12
- data/examples/app_fractal_dashboard/{bags → fragments}/system_info.rb +11 -7
- data/examples/app_fractal_dashboard/{bags → fragments}/uptime.rb +11 -7
- data/examples/verify_readme_usage/README.md +7 -4
- data/examples/verify_readme_usage/app.rb +7 -4
- data/lib/ratatui_ruby/tea/command/all.rb +71 -0
- data/lib/ratatui_ruby/tea/command/batch.rb +79 -0
- data/lib/ratatui_ruby/tea/command/custom.rb +1 -1
- data/lib/ratatui_ruby/tea/command/http.rb +194 -0
- data/lib/ratatui_ruby/tea/command/lifecycle.rb +136 -0
- data/lib/ratatui_ruby/tea/command/outlet.rb +59 -27
- data/lib/ratatui_ruby/tea/command/wait.rb +82 -0
- data/lib/ratatui_ruby/tea/command.rb +245 -64
- data/lib/ratatui_ruby/tea/message/all.rb +47 -0
- data/lib/ratatui_ruby/tea/message/http_response.rb +63 -0
- data/lib/ratatui_ruby/tea/message/system/batch.rb +63 -0
- data/lib/ratatui_ruby/tea/message/system/stream.rb +69 -0
- data/lib/ratatui_ruby/tea/message/timer.rb +48 -0
- data/lib/ratatui_ruby/tea/message.rb +40 -0
- data/lib/ratatui_ruby/tea/router.rb +11 -11
- data/lib/ratatui_ruby/tea/runtime.rb +320 -185
- data/lib/ratatui_ruby/tea/shortcuts.rb +2 -2
- data/lib/ratatui_ruby/tea/test_helper.rb +58 -0
- data/lib/ratatui_ruby/tea/version.rb +1 -1
- data/lib/ratatui_ruby/tea.rb +44 -10
- data/rbs_collection.lock.yaml +1 -17
- data/sig/concurrent.rbs +72 -0
- data/sig/ratatui_ruby/tea/command.rbs +141 -37
- data/sig/ratatui_ruby/tea/message.rbs +123 -0
- data/sig/ratatui_ruby/tea/router.rbs +1 -1
- data/sig/ratatui_ruby/tea/runtime.rbs +39 -6
- data/sig/ratatui_ruby/tea/test_helper.rbs +12 -0
- data/sig/ratatui_ruby/tea.rbs +24 -4
- metadata +63 -11
- data/examples/app_fractal_dashboard/bags/custom_shell_modal.rb +0 -73
- data/lib/ratatui_ruby/tea/command/cancellation_token.rb +0 -135
data/sig/ratatui_ruby/tea.rbs
CHANGED
|
@@ -6,23 +6,43 @@
|
|
|
6
6
|
module RatatuiRuby
|
|
7
7
|
# The Elm Architecture for RatatuiRuby.
|
|
8
8
|
module Tea
|
|
9
|
-
# Starts the MVU event loop.
|
|
9
|
+
# Starts the MVU event loop (positional fragment).
|
|
10
10
|
def self.run: [Model] (
|
|
11
|
+
?Module? root_fragment,
|
|
12
|
+
?fps: Integer
|
|
13
|
+
) -> Model
|
|
14
|
+
|
|
15
|
+
# Starts the MVU event loop (explicit parameters).
|
|
16
|
+
| [Model] (
|
|
17
|
+
?Module? root_fragment,
|
|
18
|
+
?fps: Integer,
|
|
11
19
|
model: Model,
|
|
12
|
-
view: ^(Model, RatatuiRuby::TUI) ->
|
|
20
|
+
view: ^(Model, RatatuiRuby::TUI) -> Runtime::renderable,
|
|
13
21
|
update: ^(RatatuiRuby::Event, Model) -> Runtime::update_result?,
|
|
14
|
-
?
|
|
22
|
+
?command: Command::execution?
|
|
23
|
+
) -> Model
|
|
24
|
+
|
|
25
|
+
# Starts the MVU event loop (explicit parameters without fps).
|
|
26
|
+
| [Model] (
|
|
27
|
+
?Module? root_fragment,
|
|
28
|
+
model: Model,
|
|
29
|
+
view: ^(Model, RatatuiRuby::TUI) -> Runtime::renderable,
|
|
30
|
+
update: ^(RatatuiRuby::Event, Model) -> Runtime::update_result?,
|
|
31
|
+
?command: Command::execution?
|
|
15
32
|
) -> Model
|
|
16
33
|
|
|
17
34
|
# Wraps a command with a routing prefix.
|
|
18
35
|
def self.route: (Command::execution command, Symbol prefix) -> Command::Mapped
|
|
19
36
|
|
|
20
|
-
# Delegates a prefixed message to a child
|
|
37
|
+
# Delegates a prefixed message to a child fragment's UPDATE.
|
|
21
38
|
def self.delegate: (
|
|
22
39
|
untyped message,
|
|
23
40
|
Symbol prefix,
|
|
24
41
|
^(Array[untyped]?, untyped) -> [untyped, Command::execution?] child_update,
|
|
25
42
|
untyped child_model
|
|
26
43
|
) -> ([untyped, Command::execution?] | nil)
|
|
44
|
+
|
|
45
|
+
# Normalizes Init callable return value to [model, command] tuple.
|
|
46
|
+
def self.normalize_init: [Model] (Runtime::init_result result) -> [Model?, Command::execution?]
|
|
27
47
|
end
|
|
28
48
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: ratatui_ruby-tea
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.4.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Kerrick Long
|
|
@@ -37,6 +37,34 @@ dependencies:
|
|
|
37
37
|
- - "~>"
|
|
38
38
|
- !ruby/object:Gem::Version
|
|
39
39
|
version: '0.6'
|
|
40
|
+
- !ruby/object:Gem::Dependency
|
|
41
|
+
name: concurrent-ruby
|
|
42
|
+
requirement: !ruby/object:Gem::Requirement
|
|
43
|
+
requirements:
|
|
44
|
+
- - "~>"
|
|
45
|
+
- !ruby/object:Gem::Version
|
|
46
|
+
version: '1.3'
|
|
47
|
+
type: :runtime
|
|
48
|
+
prerelease: false
|
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
50
|
+
requirements:
|
|
51
|
+
- - "~>"
|
|
52
|
+
- !ruby/object:Gem::Version
|
|
53
|
+
version: '1.3'
|
|
54
|
+
- !ruby/object:Gem::Dependency
|
|
55
|
+
name: concurrent-ruby-edge
|
|
56
|
+
requirement: !ruby/object:Gem::Requirement
|
|
57
|
+
requirements:
|
|
58
|
+
- - "~>"
|
|
59
|
+
- !ruby/object:Gem::Version
|
|
60
|
+
version: '0.7'
|
|
61
|
+
type: :runtime
|
|
62
|
+
prerelease: false
|
|
63
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
64
|
+
requirements:
|
|
65
|
+
- - "~>"
|
|
66
|
+
- !ruby/object:Gem::Version
|
|
67
|
+
version: '0.7'
|
|
40
68
|
- !ruby/object:Gem::Dependency
|
|
41
69
|
name: rdoc
|
|
42
70
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -94,6 +122,16 @@ files:
|
|
|
94
122
|
- Steepfile
|
|
95
123
|
- doc/concepts/application_architecture.md
|
|
96
124
|
- doc/concepts/application_testing.md
|
|
125
|
+
- doc/concepts/async_work.md
|
|
126
|
+
- doc/concepts/commands.md
|
|
127
|
+
- doc/concepts/message_processing.md
|
|
128
|
+
- doc/contributors/WIP/decomposition_strategies_analysis.md
|
|
129
|
+
- doc/contributors/WIP/implementation_plan.md
|
|
130
|
+
- doc/contributors/WIP/init_callable_proposal.md
|
|
131
|
+
- doc/contributors/WIP/mvu_tea_implementations_research.md
|
|
132
|
+
- doc/contributors/WIP/runtime_refactoring_status.md
|
|
133
|
+
- doc/contributors/WIP/task.md
|
|
134
|
+
- doc/contributors/WIP/v0.4.0_todo.md
|
|
97
135
|
- doc/contributors/design/commands_and_outlets.md
|
|
98
136
|
- doc/contributors/kit-no-outlet.md
|
|
99
137
|
- doc/contributors/priorities.md
|
|
@@ -105,19 +143,19 @@ files:
|
|
|
105
143
|
- doc/index.md
|
|
106
144
|
- examples/app_fractal_dashboard/README.md
|
|
107
145
|
- examples/app_fractal_dashboard/app.rb
|
|
108
|
-
- examples/app_fractal_dashboard/bags/custom_shell_input.rb
|
|
109
|
-
- examples/app_fractal_dashboard/bags/custom_shell_modal.rb
|
|
110
|
-
- examples/app_fractal_dashboard/bags/custom_shell_output.rb
|
|
111
|
-
- examples/app_fractal_dashboard/bags/disk_usage.rb
|
|
112
|
-
- examples/app_fractal_dashboard/bags/network_panel.rb
|
|
113
|
-
- examples/app_fractal_dashboard/bags/ping.rb
|
|
114
|
-
- examples/app_fractal_dashboard/bags/stats_panel.rb
|
|
115
|
-
- examples/app_fractal_dashboard/bags/system_info.rb
|
|
116
|
-
- examples/app_fractal_dashboard/bags/uptime.rb
|
|
117
146
|
- examples/app_fractal_dashboard/dashboard/base.rb
|
|
118
147
|
- examples/app_fractal_dashboard/dashboard/update_helpers.rb
|
|
119
148
|
- examples/app_fractal_dashboard/dashboard/update_manual.rb
|
|
120
149
|
- examples/app_fractal_dashboard/dashboard/update_router.rb
|
|
150
|
+
- examples/app_fractal_dashboard/fragments/custom_shell_input.rb
|
|
151
|
+
- examples/app_fractal_dashboard/fragments/custom_shell_modal.rb
|
|
152
|
+
- examples/app_fractal_dashboard/fragments/custom_shell_output.rb
|
|
153
|
+
- examples/app_fractal_dashboard/fragments/disk_usage.rb
|
|
154
|
+
- examples/app_fractal_dashboard/fragments/network_panel.rb
|
|
155
|
+
- examples/app_fractal_dashboard/fragments/ping.rb
|
|
156
|
+
- examples/app_fractal_dashboard/fragments/stats_panel.rb
|
|
157
|
+
- examples/app_fractal_dashboard/fragments/system_info.rb
|
|
158
|
+
- examples/app_fractal_dashboard/fragments/uptime.rb
|
|
121
159
|
- examples/verify_readme_usage/README.md
|
|
122
160
|
- examples/verify_readme_usage/app.rb
|
|
123
161
|
- examples/widget_command_system/README.md
|
|
@@ -125,24 +163,38 @@ files:
|
|
|
125
163
|
- exe/.gitkeep
|
|
126
164
|
- lib/ratatui_ruby/tea.rb
|
|
127
165
|
- lib/ratatui_ruby/tea/command.rb
|
|
128
|
-
- lib/ratatui_ruby/tea/command/
|
|
166
|
+
- lib/ratatui_ruby/tea/command/all.rb
|
|
167
|
+
- lib/ratatui_ruby/tea/command/batch.rb
|
|
129
168
|
- lib/ratatui_ruby/tea/command/custom.rb
|
|
169
|
+
- lib/ratatui_ruby/tea/command/http.rb
|
|
170
|
+
- lib/ratatui_ruby/tea/command/lifecycle.rb
|
|
130
171
|
- lib/ratatui_ruby/tea/command/outlet.rb
|
|
172
|
+
- lib/ratatui_ruby/tea/command/wait.rb
|
|
173
|
+
- lib/ratatui_ruby/tea/message.rb
|
|
174
|
+
- lib/ratatui_ruby/tea/message/all.rb
|
|
175
|
+
- lib/ratatui_ruby/tea/message/http_response.rb
|
|
176
|
+
- lib/ratatui_ruby/tea/message/system/batch.rb
|
|
177
|
+
- lib/ratatui_ruby/tea/message/system/stream.rb
|
|
178
|
+
- lib/ratatui_ruby/tea/message/timer.rb
|
|
131
179
|
- lib/ratatui_ruby/tea/router.rb
|
|
132
180
|
- lib/ratatui_ruby/tea/runtime.rb
|
|
133
181
|
- lib/ratatui_ruby/tea/shortcuts.rb
|
|
182
|
+
- lib/ratatui_ruby/tea/test_helper.rb
|
|
134
183
|
- lib/ratatui_ruby/tea/version.rb
|
|
135
184
|
- mise.toml
|
|
136
185
|
- rbs_collection.lock.yaml
|
|
137
186
|
- rbs_collection.yaml
|
|
187
|
+
- sig/concurrent.rbs
|
|
138
188
|
- sig/examples/verify_readme_usage/app.rbs
|
|
139
189
|
- sig/examples/widget_command_system/app.rbs
|
|
140
190
|
- sig/open3.rbs
|
|
141
191
|
- sig/ratatui_ruby/tea.rbs
|
|
142
192
|
- sig/ratatui_ruby/tea/command.rbs
|
|
193
|
+
- sig/ratatui_ruby/tea/message.rbs
|
|
143
194
|
- sig/ratatui_ruby/tea/router.rbs
|
|
144
195
|
- sig/ratatui_ruby/tea/runtime.rbs
|
|
145
196
|
- sig/ratatui_ruby/tea/shortcuts.rbs
|
|
197
|
+
- sig/ratatui_ruby/tea/test_helper.rbs
|
|
146
198
|
- sig/ratatui_ruby/tea/version.rbs
|
|
147
199
|
- tasks/example_viewer.html.erb
|
|
148
200
|
- tasks/resources/build.yml.erb
|
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
#--
|
|
4
|
-
# SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
|
|
5
|
-
# SPDX-License-Identifier: LGPL-3.0-or-later
|
|
6
|
-
#++
|
|
7
|
-
|
|
8
|
-
require_relative "custom_shell_input"
|
|
9
|
-
require_relative "custom_shell_output"
|
|
10
|
-
|
|
11
|
-
# Parent coordinator bag for custom shell modal.
|
|
12
|
-
#
|
|
13
|
-
# Routes to active child (input or output). Checks child model state for transitions.
|
|
14
|
-
module CustomShellModal
|
|
15
|
-
Command = RatatuiRuby::Tea::Command
|
|
16
|
-
|
|
17
|
-
Model = Data.define(:mode, :input, :output)
|
|
18
|
-
INITIAL = Ractor.make_shareable(Model.new(mode: :none, input: CustomShellInput::INITIAL, output: CustomShellOutput::INITIAL))
|
|
19
|
-
|
|
20
|
-
VIEW = lambda do |model, tui|
|
|
21
|
-
case model.mode
|
|
22
|
-
when :none then nil
|
|
23
|
-
when :input then CustomShellInput::VIEW.call(model.input, tui)
|
|
24
|
-
when :output then CustomShellOutput::VIEW.call(model.output, tui)
|
|
25
|
-
end
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
UPDATE = lambda do |message, model|
|
|
29
|
-
case model.mode
|
|
30
|
-
when :input
|
|
31
|
-
new_input, cmd = CustomShellInput::UPDATE.call(message, model.input)
|
|
32
|
-
|
|
33
|
-
if new_input.cancelled
|
|
34
|
-
[INITIAL, nil]
|
|
35
|
-
elsif new_input.submitted
|
|
36
|
-
shell_cmd = new_input.text
|
|
37
|
-
new_output = CustomShellOutput::INITIAL.with(command: shell_cmd, running: true)
|
|
38
|
-
[
|
|
39
|
-
model.with(mode: :output, input: CustomShellInput::INITIAL, output: new_output),
|
|
40
|
-
Command.system(shell_cmd, :shell_output, stream: true),
|
|
41
|
-
]
|
|
42
|
-
else
|
|
43
|
-
[model.with(input: new_input), cmd]
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
when :output
|
|
47
|
-
# Route streaming messages (strip :shell_output prefix)
|
|
48
|
-
routed = case message
|
|
49
|
-
in [:shell_output, *rest] then rest
|
|
50
|
-
else message
|
|
51
|
-
end
|
|
52
|
-
|
|
53
|
-
new_output, cmd = CustomShellOutput::UPDATE.call(routed, model.output)
|
|
54
|
-
|
|
55
|
-
if new_output.dismissed
|
|
56
|
-
[INITIAL, nil]
|
|
57
|
-
else
|
|
58
|
-
[model.with(output: new_output), cmd]
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
else
|
|
62
|
-
[model, nil]
|
|
63
|
-
end
|
|
64
|
-
end
|
|
65
|
-
|
|
66
|
-
def self.open
|
|
67
|
-
INITIAL.with(mode: :input, input: CustomShellInput::INITIAL)
|
|
68
|
-
end
|
|
69
|
-
|
|
70
|
-
def self.active?(model)
|
|
71
|
-
model.mode != :none
|
|
72
|
-
end
|
|
73
|
-
end
|
|
@@ -1,135 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
#--
|
|
4
|
-
# SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
|
|
5
|
-
# SPDX-License-Identifier: LGPL-3.0-or-later
|
|
6
|
-
#++
|
|
7
|
-
|
|
8
|
-
module RatatuiRuby
|
|
9
|
-
module Tea
|
|
10
|
-
module Command
|
|
11
|
-
# Cooperative cancellation mechanism for long-running commands.
|
|
12
|
-
#
|
|
13
|
-
# Long-running commands block the event loop. Commands that poll, stream, or wait
|
|
14
|
-
# indefinitely prevent clean shutdown. Killing threads mid-operation corrupts state.
|
|
15
|
-
#
|
|
16
|
-
# This class signals cancellation requests. Commands check +cancelled?+ periodically
|
|
17
|
-
# and stop gracefully. The runtime calls +cancel!+ when shutdown begins.
|
|
18
|
-
#
|
|
19
|
-
# Use it to implement WebSocket handlers, database pollers, or any command that loops.
|
|
20
|
-
#
|
|
21
|
-
# === Example
|
|
22
|
-
#
|
|
23
|
-
#--
|
|
24
|
-
# SPDX-SnippetBegin
|
|
25
|
-
# SPDX-FileCopyrightText: 2026 Kerrick Long
|
|
26
|
-
# SPDX-License-Identifier: MIT-0
|
|
27
|
-
#++
|
|
28
|
-
# class PollerCommand
|
|
29
|
-
# include Tea::Command::Custom
|
|
30
|
-
#
|
|
31
|
-
# def call(out, token)
|
|
32
|
-
# until token.cancelled?
|
|
33
|
-
# data = fetch_batch
|
|
34
|
-
# out.put(:batch, data)
|
|
35
|
-
# sleep 5
|
|
36
|
-
# end
|
|
37
|
-
# out.put(:poller_stopped)
|
|
38
|
-
# end
|
|
39
|
-
# end
|
|
40
|
-
#--
|
|
41
|
-
# SPDX-SnippetEnd
|
|
42
|
-
#++
|
|
43
|
-
class CancellationToken
|
|
44
|
-
# Number of times +cancel!+ has been called. :nodoc:
|
|
45
|
-
#
|
|
46
|
-
# Exposed for testing thread-safety. Not part of the public API.
|
|
47
|
-
attr_reader :cancel_count
|
|
48
|
-
|
|
49
|
-
# Creates a new cancellation token in the non-cancelled state.
|
|
50
|
-
def initialize
|
|
51
|
-
@cancel_count = 0
|
|
52
|
-
@mutex = Mutex.new
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
# Signals cancellation. Thread-safe.
|
|
56
|
-
#
|
|
57
|
-
# Call this to request the command stop. The command checks +cancelled?+
|
|
58
|
-
# and stops at the next safe point.
|
|
59
|
-
#
|
|
60
|
-
# === Example
|
|
61
|
-
#
|
|
62
|
-
#--
|
|
63
|
-
# SPDX-SnippetBegin
|
|
64
|
-
# SPDX-FileCopyrightText: 2026 Kerrick Long
|
|
65
|
-
# SPDX-License-Identifier: MIT-0
|
|
66
|
-
#++
|
|
67
|
-
# token = CancellationToken.new
|
|
68
|
-
# token.cancel!
|
|
69
|
-
# token.cancelled? # => true
|
|
70
|
-
#--
|
|
71
|
-
# SPDX-SnippetEnd
|
|
72
|
-
#++
|
|
73
|
-
def cancel!
|
|
74
|
-
@mutex.synchronize do
|
|
75
|
-
current = @cancel_count
|
|
76
|
-
sleep 0 # Force context switch (enables thread-safety testing)
|
|
77
|
-
@cancel_count = current + 1
|
|
78
|
-
end
|
|
79
|
-
end
|
|
80
|
-
|
|
81
|
-
# Checks if cancellation was requested. Thread-safe.
|
|
82
|
-
#
|
|
83
|
-
# Commands call this periodically in their main loop. When it returns
|
|
84
|
-
# <tt>true</tt>, the command should clean up and exit.
|
|
85
|
-
#
|
|
86
|
-
# === Example
|
|
87
|
-
#
|
|
88
|
-
#--
|
|
89
|
-
# SPDX-SnippetBegin
|
|
90
|
-
# SPDX-FileCopyrightText: 2026 Kerrick Long
|
|
91
|
-
# SPDX-License-Identifier: MIT-0
|
|
92
|
-
#++
|
|
93
|
-
# until token.cancelled?
|
|
94
|
-
# do_work
|
|
95
|
-
# sleep 1
|
|
96
|
-
# end
|
|
97
|
-
#--
|
|
98
|
-
# SPDX-SnippetEnd
|
|
99
|
-
#++
|
|
100
|
-
def cancelled?
|
|
101
|
-
@cancel_count > 0
|
|
102
|
-
end
|
|
103
|
-
|
|
104
|
-
# Null object for commands that ignore cancellation.
|
|
105
|
-
#
|
|
106
|
-
# Some commands complete quickly and do not check for cancellation.
|
|
107
|
-
# Pass this when the command signature requires a token but the
|
|
108
|
-
# command does not use it.
|
|
109
|
-
#
|
|
110
|
-
# Ractor-shareable. Calling <tt>cancel!</tt> does nothing.
|
|
111
|
-
class NoneToken < Data.define(:cancelled?)
|
|
112
|
-
# Does nothing. Ignores cancellation requests.
|
|
113
|
-
#
|
|
114
|
-
# === Example
|
|
115
|
-
#
|
|
116
|
-
#--
|
|
117
|
-
# SPDX-SnippetBegin
|
|
118
|
-
# SPDX-FileCopyrightText: 2026 Kerrick Long
|
|
119
|
-
# SPDX-License-Identifier: MIT-0
|
|
120
|
-
#++
|
|
121
|
-
# CancellationToken::NONE.cancel! # => nil (no effect)
|
|
122
|
-
#--
|
|
123
|
-
# SPDX-SnippetEnd
|
|
124
|
-
#++
|
|
125
|
-
def cancel!
|
|
126
|
-
nil
|
|
127
|
-
end
|
|
128
|
-
end
|
|
129
|
-
|
|
130
|
-
# Singleton null token. Always returns <tt>cancelled? == false</tt>.
|
|
131
|
-
NONE = NoneToken.new(cancelled?: false)
|
|
132
|
-
end
|
|
133
|
-
end
|
|
134
|
-
end
|
|
135
|
-
end
|