ratatui_ruby 0.3.1 → 0.5.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 +14 -12
- data/.builds/ruby-3.3.yml +14 -12
- data/.builds/ruby-3.4.yml +14 -12
- data/.builds/ruby-4.0.0.yml +14 -12
- data/AGENTS.md +89 -132
- data/CHANGELOG.md +223 -1
- data/README.md +23 -16
- data/REUSE.toml +20 -0
- data/doc/application_architecture.md +176 -0
- data/doc/application_testing.md +17 -10
- data/doc/contributors/design/ruby_frontend.md +11 -7
- data/doc/contributors/developing_examples.md +261 -0
- data/doc/contributors/documentation_style.md +104 -0
- data/doc/contributors/dwim_dx.md +366 -0
- data/doc/contributors/index.md +2 -0
- data/doc/custom.css +14 -0
- data/doc/event_handling.md +125 -0
- data/doc/images/app_all_events.png +0 -0
- data/doc/images/app_analytics.png +0 -0
- data/doc/images/app_color_picker.png +0 -0
- data/doc/images/app_custom_widget.png +0 -0
- data/doc/images/app_login_form.png +0 -0
- data/doc/images/app_map_demo.png +0 -0
- data/doc/images/app_mouse_events.png +0 -0
- data/doc/images/app_table_select.png +0 -0
- data/doc/images/verify_quickstart_dsl.png +0 -0
- data/doc/images/verify_quickstart_layout.png +0 -0
- data/doc/images/verify_quickstart_lifecycle.png +0 -0
- data/doc/images/verify_readme_usage.png +0 -0
- data/doc/images/widget_barchart_demo.png +0 -0
- data/doc/images/widget_block_padding.png +0 -0
- data/doc/images/widget_block_titles.png +0 -0
- data/doc/images/widget_box_demo.png +0 -0
- data/doc/images/widget_calendar_demo.png +0 -0
- data/doc/images/widget_cell_demo.png +0 -0
- data/doc/images/widget_chart_demo.png +0 -0
- data/doc/images/widget_gauge_demo.png +0 -0
- data/doc/images/widget_layout_split.png +0 -0
- data/doc/images/widget_line_gauge_demo.png +0 -0
- data/doc/images/widget_list_demo.png +0 -0
- data/doc/images/widget_list_styles.png +0 -0
- data/doc/images/widget_popup_demo.png +0 -0
- data/doc/images/widget_ratatui_logo_demo.png +0 -0
- data/doc/images/widget_ratatui_mascot_demo.png +0 -0
- data/doc/images/widget_rect.png +0 -0
- data/doc/images/widget_render.png +0 -0
- data/doc/images/widget_rich_text.png +0 -0
- data/doc/images/widget_scroll_text.png +0 -0
- data/doc/images/widget_scrollbar_demo.png +0 -0
- data/doc/images/widget_sparkline_demo.png +0 -0
- data/doc/images/widget_style_colors.png +0 -0
- data/doc/images/widget_table_flex.png +0 -0
- data/doc/images/widget_tabs_demo.png +0 -0
- data/doc/index.md +1 -0
- data/doc/interactive_design.md +116 -0
- data/doc/quickstart.md +186 -84
- data/examples/app_all_events/README.md +81 -0
- data/examples/app_all_events/app.rb +93 -0
- data/examples/app_all_events/model/event_color_cycle.rb +41 -0
- data/examples/app_all_events/model/event_entry.rb +75 -0
- data/examples/app_all_events/model/events.rb +180 -0
- data/examples/app_all_events/model/highlight.rb +57 -0
- data/examples/app_all_events/model/timestamp.rb +54 -0
- data/examples/app_all_events/test/snapshots/after_focus_lost.txt +24 -0
- data/examples/app_all_events/test/snapshots/after_focus_regained.txt +24 -0
- data/examples/app_all_events/test/snapshots/after_horizontal_resize.txt +24 -0
- data/examples/app_all_events/test/snapshots/after_key_a.txt +24 -0
- data/examples/app_all_events/test/snapshots/after_key_ctrl_x.txt +24 -0
- data/examples/app_all_events/test/snapshots/after_mouse_click.txt +24 -0
- data/examples/app_all_events/test/snapshots/after_mouse_drag.txt +24 -0
- data/examples/app_all_events/test/snapshots/after_multiple_events.txt +24 -0
- data/examples/app_all_events/test/snapshots/after_paste.txt +24 -0
- data/examples/app_all_events/test/snapshots/after_resize.txt +24 -0
- data/examples/app_all_events/test/snapshots/after_right_click.txt +24 -0
- data/examples/app_all_events/test/snapshots/after_vertical_resize.txt +24 -0
- data/examples/app_all_events/test/snapshots/initial_state.txt +24 -0
- data/examples/app_all_events/view/app_view.rb +78 -0
- data/examples/app_all_events/view/controls_view.rb +50 -0
- data/examples/app_all_events/view/counts_view.rb +55 -0
- data/examples/app_all_events/view/live_view.rb +69 -0
- data/examples/app_all_events/view/log_view.rb +60 -0
- data/{lib/ratatui_ruby/output.rb → examples/app_all_events/view.rb} +1 -1
- data/examples/app_all_events/view_state.rb +42 -0
- data/examples/app_color_picker/README.md +94 -0
- data/examples/app_color_picker/app.rb +112 -0
- data/examples/app_color_picker/clipboard.rb +84 -0
- data/examples/app_color_picker/color.rb +191 -0
- data/examples/app_color_picker/copy_dialog.rb +170 -0
- data/examples/app_color_picker/harmony.rb +56 -0
- data/examples/app_color_picker/input.rb +142 -0
- data/examples/app_color_picker/palette.rb +80 -0
- data/examples/app_color_picker/scene.rb +201 -0
- data/examples/app_login_form/app.rb +108 -0
- data/examples/app_map_demo/app.rb +93 -0
- data/examples/app_table_select/app.rb +201 -0
- data/examples/verify_quickstart_dsl/app.rb +45 -0
- data/examples/verify_quickstart_layout/app.rb +69 -0
- data/examples/verify_quickstart_lifecycle/app.rb +48 -0
- data/examples/verify_readme_usage/app.rb +34 -0
- data/examples/widget_barchart_demo/app.rb +238 -0
- data/examples/widget_block_padding/app.rb +67 -0
- data/examples/widget_block_titles/app.rb +69 -0
- data/examples/widget_box_demo/app.rb +250 -0
- data/examples/widget_calendar_demo/app.rb +109 -0
- data/examples/widget_cell_demo/app.rb +104 -0
- data/examples/widget_chart_demo/app.rb +213 -0
- data/examples/widget_gauge_demo/app.rb +212 -0
- data/examples/widget_layout_split/app.rb +246 -0
- data/examples/widget_line_gauge_demo/app.rb +217 -0
- data/examples/widget_list_demo/app.rb +382 -0
- data/examples/widget_list_styles/app.rb +141 -0
- data/examples/widget_popup_demo/app.rb +104 -0
- data/examples/widget_ratatui_logo_demo/app.rb +103 -0
- data/examples/widget_ratatui_mascot_demo/app.rb +93 -0
- data/examples/widget_rect/app.rb +205 -0
- data/examples/widget_render/app.rb +184 -0
- data/examples/widget_rich_text/app.rb +137 -0
- data/examples/widget_scroll_text/app.rb +108 -0
- data/examples/widget_scrollbar_demo/app.rb +153 -0
- data/examples/widget_sparkline_demo/app.rb +274 -0
- data/examples/widget_style_colors/app.rb +102 -0
- data/examples/widget_table_flex/app.rb +95 -0
- data/examples/widget_tabs_demo/app.rb +167 -0
- data/ext/ratatui_ruby/Cargo.lock +889 -115
- data/ext/ratatui_ruby/Cargo.toml +4 -3
- data/ext/ratatui_ruby/clippy.toml +7 -0
- data/ext/ratatui_ruby/extconf.rb +7 -0
- data/ext/ratatui_ruby/src/events.rs +293 -219
- data/ext/ratatui_ruby/src/frame.rs +115 -0
- data/ext/ratatui_ruby/src/lib.rs +105 -24
- data/ext/ratatui_ruby/src/rendering.rs +94 -10
- data/ext/ratatui_ruby/src/style.rs +357 -93
- data/ext/ratatui_ruby/src/terminal.rs +121 -31
- data/ext/ratatui_ruby/src/text.rs +178 -0
- data/ext/ratatui_ruby/src/widgets/barchart.rs +99 -24
- data/ext/ratatui_ruby/src/widgets/block.rs +32 -3
- data/ext/ratatui_ruby/src/widgets/calendar.rs +45 -44
- data/ext/ratatui_ruby/src/widgets/canvas.rs +44 -9
- data/ext/ratatui_ruby/src/widgets/chart.rs +79 -27
- data/ext/ratatui_ruby/src/widgets/clear.rs +3 -1
- data/ext/ratatui_ruby/src/widgets/gauge.rs +11 -4
- data/ext/ratatui_ruby/src/widgets/layout.rs +223 -15
- data/ext/ratatui_ruby/src/widgets/line_gauge.rs +92 -0
- data/ext/ratatui_ruby/src/widgets/list.rs +114 -11
- data/ext/ratatui_ruby/src/widgets/mod.rs +3 -0
- data/ext/ratatui_ruby/src/widgets/overlay.rs +4 -2
- data/ext/ratatui_ruby/src/widgets/paragraph.rs +35 -13
- data/ext/ratatui_ruby/src/widgets/ratatui_logo.rs +40 -0
- data/ext/ratatui_ruby/src/widgets/ratatui_mascot.rs +51 -0
- data/ext/ratatui_ruby/src/widgets/scrollbar.rs +61 -7
- data/ext/ratatui_ruby/src/widgets/sparkline.rs +73 -6
- data/ext/ratatui_ruby/src/widgets/table.rs +177 -64
- data/ext/ratatui_ruby/src/widgets/tabs.rs +105 -5
- data/lib/ratatui_ruby/cell.rb +166 -0
- data/lib/ratatui_ruby/event/focus_gained.rb +49 -0
- data/lib/ratatui_ruby/event/focus_lost.rb +50 -0
- data/lib/ratatui_ruby/event/key.rb +211 -0
- data/lib/ratatui_ruby/event/mouse.rb +124 -0
- data/lib/ratatui_ruby/event/none.rb +43 -0
- data/lib/ratatui_ruby/event/paste.rb +71 -0
- data/lib/ratatui_ruby/event/resize.rb +80 -0
- data/lib/ratatui_ruby/event.rb +131 -0
- data/lib/ratatui_ruby/frame.rb +87 -0
- data/lib/ratatui_ruby/schema/bar_chart/bar.rb +45 -0
- data/lib/ratatui_ruby/schema/bar_chart/bar_group.rb +23 -0
- data/lib/ratatui_ruby/schema/bar_chart.rb +226 -17
- data/lib/ratatui_ruby/schema/block.rb +178 -11
- data/lib/ratatui_ruby/schema/calendar.rb +70 -14
- data/lib/ratatui_ruby/schema/canvas.rb +213 -46
- data/lib/ratatui_ruby/schema/center.rb +46 -8
- data/lib/ratatui_ruby/schema/chart.rb +134 -32
- data/lib/ratatui_ruby/schema/clear.rb +22 -53
- data/lib/ratatui_ruby/schema/constraint.rb +72 -12
- data/lib/ratatui_ruby/schema/cursor.rb +23 -5
- data/lib/ratatui_ruby/schema/draw.rb +53 -0
- data/lib/ratatui_ruby/schema/gauge.rb +56 -12
- data/lib/ratatui_ruby/schema/layout.rb +91 -9
- data/lib/ratatui_ruby/schema/line_gauge.rb +78 -0
- data/lib/ratatui_ruby/schema/list.rb +92 -16
- data/lib/ratatui_ruby/schema/overlay.rb +29 -3
- data/lib/ratatui_ruby/schema/paragraph.rb +82 -25
- data/lib/ratatui_ruby/schema/ratatui_logo.rb +29 -0
- data/lib/ratatui_ruby/schema/ratatui_mascot.rb +34 -0
- data/lib/ratatui_ruby/schema/rect.rb +59 -10
- data/lib/ratatui_ruby/schema/scrollbar.rb +127 -19
- data/lib/ratatui_ruby/schema/shape/label.rb +66 -0
- data/lib/ratatui_ruby/schema/sparkline.rb +120 -12
- data/lib/ratatui_ruby/schema/style.rb +39 -11
- data/lib/ratatui_ruby/schema/table.rb +109 -18
- data/lib/ratatui_ruby/schema/tabs.rb +71 -10
- data/lib/ratatui_ruby/schema/text.rb +90 -0
- data/lib/ratatui_ruby/session/autodoc.rb +417 -0
- data/lib/ratatui_ruby/session.rb +163 -0
- data/lib/ratatui_ruby/test_helper.rb +322 -13
- data/lib/ratatui_ruby/version.rb +1 -1
- data/lib/ratatui_ruby.rb +184 -38
- data/sig/examples/app_all_events/app.rbs +11 -0
- data/sig/examples/app_all_events/model/event_entry.rbs +16 -0
- data/sig/examples/app_all_events/model/events.rbs +15 -0
- data/sig/examples/app_all_events/model/timestamp.rbs +11 -0
- data/sig/examples/app_all_events/view/app_view.rbs +8 -0
- data/sig/examples/app_all_events/view/controls_view.rbs +6 -0
- data/sig/examples/app_all_events/view/counts_view.rbs +6 -0
- data/sig/examples/app_all_events/view/live_view.rbs +6 -0
- data/sig/examples/app_all_events/view/log_view.rbs +6 -0
- data/sig/examples/app_all_events/view.rbs +8 -0
- data/sig/examples/app_all_events/view_state.rbs +15 -0
- data/sig/examples/app_color_picker/app.rbs +12 -0
- data/sig/examples/app_login_form/app.rbs +11 -0
- data/sig/examples/app_map_demo/app.rbs +11 -0
- data/sig/examples/app_table_select/app.rbs +11 -0
- data/sig/examples/verify_quickstart_dsl/app.rbs +11 -0
- data/sig/examples/verify_quickstart_lifecycle/app.rbs +11 -0
- data/sig/examples/verify_readme_usage/app.rbs +11 -0
- data/sig/examples/widget_block_padding/app.rbs +11 -0
- data/sig/examples/widget_block_titles/app.rbs +11 -0
- data/sig/examples/widget_box_demo/app.rbs +11 -0
- data/sig/examples/widget_calendar_demo/app.rbs +11 -0
- data/sig/examples/widget_cell_demo/app.rbs +11 -0
- data/sig/examples/widget_chart_demo/app.rbs +11 -0
- data/sig/examples/widget_gauge_demo/app.rbs +11 -0
- data/sig/examples/widget_layout_split/app.rbs +10 -0
- data/sig/examples/widget_line_gauge_demo/app.rbs +11 -0
- data/sig/examples/widget_list_demo/app.rbs +12 -0
- data/sig/examples/widget_list_styles/app.rbs +11 -0
- data/sig/examples/widget_popup_demo/app.rbs +11 -0
- data/sig/examples/widget_ratatui_logo_demo/app.rbs +11 -0
- data/sig/examples/widget_ratatui_mascot_demo/app.rbs +11 -0
- data/sig/examples/widget_rect/app.rbs +12 -0
- data/sig/examples/widget_render/app.rbs +10 -0
- data/sig/examples/widget_rich_text/app.rbs +11 -0
- data/sig/examples/widget_scroll_text/app.rbs +11 -0
- data/sig/examples/widget_scrollbar_demo/app.rbs +11 -0
- data/sig/examples/widget_sparkline_demo/app.rbs +10 -0
- data/sig/examples/widget_style_colors/app.rbs +14 -0
- data/sig/examples/widget_table_flex/app.rbs +11 -0
- data/sig/ratatui_ruby/event.rbs +69 -0
- data/sig/ratatui_ruby/frame.rbs +9 -0
- data/sig/ratatui_ruby/ratatui_ruby.rbs +5 -3
- data/sig/ratatui_ruby/schema/bar_chart/bar.rbs +16 -0
- data/sig/ratatui_ruby/schema/bar_chart/bar_group.rbs +13 -0
- data/sig/ratatui_ruby/schema/bar_chart.rbs +20 -2
- data/sig/ratatui_ruby/schema/block.rbs +5 -4
- data/sig/ratatui_ruby/schema/calendar.rbs +6 -2
- data/sig/ratatui_ruby/schema/canvas.rbs +52 -39
- data/sig/ratatui_ruby/schema/center.rbs +3 -3
- data/sig/ratatui_ruby/schema/chart.rbs +8 -5
- data/sig/ratatui_ruby/schema/constraint.rbs +8 -5
- data/sig/ratatui_ruby/schema/cursor.rbs +1 -1
- data/sig/ratatui_ruby/schema/draw.rbs +27 -0
- data/sig/ratatui_ruby/schema/gauge.rbs +4 -2
- data/sig/ratatui_ruby/schema/layout.rbs +11 -1
- data/sig/ratatui_ruby/schema/line_gauge.rbs +16 -0
- data/sig/ratatui_ruby/schema/list.rbs +5 -1
- data/sig/ratatui_ruby/schema/paragraph.rbs +4 -1
- data/sig/ratatui_ruby/schema/ratatui_logo.rbs +8 -0
- data/sig/ratatui_ruby/{buffer.rbs → schema/ratatui_mascot.rbs} +4 -3
- data/sig/ratatui_ruby/schema/rect.rbs +2 -1
- data/sig/ratatui_ruby/schema/scrollbar.rbs +18 -2
- data/sig/ratatui_ruby/schema/sparkline.rbs +6 -2
- data/sig/ratatui_ruby/schema/table.rbs +8 -1
- data/sig/ratatui_ruby/schema/tabs.rbs +5 -1
- data/sig/ratatui_ruby/schema/text.rbs +22 -0
- data/sig/ratatui_ruby/session.rbs +94 -0
- data/tasks/autodoc/inventory.rb +61 -0
- data/tasks/autodoc/member.rb +56 -0
- data/tasks/autodoc/name.rb +19 -0
- data/tasks/autodoc/notice.rb +26 -0
- data/tasks/autodoc/rbs.rb +38 -0
- data/tasks/autodoc/rdoc.rb +45 -0
- data/tasks/autodoc.rake +47 -0
- data/tasks/bump/history.rb +2 -2
- data/tasks/doc.rake +600 -6
- data/tasks/example_viewer.html.erb +172 -0
- data/tasks/lint.rake +8 -4
- data/tasks/resources/build.yml.erb +13 -11
- data/tasks/resources/index.html.erb +6 -0
- data/tasks/sourcehut.rake +4 -4
- data/tasks/terminal_preview/app_screenshot.rb +33 -0
- data/tasks/terminal_preview/crash_report.rb +52 -0
- data/tasks/terminal_preview/example_app.rb +25 -0
- data/tasks/terminal_preview/launcher_script.rb +46 -0
- data/tasks/terminal_preview/preview_collection.rb +58 -0
- data/tasks/terminal_preview/preview_timing.rb +22 -0
- data/tasks/terminal_preview/safety_confirmation.rb +56 -0
- data/tasks/terminal_preview/saved_screenshot.rb +53 -0
- data/tasks/terminal_preview/system_appearance.rb +11 -0
- data/tasks/terminal_preview/terminal_window.rb +136 -0
- data/tasks/terminal_preview/window_id.rb +14 -0
- data/tasks/terminal_preview.rake +28 -0
- data/tasks/test.rake +2 -2
- data/tasks/website/index_page.rb +3 -3
- data/tasks/website/version.rb +10 -10
- data/tasks/website/version_menu.rb +10 -12
- data/tasks/website/versioned_documentation.rb +49 -17
- data/tasks/website/website.rb +6 -8
- data/tasks/website.rake +4 -4
- metadata +206 -54
- data/LICENSES/BSD-2-Clause.txt +0 -9
- data/doc/images/examples-analytics.rb.png +0 -0
- data/doc/images/examples-box_demo.rb.png +0 -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-dashboard.rb.png +0 -0
- data/doc/images/examples-list_styles.rb.png +0 -0
- data/doc/images/examples-login_form.rb.png +0 -0
- data/doc/images/examples-map_demo.rb.png +0 -0
- data/doc/images/examples-mouse_events.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-scrollbar_demo.rb.png +0 -0
- data/doc/images/examples-stock_ticker.rb.png +0 -0
- data/doc/images/examples-system_monitor.rb.png +0 -0
- data/doc/images/examples-table_select.rb.png +0 -0
- data/examples/analytics.rb +0 -88
- data/examples/box_demo.rb +0 -71
- data/examples/calendar_demo.rb +0 -55
- data/examples/chart_demo.rb +0 -84
- data/examples/custom_widget.rb +0 -43
- data/examples/dashboard.rb +0 -72
- data/examples/list_styles.rb +0 -66
- data/examples/login_form.rb +0 -115
- data/examples/map_demo.rb +0 -58
- data/examples/mouse_events.rb +0 -95
- data/examples/popup_demo.rb +0 -105
- data/examples/quickstart_dsl.rb +0 -30
- data/examples/quickstart_lifecycle.rb +0 -40
- data/examples/readme_usage.rb +0 -21
- data/examples/scroll_text.rb +0 -74
- data/examples/scrollbar_demo.rb +0 -75
- data/examples/stock_ticker.rb +0 -93
- data/examples/system_monitor.rb +0 -94
- data/examples/table_select.rb +0 -70
- data/examples/test_analytics.rb +0 -65
- data/examples/test_box_demo.rb +0 -38
- data/examples/test_calendar_demo.rb +0 -66
- data/examples/test_dashboard.rb +0 -38
- data/examples/test_list_styles.rb +0 -61
- data/examples/test_login_form.rb +0 -63
- data/examples/test_map_demo.rb +0 -100
- data/examples/test_popup_demo.rb +0 -62
- data/examples/test_scroll_text.rb +0 -130
- data/examples/test_stock_ticker.rb +0 -39
- data/examples/test_system_monitor.rb +0 -40
- data/examples/test_table_select.rb +0 -37
- data/ext/ratatui_ruby/src/buffer.rs +0 -54
- data/lib/ratatui_ruby/dsl.rb +0 -64
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
3
3
|
|
|
4
4
|
use crate::style::{parse_block, parse_style};
|
|
5
|
+
use bumpalo::Bump;
|
|
5
6
|
use magnus::{prelude::*, Error, Value};
|
|
6
7
|
use ratatui::{
|
|
7
8
|
layout::Rect,
|
|
@@ -12,12 +13,16 @@ use std::convert::TryFrom;
|
|
|
12
13
|
use time::{Date, Month};
|
|
13
14
|
|
|
14
15
|
pub fn render(frame: &mut Frame, area: Rect, node: Value) -> Result<(), Error> {
|
|
16
|
+
let bump = Bump::new();
|
|
15
17
|
let ruby = magnus::Ruby::get().unwrap();
|
|
16
18
|
let year: i32 = node.funcall("year", ())?;
|
|
17
19
|
let month_u8: u8 = node.funcall("month", ())?;
|
|
18
|
-
let
|
|
20
|
+
let events_val: Value = node.funcall("events", ())?;
|
|
21
|
+
let default_style_val: Value = node.funcall("default_style", ())?;
|
|
19
22
|
let header_style_val: Value = node.funcall("header_style", ())?;
|
|
20
23
|
let block_val: Value = node.funcall("block", ())?;
|
|
24
|
+
let show_weekdays_header: bool = node.funcall("show_weekdays_header", ())?;
|
|
25
|
+
let show_surrounding_val: Value = node.funcall("show_surrounding", ())?;
|
|
21
26
|
|
|
22
27
|
let month = Month::try_from(month_u8)
|
|
23
28
|
.map_err(|e| Error::new(ruby.exception_arg_error(), e.to_string()))?;
|
|
@@ -25,58 +30,54 @@ pub fn render(frame: &mut Frame, area: Rect, node: Value) -> Result<(), Error> {
|
|
|
25
30
|
let date = Date::from_calendar_date(year, month, 1)
|
|
26
31
|
.map_err(|e| Error::new(ruby.exception_arg_error(), e.to_string()))?;
|
|
27
32
|
|
|
28
|
-
let mut
|
|
33
|
+
let mut event_store = CalendarEventStore::default();
|
|
34
|
+
if !events_val.is_nil() {
|
|
35
|
+
let events_hash = magnus::RHash::try_convert(events_val)?;
|
|
36
|
+
events_hash.foreach(|date_val: Value, style_val: Value| {
|
|
37
|
+
let year = date_val.funcall("year", ())?;
|
|
38
|
+
let month_u8: u8 = date_val.funcall("month", ())?;
|
|
39
|
+
let day: u8 = date_val.funcall("day", ())?;
|
|
29
40
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
41
|
+
let month = Month::try_from(month_u8)
|
|
42
|
+
.map_err(|e| Error::new(ruby.exception_arg_error(), e.to_string()))?;
|
|
43
|
+
let date = Date::from_calendar_date(year, month, day)
|
|
44
|
+
.map_err(|e| Error::new(ruby.exception_arg_error(), e.to_string()))?;
|
|
45
|
+
let style = parse_style(style_val)?;
|
|
46
|
+
|
|
47
|
+
event_store.add(date, style);
|
|
48
|
+
Ok(magnus::r_hash::ForEach::Continue)
|
|
49
|
+
})?;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
let mut calendar = Monthly::new(date, event_store);
|
|
53
|
+
|
|
54
|
+
let header_style = if header_style_val.is_nil() {
|
|
33
55
|
ratatui::style::Style::default()
|
|
56
|
+
} else {
|
|
57
|
+
parse_style(header_style_val)?
|
|
34
58
|
};
|
|
35
|
-
calendar = calendar
|
|
36
|
-
.show_month_header(header_style)
|
|
37
|
-
.show_weekdays_header(header_style);
|
|
38
59
|
|
|
39
|
-
|
|
40
|
-
|
|
60
|
+
let show_month_header: bool = node.funcall("show_month_header", ())?;
|
|
61
|
+
if show_month_header {
|
|
62
|
+
calendar = calendar.show_month_header(header_style);
|
|
41
63
|
}
|
|
42
64
|
|
|
43
|
-
if
|
|
44
|
-
calendar = calendar.
|
|
65
|
+
if show_weekdays_header {
|
|
66
|
+
calendar = calendar.show_weekdays_header(header_style);
|
|
45
67
|
}
|
|
46
68
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
}
|
|
69
|
+
if !show_surrounding_val.is_nil() {
|
|
70
|
+
calendar = calendar.show_surrounding(parse_style(show_surrounding_val)?);
|
|
71
|
+
}
|
|
50
72
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
use ratatui::buffer::Buffer;
|
|
55
|
-
use ratatui::widgets::Widget;
|
|
73
|
+
if !default_style_val.is_nil() {
|
|
74
|
+
calendar = calendar.default_style(parse_style(default_style_val)?);
|
|
75
|
+
}
|
|
56
76
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
let date = Date::from_calendar_date(2025, Month::December, 1).unwrap();
|
|
60
|
-
let calendar = Monthly::new(date, CalendarEventStore::default())
|
|
61
|
-
.show_month_header(ratatui::style::Style::default());
|
|
62
|
-
let mut buf = Buffer::empty(Rect::new(0, 0, 40, 20));
|
|
63
|
-
calendar.render(Rect::new(0, 0, 40, 20), &mut buf);
|
|
64
|
-
let mut content = String::new();
|
|
65
|
-
for y in 0..20 {
|
|
66
|
-
for x in 0..40 {
|
|
67
|
-
content.push_str(buf.cell((x, y)).unwrap().symbol());
|
|
68
|
-
}
|
|
69
|
-
content.push('\n');
|
|
70
|
-
}
|
|
71
|
-
assert!(
|
|
72
|
-
content.contains("December"),
|
|
73
|
-
"Content did not contain December: \n{}",
|
|
74
|
-
content
|
|
75
|
-
);
|
|
76
|
-
assert!(
|
|
77
|
-
content.contains("2025"),
|
|
78
|
-
"Content did not contain 2025: \n{}",
|
|
79
|
-
content
|
|
80
|
-
);
|
|
77
|
+
if !block_val.is_nil() {
|
|
78
|
+
calendar = calendar.block(parse_block(block_val, &bump)?);
|
|
81
79
|
}
|
|
80
|
+
|
|
81
|
+
frame.render_widget(calendar, area);
|
|
82
|
+
Ok(())
|
|
82
83
|
}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
// SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
|
|
2
2
|
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
3
3
|
|
|
4
|
-
use crate::style::{parse_block, parse_color};
|
|
4
|
+
use crate::style::{parse_block, parse_color, parse_style};
|
|
5
|
+
use crate::text::parse_text;
|
|
6
|
+
use bumpalo::Bump;
|
|
5
7
|
use magnus::{prelude::*, Error, RArray, Symbol, Value};
|
|
6
8
|
use ratatui::{
|
|
7
9
|
symbols::Marker,
|
|
@@ -9,7 +11,9 @@ use ratatui::{
|
|
|
9
11
|
Frame,
|
|
10
12
|
};
|
|
11
13
|
|
|
14
|
+
#[allow(clippy::too_many_lines)]
|
|
12
15
|
pub fn render(frame: &mut Frame, area: ratatui::layout::Rect, node: Value) -> Result<(), Error> {
|
|
16
|
+
let bump = Bump::new();
|
|
13
17
|
let shapes_val: RArray = node.funcall("shapes", ())?;
|
|
14
18
|
let x_bounds_val: RArray = node.funcall("x_bounds", ())?;
|
|
15
19
|
let y_bounds_val: RArray = node.funcall("y_bounds", ())?;
|
|
@@ -23,6 +27,10 @@ pub fn render(frame: &mut Frame, area: ratatui::layout::Rect, node: Value) -> Re
|
|
|
23
27
|
"dot" => Marker::Dot,
|
|
24
28
|
"block" => Marker::Block,
|
|
25
29
|
"bar" => Marker::Bar,
|
|
30
|
+
"half_block" => Marker::HalfBlock,
|
|
31
|
+
"quadrant" => Marker::Quadrant,
|
|
32
|
+
"sextant" => Marker::Sextant,
|
|
33
|
+
"octant" => Marker::Octant,
|
|
26
34
|
_ => Marker::Braille,
|
|
27
35
|
};
|
|
28
36
|
|
|
@@ -32,16 +40,24 @@ pub fn render(frame: &mut Frame, area: ratatui::layout::Rect, node: Value) -> Re
|
|
|
32
40
|
.marker(marker);
|
|
33
41
|
|
|
34
42
|
if !block_val.is_nil() {
|
|
35
|
-
canvas = canvas.block(parse_block(block_val)?);
|
|
43
|
+
canvas = canvas.block(parse_block(block_val, &bump)?);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
let background_color_val: Value = node.funcall("background_color", ())?;
|
|
47
|
+
if !background_color_val.is_nil() {
|
|
48
|
+
let background_color =
|
|
49
|
+
parse_color(&background_color_val.to_string()).unwrap_or(ratatui::style::Color::Reset);
|
|
50
|
+
canvas = canvas.background_color(background_color);
|
|
36
51
|
}
|
|
37
52
|
|
|
38
53
|
let canvas = canvas.paint(|ctx| {
|
|
39
54
|
for shape_val in shapes_val {
|
|
40
55
|
let class = shape_val.class();
|
|
41
|
-
|
|
56
|
+
// SAFETY: Immediate conversion to owned string avoids GC-unsafe borrowed reference.
|
|
57
|
+
let class_name = unsafe { class.name() }.into_owned();
|
|
42
58
|
|
|
43
|
-
match class_name.
|
|
44
|
-
"RatatuiRuby::Line" => {
|
|
59
|
+
match class_name.as_str() {
|
|
60
|
+
"RatatuiRuby::Shape::Line" => {
|
|
45
61
|
let x1: f64 = shape_val.funcall("x1", ()).unwrap_or(0.0);
|
|
46
62
|
let y1: f64 = shape_val.funcall("y1", ()).unwrap_or(0.0);
|
|
47
63
|
let x2: f64 = shape_val.funcall("x2", ()).unwrap_or(0.0);
|
|
@@ -57,7 +73,7 @@ pub fn render(frame: &mut Frame, area: ratatui::layout::Rect, node: Value) -> Re
|
|
|
57
73
|
color,
|
|
58
74
|
});
|
|
59
75
|
}
|
|
60
|
-
"RatatuiRuby::Rectangle" => {
|
|
76
|
+
"RatatuiRuby::Shape::Rectangle" => {
|
|
61
77
|
let x: f64 = shape_val.funcall("x", ()).unwrap_or(0.0);
|
|
62
78
|
let y: f64 = shape_val.funcall("y", ()).unwrap_or(0.0);
|
|
63
79
|
let width: f64 = shape_val.funcall("width", ()).unwrap_or(0.0);
|
|
@@ -73,7 +89,7 @@ pub fn render(frame: &mut Frame, area: ratatui::layout::Rect, node: Value) -> Re
|
|
|
73
89
|
color,
|
|
74
90
|
});
|
|
75
91
|
}
|
|
76
|
-
"RatatuiRuby::Circle" => {
|
|
92
|
+
"RatatuiRuby::Shape::Circle" => {
|
|
77
93
|
let x: f64 = shape_val.funcall("x", ()).unwrap_or(0.0);
|
|
78
94
|
let y: f64 = shape_val.funcall("y", ()).unwrap_or(0.0);
|
|
79
95
|
let radius: f64 = shape_val.funcall("radius", ()).unwrap_or(0.0);
|
|
@@ -87,7 +103,7 @@ pub fn render(frame: &mut Frame, area: ratatui::layout::Rect, node: Value) -> Re
|
|
|
87
103
|
color,
|
|
88
104
|
});
|
|
89
105
|
}
|
|
90
|
-
"RatatuiRuby::Map" => {
|
|
106
|
+
"RatatuiRuby::Shape::Map" => {
|
|
91
107
|
let color_val: Value = shape_val.funcall("color", ()).unwrap();
|
|
92
108
|
let color =
|
|
93
109
|
parse_color(&color_val.to_string()).unwrap_or(ratatui::style::Color::Reset);
|
|
@@ -98,6 +114,26 @@ pub fn render(frame: &mut Frame, area: ratatui::layout::Rect, node: Value) -> Re
|
|
|
98
114
|
};
|
|
99
115
|
ctx.draw(&Map { color, resolution });
|
|
100
116
|
}
|
|
117
|
+
"RatatuiRuby::Shape::Label" => {
|
|
118
|
+
let x: f64 = shape_val.funcall("x", ()).unwrap_or(0.0);
|
|
119
|
+
let y: f64 = shape_val.funcall("y", ()).unwrap_or(0.0);
|
|
120
|
+
let text_val: Value = shape_val.funcall("text", ()).unwrap();
|
|
121
|
+
let style_val: Value = shape_val.funcall("style", ()).unwrap();
|
|
122
|
+
|
|
123
|
+
// Parse text - take first line if multiple
|
|
124
|
+
if let Ok(lines) = parse_text(text_val) {
|
|
125
|
+
let mut line = lines.into_iter().next().unwrap_or_default();
|
|
126
|
+
|
|
127
|
+
// Apply style if provided
|
|
128
|
+
if !style_val.is_nil() {
|
|
129
|
+
if let Ok(style) = parse_style(style_val) {
|
|
130
|
+
line = line.style(style);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
ctx.print(x, y, line);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
101
137
|
_ => {}
|
|
102
138
|
}
|
|
103
139
|
}
|
|
@@ -132,7 +168,6 @@ mod tests {
|
|
|
132
168
|
let mut buf = Buffer::empty(Rect::new(0, 0, 5, 5));
|
|
133
169
|
canvas.render(Rect::new(0, 0, 5, 5), &mut buf);
|
|
134
170
|
|
|
135
|
-
// Verify that some Braille characters are rendered
|
|
136
171
|
let mut found_braille = false;
|
|
137
172
|
for cell in buf.content() {
|
|
138
173
|
if !cell.symbol().trim().is_empty() {
|
|
@@ -2,19 +2,21 @@
|
|
|
2
2
|
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
3
3
|
|
|
4
4
|
use crate::style::{parse_block, parse_style};
|
|
5
|
+
use bumpalo::Bump;
|
|
5
6
|
use magnus::{prelude::*, Error, Symbol, Value};
|
|
6
7
|
use ratatui::{
|
|
7
8
|
layout::Rect,
|
|
8
9
|
symbols,
|
|
9
10
|
text::Span,
|
|
10
|
-
widgets::{Axis, Chart, Dataset, GraphType},
|
|
11
|
+
widgets::{Axis, Chart, Dataset, GraphType, LegendPosition},
|
|
11
12
|
Frame,
|
|
12
13
|
};
|
|
13
14
|
|
|
14
15
|
pub fn render(frame: &mut Frame, area: Rect, node: Value) -> Result<(), Error> {
|
|
16
|
+
let bump = Bump::new();
|
|
15
17
|
let ruby = magnus::Ruby::get().unwrap();
|
|
16
|
-
|
|
17
|
-
let class_name = unsafe { class.name() };
|
|
18
|
+
// SAFETY: Immediate conversion to owned string avoids GC-unsafe borrowed reference.
|
|
19
|
+
let class_name = unsafe { node.class().name() }.into_owned();
|
|
18
20
|
|
|
19
21
|
if class_name == "RatatuiRuby::LineChart" {
|
|
20
22
|
return render_line_chart(frame, area, node);
|
|
@@ -25,18 +27,24 @@ pub fn render(frame: &mut Frame, area: Rect, node: Value) -> Result<(), Error> {
|
|
|
25
27
|
let y_axis_val: Value = node.funcall("y_axis", ())?;
|
|
26
28
|
let block_val: Value = node.funcall("block", ())?;
|
|
27
29
|
let style_val: Value = node.funcall("style", ())?;
|
|
30
|
+
let legend_position_val: Value = node.funcall("legend_position", ())?;
|
|
31
|
+
let hidden_legend_constraints_val: Value = node.funcall("hidden_legend_constraints", ())?;
|
|
28
32
|
|
|
29
33
|
let mut datasets = Vec::new();
|
|
30
34
|
// We need to keep the data alive until the chart is rendered
|
|
31
35
|
let mut data_storage: Vec<Vec<(f64, f64)>> = Vec::new();
|
|
32
36
|
|
|
33
37
|
for i in 0..datasets_val.len() {
|
|
34
|
-
let
|
|
38
|
+
let index = isize::try_from(i)
|
|
39
|
+
.map_err(|e| Error::new(ruby.exception_range_error(), e.to_string()))?;
|
|
40
|
+
let ds_val: Value = datasets_val.entry(index)?;
|
|
35
41
|
let data_array: magnus::RArray = ds_val.funcall("data", ())?;
|
|
36
42
|
|
|
37
43
|
let mut points = Vec::new();
|
|
38
44
|
for j in 0..data_array.len() {
|
|
39
|
-
let
|
|
45
|
+
let index = isize::try_from(j)
|
|
46
|
+
.map_err(|e| Error::new(ruby.exception_range_error(), e.to_string()))?;
|
|
47
|
+
let point_array_val: Value = data_array.entry(index)?;
|
|
40
48
|
let point_array = magnus::RArray::from_value(point_array_val).ok_or_else(|| {
|
|
41
49
|
Error::new(ruby.exception_type_error(), "expected array for point")
|
|
42
50
|
})?;
|
|
@@ -48,13 +56,14 @@ pub fn render(frame: &mut Frame, area: Rect, node: Value) -> Result<(), Error> {
|
|
|
48
56
|
}
|
|
49
57
|
|
|
50
58
|
for (i, points) in data_storage.iter().enumerate() {
|
|
51
|
-
let
|
|
59
|
+
let index = isize::try_from(i)
|
|
60
|
+
.map_err(|e| Error::new(ruby.exception_range_error(), e.to_string()))?;
|
|
61
|
+
let ds_val: Value = datasets_val.entry(index)?;
|
|
52
62
|
let name: String = ds_val.funcall("name", ())?;
|
|
53
63
|
let marker_sym: Symbol = ds_val.funcall("marker", ())?;
|
|
54
64
|
let graph_type_sym: Symbol = ds_val.funcall("graph_type", ())?;
|
|
55
65
|
|
|
56
66
|
let marker = match marker_sym.to_string().as_str() {
|
|
57
|
-
"dot" => symbols::Marker::Dot,
|
|
58
67
|
"braille" => symbols::Marker::Braille,
|
|
59
68
|
"block" => symbols::Marker::Block,
|
|
60
69
|
"bar" => symbols::Marker::Bar,
|
|
@@ -62,18 +71,14 @@ pub fn render(frame: &mut Frame, area: Rect, node: Value) -> Result<(), Error> {
|
|
|
62
71
|
};
|
|
63
72
|
|
|
64
73
|
let graph_type = match graph_type_sym.to_string().as_str() {
|
|
65
|
-
"line" => GraphType::Line,
|
|
66
74
|
"scatter" => GraphType::Scatter,
|
|
67
75
|
_ => GraphType::Line,
|
|
68
76
|
};
|
|
69
77
|
|
|
70
78
|
let mut ds_style = ratatui::style::Style::default();
|
|
71
|
-
let
|
|
72
|
-
if !
|
|
73
|
-
|
|
74
|
-
if let Some(color) = crate::style::parse_color(&color_str) {
|
|
75
|
-
ds_style = ds_style.fg(color);
|
|
76
|
-
}
|
|
79
|
+
let style_val: Value = ds_val.funcall("style", ())?;
|
|
80
|
+
if !style_val.is_nil() {
|
|
81
|
+
ds_style = parse_style(style_val)?;
|
|
77
82
|
}
|
|
78
83
|
|
|
79
84
|
let ds = Dataset::default()
|
|
@@ -91,28 +96,55 @@ pub fn render(frame: &mut Frame, area: Rect, node: Value) -> Result<(), Error> {
|
|
|
91
96
|
let mut chart = Chart::new(datasets).x_axis(x_axis).y_axis(y_axis);
|
|
92
97
|
|
|
93
98
|
if !block_val.is_nil() {
|
|
94
|
-
chart = chart.block(parse_block(block_val)?);
|
|
99
|
+
chart = chart.block(parse_block(block_val, &bump)?);
|
|
95
100
|
}
|
|
96
101
|
|
|
97
102
|
if !style_val.is_nil() {
|
|
98
103
|
chart = chart.style(parse_style(style_val)?);
|
|
99
104
|
}
|
|
100
105
|
|
|
106
|
+
if !legend_position_val.is_nil() {
|
|
107
|
+
let pos_sym: Symbol = legend_position_val.funcall("to_sym", ())?;
|
|
108
|
+
let pos = match pos_sym.to_string().as_str() {
|
|
109
|
+
"top_left" => LegendPosition::TopLeft,
|
|
110
|
+
"bottom_left" => LegendPosition::BottomLeft,
|
|
111
|
+
"bottom_right" => LegendPosition::BottomRight,
|
|
112
|
+
_ => LegendPosition::TopRight,
|
|
113
|
+
};
|
|
114
|
+
chart = chart.legend_position(Some(pos));
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
if !hidden_legend_constraints_val.is_nil() {
|
|
118
|
+
let constraints_array: magnus::RArray =
|
|
119
|
+
hidden_legend_constraints_val.funcall("to_a", ())?;
|
|
120
|
+
if constraints_array.len() == 2 {
|
|
121
|
+
let width_val: Value = constraints_array.entry(0)?;
|
|
122
|
+
let height_val: Value = constraints_array.entry(1)?;
|
|
123
|
+
let width_constraint = super::layout::parse_constraint(width_val)?;
|
|
124
|
+
let height_constraint = super::layout::parse_constraint(height_val)?;
|
|
125
|
+
chart = chart.hidden_legend_constraints((width_constraint, height_constraint));
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
101
129
|
frame.render_widget(chart, area);
|
|
102
130
|
Ok(())
|
|
103
131
|
}
|
|
104
132
|
|
|
105
133
|
fn parse_axis(axis_val: Value) -> Result<Axis<'static>, Error> {
|
|
134
|
+
let ruby = magnus::Ruby::get().unwrap();
|
|
106
135
|
let title: String = axis_val.funcall("title", ())?;
|
|
107
136
|
let bounds_val: magnus::RArray = axis_val.funcall("bounds", ())?;
|
|
108
137
|
let labels_val: magnus::RArray = axis_val.funcall("labels", ())?;
|
|
109
138
|
let style_val: Value = axis_val.funcall("style", ())?;
|
|
139
|
+
let labels_alignment_val: Value = axis_val.funcall("labels_alignment", ())?;
|
|
110
140
|
|
|
111
141
|
let bounds: [f64; 2] = [bounds_val.entry(0)?, bounds_val.entry(1)?];
|
|
112
142
|
|
|
113
143
|
let mut labels = Vec::new();
|
|
114
144
|
for i in 0..labels_val.len() {
|
|
115
|
-
let
|
|
145
|
+
let index = isize::try_from(i)
|
|
146
|
+
.map_err(|e| Error::new(ruby.exception_range_error(), e.to_string()))?;
|
|
147
|
+
let label: String = labels_val.entry(index)?;
|
|
116
148
|
labels.push(Span::from(label));
|
|
117
149
|
}
|
|
118
150
|
|
|
@@ -122,10 +154,21 @@ fn parse_axis(axis_val: Value) -> Result<Axis<'static>, Error> {
|
|
|
122
154
|
axis = axis.style(parse_style(style_val)?);
|
|
123
155
|
}
|
|
124
156
|
|
|
157
|
+
if !labels_alignment_val.is_nil() {
|
|
158
|
+
let alignment_sym: Symbol = labels_alignment_val.funcall("to_sym", ())?;
|
|
159
|
+
let alignment = match alignment_sym.to_string().as_str() {
|
|
160
|
+
"left" => ratatui::layout::HorizontalAlignment::Left,
|
|
161
|
+
"right" => ratatui::layout::HorizontalAlignment::Right,
|
|
162
|
+
_ => ratatui::layout::HorizontalAlignment::Center,
|
|
163
|
+
};
|
|
164
|
+
axis = axis.labels_alignment(alignment);
|
|
165
|
+
}
|
|
166
|
+
|
|
125
167
|
Ok(axis)
|
|
126
168
|
}
|
|
127
169
|
|
|
128
170
|
fn render_line_chart(frame: &mut Frame, area: Rect, node: Value) -> Result<(), Error> {
|
|
171
|
+
let bump = Bump::new();
|
|
129
172
|
let ruby = magnus::Ruby::get().unwrap();
|
|
130
173
|
let datasets_val: magnus::RArray = node.funcall("datasets", ())?;
|
|
131
174
|
let x_labels_val: magnus::RArray = node.funcall("x_labels", ())?;
|
|
@@ -137,12 +180,16 @@ fn render_line_chart(frame: &mut Frame, area: Rect, node: Value) -> Result<(), E
|
|
|
137
180
|
let mut data_storage: Vec<Vec<(f64, f64)>> = Vec::new();
|
|
138
181
|
|
|
139
182
|
for i in 0..datasets_val.len() {
|
|
140
|
-
let
|
|
183
|
+
let index = isize::try_from(i)
|
|
184
|
+
.map_err(|e| Error::new(ruby.exception_range_error(), e.to_string()))?;
|
|
185
|
+
let ds_val: Value = datasets_val.entry(index)?;
|
|
141
186
|
let data_array: magnus::RArray = ds_val.funcall("data", ())?;
|
|
142
187
|
|
|
143
188
|
let mut points = Vec::new();
|
|
144
189
|
for j in 0..data_array.len() {
|
|
145
|
-
let
|
|
190
|
+
let index = isize::try_from(j)
|
|
191
|
+
.map_err(|e| Error::new(ruby.exception_range_error(), e.to_string()))?;
|
|
192
|
+
let point_array_val: Value = data_array.entry(index)?;
|
|
146
193
|
let point_array = magnus::RArray::from_value(point_array_val).ok_or_else(|| {
|
|
147
194
|
Error::new(ruby.exception_type_error(), "expected array for point")
|
|
148
195
|
})?;
|
|
@@ -154,14 +201,15 @@ fn render_line_chart(frame: &mut Frame, area: Rect, node: Value) -> Result<(), E
|
|
|
154
201
|
}
|
|
155
202
|
|
|
156
203
|
for (i, points) in data_storage.iter().enumerate() {
|
|
157
|
-
let
|
|
204
|
+
let index = isize::try_from(i)
|
|
205
|
+
.map_err(|e| Error::new(ruby.exception_range_error(), e.to_string()))?;
|
|
206
|
+
let ds_val: Value = datasets_val.entry(index)?;
|
|
158
207
|
let name: String = ds_val.funcall("name", ())?;
|
|
159
208
|
|
|
160
209
|
let mut ds_style = ratatui::style::Style::default();
|
|
161
|
-
let
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
ds_style = ds_style.fg(color);
|
|
210
|
+
let style_val: Value = ds_val.funcall("style", ())?;
|
|
211
|
+
if !style_val.is_nil() {
|
|
212
|
+
ds_style = parse_style(style_val)?;
|
|
165
213
|
}
|
|
166
214
|
|
|
167
215
|
let ds = Dataset::default()
|
|
@@ -174,13 +222,17 @@ fn render_line_chart(frame: &mut Frame, area: Rect, node: Value) -> Result<(), E
|
|
|
174
222
|
|
|
175
223
|
let mut x_labels = Vec::new();
|
|
176
224
|
for i in 0..x_labels_val.len() {
|
|
177
|
-
let
|
|
225
|
+
let index = isize::try_from(i)
|
|
226
|
+
.map_err(|e| Error::new(ruby.exception_range_error(), e.to_string()))?;
|
|
227
|
+
let label: String = x_labels_val.entry(index)?;
|
|
178
228
|
x_labels.push(Span::from(label));
|
|
179
229
|
}
|
|
180
230
|
|
|
181
231
|
let mut y_labels = Vec::new();
|
|
182
232
|
for i in 0..y_labels_val.len() {
|
|
183
|
-
let
|
|
233
|
+
let index = isize::try_from(i)
|
|
234
|
+
.map_err(|e| Error::new(ruby.exception_range_error(), e.to_string()))?;
|
|
235
|
+
let label: String = y_labels_val.entry(index)?;
|
|
184
236
|
y_labels.push(Span::from(label));
|
|
185
237
|
}
|
|
186
238
|
// Ratatui 0.29+ requires labels to be present for the axis line to render
|
|
@@ -210,7 +262,7 @@ fn render_line_chart(frame: &mut Frame, area: Rect, node: Value) -> Result<(), E
|
|
|
210
262
|
}
|
|
211
263
|
}
|
|
212
264
|
}
|
|
213
|
-
if min_x
|
|
265
|
+
if (min_x - max_x).abs() < f64::EPSILON {
|
|
214
266
|
max_x = min_x + 1.0;
|
|
215
267
|
}
|
|
216
268
|
|
|
@@ -219,7 +271,7 @@ fn render_line_chart(frame: &mut Frame, area: Rect, node: Value) -> Result<(), E
|
|
|
219
271
|
|
|
220
272
|
let mut chart = Chart::new(datasets).x_axis(x_axis).y_axis(y_axis);
|
|
221
273
|
if !block_val.is_nil() {
|
|
222
|
-
chart = chart.block(parse_block(block_val)?);
|
|
274
|
+
chart = chart.block(parse_block(block_val, &bump)?);
|
|
223
275
|
}
|
|
224
276
|
|
|
225
277
|
frame.render_widget(chart, area);
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
|
|
2
2
|
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
3
3
|
|
|
4
|
+
use bumpalo::Bump;
|
|
4
5
|
use magnus::{prelude::*, Error, Value};
|
|
5
6
|
use ratatui::{layout::Rect, widgets::Widget, Frame};
|
|
6
7
|
|
|
@@ -10,7 +11,8 @@ pub fn render(frame: &mut Frame, area: Rect, node: Value) -> Result<(), Error> {
|
|
|
10
11
|
// If a block is provided, render it on top of the cleared area
|
|
11
12
|
if let Ok(block_val) = node.funcall::<_, _, Value>("block", ()) {
|
|
12
13
|
if !block_val.is_nil() {
|
|
13
|
-
let
|
|
14
|
+
let bump = Bump::new();
|
|
15
|
+
let block = crate::style::parse_block(block_val, &bump)?;
|
|
14
16
|
block.render(area, frame.buffer_mut());
|
|
15
17
|
}
|
|
16
18
|
}
|
|
@@ -2,16 +2,19 @@
|
|
|
2
2
|
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
3
3
|
|
|
4
4
|
use crate::style::{parse_block, parse_style};
|
|
5
|
+
use bumpalo::Bump;
|
|
5
6
|
use magnus::{prelude::*, Error, Value};
|
|
6
7
|
use ratatui::{layout::Rect, widgets::Gauge, Frame};
|
|
7
8
|
|
|
8
9
|
pub fn render(frame: &mut Frame, area: Rect, node: Value) -> Result<(), Error> {
|
|
10
|
+
let bump = Bump::new();
|
|
9
11
|
let ratio: f64 = node.funcall("ratio", ())?;
|
|
10
12
|
let label_val: Value = node.funcall("label", ())?;
|
|
11
13
|
let style_val: Value = node.funcall("style", ())?;
|
|
14
|
+
let gauge_style_val: Value = node.funcall("gauge_style", ())?;
|
|
12
15
|
let block_val: Value = node.funcall("block", ())?;
|
|
13
|
-
|
|
14
|
-
let mut gauge = Gauge::default().ratio(ratio);
|
|
16
|
+
let use_unicode: bool = node.funcall("use_unicode", ())?;
|
|
17
|
+
let mut gauge = Gauge::default().ratio(ratio).use_unicode(use_unicode);
|
|
15
18
|
|
|
16
19
|
if !label_val.is_nil() {
|
|
17
20
|
let label_str: String = label_val.funcall("to_s", ())?;
|
|
@@ -19,11 +22,15 @@ pub fn render(frame: &mut Frame, area: Rect, node: Value) -> Result<(), Error> {
|
|
|
19
22
|
}
|
|
20
23
|
|
|
21
24
|
if !style_val.is_nil() {
|
|
22
|
-
gauge = gauge.
|
|
25
|
+
gauge = gauge.style(parse_style(style_val)?);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
if !gauge_style_val.is_nil() {
|
|
29
|
+
gauge = gauge.gauge_style(parse_style(gauge_style_val)?);
|
|
23
30
|
}
|
|
24
31
|
|
|
25
32
|
if !block_val.is_nil() {
|
|
26
|
-
gauge = gauge.block(parse_block(block_val)?);
|
|
33
|
+
gauge = gauge.block(parse_block(block_val, &bump)?);
|
|
27
34
|
}
|
|
28
35
|
|
|
29
36
|
frame.render_widget(gauge, area);
|