ratatui_ruby 0.1.0 → 0.2.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.
Files changed (72) hide show
  1. checksums.yaml +4 -4
  2. data/.builds/ruby-3.2.yml +52 -0
  3. data/.builds/ruby-3.3.yml +52 -0
  4. data/.builds/ruby-3.4.yml +52 -0
  5. data/.builds/ruby-4.0.0-preview3.yml +53 -0
  6. data/AGENTS.md +2 -2
  7. data/README.md +33 -13
  8. data/REUSE.toml +5 -0
  9. data/Rakefile +3 -100
  10. data/docs/images/examples-calendar_demo.rb.png +0 -0
  11. data/docs/images/examples-chart_demo.rb.png +0 -0
  12. data/docs/images/examples-list_styles.rb.png +0 -0
  13. data/docs/images/examples-quickstart_lifecycle.rb.png +0 -0
  14. data/docs/images/examples-stock_ticker.rb.png +0 -0
  15. data/docs/quickstart.md +57 -11
  16. data/examples/analytics.rb +2 -1
  17. data/examples/calendar_demo.rb +55 -0
  18. data/examples/chart_demo.rb +84 -0
  19. data/examples/list_styles.rb +66 -0
  20. data/examples/login_form.rb +2 -1
  21. data/examples/quickstart_dsl.rb +30 -0
  22. data/examples/quickstart_lifecycle.rb +40 -0
  23. data/examples/readme_usage.rb +21 -0
  24. data/examples/stock_ticker.rb +13 -5
  25. data/examples/system_monitor.rb +2 -1
  26. data/examples/test_calendar_demo.rb +66 -0
  27. data/examples/test_list_styles.rb +61 -0
  28. data/ext/ratatui_ruby/.cargo/config.toml +5 -0
  29. data/ext/ratatui_ruby/Cargo.lock +94 -1
  30. data/ext/ratatui_ruby/Cargo.toml +3 -2
  31. data/ext/ratatui_ruby/extconf.rb +1 -1
  32. data/ext/ratatui_ruby/src/events.rs +4 -1
  33. data/ext/ratatui_ruby/src/rendering.rs +4 -1
  34. data/ext/ratatui_ruby/src/terminal.rs +4 -6
  35. data/ext/ratatui_ruby/src/widgets/calendar.rs +81 -0
  36. data/ext/ratatui_ruby/src/widgets/chart.rs +253 -0
  37. data/ext/ratatui_ruby/src/widgets/list.rs +41 -4
  38. data/ext/ratatui_ruby/src/widgets/mod.rs +2 -1
  39. data/lib/ratatui_ruby/dsl.rb +62 -0
  40. data/lib/ratatui_ruby/schema/calendar.rb +26 -0
  41. data/lib/ratatui_ruby/schema/chart.rb +81 -0
  42. data/lib/ratatui_ruby/schema/list.rb +8 -2
  43. data/lib/ratatui_ruby/version.rb +1 -1
  44. data/lib/ratatui_ruby.rb +21 -1
  45. data/mise.toml +8 -0
  46. data/sig/ratatui_ruby/schema/calendar.rbs +13 -0
  47. data/sig/ratatui_ruby/schema/{line_chart.rbs → chart.rbs} +20 -1
  48. data/sig/ratatui_ruby/schema/list.rbs +4 -1
  49. data/tasks/bump/cargo_lockfile.rb +19 -0
  50. data/tasks/bump/manifest.rb +23 -0
  51. data/tasks/bump/ruby_gem.rb +39 -0
  52. data/tasks/bump/sem_ver.rb +28 -0
  53. data/tasks/bump.rake +45 -0
  54. data/tasks/doc.rake +24 -0
  55. data/tasks/extension.rake +12 -0
  56. data/tasks/lint.rake +49 -0
  57. data/tasks/rdoc_config.rb +15 -0
  58. data/tasks/resources/build.yml.erb +65 -0
  59. data/tasks/resources/index.html.erb +38 -0
  60. data/tasks/resources/rubies.yml +7 -0
  61. data/tasks/sourcehut.rake +29 -0
  62. data/tasks/test.rake +31 -0
  63. data/tasks/website/index_page.rb +28 -0
  64. data/tasks/website/version.rb +116 -0
  65. data/tasks/website/versioned_documentation.rb +48 -0
  66. data/tasks/website/website.rb +50 -0
  67. data/tasks/website.rake +26 -0
  68. metadata +51 -10
  69. data/.build.yml +0 -34
  70. data/.ruby-version +0 -1
  71. data/ext/ratatui_ruby/src/widgets/linechart.rs +0 -154
  72. data/lib/ratatui_ruby/schema/line_chart.rb +0 -41
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 996cd8cc08b1f95614ad8ff31c735fcee9150cebaa35ced2d844088e34730390
4
- data.tar.gz: 4156030673a39867c6a99036cb6618910110c0d287c94500d601047163d87524
3
+ metadata.gz: a5a3b028ff3dc634d6b77c5c0b13d63dcc1dc501f0cca3fd541499dbab8ca3a9
4
+ data.tar.gz: a8e6f86565a4dec484935444fa3f2a2e5e1691aaa8db5c5bd244c92f07e082fc
5
5
  SHA512:
6
- metadata.gz: 9d08516a876ec1265246ebbb2855e647e2fc50846756abb07a466a8506aaf1acf5b0547276faedc017b44795b9d237b4ac1003796209094868e627a482a0fbd3
7
- data.tar.gz: 573b6c07ba542e1f5399da620b502a09cc999f70ae4dfa14f49974994e3b22d3bff2458c2076aa920281c418a232984834fbb6f6fd306f1a2a951ac308158f91
6
+ metadata.gz: efcd43721bd3db1f115529deaabc40d7ec0549490b4bc899b0b0e9120399be5201892fd213dd799aa19c99d120674ecd2cea54afb53c58bfbb14a3bef3ceb6b2
7
+ data.tar.gz: 7b3abbb0dcefbab609c5fdeff706b28421215f15d48c272c065b47469d1095073686fdbd85045594c82bc7f528fe9bd2511b09984314ec44f5d2358adfec8827
@@ -0,0 +1,52 @@
1
+ # SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
2
+ # SPDX-License-Identifier: AGPL-3.0-or-later
3
+
4
+ image: alpine/edge
5
+ packages:
6
+ - bash
7
+ - build-base
8
+ - curl
9
+ - openssl-dev
10
+ - yaml-dev
11
+ - zlib-dev
12
+ - readline-dev
13
+ - gdbm-dev
14
+ - ncurses-dev
15
+ - libffi-dev
16
+ - clang-dev
17
+ - git
18
+ artifacts:
19
+ - ratatui_ruby/pkg/ratatui_ruby-0.2.0.gem
20
+ sources:
21
+ - https://git.sr.ht/~kerrick/ratatui_ruby
22
+ tasks:
23
+ - setup: |
24
+ curl https://mise.jdx.dev/install.sh | sh
25
+ echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.buildenv
26
+ echo 'eval "$($HOME/.local/bin/mise activate bash)"' >> ~/.buildenv
27
+ . ~/.buildenv
28
+ export RUSTFLAGS="-C target-feature=-crt-static"
29
+ export CI="true"
30
+ cd ratatui_ruby
31
+ sed -i 's/ruby = .*/ruby = "3.2"/' mise.toml
32
+ mise install
33
+ mise x -- pip install reuse
34
+ mise x -- gem install bundler
35
+ mise reshim
36
+ mise x -- bundle config set --local frozen 'true'
37
+ mise x -- bundle install
38
+ mise x -- bundle exec rake compile
39
+ - test: |
40
+ . ~/.buildenv
41
+ cd ratatui_ruby
42
+ echo "Testing Ruby 3.2"
43
+ mise x -- bundle exec rake test
44
+ - lint: |
45
+ . ~/.buildenv
46
+ cd ratatui_ruby
47
+ echo "Linting Ruby 3.2"
48
+ mise x -- bundle exec rake lint
49
+ - package: |
50
+ . ~/.buildenv
51
+ cd ratatui_ruby
52
+ mise x -- bundle exec rake build
@@ -0,0 +1,52 @@
1
+ # SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
2
+ # SPDX-License-Identifier: AGPL-3.0-or-later
3
+
4
+ image: alpine/edge
5
+ packages:
6
+ - bash
7
+ - build-base
8
+ - curl
9
+ - openssl-dev
10
+ - yaml-dev
11
+ - zlib-dev
12
+ - readline-dev
13
+ - gdbm-dev
14
+ - ncurses-dev
15
+ - libffi-dev
16
+ - clang-dev
17
+ - git
18
+ artifacts:
19
+ - ratatui_ruby/pkg/ratatui_ruby-0.2.0.gem
20
+ sources:
21
+ - https://git.sr.ht/~kerrick/ratatui_ruby
22
+ tasks:
23
+ - setup: |
24
+ curl https://mise.jdx.dev/install.sh | sh
25
+ echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.buildenv
26
+ echo 'eval "$($HOME/.local/bin/mise activate bash)"' >> ~/.buildenv
27
+ . ~/.buildenv
28
+ export RUSTFLAGS="-C target-feature=-crt-static"
29
+ export CI="true"
30
+ cd ratatui_ruby
31
+ sed -i 's/ruby = .*/ruby = "3.3"/' mise.toml
32
+ mise install
33
+ mise x -- pip install reuse
34
+ mise x -- gem install bundler
35
+ mise reshim
36
+ mise x -- bundle config set --local frozen 'true'
37
+ mise x -- bundle install
38
+ mise x -- bundle exec rake compile
39
+ - test: |
40
+ . ~/.buildenv
41
+ cd ratatui_ruby
42
+ echo "Testing Ruby 3.3"
43
+ mise x -- bundle exec rake test
44
+ - lint: |
45
+ . ~/.buildenv
46
+ cd ratatui_ruby
47
+ echo "Linting Ruby 3.3"
48
+ mise x -- bundle exec rake lint
49
+ - package: |
50
+ . ~/.buildenv
51
+ cd ratatui_ruby
52
+ mise x -- bundle exec rake build
@@ -0,0 +1,52 @@
1
+ # SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
2
+ # SPDX-License-Identifier: AGPL-3.0-or-later
3
+
4
+ image: alpine/edge
5
+ packages:
6
+ - bash
7
+ - build-base
8
+ - curl
9
+ - openssl-dev
10
+ - yaml-dev
11
+ - zlib-dev
12
+ - readline-dev
13
+ - gdbm-dev
14
+ - ncurses-dev
15
+ - libffi-dev
16
+ - clang-dev
17
+ - git
18
+ artifacts:
19
+ - ratatui_ruby/pkg/ratatui_ruby-0.2.0.gem
20
+ sources:
21
+ - https://git.sr.ht/~kerrick/ratatui_ruby
22
+ tasks:
23
+ - setup: |
24
+ curl https://mise.jdx.dev/install.sh | sh
25
+ echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.buildenv
26
+ echo 'eval "$($HOME/.local/bin/mise activate bash)"' >> ~/.buildenv
27
+ . ~/.buildenv
28
+ export RUSTFLAGS="-C target-feature=-crt-static"
29
+ export CI="true"
30
+ cd ratatui_ruby
31
+ sed -i 's/ruby = .*/ruby = "3.4"/' mise.toml
32
+ mise install
33
+ mise x -- pip install reuse
34
+ mise x -- gem install bundler
35
+ mise reshim
36
+ mise x -- bundle config set --local frozen 'true'
37
+ mise x -- bundle install
38
+ mise x -- bundle exec rake compile
39
+ - test: |
40
+ . ~/.buildenv
41
+ cd ratatui_ruby
42
+ echo "Testing Ruby 3.4"
43
+ mise x -- bundle exec rake test
44
+ - lint: |
45
+ . ~/.buildenv
46
+ cd ratatui_ruby
47
+ echo "Linting Ruby 3.4"
48
+ mise x -- bundle exec rake lint
49
+ - package: |
50
+ . ~/.buildenv
51
+ cd ratatui_ruby
52
+ mise x -- bundle exec rake build
@@ -0,0 +1,53 @@
1
+ # SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
2
+ # SPDX-License-Identifier: AGPL-3.0-or-later
3
+
4
+ image: alpine/edge
5
+ packages:
6
+ - bash
7
+ - build-base
8
+ - curl
9
+ - openssl-dev
10
+ - yaml-dev
11
+ - zlib-dev
12
+ - readline-dev
13
+ - gdbm-dev
14
+ - ncurses-dev
15
+ - libffi-dev
16
+ - clang-dev
17
+ - git
18
+ artifacts:
19
+ - ratatui_ruby/pkg/ratatui_ruby-0.2.0.gem
20
+ sources:
21
+ - https://git.sr.ht/~kerrick/ratatui_ruby
22
+ tasks:
23
+ - setup: |
24
+ curl https://mise.jdx.dev/install.sh | sh
25
+ echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.buildenv
26
+ echo 'eval "$($HOME/.local/bin/mise activate bash)"' >> ~/.buildenv
27
+ . ~/.buildenv
28
+ export RUSTFLAGS="-C target-feature=-crt-static"
29
+ export CI="true"
30
+ cd ratatui_ruby
31
+ sed -i 's/ruby = .*/ruby = "4.0.0-preview3"/' mise.toml
32
+ mise install
33
+ mise x -- pip install reuse
34
+ mise x -- gem install bundler
35
+ mise reshim
36
+ mise x -- bundle config set --local frozen 'true'
37
+ mise x -- bundle install
38
+ # We allow this to fail so we can see logs without stopping the CI pipeline
39
+ mise x -- bundle exec rake compile || echo "⚠️ Compilation failed (Allowed Failure)"
40
+ - test: |
41
+ . ~/.buildenv
42
+ cd ratatui_ruby
43
+ echo "Testing Ruby 4.0.0-preview3"
44
+ mise x -- bundle exec rake test || true
45
+ - lint: |
46
+ . ~/.buildenv
47
+ cd ratatui_ruby
48
+ echo "Linting Ruby 4.0.0-preview3"
49
+ mise x -- bundle exec rake lint || true
50
+ - package: |
51
+ . ~/.buildenv
52
+ cd ratatui_ruby
53
+ mise x -- bundle exec rake build
data/AGENTS.md CHANGED
@@ -35,14 +35,14 @@ Every file must begin with an SPDX-compliant header. Use the following format:
35
35
 
36
36
  ### Ruby Standards
37
37
 
38
- - **Version:** Strict Ruby 3.4 compatibility (Target `3.4.7` as per cosmoruby).
38
+ - **Version:** Tested against the latest releases of Ruby 3.2, 3.3, and 3.4, and must work. Also tested in CI (with allowed failures) against the latest preview Ruby 4.0 to prepare for its release. Local development happens on the latest stable release.
39
39
  - **Linter:** Run via `rake lint`. You are not done until all linting passes.
40
40
  - **Style:**
41
41
  - Use `Data.define` for all value objects (UI Nodes). (Prefer `class Foo < Data.define()` over `Foo = Data.define() do`).
42
42
  - Prefer `frozen_string_literal: true`.
43
43
  - Use `Minitest` for testing.
44
44
  - Define types in `.rbs` files. Don't use `untyped` just because it's easy; be comprehensive and accurate. Do not include `initialize` in `.rbs` files; use `self.new` for constructors instead.
45
- - Every line of Ruby must be covered by tests that would stand up to mutation testing. This includes all examples in the `examples/` directory; they should have corresponding tests in `examples/` to ensure they continue to work as intended and serve as reliable documentation. Tests must be meaningful and verify specific behavior or rendering output; simply verifying that code "doesn't crash" is insufficient and unacceptable.
45
+ - Every line of Ruby must be covered by tests that would stand up to mutation testing. This includes all examples in the `examples/` directory; they should have corresponding tests in `examples/` to ensure they continue to work as intended and serve as reliable documentation. Tests must be meaningful and verify specific behavior or rendering output; simply verifying that code "doesn't crash" is insufficient and unacceptable. For UI widgets, this means using `with_test_terminal` to verify every character of the terminal buffer's content.
46
46
  - Every public Ruby class/method must be documented for humans in RDoc (preferred)--**not** YARD--or markdown files (fallback), and must have `*.rbs` types defined.
47
47
  - Every significant architectural and design decision must be documented for contributors in markdown files. Mermaid is allowed.
48
48
 
data/README.md CHANGED
@@ -4,13 +4,21 @@
4
4
  -->
5
5
  # ratatui_ruby
6
6
 
7
- > [!NOTE]
8
- > **ratatui_ruby** is a community wrapper that is not affiliated with [the Ratatui team](https://github.com/orgs/ratatui/people).
7
+ [![
8
+ builds.sr.ht status](https://builds.sr.ht/~kerrick/ratatui_ruby.svg)](https://builds.sr.ht/~kerrick/ratatui_ruby?) [![
9
+ License](https://img.shields.io/badge/dynamic/regex?url=https%3A%2F%2Fgit.sr.ht%2F~kerrick%2Fratatui_ruby%2Fblob%2Fmain%2Fratatui_ruby.gemspec&search=spec%5C.license%20%3D%20%22(.*)%22&replace=%241&label=License&color=a2c93e)](https://spdx.org/licenses/AGPL-3.0-or-later.html) [![
10
+ Gem Total Downloads](https://img.shields.io/gem/dt/ratatui_ruby)](https://rubygems.org/gems/ratatui_ruby) [![
11
+ Gem Version](https://img.shields.io/gem/v/ratatui_ruby)](https://rubygems.org/gems/ratatui_ruby) [![
12
+ Ratatui Version](https://img.shields.io/badge/dynamic/toml?url=https%3A%2F%2Fgit.sr.ht%2F~kerrick%2Fratatui_ruby%2Fblob%2Fmain%2Fext%2Fratatui_ruby%2FCargo.toml&query=%24.dependencies.ratatui.version&prefix=v&logo=ratatui&label=Ratatui)](https://crates.io/crates/ratatui/0.26.3) [![
13
+ Mailing List: Discussion](https://img.shields.io/badge/mailing_list-discussion-5865F2.svg?logo=data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9IiNmZmZmZmYiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBjbGFzcz0iaWNvbiBpY29uLXRhYmxlciBpY29ucy10YWJsZXItb3V0bGluZSBpY29uLXRhYmxlci1tYWlsIj48cGF0aCBzdHJva2U9Im5vbmUiIGQ9Ik0wIDBoMjR2MjRIMHoiIGZpbGw9Im5vbmUiLz48cGF0aCBkPSJNMyA3YTIgMiAwIDAgMSAyIC0yaDE0YTIgMiAwIDAgMSAyIDJ2MTBhMiAyIDAgMCAxIC0yIDJoLTE0YTIgMiAwIDAgMSAtMiAtMnYtMTB6IiAvPjxwYXRoIGQ9Ik0zIDdsOSA2bDkgLTYiIC8+PC9zdmc+Cg==)](https://lists.sr.ht/~kerrick/ratatui_ruby-discuss) [![
14
+ Mailing List: Development](https://img.shields.io/badge/mailing_list-development-4954d5.svg?logo=data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9IiNmZmZmZmYiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBjbGFzcz0iaWNvbiBpY29uLXRhYmxlciBpY29ucy10YWJsZXItb3V0bGluZSBpY29uLXRhYmxlci1tYWlsIj48cGF0aCBzdHJva2U9Im5vbmUiIGQ9Ik0wIDBoMjR2MjRIMHoiIGZpbGw9Im5vbmUiLz48cGF0aCBkPSJNMyA3YTIgMiAwIDAgMSAyIC0yaDE0YTIgMiAwIDAgMSAyIDJ2MTBhMiAyIDAgMCAxIC0yIDJoLTE0YTIgMiAwIDAgMSAtMiAtMnYtMTB6IiAvPjxwYXRoIGQ9Ik0zIDdsOSA2bDkgLTYiIC8+PC9zdmc+Cg==)](https://lists.sr.ht/~kerrick/ratatui_ruby-devel) [![
15
+ Mailing List: Announcements](https://img.shields.io/badge/mailing_list-announcements-3b44ac.svg?logo=data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9IiNmZmZmZmYiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBjbGFzcz0iaWNvbiBpY29uLXRhYmxlciBpY29ucy10YWJsZXItb3V0bGluZSBpY29uLXRhYmxlci1tYWlsIj48cGF0aCBzdHJva2U9Im5vbmUiIGQ9Ik0wIDBoMjR2MjRIMHoiIGZpbGw9Im5vbmUiLz48cGF0aCBkPSJNMyA3YTIgMiAwIDAgMSAyIC0yaDE0YTIgMiAwIDAgMSAyIDJ2MTBhMiAyIDAgMCAxIC0yIDJoLTE0YTIgMiAwIDAgMSAtMiAtMnYtMTB6IiAvPjxwYXRoIGQ9Ik0zIDdsOSA2bDkgLTYiIC8+PC9zdmc+Cg==)](https://lists.sr.ht/~kerrick/ratatui_ruby-announce)
9
16
 
10
17
 
11
18
  ## Introduction
12
19
 
13
20
  **ratatui_ruby** is a Ruby wrapper for [Ratatui](https://ratatui.rs). It allows you to cook up Terminal User Interfaces in Ruby.
21
+ **ratatui_ruby** is a community wrapper that is not affiliated with [the Ratatui team](https://github.com/orgs/ratatui/people).
14
22
 
15
23
  > [!WARNING]
16
24
  > **ratatui_ruby** is currently in an early stage of development. Use at your own risk.
@@ -25,13 +33,17 @@ Please join our **announce** mailing list at https://lists.sr.ht/~kerrick/ratatu
25
33
  - GNU/Linux, macOS, Windows, OpenBSD, and FreeBSD; and
26
34
  - x86_64 (AMD, Intel) and ARM (Apple Silicon, Raspberry Pi).
27
35
 
36
+ We support the latest minor version of every
37
+ [non-eol Ruby version](https://www.ruby-lang.org/en/downloads/branches/),
38
+ plus the latest preview of the next version.
39
+
28
40
 
29
41
  ## Installation
30
42
 
31
43
  Add this line to your application's Gemfile:
32
44
 
33
45
  ```ruby
34
- gem 'ratatui_ruby'
46
+ gem "ratatui_ruby"
35
47
  ```
36
48
 
37
49
  And then execute:
@@ -40,7 +52,7 @@ And then execute:
40
52
  bundle install
41
53
  ```
42
54
 
43
- Or install it yourself as:
55
+ Or install it yourself with:
44
56
 
45
57
  ```bash
46
58
  gem install ratatui_ruby
@@ -49,16 +61,22 @@ gem install ratatui_ruby
49
61
 
50
62
  ## Usage
51
63
 
52
- **ratatui_ruby** uses an immediate-mode API. You describe your UI using Ruby `Data` objects and call `draw` in a loop.
64
+ **ratatui_ruby** uses an immediate-mode API. You describe your UI using Ruby objects and call `draw` in a loop.
53
65
 
54
66
  ```ruby
55
- RatatuiRuby.init_terminal
56
- begin
57
- view = RatatuiRuby::Paragraph.new(text: "Hello World", block: RatatuiRuby::Block.new(borders: [:all]))
58
- RatatuiRuby.draw(view)
59
- sleep 2
60
- ensure
61
- RatatuiRuby.restore_terminal
67
+ require "ratatui_ruby"
68
+ RatatuiRuby.main_loop do |tui|
69
+ tui.draw \
70
+ tui.paragraph \
71
+ text: "Hello, Ratatui! Press 'q' to quit.",
72
+ align: :center,
73
+ block: tui.block(
74
+ title: "My Ruby TUI App",
75
+ borders: [:all],
76
+ border_color: "cyan"
77
+ )
78
+ event = tui.poll_event
79
+ break if event && event[:type] == :key && event[:code] == "q"
62
80
  end
63
81
  ```
64
82
 
@@ -83,4 +101,6 @@ Want to help develop **ratatui_ruby**? Check out our [contribution guide](./CONT
83
101
 
84
102
  **ratatui_ruby** is copyright 2025, Kerrick Long. **ratatui_ruby** is licensed under the GNU Affero General Public License v3.0 or later; see [LICENSES/AGPL-3.0-or-later.txt](./LICENSES/AGPL-3.0-or-later) for the full text.
85
103
 
86
- Some parts of this program are copied from other sources under appropriate reuse licenses, and the copyright belongs to their respective owners. See the [REUSE Specification – Version 3.3](https://reuse.software/spec-3.3/) for information about how we comply with attribution and licensing requirements.
104
+ Some parts of this program are copied from other sources under appropriate reuse licenses, and the copyright belongs to their respective owners. See the [REUSE Specification – Version 3.3](https://reuse.software/spec-3.3/) for information about how we comply with attribution and licensing requirements.
105
+
106
+ This program was created with significant assistance from multiple LLMs. The process was human-controlled through creative prompts, with human contributions to each commit. See commit footers for model attribution. [declare-ai.org](https://declare-ai.org/1.0.0/creative.html)
data/REUSE.toml CHANGED
@@ -15,3 +15,8 @@ SPDX-License-Identifier = "CC0-1.0"
15
15
  path = 'ext/ratatui_ruby/Cargo.lock'
16
16
  SPDX-FileCopyrightText = "2025 Kerrick Long <me@kerricklong.com>"
17
17
  SPDX-License-Identifier = "CC0-1.0"
18
+
19
+ [[annotations]]
20
+ path = 'docs/images/*.png'
21
+ SPDX-FileCopyrightText = "2025 Kerrick Long <me@kerricklong.com>"
22
+ SPDX-License-Identifier = "CC-BY-SA-4.0"
data/Rakefile CHANGED
@@ -4,105 +4,8 @@
4
4
  # SPDX-License-Identifier: AGPL-3.0-or-later
5
5
 
6
6
  require "bundler/gem_tasks"
7
- require "minitest/test_task"
8
7
 
9
- # Ruby tests are handled by test:ruby
10
- # Cargo tests are handled by test:rust
8
+ # Import all tasks from the tasks/ directory
9
+ Dir.glob("tasks/*.rake").each { |r| import r }
11
10
 
12
- require "rake/extensiontask"
13
-
14
- spec = Gem::Specification.load("ratatui_ruby.gemspec")
15
- Rake::ExtensionTask.new("ratatui_ruby", spec) do |ext|
16
- ext.lib_dir = "lib/ratatui_ruby"
17
- ext.ext_dir = "ext/ratatui_ruby"
18
- end
19
-
20
- # The :compile task is now provided by rake-compiler
21
-
22
- require "rubocop/rake_task"
23
-
24
- RuboCop::RakeTask.new
25
-
26
- require "rdoc/task"
27
-
28
- RDoc::Task.new do |rdoc|
29
- rdoc.rdoc_dir = "doc"
30
- rdoc.main = "README.md"
31
- rdoc.rdoc_files.include("**/*.md", "**/*.rdoc", "lib/**/*.rb", "exe/**/*")
32
- end
33
-
34
- Rake::Task[:rdoc].enhance do
35
- FileUtils.mkdir_p "doc/docs/images"
36
- FileUtils.cp_r FileList["docs/images/*.png"], "doc/docs/images"
37
- end
38
-
39
- Rake::Task[:rerdoc].enhance do
40
- FileUtils.mkdir_p "doc/docs/images"
41
- FileUtils.cp_r FileList["docs/images/*.png"], "doc/docs/images"
42
- end
43
-
44
- require "rubycritic/rake_task"
45
-
46
- RubyCritic::RakeTask.new do |task|
47
- task.options = "--no-browser"
48
- task.paths = FileList.new.include("exe/**/*.rb", "lib/**/*.rb", "sig/**/*.rbs")
49
- end
50
-
51
- require "inch/rake"
52
-
53
- Inch::Rake::Suggest.new("doc:suggest", "exe/**/*.rb", "lib/**/*.rb", "sig/**/*.rbs") do |suggest|
54
- suggest.args << ""
55
- end
56
-
57
- namespace :cargo do
58
- desc "Run cargo fmt"
59
- task :fmt do
60
- sh "cd ext/ratatui_ruby && cargo fmt --all -- --check"
61
- end
62
-
63
- desc "Run cargo clippy"
64
- task :clippy do
65
- sh "cd ext/ratatui_ruby && cargo clippy -- -D warnings"
66
- end
67
-
68
- desc "Run cargo tests"
69
- task :test do
70
- sh "cd ext/ratatui_ruby && cargo test"
71
- end
72
- end
73
-
74
- namespace :reuse do
75
- desc "Run the REUSE Tool to confirm REUSE compliance"
76
- task :lint do
77
- sh "pipx run reuse lint"
78
- end
79
- end
80
- task(:reuse) { Rake::Task["reuse:lint"].invoke }
81
-
82
- namespace :lint do
83
- multitask docs: %i[rubycritic rdoc:coverage reuse:lint]
84
- multitask code: %i[rubocop rubycritic cargo:fmt cargo:clippy cargo:test]
85
- multitask licenses: %i[reuse:lint]
86
- multitask all: %i[docs code licenses]
87
- end
88
- task(:lint) { Rake::Task["lint:all"].invoke }
89
-
90
- # Clear the default test task created by Minitest::TestTask
91
- Rake::Task["test"].clear
92
-
93
- desc "Run all tests (Ruby and Rust)"
94
- task test: %w[test:ruby test:rust]
95
-
96
- namespace :test do
97
- desc "Run Rust tests"
98
- task :rust do
99
- Rake::Task["cargo:test"].invoke
100
- end
101
-
102
- # Create a specific Minitest task for Ruby tests
103
- Minitest::TestTask.create(:ruby) do |t|
104
- t.test_globs = ["test/**/test_*.rb", "examples/**/test_*.rb"]
105
- end
106
- end
107
-
108
- multitask default: %i[test lint]
11
+ task default: %w[sourcehut test lint]
data/docs/quickstart.md CHANGED
@@ -11,7 +11,7 @@ Welcome to **ratatui_ruby**! This guide will help you get up and running with yo
11
11
  Add this line to your application's Gemfile:
12
12
 
13
13
  ```ruby
14
- gem 'ratatui_ruby'
14
+ gem "ratatui_ruby"
15
15
  ```
16
16
 
17
17
  And then execute:
@@ -32,10 +32,10 @@ Here is a "Hello World" application that demonstrates the core lifecycle of a **
32
32
 
33
33
  ```ruby
34
34
  require "ratatui_ruby"
35
-
35
+
36
36
  # 1. Initialize the terminal
37
37
  RatatuiRuby.init_terminal
38
-
38
+
39
39
  begin
40
40
  # The Main Loop
41
41
  loop do
@@ -43,17 +43,17 @@ begin
43
43
  # We define a Paragraph widget inside a Block with a title and borders.
44
44
  view = RatatuiRuby::Paragraph.new(
45
45
  text: "Hello, Ratatui! Press 'q' to quit.",
46
+ align: :center,
46
47
  block: RatatuiRuby::Block.new(
47
- title: "My First App",
48
+ title: "My Ruby TUI App",
48
49
  borders: [:all],
49
- border_style: "cyan"
50
- ),
51
- alignment: :center
50
+ border_color: "cyan"
51
+ )
52
52
  )
53
-
53
+
54
54
  # 3. Draw the UI
55
55
  RatatuiRuby.draw(view)
56
-
56
+
57
57
  # 4. Poll for events
58
58
  event = RatatuiRuby.poll_event
59
59
  if event && event[:type] == :key && event[:code] == "q"
@@ -66,6 +66,8 @@ ensure
66
66
  end
67
67
  ```
68
68
 
69
+ ![Basic Application Screenshot](./images/examples-quickstart_lifecycle.rb.png)
70
+
69
71
  ### How it works
70
72
 
71
73
  1. **`RatatuiRuby.init_terminal`**: Enters raw mode and switches to the alternate screen.
@@ -73,7 +75,42 @@ end
73
75
  3. **`RatatuiRuby.draw(view)`**: The Ruby UI tree is passed to the Rust backend, which renders it to the terminal.
74
76
  4. **`RatatuiRuby.poll_event`**: Checks for keyboard, mouse, or resize events.
75
77
  5. **`RatatuiRuby.restore_terminal`**: Crucial for leaving raw mode and returning the user to their shell properly. Always wrap your loop in a `begin...ensure` block to guarantee this runs.
76
- 6. **`sleep 0.05`**: In a real app, you'd want to control your frame rate to avoid consuming 100% CPU.
78
+
79
+ ### DSL
80
+
81
+ A small DSL is provided for convenience when writing scripts.
82
+
83
+ ```rb
84
+ require "ratatui_ruby"
85
+
86
+ # 1. Initialize the terminal, start the main loop, and ensure the terminal is restored.
87
+ RatatuiRuby.main_loop do |tui|
88
+ # 2. Create your UI with methods instead of classes.
89
+ view = tui.paragraph(
90
+ text: "Hello, Ratatui! Press 'q' to quit.",
91
+ align: :center,
92
+ block: tui.block(
93
+ title: "My Ruby TUI App",
94
+ borders: [:all],
95
+ border_color: "cyan"
96
+ )
97
+ )
98
+
99
+ # 3. Use RatatuiRuby methods, too.
100
+ tui.draw(view)
101
+ event = tui.poll_event
102
+
103
+ if event && event[:type] == :key && event[:code] == "q"
104
+ break
105
+ end
106
+ end
107
+ ```
108
+
109
+ #### How it works
110
+
111
+ 1. **`RatatuiRuby.main_loop`**: This helper method manages the entire terminal lifecycle for you. It initializes the terminal before the block starts and ensures `restore_terminal` is called when the block exits (even if an error occurs).
112
+ 2. **Widget Shorthand**: The block yields a special DSL object (here named `tui`). This object provides factory methods for every widget, allowing you to write `tui.paragraph(...)` instead of the more verbose `RatatuiRuby::Paragraph.new(...)`.
113
+ 3. **Method SHorthand**: The DSL object also provides aliases for module functions of `RatatuiRuby`, allowing you to write `tui.draw(...)` instead of the more verbose `RatatuiRuby::draw(...)`.
77
114
 
78
115
  ## Examples
79
116
 
@@ -89,11 +126,20 @@ A simple demonstration of `Block` and `Paragraph` widgets, reacting to arrow key
89
126
 
90
127
  ![Box Demo Screenshot](./images/examples-box_demo.rb.png)
91
128
 
129
+ ### [Calendar Demo](https://git.sr.ht/~kerrick/ratatui_ruby/tree/main/item/examples/calendar_demo.rb)
130
+ A simple demo application for the `Calendar` widget.
131
+
132
+ ### [Chart Demo](https://git.sr.ht/~kerrick/ratatui_ruby/tree/main/item/examples/chart_demo.rb)
133
+ Demonstrates the `Chart` widget with both scatter and line datasets, including custom axes.
134
+
92
135
  ### [Dashboard](https://git.sr.ht/~kerrick/ratatui_ruby/tree/main/item/examples/dashboard.rb)
93
136
  Uses `Layout`, `List`, and `Paragraph` to create a classic sidebar-and-content interface.
94
137
 
95
138
  ![Dashboard Screenshot](./images/examples-dashboard.rb.png)
96
139
 
140
+ ### [List Styles](https://git.sr.ht/~kerrick/ratatui_ruby/tree/main/item/examples/list_styles.rb)
141
+ Showcases advanced styling options for the `List` widget, including selection highlighting.
142
+
97
143
  ### [Login Form](https://git.sr.ht/~kerrick/ratatui_ruby/tree/main/item/examples/login_form.rb)
98
144
  Shows how to use `Overlay`, `Center`, and `Cursor` to build a modal login form with text input.
99
145
 
@@ -115,7 +161,7 @@ A simple example of integrating the `Scrollbar` widget and handling mouse wheel
115
161
  ![Scrollbar Demo Screenshot](./images/examples-scrollbar_demo.rb.png)
116
162
 
117
163
  ### [Stock Ticker](https://git.sr.ht/~kerrick/ratatui_ruby/tree/main/item/examples/stock_ticker.rb)
118
- Utilizes `Sparkline` and `LineChart` widgets to visualize real-time (simulated) data.
164
+ Utilizes `Sparkline` and `Chart` widgets to visualize real-time (simulated) data.
119
165
 
120
166
  ![Stock Ticker Screenshot](./images/examples-stock_ticker.rb.png)
121
167
 
@@ -3,7 +3,8 @@
3
3
  # SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
4
4
  # SPDX-License-Identifier: AGPL-3.0-or-later
5
5
 
6
- require_relative "../lib/ratatui_ruby"
6
+ $LOAD_PATH.unshift File.expand_path("../lib", __dir__)
7
+ require "ratatui_ruby"
7
8
 
8
9
  # Analytics Dashboard Example
9
10
  # Demonstrates Tabs and BarChart widgets.
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ # SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
4
+ # SPDX-License-Identifier: AGPL-3.0-or-later
5
+
6
+ $LOAD_PATH.unshift File.expand_path("../lib", __dir__)
7
+ require "ratatui_ruby"
8
+
9
+ # A demo application for the Calendar widget.
10
+ module CalendarDemo
11
+ def self.run
12
+ RatatuiRuby.init_terminal
13
+
14
+ loop do
15
+ now = Time.now
16
+ calendar = RatatuiRuby::Calendar.new(
17
+ year: now.year,
18
+ month: now.month,
19
+ header_style: RatatuiRuby::Style.new(fg: "yellow", modifiers: [:bold]),
20
+ block: RatatuiRuby::Block.new(title: " Calendar (q = quit) ", borders: [:all])
21
+ )
22
+
23
+ # Constrain the calendar to 24x10 characters
24
+ view = RatatuiRuby::Layout.new(
25
+ direction: :vertical,
26
+ constraints: [
27
+ RatatuiRuby::Constraint.length(10),
28
+ RatatuiRuby::Constraint.min(0),
29
+ ],
30
+ children: [
31
+ RatatuiRuby::Layout.new(
32
+ direction: :horizontal,
33
+ constraints: [
34
+ RatatuiRuby::Constraint.length(24),
35
+ RatatuiRuby::Constraint.min(0),
36
+ ],
37
+ children: [calendar, nil],
38
+ ),
39
+ nil,
40
+ ],
41
+ )
42
+
43
+ RatatuiRuby.draw(view)
44
+
45
+ event = RatatuiRuby.poll_event
46
+ break if event && event[:type] == :key && event[:code] == "q"
47
+
48
+ sleep 0.1
49
+ end
50
+ ensure
51
+ RatatuiRuby.restore_terminal
52
+ end
53
+ end
54
+
55
+ CalendarDemo.run if __FILE__ == $PROGRAM_NAME