ratatui_ruby 0.1.0 → 0.3.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/.builds/ruby-3.2.yml +52 -0
- data/.builds/ruby-3.3.yml +52 -0
- data/.builds/ruby-3.4.yml +52 -0
- data/.builds/ruby-4.0.0.yml +53 -0
- data/.pre-commit-config.yaml +9 -2
- data/AGENTS.md +53 -5
- data/CHANGELOG.md +51 -1
- data/README.md +38 -18
- data/REUSE.toml +5 -0
- data/Rakefile +3 -100
- data/{docs → doc}/contributors/index.md +2 -1
- data/doc/custom.css +8 -0
- data/doc/images/examples-calendar_demo.rb.png +0 -0
- data/doc/images/examples-chart_demo.rb.png +0 -0
- data/doc/images/examples-custom_widget.rb.png +0 -0
- data/doc/images/examples-list_styles.rb.png +0 -0
- data/doc/images/examples-popup_demo.rb.gif +0 -0
- data/doc/images/examples-quickstart_lifecycle.rb.png +0 -0
- data/doc/images/examples-scroll_text.rb.png +0 -0
- data/doc/images/examples-stock_ticker.rb.png +0 -0
- data/doc/images/examples-table_select.rb.png +0 -0
- data/{docs → doc}/index.md +1 -1
- data/{docs → doc}/quickstart.md +81 -11
- data/examples/analytics.rb +2 -1
- data/examples/calendar_demo.rb +55 -0
- data/examples/chart_demo.rb +84 -0
- data/examples/custom_widget.rb +43 -0
- data/examples/list_styles.rb +66 -0
- data/examples/login_form.rb +2 -1
- data/examples/popup_demo.rb +105 -0
- data/examples/quickstart_dsl.rb +30 -0
- data/examples/quickstart_lifecycle.rb +40 -0
- data/examples/readme_usage.rb +21 -0
- data/examples/scroll_text.rb +74 -0
- data/examples/stock_ticker.rb +13 -5
- data/examples/system_monitor.rb +2 -1
- data/examples/table_select.rb +70 -0
- data/examples/test_calendar_demo.rb +66 -0
- data/examples/test_list_styles.rb +61 -0
- data/examples/test_popup_demo.rb +62 -0
- data/examples/test_scroll_text.rb +130 -0
- data/examples/test_table_select.rb +37 -0
- data/ext/ratatui_ruby/.cargo/config.toml +5 -0
- data/ext/ratatui_ruby/Cargo.lock +260 -50
- data/ext/ratatui_ruby/Cargo.toml +5 -4
- data/ext/ratatui_ruby/extconf.rb +1 -1
- data/ext/ratatui_ruby/src/buffer.rs +54 -0
- data/ext/ratatui_ruby/src/events.rs +115 -107
- data/ext/ratatui_ruby/src/lib.rs +15 -6
- data/ext/ratatui_ruby/src/rendering.rs +18 -1
- data/ext/ratatui_ruby/src/style.rs +2 -1
- data/ext/ratatui_ruby/src/terminal.rs +27 -24
- data/ext/ratatui_ruby/src/widgets/calendar.rs +82 -0
- data/ext/ratatui_ruby/src/widgets/canvas.rs +1 -2
- data/ext/ratatui_ruby/src/widgets/center.rs +0 -2
- data/ext/ratatui_ruby/src/widgets/chart.rs +260 -0
- data/ext/ratatui_ruby/src/widgets/clear.rs +37 -0
- data/ext/ratatui_ruby/src/widgets/cursor.rs +1 -1
- data/ext/ratatui_ruby/src/widgets/layout.rs +2 -1
- data/ext/ratatui_ruby/src/widgets/list.rs +44 -5
- data/ext/ratatui_ruby/src/widgets/mod.rs +3 -1
- data/ext/ratatui_ruby/src/widgets/overlay.rs +2 -1
- data/ext/ratatui_ruby/src/widgets/paragraph.rs +10 -0
- data/ext/ratatui_ruby/src/widgets/table.rs +25 -6
- data/ext/ratatui_ruby/src/widgets/tabs.rs +2 -1
- data/lib/ratatui_ruby/dsl.rb +64 -0
- data/lib/ratatui_ruby/schema/calendar.rb +26 -0
- data/lib/ratatui_ruby/schema/chart.rb +81 -0
- data/lib/ratatui_ruby/schema/clear.rb +83 -0
- data/lib/ratatui_ruby/schema/list.rb +8 -2
- data/lib/ratatui_ruby/schema/paragraph.rb +7 -4
- data/lib/ratatui_ruby/schema/rect.rb +24 -0
- data/lib/ratatui_ruby/schema/table.rb +8 -2
- data/lib/ratatui_ruby/version.rb +1 -1
- data/lib/ratatui_ruby.rb +24 -2
- data/mise.toml +8 -0
- data/sig/ratatui_ruby/buffer.rbs +11 -0
- data/sig/ratatui_ruby/schema/calendar.rbs +13 -0
- data/sig/ratatui_ruby/schema/{line_chart.rbs → chart.rbs} +20 -1
- data/sig/ratatui_ruby/schema/list.rbs +4 -1
- data/sig/ratatui_ruby/schema/rect.rbs +14 -0
- data/tasks/bump/cargo_lockfile.rb +19 -0
- data/tasks/bump/changelog.rb +37 -0
- data/tasks/bump/comparison_links.rb +41 -0
- data/tasks/bump/header.rb +30 -0
- data/tasks/bump/history.rb +30 -0
- data/tasks/bump/manifest.rb +31 -0
- data/tasks/bump/ruby_gem.rb +35 -0
- data/tasks/bump/sem_ver.rb +34 -0
- data/tasks/bump/unreleased_section.rb +38 -0
- data/tasks/bump.rake +49 -0
- data/tasks/doc.rake +25 -0
- data/tasks/extension.rake +12 -0
- data/tasks/lint.rake +49 -0
- data/tasks/rdoc_config.rb +15 -0
- data/tasks/resources/build.yml.erb +65 -0
- data/tasks/resources/index.html.erb +38 -0
- data/tasks/resources/rubies.yml +7 -0
- data/tasks/sourcehut.rake +38 -0
- data/tasks/test.rake +31 -0
- data/tasks/website/index_page.rb +28 -0
- data/tasks/website/version.rb +117 -0
- data/tasks/website/version_menu.rb +68 -0
- data/tasks/website/versioned_documentation.rb +49 -0
- data/tasks/website/website.rb +53 -0
- data/tasks/website.rake +26 -0
- metadata +119 -28
- data/.build.yml +0 -34
- data/.ruby-version +0 -1
- data/CODE_OF_CONDUCT.md +0 -30
- data/CONTRIBUTING.md +0 -40
- data/docs/images/examples-stock_ticker.rb.png +0 -0
- data/ext/ratatui_ruby/src/widgets/linechart.rs +0 -154
- data/lib/ratatui_ruby/schema/line_chart.rb +0 -41
- /data/{docs → doc}/application_testing.md +0 -0
- /data/{docs → doc}/contributors/design/ruby_frontend.md +0 -0
- /data/{docs → doc}/contributors/design/rust_backend.md +0 -0
- /data/{docs → doc}/contributors/design.md +0 -0
- /data/{docs → doc}/images/examples-analytics.rb.png +0 -0
- /data/{docs → doc}/images/examples-box_demo.rb.png +0 -0
- /data/{docs → doc}/images/examples-dashboard.rb.png +0 -0
- /data/{docs → doc}/images/examples-login_form.rb.png +0 -0
- /data/{docs → doc}/images/examples-map_demo.rb.png +0 -0
- /data/{docs → doc}/images/examples-mouse_events.rb.png +0 -0
- /data/{docs → doc}/images/examples-scrollbar_demo.rb.png +0 -0
- /data/{docs → doc}/images/examples-system_monitor.rb.png +0 -0
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 0e4a0958532fe7b493fcf0d9ee971bbc94194f5ff03fd420f895197597dac1c8
|
|
4
|
+
data.tar.gz: 480c3a5a467d478626a12c739064f894952e23d7a4574d0ad73a21dcc7b80ff5
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 28f9f71581859a3ddaecb62df012e942fa3617dfcac1634af88e84b676b13802d3bb0bf7443ebba96f2bc1a00f503e86b8a2e2d3d6f613864d35b7002d432dac
|
|
7
|
+
data.tar.gz: f08716e00372054fcbee63e44ecb39e692ec2cc0b23d6e5596243b6df5c248274bf5b750b376d004644d8cf7a91993bde3e7c5dc980856befe84e0ce680de7b5
|
|
@@ -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.3.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:2.6.9
|
|
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.3.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:2.6.9
|
|
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.3.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:2.6.9
|
|
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.3.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"/' mise.toml
|
|
32
|
+
mise install
|
|
33
|
+
mise x -- pip install reuse
|
|
34
|
+
mise x -- gem install bundler:2.6.9
|
|
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"
|
|
44
|
+
mise x -- bundle exec rake test || true
|
|
45
|
+
- lint: |
|
|
46
|
+
. ~/.buildenv
|
|
47
|
+
cd ratatui_ruby
|
|
48
|
+
echo "Linting Ruby 4.0.0"
|
|
49
|
+
mise x -- bundle exec rake lint || true
|
|
50
|
+
- package: |
|
|
51
|
+
. ~/.buildenv
|
|
52
|
+
cd ratatui_ruby
|
|
53
|
+
mise x -- bundle exec rake build
|
data/.pre-commit-config.yaml
CHANGED
|
@@ -3,7 +3,14 @@
|
|
|
3
3
|
repos:
|
|
4
4
|
- repo: local
|
|
5
5
|
hooks:
|
|
6
|
+
- id: bundle-check
|
|
7
|
+
name: Check Gemfile.lock
|
|
8
|
+
entry: bundle check
|
|
9
|
+
language: system
|
|
10
|
+
files: (Gemfile|Gemfile\.lock|ratatui_ruby\.gemspec)
|
|
11
|
+
pass_filenames: false
|
|
6
12
|
- id: rake
|
|
7
13
|
name: rake
|
|
8
|
-
entry: rake
|
|
9
|
-
language:
|
|
14
|
+
entry: bundle exec rake
|
|
15
|
+
language: system
|
|
16
|
+
pass_filenames: false
|
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:**
|
|
39
|
-
- **Linter:** Run via `rake lint`. You are not done until all linting passes.
|
|
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
|
+
- **Linter:** Run via `bundle exec 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
|
|
|
@@ -94,14 +94,15 @@ The project follows a standard Gem layout with an `ext/` directory for Rust code
|
|
|
94
94
|
### Development Environment
|
|
95
95
|
|
|
96
96
|
- **Setup:** `bin/setup` must handle both Bundler and Cargo dependencies.
|
|
97
|
-
- **Pre-commit:** Use `.pre-commit-config.yaml` to enforce `rake` and `cargo fmt`.
|
|
97
|
+
- **Pre-commit:** Use `.pre-commit-config.yaml` to enforce `bundle exec rake` and `cargo fmt`.
|
|
98
98
|
|
|
99
99
|
### Documentation
|
|
100
100
|
|
|
101
101
|
- Follow the `docs/` structure: `index.md` -> `contributors/` | `quickstart.md`.
|
|
102
102
|
- Documentation should separate "User Guide" (Ruby API for TUI developers) from "Contributor Guide" (Ruby/Rust/Magnus internals).
|
|
103
103
|
- Don't write .md files for something RDoc (Ruby) or rustdoc (Rust) can generate.
|
|
104
|
-
- **
|
|
104
|
+
- **The `doc/` folder contains source markdown files** that are included in RDoc output. You can edit these files.
|
|
105
|
+
- **The `tmp/rdoc/` folder is auto-generated** by `bundle exec rake rerdoc`. Never edit files in `tmp/rdoc/` directly.
|
|
105
106
|
|
|
106
107
|
## 4. The Ruby <-> Rust Bridge Contract
|
|
107
108
|
|
|
@@ -117,3 +118,50 @@ The project follows a standard Gem layout with an `ext/` directory for Rust code
|
|
|
117
118
|
|
|
118
119
|
- The gem builds a native extension.
|
|
119
120
|
- Artifact naming: Ensure the output shared library matches Ruby's expectation on macOS (rename `.dylib`to `.bundle` if necessary during the build process in `extconf.rb` or `Rakefile`).
|
|
121
|
+
|
|
122
|
+
## 6. Source Control Standards
|
|
123
|
+
|
|
124
|
+
- **Commits:**
|
|
125
|
+
- Who commits: Only humans should affect the git index and history. Rather than staging and/or committing, you should suggest a commit message.
|
|
126
|
+
- When: At the end of each task, before reporting the task as complete to the user, suggest the commit message.
|
|
127
|
+
- **Format:**
|
|
128
|
+
- Subject line: Concise summary (50 chars or less).
|
|
129
|
+
- Body: Detailed explanation if necessary (wrap at 72 chars). Explain why this is the implementation, as opposed to other possible implementations. Skip the body entirely if it's rote, a duplication of the diff, or otherwise unhelpful. **Do not simply list the files changed or the minor edits made to them.** Do not use markdown, except as required in AI Attribution.
|
|
130
|
+
- Footer: AI attribution if generated by an agent, sourcehut ticket if implemented by a ticket, or both.
|
|
131
|
+
- **AI Attribution:**
|
|
132
|
+
- **Antigravity:**
|
|
133
|
+
Specify the model used in the footer. Examples:
|
|
134
|
+
```
|
|
135
|
+
Generated with [Antigravity](https://antigravity.google)
|
|
136
|
+
|
|
137
|
+
Co-Authored-By: Gemini 3 Pro (High) <noreply@google.com>
|
|
138
|
+
```
|
|
139
|
+
```
|
|
140
|
+
Generated with [Antigravity](https://antigravity.google)
|
|
141
|
+
|
|
142
|
+
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
|
|
143
|
+
```
|
|
144
|
+
- **Gemini 3:**
|
|
145
|
+
```
|
|
146
|
+
Generated with [Gemini 3 Pro](https://gemini.google.com/)
|
|
147
|
+
|
|
148
|
+
Co-Authored-By: Gemini 3 Pro <noreply@google.com>
|
|
149
|
+
```
|
|
150
|
+
- **JetBrains Junie:**
|
|
151
|
+
```
|
|
152
|
+
Generated with [JetBrains Junie](https://www.jetbrains.com/ai/)
|
|
153
|
+
|
|
154
|
+
Co-Authored-By: Junie <junie@jetbrains.com>
|
|
155
|
+
```
|
|
156
|
+
- **Sourcehut Tickets:**
|
|
157
|
+
- If the commit implements a specific ticket, include a footer: `Implements: https://todo.sr.ht/~kerrick/ratatui_ruby/<id>`
|
|
158
|
+
- This must be the **last** item in the footer, if present.
|
|
159
|
+
|
|
160
|
+
## 7. Definition of Done
|
|
161
|
+
|
|
162
|
+
Before considering a task complete and returning control to the user, you **MUST** ensure:
|
|
163
|
+
|
|
164
|
+
1. **Tests & Linting Pass:** Run `bundle exec rake` and confirm it passes. No new errors **or warnings** should be introduced.
|
|
165
|
+
2. **Documentation Updated:** If public APIs or observable behavior changed, update relevant `doc/` files, `README.md`, and/or `ratatui_ruby-wiki` files,.
|
|
166
|
+
3. **Changelog Updated:** If public APIs, observable behavior, or gemspec dependencies changed, update [CHANGELOG.md](CHANGELOG.md)'s **Unreleased** section according to the [Semantic Versioning](https://semver.org/) and [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) specifications. Changelogs should be useful to human users of the library, not simple restatements of diffs or commit messages. **Do not add entries for internal tooling, CI, or build configuration changes that do not affect the distributed gem.**
|
|
167
|
+
4. **Commit Message Suggested:** You **MUST** ensure the final message to the user includes a suggested commit message block. This is NOT optional.
|
data/CHANGELOG.md
CHANGED
|
@@ -12,4 +12,54 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
|
|
|
12
12
|
|
|
13
13
|
### Added
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
### Changed
|
|
16
|
+
|
|
17
|
+
### Fixed
|
|
18
|
+
|
|
19
|
+
### Removed
|
|
20
|
+
|
|
21
|
+
## [0.3.0] - 2025-12-28
|
|
22
|
+
|
|
23
|
+
### Added
|
|
24
|
+
|
|
25
|
+
- **The Escape Hatch (Ruby Render Callback)**: Added the ability to define custom widgets in pure Ruby by implementing a `render(area, buffer)` method. The `Buffer` object provides low-level drawing primitives like `set_string`, allowing developers to create custom TUI components without writing Rust code.
|
|
26
|
+
- **Clear Widget**: Added the `Clear` widget, which resets the terminal buffer in the area it is rendered. This is essential for creating opaque popups and modals that prevent background styles from "bleeding" through transparent widgets.
|
|
27
|
+
- **Interactive Table Selection**: The `Table` widget now supports row selection with `selected_row`, `highlight_style`, and `highlight_symbol` parameters. This enables building interactive data grids and file explorers where users can navigate through rows using keyboard input.
|
|
28
|
+
- **Scrollable Paragraphs**: The `Paragraph` widget now supports a `scroll` parameter that accepts a `(y, x)` array to scroll content vertically and horizontally. This enables viewing long text content that exceeds the visible area, such as logs or documents. The parameter order matches ratatui's convention.
|
|
29
|
+
|
|
30
|
+
### Changed
|
|
31
|
+
|
|
32
|
+
- **Center Widget**: Removed the implicit `Clear` call from the `Center` widget. `Center` is now a pure layout widget, requiring an explicit `Clear` widget if background clearing is desired. This restores correct behavior for transparent overlays.
|
|
33
|
+
|
|
34
|
+
## [0.2.0] - 2025-12-24
|
|
35
|
+
|
|
36
|
+
### Added
|
|
37
|
+
|
|
38
|
+
- **DSL for Simpler Apps**: Introduced `RatatuiRuby.main_loop`, a new entrypoint that simplifies application structure when you don't need control of the event loop or application lifecycle.
|
|
39
|
+
- **Calendar Widget**: Added the `Calendar` widget, allowing you to display monthly views and visualize date-based information.
|
|
40
|
+
- **Generic Charts**: Implemented the full `Chart` widget, which supersedes the now-deprecated `LineChart` and `BarChart` widgets, giving you more freedom to visualize data sets.
|
|
41
|
+
- **Enhanced List Styling**: You can now customize the appearance of selected items in a `List` using `highlight_style` and `highlight_symbol`.
|
|
42
|
+
- **Broader Ruby Support**: Added support for a wider range of Ruby versions: every non-EOL version. The latest preview of Ruby 4.0 is tested in CI, but not supported.
|
|
43
|
+
- **Dev Tools**: Added internal Rake tasks for managing historical documentation and SemVer checks.
|
|
44
|
+
|
|
45
|
+
## [0.1.0] - 2025-12-22
|
|
46
|
+
|
|
47
|
+
### Added
|
|
48
|
+
|
|
49
|
+
- **First Release**: Initial public release of `ratatui_ruby`, bringing the power of the Rust [ratatui](https://github.com/ratatui-org/ratatui) library to Rubyists!
|
|
50
|
+
- **Core Widget Set**: Includes a comprehensive suite of widgets to get you started:
|
|
51
|
+
- `Block`, `Borders`, and `Paragraph` for basic content.
|
|
52
|
+
- `List` and `Table` for structured data.
|
|
53
|
+
- `Gauge` and `Sparkline` for progress and metrics.
|
|
54
|
+
- `Tabs` for navigation.
|
|
55
|
+
- `Canvas` for drawing shapes (Lines, Circles, Rectangles, Maps).
|
|
56
|
+
- **Layout System**: A flexible layout engine using `Flex`, `Layout`, and `Constraints` to build responsive interfaces that adapt to any terminal size.
|
|
57
|
+
- **Forms & Layers**: Primitives like `Overlay` and `Center` for creating modal dialogs, plus a `Cursor` widget for text input interactions.
|
|
58
|
+
- **Styling**: Full support for `Ratatui`'s styling primitives, including modifiers and RGB/ANSI colors.
|
|
59
|
+
- **Input Handling**: Robust handling for both Keyboard and Mouse events.
|
|
60
|
+
- **Testing Support**: Included `RatatuiRuby::TestHelper` and RSpec integration to make testing your TUI applications possible.
|
|
61
|
+
|
|
62
|
+
[Unreleased]: https://git.sr.ht/~kerrick/ratatui_ruby/compare/v0.3.0...HEAD
|
|
63
|
+
[0.3.0]: https://git.sr.ht/~kerrick/ratatui_ruby/compare/v0.2.0...v0.3.0
|
|
64
|
+
[0.2.0]: https://git.sr.ht/~kerrick/ratatui_ruby/compare/v0.1.0...v0.2.0
|
|
65
|
+
[0.1.0]: https://git.sr.ht/~kerrick/ratatui_ruby/tree/v0.1.0
|
data/README.md
CHANGED
|
@@ -4,18 +4,26 @@
|
|
|
4
4
|
-->
|
|
5
5
|
# ratatui_ruby
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
[](https://builds.sr.ht/~kerrick/ratatui_ruby?) [%22&replace=%241&label=License&color=a2c93e)](https://spdx.org/licenses/AGPL-3.0-or-later.html) [](https://rubygems.org/gems/ratatui_ruby) [](https://rubygems.org/gems/ratatui_ruby) [](https://crates.io/crates/ratatui/0.26.3) [](https://lists.sr.ht/~kerrick/ratatui_ruby-discuss) [](https://lists.sr.ht/~kerrick/ratatui_ruby-devel) [](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.
|
|
17
25
|
|
|
18
|
-
Please join
|
|
26
|
+
Please join the **announce** mailing list at https://lists.sr.ht/~kerrick/ratatui_ruby-announce to stay up-to-date on new releases and announcements.
|
|
19
27
|
|
|
20
28
|
|
|
21
29
|
## Compatibility
|
|
@@ -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
|
+
Support for Ruby 4 is coming soon.
|
|
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
|
|
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
|
|
55
|
+
Or install it yourself with:
|
|
44
56
|
|
|
45
57
|
```bash
|
|
46
58
|
gem install ratatui_ruby
|
|
@@ -49,38 +61,46 @@ 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
|
|
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
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
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
|
|
|
65
|
-
For a full tutorial, see [the Quickstart](./
|
|
83
|
+
For a full tutorial, see [the Quickstart](./doc/quickstart.md).
|
|
66
84
|
|
|
67
85
|
|
|
68
86
|
## Documentation
|
|
69
87
|
|
|
70
|
-
For the full documentation on how to use **ratatui_ruby**, see
|
|
88
|
+
For the full documentation on how to use **ratatui_ruby**, see the [documentation](./doc/index.md). For other information, see the [wiki](https://man.sr.ht/~kerrick/ratatui_ruby).
|
|
71
89
|
|
|
72
90
|
|
|
73
91
|
## Contributing
|
|
74
92
|
|
|
75
|
-
Bug reports and pull requests are welcome on [sourcehut](https://sourcehut.org) at https://sr.ht/~kerrick/ratatui_ruby/. This project is intended to be a safe, productive collaboration, and contributors are expected to adhere to the [
|
|
93
|
+
Bug reports and pull requests are welcome on [sourcehut](https://sourcehut.org) at https://sr.ht/~kerrick/ratatui_ruby/. This project is intended to be a safe, productive collaboration, and contributors are expected to adhere to the [Code of Conduct](https://man.sr.ht/~kerrick/ratatui_ruby/code_of_conduct.md).
|
|
76
94
|
|
|
77
95
|
Issues for the underlying Rust library should be filed at [ratatui/ratatui](https://github.com/ratatui/ratatui).
|
|
78
96
|
|
|
79
|
-
Want to help develop **ratatui_ruby**? Check out
|
|
97
|
+
Want to help develop **ratatui_ruby**? Check out the [contribution guide on the wiki](https://man.sr.ht/~kerrick/ratatui_ruby/contributing.md).
|
|
80
98
|
|
|
81
99
|
|
|
82
100
|
## Copyright & License
|
|
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 = 'doc/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
|
-
#
|
|
10
|
-
|
|
8
|
+
# Import all tasks from the tasks/ directory
|
|
9
|
+
Dir.glob("tasks/*.rake").each { |r| import r }
|
|
11
10
|
|
|
12
|
-
|
|
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]
|
|
@@ -7,7 +7,8 @@
|
|
|
7
7
|
|
|
8
8
|
## Documentation for Contributors
|
|
9
9
|
|
|
10
|
-
- [Contributing Guidelines](
|
|
10
|
+
- [Contributing Guidelines](https://man.sr.ht/~kerrick/ratatui_ruby/contributing.md)
|
|
11
|
+
- [Documentation Guide](https://man.sr.ht/~kerrick/ratatui_ruby/documentation_guide.md)
|
|
11
12
|
- [The Design of **ratatui_ruby**](./design.md)
|
|
12
13
|
|
|
13
14
|
## Documentation for Users
|
data/doc/custom.css
ADDED
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|