ratatui_ruby 0.1.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 +7 -0
- data/.build.yml +34 -0
- data/.pre-commit-config.yaml +9 -0
- data/.rubocop.yml +8 -0
- data/.ruby-version +1 -0
- data/AGENTS.md +119 -0
- data/CHANGELOG.md +15 -0
- data/CODE_OF_CONDUCT.md +30 -0
- data/CONTRIBUTING.md +40 -0
- data/LICENSE +15 -0
- data/LICENSES/AGPL-3.0-or-later.txt +661 -0
- data/LICENSES/BSD-2-Clause.txt +9 -0
- data/LICENSES/CC-BY-SA-4.0.txt +427 -0
- data/LICENSES/CC0-1.0.txt +121 -0
- data/LICENSES/MIT.txt +21 -0
- data/README.md +86 -0
- data/REUSE.toml +17 -0
- data/Rakefile +108 -0
- data/docs/application_testing.md +96 -0
- data/docs/contributors/design/ruby_frontend.md +100 -0
- data/docs/contributors/design/rust_backend.md +61 -0
- data/docs/contributors/design.md +11 -0
- data/docs/contributors/index.md +16 -0
- data/docs/images/examples-analytics.rb.png +0 -0
- data/docs/images/examples-box_demo.rb.png +0 -0
- data/docs/images/examples-dashboard.rb.png +0 -0
- data/docs/images/examples-login_form.rb.png +0 -0
- data/docs/images/examples-map_demo.rb.png +0 -0
- data/docs/images/examples-mouse_events.rb.png +0 -0
- data/docs/images/examples-scrollbar_demo.rb.png +0 -0
- data/docs/images/examples-stock_ticker.rb.png +0 -0
- data/docs/images/examples-system_monitor.rb.png +0 -0
- data/docs/index.md +18 -0
- data/docs/quickstart.md +126 -0
- data/examples/analytics.rb +87 -0
- data/examples/box_demo.rb +71 -0
- data/examples/dashboard.rb +72 -0
- data/examples/login_form.rb +114 -0
- data/examples/map_demo.rb +58 -0
- data/examples/mouse_events.rb +95 -0
- data/examples/scrollbar_demo.rb +75 -0
- data/examples/stock_ticker.rb +85 -0
- data/examples/system_monitor.rb +93 -0
- data/examples/test_analytics.rb +65 -0
- data/examples/test_box_demo.rb +38 -0
- data/examples/test_dashboard.rb +38 -0
- data/examples/test_login_form.rb +63 -0
- data/examples/test_map_demo.rb +100 -0
- data/examples/test_stock_ticker.rb +39 -0
- data/examples/test_system_monitor.rb +40 -0
- data/ext/ratatui_ruby/.cargo/config.toml +8 -0
- data/ext/ratatui_ruby/.gitignore +4 -0
- data/ext/ratatui_ruby/Cargo.lock +698 -0
- data/ext/ratatui_ruby/Cargo.toml +16 -0
- data/ext/ratatui_ruby/extconf.rb +12 -0
- data/ext/ratatui_ruby/src/events.rs +279 -0
- data/ext/ratatui_ruby/src/lib.rs +105 -0
- data/ext/ratatui_ruby/src/rendering.rs +31 -0
- data/ext/ratatui_ruby/src/style.rs +149 -0
- data/ext/ratatui_ruby/src/terminal.rs +131 -0
- data/ext/ratatui_ruby/src/widgets/barchart.rs +73 -0
- data/ext/ratatui_ruby/src/widgets/block.rs +12 -0
- data/ext/ratatui_ruby/src/widgets/canvas.rs +146 -0
- data/ext/ratatui_ruby/src/widgets/center.rs +81 -0
- data/ext/ratatui_ruby/src/widgets/cursor.rs +29 -0
- data/ext/ratatui_ruby/src/widgets/gauge.rs +50 -0
- data/ext/ratatui_ruby/src/widgets/layout.rs +82 -0
- data/ext/ratatui_ruby/src/widgets/linechart.rs +154 -0
- data/ext/ratatui_ruby/src/widgets/list.rs +62 -0
- data/ext/ratatui_ruby/src/widgets/mod.rs +18 -0
- data/ext/ratatui_ruby/src/widgets/overlay.rs +20 -0
- data/ext/ratatui_ruby/src/widgets/paragraph.rs +56 -0
- data/ext/ratatui_ruby/src/widgets/scrollbar.rs +68 -0
- data/ext/ratatui_ruby/src/widgets/sparkline.rs +59 -0
- data/ext/ratatui_ruby/src/widgets/table.rs +117 -0
- data/ext/ratatui_ruby/src/widgets/tabs.rs +51 -0
- data/lib/ratatui_ruby/output.rb +7 -0
- data/lib/ratatui_ruby/schema/bar_chart.rb +28 -0
- data/lib/ratatui_ruby/schema/block.rb +23 -0
- data/lib/ratatui_ruby/schema/canvas.rb +62 -0
- data/lib/ratatui_ruby/schema/center.rb +19 -0
- data/lib/ratatui_ruby/schema/constraint.rb +33 -0
- data/lib/ratatui_ruby/schema/cursor.rb +17 -0
- data/lib/ratatui_ruby/schema/gauge.rb +24 -0
- data/lib/ratatui_ruby/schema/layout.rb +22 -0
- data/lib/ratatui_ruby/schema/line_chart.rb +41 -0
- data/lib/ratatui_ruby/schema/list.rb +22 -0
- data/lib/ratatui_ruby/schema/overlay.rb +15 -0
- data/lib/ratatui_ruby/schema/paragraph.rb +37 -0
- data/lib/ratatui_ruby/schema/scrollbar.rb +33 -0
- data/lib/ratatui_ruby/schema/sparkline.rb +24 -0
- data/lib/ratatui_ruby/schema/style.rb +31 -0
- data/lib/ratatui_ruby/schema/table.rb +24 -0
- data/lib/ratatui_ruby/schema/tabs.rb +22 -0
- data/lib/ratatui_ruby/test_helper.rb +75 -0
- data/lib/ratatui_ruby/version.rb +10 -0
- data/lib/ratatui_ruby.rb +87 -0
- data/sig/ratatui_ruby/ratatui_ruby.rbs +16 -0
- data/sig/ratatui_ruby/schema/bar_chart.rbs +14 -0
- data/sig/ratatui_ruby/schema/block.rbs +11 -0
- data/sig/ratatui_ruby/schema/canvas.rbs +62 -0
- data/sig/ratatui_ruby/schema/center.rbs +11 -0
- data/sig/ratatui_ruby/schema/constraint.rbs +13 -0
- data/sig/ratatui_ruby/schema/cursor.rbs +10 -0
- data/sig/ratatui_ruby/schema/gauge.rbs +13 -0
- data/sig/ratatui_ruby/schema/layout.rbs +11 -0
- data/sig/ratatui_ruby/schema/line_chart.rbs +20 -0
- data/sig/ratatui_ruby/schema/list.rbs +11 -0
- data/sig/ratatui_ruby/schema/overlay.rbs +9 -0
- data/sig/ratatui_ruby/schema/paragraph.rbs +11 -0
- data/sig/ratatui_ruby/schema/scrollbar.rbs +20 -0
- data/sig/ratatui_ruby/schema/sparkline.rbs +12 -0
- data/sig/ratatui_ruby/schema/style.rbs +13 -0
- data/sig/ratatui_ruby/schema/table.rbs +13 -0
- data/sig/ratatui_ruby/schema/tabs.rbs +11 -0
- data/sig/ratatui_ruby/test_helper.rbs +11 -0
- data/sig/ratatui_ruby/version.rbs +6 -0
- data/vendor/goodcop/base.yml +1047 -0
- metadata +196 -0
|
@@ -0,0 +1,62 @@
|
|
|
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
|
+
module RatatuiRuby
|
|
7
|
+
# A point in the canvas coordinate system.
|
|
8
|
+
# @param x [Float] The x-coordinate.
|
|
9
|
+
# @param y [Float] The y-coordinate.
|
|
10
|
+
class Point < Data.define(:x, :y)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
# A line shape on a canvas.
|
|
14
|
+
# @param x1 [Float] The starting x-coordinate.
|
|
15
|
+
# @param y1 [Float] The starting y-coordinate.
|
|
16
|
+
# @param x2 [Float] The ending x-coordinate.
|
|
17
|
+
# @param y2 [Float] The ending y-coordinate.
|
|
18
|
+
# @param color [String, Symbol] The color of the line.
|
|
19
|
+
class Line < Data.define(:x1, :y1, :x2, :y2, :color)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# A rectangle shape on a canvas.
|
|
23
|
+
# @param x [Float] The x-coordinate of the bottom-left corner.
|
|
24
|
+
# @param y [Float] The y-coordinate of the bottom-left corner.
|
|
25
|
+
# @param width [Float] The width of the rectangle.
|
|
26
|
+
# @param height [Float] The height of the rectangle.
|
|
27
|
+
# @param color [String, Symbol] The color of the rectangle.
|
|
28
|
+
class Rectangle < Data.define(:x, :y, :width, :height, :color)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# A circle shape on a canvas.
|
|
32
|
+
# @param x [Float] The x-coordinate of the center.
|
|
33
|
+
# @param y [Float] The y-coordinate of the center.
|
|
34
|
+
# @param radius [Float] The radius of the circle.
|
|
35
|
+
# @param color [String, Symbol] The color of the circle.
|
|
36
|
+
class Circle < Data.define(:x, :y, :radius, :color)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# A world map shape on a canvas.
|
|
40
|
+
# @param color [String, Symbol] The color of the map.
|
|
41
|
+
# @param resolution [Symbol] The resolution of the map (:low, :high).
|
|
42
|
+
class Map < Data.define(:color, :resolution)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# The Canvas Widget.
|
|
46
|
+
# @param shapes [Array] Array of shape objects (Line, Rectangle, Circle, Map).
|
|
47
|
+
# @param x_bounds [Array<Float>] [min, max] range for the x-axis.
|
|
48
|
+
# @param y_bounds [Array<Float>] [min, max] range for the y-axis.
|
|
49
|
+
# @param marker [Symbol] The marker to use for drawing (:braille, :dot, :block, :bar).
|
|
50
|
+
# @param block [Block, nil] Optional Block widget to wrap the canvas.
|
|
51
|
+
class Canvas < Data.define(:shapes, :x_bounds, :y_bounds, :marker, :block)
|
|
52
|
+
# Creates a new Canvas.
|
|
53
|
+
# @param shapes [Array] Array of shape objects (Line, Rectangle, Circle, Map).
|
|
54
|
+
# @param x_bounds [Array<Float>] [min, max] range for the x-axis.
|
|
55
|
+
# @param y_bounds [Array<Float>] [min, max] range for the y-axis.
|
|
56
|
+
# @param marker [Symbol] The marker to use for drawing (:braille, :dot, :block, :bar).
|
|
57
|
+
# @param block [Block, nil] Optional Block widget to wrap the canvas.
|
|
58
|
+
def initialize(shapes: [], x_bounds: [0.0, 100.0], y_bounds: [0.0, 100.0], marker: :braille, block: nil)
|
|
59
|
+
super
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
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
|
+
module RatatuiRuby
|
|
7
|
+
# Centers a child widget within the current area.
|
|
8
|
+
#
|
|
9
|
+
# [child] the widget to center.
|
|
10
|
+
# [width_percent] the width percentage of the centered area.
|
|
11
|
+
# [height_percent] the height percentage of the centered area.
|
|
12
|
+
class Center < Data.define(:child, :width_percent, :height_percent)
|
|
13
|
+
# Creates a new Center.
|
|
14
|
+
#
|
|
15
|
+
# [child] the widget to center.
|
|
16
|
+
# [width_percent] the width percentage of the centered area.
|
|
17
|
+
# [height_percent] the height percentage of the centered area.
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
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
|
+
module RatatuiRuby
|
|
7
|
+
# Defines constraints for layout sections or table columns.
|
|
8
|
+
#
|
|
9
|
+
# [type] The type of constraint (:length, :percentage, :min).
|
|
10
|
+
# [value] The numeric value associated with the constraint.
|
|
11
|
+
class Constraint < Data.define(:type, :value)
|
|
12
|
+
# Creates a length constraint (fixed number of cells).
|
|
13
|
+
#
|
|
14
|
+
# [v] The length value in cells.
|
|
15
|
+
def self.length(v)
|
|
16
|
+
new(type: :length, value: v)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# Creates a percentage constraint (portion of available space).
|
|
20
|
+
#
|
|
21
|
+
# [v] The percentage value (0-100).
|
|
22
|
+
def self.percentage(v)
|
|
23
|
+
new(type: :percentage, value: v)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# Creates a minimum size constraint.
|
|
27
|
+
#
|
|
28
|
+
# [v] The minimum number of cells.
|
|
29
|
+
def self.min(v)
|
|
30
|
+
new(type: :min, value: v)
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
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
|
+
module RatatuiRuby
|
|
7
|
+
# Sets the terminal cursor position (ghost widget).
|
|
8
|
+
#
|
|
9
|
+
# [x] the x coordinate.
|
|
10
|
+
# [y] the y coordinate.
|
|
11
|
+
class Cursor < Data.define(:x, :y)
|
|
12
|
+
# Creates a new Cursor.
|
|
13
|
+
#
|
|
14
|
+
# [x] the x coordinate.
|
|
15
|
+
# [y] the y coordinate.
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
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
|
+
module RatatuiRuby
|
|
7
|
+
# A widget that displays a progress bar.
|
|
8
|
+
#
|
|
9
|
+
# [ratio] A value between 0.0 and 1.0 representing the progress.
|
|
10
|
+
# [label] An optional string to display on the gauge.
|
|
11
|
+
# [style] The Style object to apply to the gauge.
|
|
12
|
+
# [block] An optional Block widget to wrap the gauge.
|
|
13
|
+
class Gauge < Data.define(:ratio, :label, :style, :block)
|
|
14
|
+
# Creates a new Gauge.
|
|
15
|
+
#
|
|
16
|
+
# [ratio] A value between 0.0 and 1.0 representing the progress.
|
|
17
|
+
# [label] An optional string to display on the gauge.
|
|
18
|
+
# [style] The Style object to apply to the gauge.
|
|
19
|
+
# [block] An optional Block widget to wrap the gauge.
|
|
20
|
+
def initialize(ratio: 0.0, label: nil, style: Style.default, block: nil)
|
|
21
|
+
super
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
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
|
+
module RatatuiRuby
|
|
7
|
+
# A widget that splits an area into multiple sections based on constraints.
|
|
8
|
+
#
|
|
9
|
+
# [direction] The direction of the layout (:vertical or :horizontal).
|
|
10
|
+
# [constraints] An array of Constraint objects defining the size of each section.
|
|
11
|
+
# [children] An array of widgets to render within each section.
|
|
12
|
+
class Layout < Data.define(:direction, :constraints, :children)
|
|
13
|
+
# Creates a new Layout.
|
|
14
|
+
#
|
|
15
|
+
# [direction] The direction of the layout (:vertical or :horizontal).
|
|
16
|
+
# [constraints] An array of Constraint objects defining the size of each section.
|
|
17
|
+
# [children] An array of widgets to render within each section.
|
|
18
|
+
def initialize(direction: :vertical, constraints: [], children: [])
|
|
19
|
+
super
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
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
|
+
module RatatuiRuby
|
|
7
|
+
# A single line on a chart.
|
|
8
|
+
#
|
|
9
|
+
# [name] The name of the dataset.
|
|
10
|
+
# [data] Array of arrays [[x, y], [x, y]] (Floats).
|
|
11
|
+
# [color] The color of the line.
|
|
12
|
+
class Dataset < Data.define(:name, :data, :color)
|
|
13
|
+
# Creates a new Dataset.
|
|
14
|
+
# [name] The name of the dataset.
|
|
15
|
+
# [data] Array of arrays [[x, y], [x, y]] (Floats).
|
|
16
|
+
# [color] The color of the line.
|
|
17
|
+
def initialize(name:, data:, color: "white")
|
|
18
|
+
super
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# A complex chart widget.
|
|
23
|
+
#
|
|
24
|
+
# [datasets] Array of Dataset objects.
|
|
25
|
+
# [x_labels] Array of Strings for the X-axis labels.
|
|
26
|
+
# [y_labels] Array of Strings for the Y-axis labels.
|
|
27
|
+
# [y_bounds] Array of two Floats [min, max] for the Y-axis.
|
|
28
|
+
# [block] Optional block widget to wrap the chart.
|
|
29
|
+
class LineChart < Data.define(:datasets, :x_labels, :y_labels, :y_bounds, :block)
|
|
30
|
+
# Creates a new LineChart widget.
|
|
31
|
+
#
|
|
32
|
+
# [datasets] Array of Dataset objects.
|
|
33
|
+
# [x_labels] Array of Strings for the X-axis labels.
|
|
34
|
+
# [y_labels] Array of Strings for the Y-axis labels.
|
|
35
|
+
# [y_bounds] Array of two Floats [min, max] for the Y-axis.
|
|
36
|
+
# [block] Optional block widget to wrap the chart.
|
|
37
|
+
def initialize(datasets:, x_labels: [], y_labels: [], y_bounds: [0.0, 100.0], block: nil)
|
|
38
|
+
super
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
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
|
+
module RatatuiRuby
|
|
7
|
+
# A widget that displays a list of selectable items.
|
|
8
|
+
#
|
|
9
|
+
# [items] An array of strings to display in the list.
|
|
10
|
+
# [selected_index] The index of the currently selected item, or nil if none.
|
|
11
|
+
# [block] An optional Block widget to wrap the list.
|
|
12
|
+
class List < Data.define(:items, :selected_index, :block)
|
|
13
|
+
# Creates a new List.
|
|
14
|
+
#
|
|
15
|
+
# [items] An array of strings to display in the list.
|
|
16
|
+
# [selected_index] The index of the currently selected item, or nil if none.
|
|
17
|
+
# [block] An optional Block widget to wrap the list.
|
|
18
|
+
def initialize(items: [], selected_index: nil, block: nil)
|
|
19
|
+
super
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
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
|
+
module RatatuiRuby
|
|
7
|
+
# Renders children on top of each other (Painter's Algorithm).
|
|
8
|
+
#
|
|
9
|
+
# [layers] Array of Widgets.
|
|
10
|
+
class Overlay < Data.define(:layers)
|
|
11
|
+
# Creates a new Overlay.
|
|
12
|
+
#
|
|
13
|
+
# [layers] Array of Widgets.
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,37 @@
|
|
|
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
|
+
module RatatuiRuby
|
|
7
|
+
# A widget that displays a block of text.
|
|
8
|
+
#
|
|
9
|
+
# [text] the text to display.
|
|
10
|
+
# [style] the style to apply (Style object).
|
|
11
|
+
# [block] an optional Block widget to wrap the paragraph.
|
|
12
|
+
class Paragraph < Data.define(:text, :style, :block, :wrap, :align)
|
|
13
|
+
# Creates a new Paragraph.
|
|
14
|
+
#
|
|
15
|
+
# [text] the text to display.
|
|
16
|
+
# [style] the style to apply.
|
|
17
|
+
# [block] the block to wrap the paragraph.
|
|
18
|
+
# [wrap] whether to wrap text at width.
|
|
19
|
+
# [align] alignment (:left, :center, :right).
|
|
20
|
+
def initialize(text:, style: Style.default, block: nil, wrap: false, align: :left)
|
|
21
|
+
super
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# Support for legacy fg/bg arguments.
|
|
25
|
+
# [text] the text to display.
|
|
26
|
+
# [style] the style to apply.
|
|
27
|
+
# [fg] legacy foreground color.
|
|
28
|
+
# [bg] legacy background color.
|
|
29
|
+
# [block] the block to wrap the paragraph.
|
|
30
|
+
# [wrap] whether to wrap text at width.
|
|
31
|
+
# [align] alignment (:left, :center, :right).
|
|
32
|
+
def self.new(text:, style: nil, fg: nil, bg: nil, block: nil, wrap: false, align: :left)
|
|
33
|
+
style ||= Style.new(fg:, bg:)
|
|
34
|
+
super(text:, style:, block:, wrap:, align:)
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
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
|
+
module RatatuiRuby
|
|
7
|
+
##
|
|
8
|
+
# Visual scroll indicator.
|
|
9
|
+
#
|
|
10
|
+
# A Scrollbar widget that can be oriented vertically or horizontally.
|
|
11
|
+
# It displays a track and a thumb to indicate the current scroll position
|
|
12
|
+
# relative to the total content length.
|
|
13
|
+
#
|
|
14
|
+
# == Fields
|
|
15
|
+
#
|
|
16
|
+
# [+content_length+] Total length of the content (Integer).
|
|
17
|
+
# [+position+] Current scroll position (Integer).
|
|
18
|
+
# [+orientation+] +:vertical+ or +:horizontal+ (Symbol, default: +:vertical+).
|
|
19
|
+
# [+thumb_symbol+] The character used for the scrollbar thumb (String, default: "█").
|
|
20
|
+
# [+block+] An optional Block to wrap the scrollbar.
|
|
21
|
+
class Scrollbar < Data.define(:content_length, :position, :orientation, :thumb_symbol, :block)
|
|
22
|
+
# Creates a new Scrollbar.
|
|
23
|
+
#
|
|
24
|
+
# [+content_length+] Total length of the content (Integer).
|
|
25
|
+
# [+position+] Current scroll position (Integer).
|
|
26
|
+
# [+orientation+] +:vertical+ or +:horizontal+ (Symbol, default: +:vertical+).
|
|
27
|
+
# [+thumb_symbol+] The character used for the scrollbar thumb (String, default: "█").
|
|
28
|
+
# [+block+] An optional Block to wrap the scrollbar.
|
|
29
|
+
def initialize(content_length:, position:, orientation: :vertical, thumb_symbol: "█", block: nil)
|
|
30
|
+
super
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
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
|
+
module RatatuiRuby
|
|
7
|
+
# A widget that displays a compact data row.
|
|
8
|
+
#
|
|
9
|
+
# [data] Array of Integers.
|
|
10
|
+
# [max] Optional maximum value.
|
|
11
|
+
# [style] Optional style for the sparkline.
|
|
12
|
+
# [block] Optional block widget to wrap the sparkline.
|
|
13
|
+
class Sparkline < Data.define(:data, :max, :style, :block)
|
|
14
|
+
# Creates a new Sparkline widget.
|
|
15
|
+
#
|
|
16
|
+
# [data] Array of Integers.
|
|
17
|
+
# [max] Optional maximum value.
|
|
18
|
+
# [style] Optional style for the sparkline.
|
|
19
|
+
# [block] Optional block widget to wrap the sparkline.
|
|
20
|
+
def initialize(data:, max: nil, style: nil, block: nil)
|
|
21
|
+
super
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
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
|
+
module RatatuiRuby
|
|
7
|
+
# A value object that defines colors and modifiers for text or widgets.
|
|
8
|
+
#
|
|
9
|
+
# [fg] The foreground color (e.g., +:red+, +"#ff0000"+).
|
|
10
|
+
# [bg] The background color (e.g., +:black+, +"#000000"+).
|
|
11
|
+
# [modifiers] An array of symbols representing text modifiers:
|
|
12
|
+
# [+:bold+, +:italic+, +:dim+, +:reversed+, +:underlined+, +:slow_blink+, +:rapid_blink+, +:crossed_out+, +:hidden+]
|
|
13
|
+
class Style < Data.define(:fg, :bg, :modifiers)
|
|
14
|
+
# Creates a new Style.
|
|
15
|
+
#
|
|
16
|
+
# [fg] The foreground color (e.g., "red", "#ff0000").
|
|
17
|
+
# [bg] The background color (e.g., "black", "#000000").
|
|
18
|
+
# [modifiers] An array of symbols representing text modifiers.
|
|
19
|
+
def initialize(fg: nil, bg: nil, modifiers: [])
|
|
20
|
+
super
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# Returns a default style with no colors or modifiers.
|
|
24
|
+
#
|
|
25
|
+
# Style.default
|
|
26
|
+
# # => #<RatatuiRuby::Style fg=nil, bg=nil, modifiers=[]>
|
|
27
|
+
def self.default
|
|
28
|
+
new
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
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
|
+
module RatatuiRuby
|
|
7
|
+
# A widget that displays data in a grid with rows and columns.
|
|
8
|
+
#
|
|
9
|
+
# [header] An array of strings or Paragraphs representing the header row.
|
|
10
|
+
# [rows] An array of arrays of strings or Paragraphs representing the data rows.
|
|
11
|
+
# [widths] An array of Constraint objects defining column widths.
|
|
12
|
+
# [block] An optional Block widget to wrap the table.
|
|
13
|
+
class Table < Data.define(:header, :rows, :widths, :block)
|
|
14
|
+
# Creates a new Table.
|
|
15
|
+
#
|
|
16
|
+
# [header] An array of strings or Paragraphs representing the header row.
|
|
17
|
+
# [rows] An array of arrays of strings or Paragraphs representing the data rows.
|
|
18
|
+
# [widths] An array of Constraint objects defining column widths.
|
|
19
|
+
# [block] An optional Block widget to wrap the table.
|
|
20
|
+
def initialize(header: nil, rows: [], widths: [], block: nil)
|
|
21
|
+
super
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
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
|
+
module RatatuiRuby
|
|
7
|
+
# A widget that displays a set of tabs, one of which is selected.
|
|
8
|
+
#
|
|
9
|
+
# [titles] Array of strings or lines to display as tab titles.
|
|
10
|
+
# [selected_index] The index of the currently selected tab.
|
|
11
|
+
# [block] Optional block widget to wrap the tabs.
|
|
12
|
+
class Tabs < Data.define(:titles, :selected_index, :block)
|
|
13
|
+
# Creates a new Tabs widget.
|
|
14
|
+
#
|
|
15
|
+
# [titles] Array of strings or lines to display as tab titles.
|
|
16
|
+
# [selected_index] The index of the currently selected tab.
|
|
17
|
+
# [block] Optional block widget to wrap the tabs.
|
|
18
|
+
def initialize(titles: [], selected_index: 0, block: nil)
|
|
19
|
+
super
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,75 @@
|
|
|
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
|
+
module RatatuiRuby
|
|
7
|
+
##
|
|
8
|
+
# Helpers for testing RatatuiRuby applications.
|
|
9
|
+
#
|
|
10
|
+
# This module provides methods to set up a test terminal, capture buffer content,
|
|
11
|
+
# and check cursor position, making it easier to write unit tests for your TUI apps.
|
|
12
|
+
#
|
|
13
|
+
# == Usage
|
|
14
|
+
#
|
|
15
|
+
# require "ratatui_ruby/test_helper"
|
|
16
|
+
#
|
|
17
|
+
# class MyTest < Minitest::Test
|
|
18
|
+
# include RatatuiRuby::TestHelper
|
|
19
|
+
#
|
|
20
|
+
# def test_rendering
|
|
21
|
+
# with_test_terminal(width: 80, height: 24) do
|
|
22
|
+
# # ... render your app ...
|
|
23
|
+
# assert_includes buffer_content, "Hello World"
|
|
24
|
+
# end
|
|
25
|
+
# end
|
|
26
|
+
# end
|
|
27
|
+
module TestHelper
|
|
28
|
+
##
|
|
29
|
+
# Initializes a test terminal context with specified dimensions.
|
|
30
|
+
# Restores the original terminal state after the block executes.
|
|
31
|
+
#
|
|
32
|
+
# +width+:: width of the test terminal (default: 20)
|
|
33
|
+
# +height+:: height of the test terminal (default: 10)
|
|
34
|
+
#
|
|
35
|
+
# If a block is given, it is executed within the test terminal context.
|
|
36
|
+
def with_test_terminal(width = 20, height = 10)
|
|
37
|
+
RatatuiRuby.init_test_terminal(width, height)
|
|
38
|
+
yield
|
|
39
|
+
ensure
|
|
40
|
+
RatatuiRuby.restore_terminal
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
##
|
|
44
|
+
# Returns the current content of the terminal buffer as an array of strings.
|
|
45
|
+
# Each string represents a row in the terminal.
|
|
46
|
+
#
|
|
47
|
+
# buffer_content
|
|
48
|
+
# # => ["Row 1 text", "Row 2 text", ...]
|
|
49
|
+
def buffer_content
|
|
50
|
+
RatatuiRuby.get_buffer_content.split("\n")
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
##
|
|
54
|
+
# Returns the current cursor position as a hash with +:x+ and +:y+ keys.
|
|
55
|
+
#
|
|
56
|
+
# cursor_position
|
|
57
|
+
# # => { x: 0, y: 0 }
|
|
58
|
+
def cursor_position
|
|
59
|
+
x, y = RatatuiRuby.get_cursor_position
|
|
60
|
+
{ x:, y: }
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
##
|
|
64
|
+
# Injects a mock event into the event queue for testing purposes.
|
|
65
|
+
#
|
|
66
|
+
# +event_type+:: "key" or "mouse"
|
|
67
|
+
# +data+:: a Hash containing event data
|
|
68
|
+
#
|
|
69
|
+
# inject_event("key", { code: "a" })
|
|
70
|
+
# inject_event("mouse", { kind: "down", x: 0, y: 0 })
|
|
71
|
+
def inject_event(event_type, data)
|
|
72
|
+
RatatuiRuby.inject_test_event(event_type, data)
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
@@ -0,0 +1,10 @@
|
|
|
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
|
+
module RatatuiRuby
|
|
7
|
+
# The version of the ratatui_ruby gem.
|
|
8
|
+
# See https://semver.org/spec/v2.0.0.html
|
|
9
|
+
VERSION = "0.1.0"
|
|
10
|
+
end
|
data/lib/ratatui_ruby.rb
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
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
|
+
require_relative "ratatui_ruby/version"
|
|
7
|
+
require_relative "ratatui_ruby/schema/paragraph"
|
|
8
|
+
require_relative "ratatui_ruby/schema/layout"
|
|
9
|
+
require_relative "ratatui_ruby/schema/block"
|
|
10
|
+
require_relative "ratatui_ruby/schema/constraint"
|
|
11
|
+
require_relative "ratatui_ruby/schema/list"
|
|
12
|
+
require_relative "ratatui_ruby/schema/style"
|
|
13
|
+
require_relative "ratatui_ruby/schema/gauge"
|
|
14
|
+
require_relative "ratatui_ruby/schema/table"
|
|
15
|
+
require_relative "ratatui_ruby/schema/tabs"
|
|
16
|
+
require_relative "ratatui_ruby/schema/bar_chart"
|
|
17
|
+
require_relative "ratatui_ruby/schema/sparkline"
|
|
18
|
+
require_relative "ratatui_ruby/schema/line_chart"
|
|
19
|
+
require_relative "ratatui_ruby/schema/cursor"
|
|
20
|
+
require_relative "ratatui_ruby/schema/overlay"
|
|
21
|
+
require_relative "ratatui_ruby/schema/center"
|
|
22
|
+
require_relative "ratatui_ruby/schema/scrollbar"
|
|
23
|
+
require_relative "ratatui_ruby/schema/canvas"
|
|
24
|
+
|
|
25
|
+
begin
|
|
26
|
+
require "ratatui_ruby/ratatui_ruby"
|
|
27
|
+
rescue LoadError
|
|
28
|
+
# Fallback for development/CI if the bundle is not in the load path
|
|
29
|
+
require_relative "ratatui_ruby/ratatui_ruby"
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# The RatatuiRuby module acts as a namespace for the entire gem.
|
|
33
|
+
# It provides the main entry points for initializing the terminal and drawing the UI.
|
|
34
|
+
module RatatuiRuby
|
|
35
|
+
# Generic error class for RatatuiRuby.
|
|
36
|
+
class Error < StandardError; end
|
|
37
|
+
|
|
38
|
+
##
|
|
39
|
+
# :method: init_terminal
|
|
40
|
+
# :call-seq: init_terminal() -> nil
|
|
41
|
+
#
|
|
42
|
+
# Initializes the terminal for TUI mode.
|
|
43
|
+
# Enters alternate screen and enables raw mode.
|
|
44
|
+
#
|
|
45
|
+
# (Native method implemented in Rust)
|
|
46
|
+
|
|
47
|
+
##
|
|
48
|
+
# :method: restore_terminal
|
|
49
|
+
# :call-seq: restore_terminal() -> nil
|
|
50
|
+
#
|
|
51
|
+
# Restores the terminal to its original state.
|
|
52
|
+
# Leaves alternate screen and disables raw mode.
|
|
53
|
+
#
|
|
54
|
+
# (Native method implemented in Rust)
|
|
55
|
+
|
|
56
|
+
##
|
|
57
|
+
# :method: draw
|
|
58
|
+
# :call-seq: draw(node) -> nil
|
|
59
|
+
#
|
|
60
|
+
# Draws the given UI node tree to the terminal.
|
|
61
|
+
# [node] the root node of the UI tree (Paragraph, Layout).
|
|
62
|
+
#
|
|
63
|
+
# (Native method implemented in Rust)
|
|
64
|
+
|
|
65
|
+
##
|
|
66
|
+
# :method: poll_event
|
|
67
|
+
# :call-seq: poll_event() -> Hash, nil
|
|
68
|
+
#
|
|
69
|
+
# Polls for a keyboard event.
|
|
70
|
+
#
|
|
71
|
+
# poll_event
|
|
72
|
+
# # => { type: "key", code: "char", value: "a", modifiers: [] }
|
|
73
|
+
#
|
|
74
|
+
# (Native method implemented in Rust)
|
|
75
|
+
|
|
76
|
+
##
|
|
77
|
+
# :method: inject_test_event
|
|
78
|
+
# :call-seq: inject_test_event(event_type, data) -> nil
|
|
79
|
+
#
|
|
80
|
+
# Injects a mock event into the event queue for testing purposes.
|
|
81
|
+
# [event_type] "key" or "mouse"
|
|
82
|
+
# [data] a Hash containing event data
|
|
83
|
+
#
|
|
84
|
+
# inject_test_event("key", { code: "a" })
|
|
85
|
+
#
|
|
86
|
+
# (Native method implemented in Rust)
|
|
87
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
|
|
2
|
+
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
3
|
+
|
|
4
|
+
module RatatuiRuby
|
|
5
|
+
type widget = Paragraph | Layout | List | Gauge | Table | Tabs | BarChart | Block | Sparkline | LineChart
|
|
6
|
+
|
|
7
|
+
interface _ToS
|
|
8
|
+
def to_s: () -> String
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def self.init_terminal: () -> void
|
|
12
|
+
def self.restore_terminal: () -> void
|
|
13
|
+
def self.draw: (widget) -> void
|
|
14
|
+
def self.poll_event: () -> Hash[Symbol, untyped]?
|
|
15
|
+
def self.inject_test_event: (String, Hash[Symbol, untyped]) -> void
|
|
16
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
|
|
2
|
+
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
3
|
+
|
|
4
|
+
module RatatuiRuby
|
|
5
|
+
class BarChart < Data
|
|
6
|
+
attr_reader data: Hash[String | Symbol | _ToS, Integer]
|
|
7
|
+
attr_reader bar_width: Integer
|
|
8
|
+
attr_reader bar_gap: Integer
|
|
9
|
+
attr_reader max: Integer?
|
|
10
|
+
attr_reader style: Style?
|
|
11
|
+
attr_reader block: Block?
|
|
12
|
+
def self.new: (data: Hash[String | Symbol | _ToS, Integer], ?bar_width: Integer, ?bar_gap: Integer, ?max: Integer?, ?style: Style?, ?block: Block?) -> BarChart
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
|
|
2
|
+
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
3
|
+
|
|
4
|
+
module RatatuiRuby
|
|
5
|
+
class Block < Data
|
|
6
|
+
attr_reader title: String?
|
|
7
|
+
attr_reader borders: Array[Symbol]
|
|
8
|
+
attr_reader border_color: (String | Symbol)?
|
|
9
|
+
def self.new: (?title: String?, ?borders: Array[Symbol], ?border_color: (String | Symbol)?) -> Block
|
|
10
|
+
end
|
|
11
|
+
end
|