ratatui_ruby-tea 0.2.0 → 0.3.1

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.
Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. data/AGENTS.md +17 -5
  3. data/CHANGELOG.md +74 -0
  4. data/README.md +18 -1
  5. data/Rakefile +1 -1
  6. data/Steepfile +3 -3
  7. data/doc/concepts/application_architecture.md +182 -3
  8. data/doc/contributors/design/commands_and_outlets.md +204 -0
  9. data/doc/contributors/kit-no-outlet.md +237 -0
  10. data/examples/app_fractal_dashboard/README.md +60 -0
  11. data/examples/app_fractal_dashboard/app.rb +67 -0
  12. data/examples/app_fractal_dashboard/bags/custom_shell_input.rb +77 -0
  13. data/examples/app_fractal_dashboard/bags/custom_shell_modal.rb +73 -0
  14. data/examples/app_fractal_dashboard/bags/custom_shell_output.rb +86 -0
  15. data/examples/app_fractal_dashboard/bags/disk_usage.rb +44 -0
  16. data/examples/app_fractal_dashboard/bags/network_panel.rb +45 -0
  17. data/examples/app_fractal_dashboard/bags/ping.rb +43 -0
  18. data/examples/app_fractal_dashboard/bags/stats_panel.rb +45 -0
  19. data/examples/app_fractal_dashboard/bags/system_info.rb +43 -0
  20. data/examples/app_fractal_dashboard/bags/uptime.rb +43 -0
  21. data/examples/app_fractal_dashboard/dashboard/base.rb +74 -0
  22. data/examples/app_fractal_dashboard/dashboard/update_helpers.rb +86 -0
  23. data/examples/app_fractal_dashboard/dashboard/update_manual.rb +87 -0
  24. data/examples/app_fractal_dashboard/dashboard/update_router.rb +43 -0
  25. data/examples/verify_readme_usage/README.md +1 -1
  26. data/examples/verify_readme_usage/app.rb +1 -1
  27. data/examples/{widget_cmd_exec → widget_command_system}/app.rb +18 -18
  28. data/lib/ratatui_ruby/tea/command/cancellation_token.rb +135 -0
  29. data/lib/ratatui_ruby/tea/command/custom.rb +106 -0
  30. data/lib/ratatui_ruby/tea/command/outlet.rb +127 -0
  31. data/lib/ratatui_ruby/tea/command.rb +367 -0
  32. data/lib/ratatui_ruby/tea/router.rb +405 -0
  33. data/lib/ratatui_ruby/tea/runtime.rb +147 -43
  34. data/lib/ratatui_ruby/tea/shortcuts.rb +51 -0
  35. data/lib/ratatui_ruby/tea/version.rb +1 -1
  36. data/lib/ratatui_ruby/tea.rb +59 -1
  37. data/rbs_collection.lock.yaml +124 -0
  38. data/rbs_collection.yaml +15 -0
  39. data/sig/examples/verify_readme_usage/app.rbs +1 -1
  40. data/sig/examples/{widget_cmd_exec → widget_command_system}/app.rbs +1 -1
  41. data/sig/open3.rbs +17 -0
  42. data/sig/ratatui_ruby/tea/command.rbs +163 -0
  43. data/sig/ratatui_ruby/tea/router.rbs +155 -0
  44. data/sig/ratatui_ruby/tea/runtime.rbs +29 -11
  45. data/sig/ratatui_ruby/tea/shortcuts.rbs +18 -0
  46. data/sig/ratatui_ruby/tea/version.rbs +10 -0
  47. data/sig/ratatui_ruby/tea.rbs +19 -7
  48. data/tasks/steep.rake +11 -0
  49. metadata +37 -8
  50. data/lib/ratatui_ruby/tea/cmd.rb +0 -88
  51. data/sig/ratatui_ruby/tea/cmd.rbs +0 -32
  52. /data/examples/{widget_cmd_exec → widget_command_system}/README.md +0 -0
@@ -0,0 +1,18 @@
1
+ #--
2
+ # SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
3
+ # SPDX-License-Identifier: LGPL-3.0-or-later
4
+ #++
5
+
6
+ module RatatuiRuby
7
+ module Tea
8
+ # Convenient short aliases for Tea APIs.
9
+ module Shortcuts
10
+ # Short alias for Command.
11
+ module Cmd
12
+ def self.exit: () -> Command::Exit
13
+ def self.sh: (String command, Symbol | Class tag) -> Command::System
14
+ def self.map: (Command::execution inner_command) { (Array[untyped]) -> Array[untyped] } -> Command::Mapped
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,10 @@
1
+ #--
2
+ # SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
3
+ # SPDX-License-Identifier: LGPL-3.0-or-later
4
+ #++
5
+
6
+ module RatatuiRuby
7
+ module Tea
8
+ VERSION: String
9
+ end
10
+ end
@@ -4,13 +4,25 @@
4
4
  #++
5
5
 
6
6
  module RatatuiRuby
7
+ # The Elm Architecture for RatatuiRuby.
7
8
  module Tea
8
- # See RatatuiRuby::Tea::Runtime.run
9
- def self.run: [M, Msg] (
10
- model: M,
11
- view: ^(M model, RatatuiRuby::TUI tui) -> untyped,
12
- update: ^(Msg msg, M model) -> (M | [M, Cmd::execution?] | [M, Cmd::Quit] | [M, nil]),
13
- ?init: ^() -> Msg
14
- ) -> M
9
+ # Starts the MVU event loop.
10
+ def self.run: [Model] (
11
+ model: Model,
12
+ view: ^(Model, RatatuiRuby::TUI) -> (RatatuiRuby::_CustomWidget | RatatuiRuby::widget),
13
+ update: ^(RatatuiRuby::Event, Model) -> Runtime::update_result?,
14
+ ?init: (^() -> untyped)?
15
+ ) -> Model
16
+
17
+ # Wraps a command with a routing prefix.
18
+ def self.route: (Command::execution command, Symbol prefix) -> Command::Mapped
19
+
20
+ # Delegates a prefixed message to a child bag's UPDATE.
21
+ def self.delegate: (
22
+ untyped message,
23
+ Symbol prefix,
24
+ ^(Array[untyped]?, untyped) -> [untyped, Command::execution?] child_update,
25
+ untyped child_model
26
+ ) -> ([untyped, Command::execution?] | nil)
15
27
  end
16
28
  end
data/tasks/steep.rake ADDED
@@ -0,0 +1,11 @@
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
+ desc "Run Steep type checker"
9
+ task :steep do
10
+ sh "bundle exec steep check"
11
+ 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.2.0
4
+ version: 0.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kerrick Long
@@ -15,14 +15,14 @@ dependencies:
15
15
  requirements:
16
16
  - - "~>"
17
17
  - !ruby/object:Gem::Version
18
- version: '0.9'
18
+ version: 0.10.1
19
19
  type: :runtime
20
20
  prerelease: false
21
21
  version_requirements: !ruby/object:Gem::Requirement
22
22
  requirements:
23
23
  - - "~>"
24
24
  - !ruby/object:Gem::Version
25
- version: '0.9'
25
+ version: 0.10.1
26
26
  - !ruby/object:Gem::Dependency
27
27
  name: ostruct
28
28
  requirement: !ruby/object:Gem::Requirement
@@ -94,6 +94,8 @@ files:
94
94
  - Steepfile
95
95
  - doc/concepts/application_architecture.md
96
96
  - doc/concepts/application_testing.md
97
+ - doc/contributors/design/commands_and_outlets.md
98
+ - doc/contributors/kit-no-outlet.md
97
99
  - doc/contributors/priorities.md
98
100
  - doc/custom.css
99
101
  - doc/getting_started/quickstart.md
@@ -101,25 +103,52 @@ files:
101
103
  - doc/images/verify_readme_usage.png
102
104
  - doc/images/widget_cmd_exec.png
103
105
  - doc/index.md
106
+ - examples/app_fractal_dashboard/README.md
107
+ - 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
+ - examples/app_fractal_dashboard/dashboard/base.rb
118
+ - examples/app_fractal_dashboard/dashboard/update_helpers.rb
119
+ - examples/app_fractal_dashboard/dashboard/update_manual.rb
120
+ - examples/app_fractal_dashboard/dashboard/update_router.rb
104
121
  - examples/verify_readme_usage/README.md
105
122
  - examples/verify_readme_usage/app.rb
106
- - examples/widget_cmd_exec/README.md
107
- - examples/widget_cmd_exec/app.rb
123
+ - examples/widget_command_system/README.md
124
+ - examples/widget_command_system/app.rb
108
125
  - exe/.gitkeep
109
126
  - lib/ratatui_ruby/tea.rb
110
- - lib/ratatui_ruby/tea/cmd.rb
127
+ - lib/ratatui_ruby/tea/command.rb
128
+ - lib/ratatui_ruby/tea/command/cancellation_token.rb
129
+ - lib/ratatui_ruby/tea/command/custom.rb
130
+ - lib/ratatui_ruby/tea/command/outlet.rb
131
+ - lib/ratatui_ruby/tea/router.rb
111
132
  - lib/ratatui_ruby/tea/runtime.rb
133
+ - lib/ratatui_ruby/tea/shortcuts.rb
112
134
  - lib/ratatui_ruby/tea/version.rb
113
135
  - mise.toml
136
+ - rbs_collection.lock.yaml
137
+ - rbs_collection.yaml
114
138
  - sig/examples/verify_readme_usage/app.rbs
115
- - sig/examples/widget_cmd_exec/app.rbs
139
+ - sig/examples/widget_command_system/app.rbs
140
+ - sig/open3.rbs
116
141
  - sig/ratatui_ruby/tea.rbs
117
- - sig/ratatui_ruby/tea/cmd.rbs
142
+ - sig/ratatui_ruby/tea/command.rbs
143
+ - sig/ratatui_ruby/tea/router.rbs
118
144
  - sig/ratatui_ruby/tea/runtime.rbs
145
+ - sig/ratatui_ruby/tea/shortcuts.rbs
146
+ - sig/ratatui_ruby/tea/version.rbs
119
147
  - tasks/example_viewer.html.erb
120
148
  - tasks/resources/build.yml.erb
121
149
  - tasks/resources/index.html.erb
122
150
  - tasks/resources/rubies.yml
151
+ - tasks/steep.rake
123
152
  - vendor/goodcop/base.yml
124
153
  homepage: https://sr.ht/~kerrick/ratatui_ruby/
125
154
  licenses:
@@ -1,88 +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
- # Commands represent side effects.
11
- #
12
- # The MVU pattern separates logic from effects. Your update function returns a pure
13
- # model transformation. Side effects go in commands. The runtime executes them.
14
- #
15
- # Commands produce **messages**, not callbacks. The +tag+ argument names the message
16
- # so your update function can pattern-match on it. This keeps all logic in +update+
17
- # and ensures messages are Ractor-shareable.
18
- #
19
- # === Examples
20
- #
21
- # # Terminate the application
22
- # [model, Cmd.quit]
23
- #
24
- # # Run a shell command; produces [:got_files, {stdout:, stderr:, status:}]
25
- # [model, Cmd.exec("ls -la", :got_files)]
26
- #
27
- # # No side effect
28
- # [model, nil]
29
- module Cmd
30
- # Sentinel value for application termination.
31
- #
32
- # The runtime detects this before dispatching. It breaks the loop immediately.
33
- Quit = Data.define
34
-
35
- # Creates a quit command.
36
- #
37
- # Returns a sentinel the runtime detects to terminate the application.
38
- #
39
- # === Example
40
- #
41
- # def update(msg, model)
42
- # case msg
43
- # in { type: :key, code: "q" }
44
- # [model, Cmd.quit]
45
- # else
46
- # [model, nil]
47
- # end
48
- # end
49
- def self.quit
50
- Quit.new
51
- end
52
-
53
- # Command to run a shell command via Open3.
54
- #
55
- # The runtime executes the command and produces a message:
56
- # <tt>[tag, {stdout:, stderr:, status:}]</tt>
57
- #
58
- # The +status+ is the integer exit code (0 = success).
59
- Exec = Data.define(:command, :tag)
60
-
61
- # Creates a shell execution command.
62
- #
63
- # [command] Shell command string to execute.
64
- # [tag] Symbol or class to tag the result message.
65
- #
66
- # When the command completes, the runtime sends
67
- # <tt>[tag, {stdout:, stderr:, status:}]</tt> to update.
68
- #
69
- # === Example
70
- #
71
- # # Return this from update:
72
- # [model.with(loading: true), Cmd.exec("ls -la", :got_files)]
73
- #
74
- # # Then handle it later:
75
- # def update(msg, model)
76
- # case msg
77
- # in [:got_files, {stdout:, status: 0}]
78
- # [model.with(files: stdout.lines), nil]
79
- # in [:got_files, {stderr:, status:}]
80
- # [model.with(error: stderr), nil]
81
- # end
82
- # end
83
- def self.exec(command, tag)
84
- Exec.new(command:, tag:)
85
- end
86
- end
87
- end
88
- end
@@ -1,32 +0,0 @@
1
- #--
2
- # SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
3
- # SPDX-License-Identifier: LGPL-3.0-or-later
4
- #++
5
-
6
- module RatatuiRuby
7
- module Tea
8
- module Cmd
9
- # Sentinel value for application termination.
10
- class Quit < Data
11
- def self.new: () -> instance
12
- end
13
-
14
- # Command to run a shell command via Open3.
15
- class Exec < Data
16
- attr_reader command: String
17
- attr_reader tag: Symbol | Class
18
-
19
- def self.new: (command: String, tag: (Symbol | Class)) -> instance
20
- end
21
-
22
- # Union type for all valid commands
23
- type execution = Exec
24
-
25
- # Creates a quit command.
26
- def self.quit: () -> Quit
27
-
28
- # Creates a shell execution command.
29
- def self.exec: (String command, (Symbol | Class) tag) -> Exec
30
- end
31
- end
32
- end