ratatui_ruby 1.0.0.pre.beta.1 → 1.0.0.pre.beta.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c251e31a8aea8d5e84bc0969f8f6c95f690a2ce94d0cbd3538856bfbdafd055a
4
- data.tar.gz: ee38d86ebdc50612ba5a32990e7f1c3757e9f35ced6d621fc92203836c938793
3
+ metadata.gz: 69c2adadc9306ebeb02ffefa11e56abe7db2f0ef1c361a2edaf1cf5a3f9b9fee
4
+ data.tar.gz: c8e07b3361a46597f957fa6a4ade8e9eef426fa85a0df8650f7188a306384d5a
5
5
  SHA512:
6
- metadata.gz: 4f555dd2eddeef420df2512c53e26a136a791cfabd72bfe74ac1c5bd3f652d317bc9c60d47a78611f3a20e76ae72925494d867fcd992a17f0dcd29b3bb18b33d
7
- data.tar.gz: 47d21c6a4e5969a5457705eb088efaa45dd29ee5d6fac1f67166f3a4c2114aa65d54b926b05191fcf8f2a20b8a1c6481d19ffed195f0e2ee045bfaf561589dc5
6
+ metadata.gz: eb439fe49d032bf2d7221b4771b2b6b0156d9b5373d32fe6710ff0077046263fc5e719c1d91d1ed271b3cb58c18cf9f31ef6d366daed59b6f4413ac66db82447
7
+ data.tar.gz: dc395bd562a70d0bc8a9d6eafa4ca0b488ef3ce450a3f3d65b125550ed616c1516b2b5301bb0b634028433f90d4306885ba8f756542241fb9d5e0c4fa25d6644
data/.builds/ruby-3.2.yml CHANGED
@@ -16,7 +16,7 @@ packages:
16
16
  - clang
17
17
  - git
18
18
  artifacts:
19
- - ratatui_ruby/pkg/ratatui_ruby-1.0.0.pre.beta.1.gem
19
+ - ratatui_ruby/pkg/ratatui_ruby-1.0.0.pre.beta.2.gem
20
20
  sources:
21
21
  - https://git.sr.ht/~kerrick/ratatui_ruby
22
22
  tasks:
data/.builds/ruby-3.3.yml CHANGED
@@ -16,7 +16,7 @@ packages:
16
16
  - clang
17
17
  - git
18
18
  artifacts:
19
- - ratatui_ruby/pkg/ratatui_ruby-1.0.0.pre.beta.1.gem
19
+ - ratatui_ruby/pkg/ratatui_ruby-1.0.0.pre.beta.2.gem
20
20
  sources:
21
21
  - https://git.sr.ht/~kerrick/ratatui_ruby
22
22
  tasks:
data/.builds/ruby-3.4.yml CHANGED
@@ -16,7 +16,7 @@ packages:
16
16
  - clang
17
17
  - git
18
18
  artifacts:
19
- - ratatui_ruby/pkg/ratatui_ruby-1.0.0.pre.beta.1.gem
19
+ - ratatui_ruby/pkg/ratatui_ruby-1.0.0.pre.beta.2.gem
20
20
  sources:
21
21
  - https://git.sr.ht/~kerrick/ratatui_ruby
22
22
  tasks:
@@ -16,7 +16,7 @@ packages:
16
16
  - clang
17
17
  - git
18
18
  artifacts:
19
- - ratatui_ruby/pkg/ratatui_ruby-1.0.0.pre.beta.1.gem
19
+ - ratatui_ruby/pkg/ratatui_ruby-1.0.0.pre.beta.2.gem
20
20
  sources:
21
21
  - https://git.sr.ht/~kerrick/ratatui_ruby
22
22
  tasks:
data/.rubocop.yml CHANGED
@@ -5,4 +5,6 @@ inherit_from:
5
5
  - ./vendor/goodcop/base.yml
6
6
 
7
7
  AllCops:
8
- TargetRubyVersion: "3.3"
8
+ TargetRubyVersion: "3.3"
9
+ Exclude:
10
+ - 'examples/verify_website_menu/app.rb'
data/CHANGELOG.md CHANGED
@@ -18,6 +18,18 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
18
18
 
19
19
  ### Removed
20
20
 
21
+ ## [1.0.0-beta.2] - 2026-01-20
22
+
23
+ ### Added
24
+
25
+ ### Changed
26
+
27
+ ### Fixed
28
+
29
+ - **TableState Row Navigation Methods**: Added missing row navigation methods (`select_next`, `select_previous`, `select_first`, `select_last`) that should have been included alongside the column navigation methods added in v0.10.0. These methods match `ListState`'s navigation API and are used in the `app_stateful_interaction` example.
30
+
31
+ ### Removed
32
+
21
33
  ## [1.0.0-beta.1] - 2026-01-20
22
34
  This release is functionally equivalent to v0.10.3. The version bump signals the beginning of the 1.0 release series.
23
35
 
@@ -670,6 +682,7 @@ This release is functionally equivalent to v0.10.3. The version bump signals the
670
682
  - **Testing Support**: Included `RatatuiRuby::TestHelper` and RSpec integration to make testing your TUI applications possible.
671
683
 
672
684
  [Unreleased]: https://git.sr.ht/~kerrick/ratatui_ruby/refs/HEAD
685
+ [1.0.0-beta.2]: https://git.sr.ht/~kerrick/ratatui_ruby/refs/v1.0.0-beta.2
673
686
  [1.0.0-beta.1]: https://git.sr.ht/~kerrick/ratatui_ruby/refs/v1.0.0-beta.1
674
687
  [0.10.3]: https://git.sr.ht/~kerrick/ratatui_ruby/refs/v0.10.3
675
688
  [0.10.2]: https://git.sr.ht/~kerrick/ratatui_ruby/refs/v0.10.2
data/README.md CHANGED
@@ -21,7 +21,7 @@ Mailing List: Announcements](https://img.shields.io/badge/mailing_list-announcem
21
21
  **ratatui_ruby** is a community wrapper that is not affiliated with [the Ratatui team](https://github.com/orgs/ratatui/people).
22
22
 
23
23
  > [!WARNING]
24
- > **ratatui_ruby** is currently in **ALPHA**. The API may change between minor versions.
24
+ > **ratatui_ruby** is currently in **BETA**. Please report any bugs you find!
25
25
 
26
26
  **[Why RatatuiRuby?](./doc/getting_started/why.md)** — Native Rust performance, zero runtime overhead, and Ruby's expressiveness. [See how we compare](./doc/getting_started/why.md) to CharmRuby, raw Rust, and Go.
27
27
 
@@ -91,7 +91,7 @@ Or install it yourself with:
91
91
  SPDX-License-Identifier: MIT-0
92
92
  -->
93
93
  ```bash
94
- gem install ratatui_ruby
94
+ gem install ratatui_ruby --pre
95
95
  ```
96
96
  <!-- SPDX-SnippetEnd -->
97
97
 
data/README.rdoc CHANGED
@@ -5,7 +5,7 @@ RatatuiRuby[https://rubygems.org/gems/ratatui_ruby] is a RubyGem built on
5
5
  Ratatui[https://ratatui.rs], a leading TUI library written in
6
6
  Rust[https://rust-lang.org]. You get native performance with the joy of Ruby.
7
7
 
8
- gem install ratatui_ruby
8
+ gem install ratatui_ruby --pre
9
9
 
10
10
  {rdoc-image:https://ratatui-ruby.dev/hero.gif}[https://www.ratatui-ruby.dev/docs/v0.10/examples/app_cli_rich_moments/README_md.html]
11
11
 
@@ -49,7 +49,7 @@ class View::Live
49
49
  desc_str = event_data ? event_data[:description] : "—"
50
50
 
51
51
  is_lit = model.lit?(type)
52
- row_style = is_lit ? tui.style(fg: :black, bg: :green) : nil
52
+ row_style = is_lit ? tui.style(fg: :green, modifiers: [:reversed]) : nil
53
53
 
54
54
  rows << tui.text_line(spans: [
55
55
  tui.text_span(content: class_str.ljust(9), style: row_style || tui.style(fg: :cyan)),
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+ # rubocop:disable all
2
3
 
3
4
  #--
4
5
  # SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
@@ -15,14 +16,10 @@ class RadioMenu
15
16
  CHOICES = ["Production", "Staging", "Development"] # ASCII strings are universally supported.
16
17
  PREFIXES = { active: "●", inactive: "○" } # Some terminals may not support Unicode.
17
18
  CONTROLS = "↑/↓: Select | Enter: Choose | Ctrl+C: Cancel" # Let users know what keys you handle.
18
- TITLES = [
19
- "Select Environment", # The default title position is top left.
20
- {
21
- content: CONTROLS, # Multiple titles can save space.
22
- position: :bottom, # Titles go on the top or bottom,
23
- alignment: :right,
24
- },
25
- ] # aligned left, right, or center
19
+ TITLES = ["Select Environment", # The default title position is top left.
20
+ { content: CONTROLS, # Multiple titles can save space.
21
+ position: :bottom, # Titles go on the top or bottom,
22
+ alignment: :right }] # aligned left, right, or center
26
23
 
27
24
  def call # This method blocks until a choice is made.
28
25
  RatatuiRuby.run(viewport: :inline, height: 5) do |tui| # RatauiRuby.run manages the terminal.
@@ -32,8 +29,9 @@ alignment: :right,
32
29
  RadioMenu::CHOICES[@choice] # so you can use it synchronously.
33
30
  end
34
31
  # Classes like RadioMenu are convenient for
32
+ private # CLI authors to offer "rich moments."
35
33
 
36
- private def show_menu = @tui.draw do |frame| # RatatuiRuby gives you low-level access.
34
+ def show_menu = @tui.draw do |frame| # RatatuiRuby gives you low-level access.
37
35
  widget = @tui.paragraph( # But the TUI facade makes it easy to use.
38
36
  text: menu_items, # Text can be spans, lines, or paragraphs.
39
37
  block: @tui.block(borders: :all, titles: TITLES) # Blocks give you boxes and titles, and hold
@@ -41,7 +39,7 @@ alignment: :right,
41
39
  frame.render_widget(widget, frame.area) # but "area" lets you compose sub-views.
42
40
  end
43
41
 
44
- private def chosen? # You are responsible for handling input.
42
+ def chosen? # You are responsible for handling input.
45
43
  interaction = @tui.poll_event # Every frame, you receive an event object:
46
44
  return choose if interaction.enter? # Key, Mouse, Resize, Paste, FocusGained,
47
45
  # FocusLost, or None objects. They come with
@@ -51,39 +49,36 @@ alignment: :right,
51
49
  false # even interrupts and other exit patterns.
52
50
  end
53
51
 
54
- private def choose # Here, the loop is about to exit, and the
52
+ def choose # Here, the loop is about to exit, and the
55
53
  prepare_next_line # block will return. The inline viewport
56
54
  @choice # will be torn down and the terminal will
57
55
  end # be restored, but you are responsible for
58
-
59
56
  # positioning the cursor.
60
- private def prepare_next_line # To ensure the next output is on a new
57
+ def prepare_next_line # To ensure the next output is on a new
61
58
  area = @tui.viewport_area # line, query the viewport area and move
62
59
  RatatuiRuby.cursor_position = [0, area.y + area.height] # the cursor to the start of the last line.
63
60
  puts # Then print a newline.
64
61
  end
65
62
 
66
- private def quit! # All of your familiar Ruby control flow
63
+ def quit! # All of your familiar Ruby control flow
67
64
  prepare_next_line # keywords work as expected, so we can
68
65
  exit 0 # use them to leave the TUI.
69
66
  end
70
67
 
71
- private def move_by(line_count) # You are in full control of your UX, so
68
+ def move_by(line_count) # You are in full control of your UX, so
72
69
  @choice = (@choice + line_count) % CHOICES.size # you can implement any logic you need:
73
70
  end # Would you "wrap around" here, or not?
74
-
75
- private def menu_items = CHOICES.map.with_index do |choice, i| # Notably, RatatuiRuby has no concept of
71
+ #
72
+ def menu_items = CHOICES.map.with_index do |choice, i| # Notably, RatatuiRuby has no concept of
76
73
  "#{prefix_for(i)} #{choice}" # "menus" or "radio buttons". You are in
77
74
  end # full control, but it also means you must
78
-
79
- private def prefix_for(choice_index) # implement the logic yourself. For larger
75
+ def prefix_for(choice_index) # implement the logic yourself. For larger
80
76
  return PREFIXES[:active] if choice_index == @choice # applications, consider using Rooibos,
81
77
  PREFIXES[:inactive] # an MVU framework built with RatatuiRuby.
82
78
  end # Or, use the upcoming ratatui-ruby-kit,
83
-
84
79
  # our object-oriented component library.
85
- private def initialize = @choice = 0 # However, those are both optional, and
80
+ def initialize = @choice = 0 # However, those are both optional, and
86
81
  end # designed for full-screen Terminal UIs.
87
82
  # RatatuiRuby will always give you the most
88
83
  choice = RadioMenu.new.call # control, and is enough for "rich CLI
89
- puts "You chose #{choice}!" # moments" like this one.
84
+ puts "You chose #{choice}!" # moments" like this one.
@@ -1059,7 +1059,7 @@ dependencies = [
1059
1059
 
1060
1060
  [[package]]
1061
1061
  name = "ratatui_ruby"
1062
- version = "1.0.0-beta.1"
1062
+ version = "1.0.0-beta.2"
1063
1063
  dependencies = [
1064
1064
  "bumpalo",
1065
1065
  "lazy_static",
@@ -3,7 +3,7 @@
3
3
 
4
4
  [package]
5
5
  name = "ratatui_ruby"
6
- version = "1.0.0-beta.1"
6
+ version = "1.0.0-beta.2"
7
7
  edition = "2021"
8
8
 
9
9
  [lib]
@@ -95,6 +95,26 @@ impl RubyTableState {
95
95
  self.inner.borrow_mut().select_last_column();
96
96
  }
97
97
 
98
+ /// Selects the next row or the first one if no row is selected.
99
+ pub fn select_next(&self) {
100
+ self.inner.borrow_mut().select_next();
101
+ }
102
+
103
+ /// Selects the previous row or the last one if no row is selected.
104
+ pub fn select_previous(&self) {
105
+ self.inner.borrow_mut().select_previous();
106
+ }
107
+
108
+ /// Selects the first row.
109
+ pub fn select_first(&self) {
110
+ self.inner.borrow_mut().select_first();
111
+ }
112
+
113
+ /// Selects the last row.
114
+ pub fn select_last(&self) {
115
+ self.inner.borrow_mut().select_last();
116
+ }
117
+
98
118
  /// Creates a new `RubyTableState` with a selected cell (row, column).
99
119
  pub fn with_selected_cell(cell: Option<(usize, usize)>) -> Self {
100
120
  let state = TableState::default().with_selected_cell(cell);
@@ -144,6 +164,13 @@ pub fn register(ruby: &Ruby, module: magnus::RModule) -> Result<(), Error> {
144
164
  class.define_method("offset", method!(RubyTableState::offset, 0))?;
145
165
  class.define_method("scroll_down_by", method!(RubyTableState::scroll_down_by, 1))?;
146
166
  class.define_method("scroll_up_by", method!(RubyTableState::scroll_up_by, 1))?;
167
+ class.define_method("select_next", method!(RubyTableState::select_next, 0))?;
168
+ class.define_method(
169
+ "select_previous",
170
+ method!(RubyTableState::select_previous, 0),
171
+ )?;
172
+ class.define_method("select_first", method!(RubyTableState::select_first, 0))?;
173
+ class.define_method("select_last", method!(RubyTableState::select_last, 0))?;
147
174
  Ok(())
148
175
  }
149
176
 
@@ -138,6 +138,106 @@ module RatatuiRuby
138
138
  #
139
139
  # (Native method implemented in Rust)
140
140
 
141
+ ##
142
+ # :method: select_next
143
+ # :call-seq: select_next() -> nil
144
+ #
145
+ # Moves selection to the next row. Selects first row if nothing selected.
146
+ #
147
+ # === Optimistic Indexing
148
+ #
149
+ # Increments the index immediately, even past table bounds. The renderer
150
+ # clamps to valid range on draw. Reading <tt>selected</tt> between this
151
+ # call and render may return an out-of-bounds value.
152
+ #
153
+ # To detect actual selection changes, check bounds first:
154
+ #
155
+ #--
156
+ # SPDX-SnippetBegin
157
+ # SPDX-FileCopyrightText: 2026 Kerrick Long
158
+ # SPDX-License-Identifier: MIT-0
159
+ #++
160
+ # max_index = rows.size - 1
161
+ # return if (state.selected || 0) >= max_index
162
+ # state.select_next
163
+ #
164
+ #--
165
+ # SPDX-SnippetEnd
166
+ #++
167
+ # (Native method implemented in Rust)
168
+
169
+ ##
170
+ # :method: select_previous
171
+ # :call-seq: select_previous() -> nil
172
+ #
173
+ # Moves selection to the previous row. Selects last row if nothing selected.
174
+ #
175
+ # === Optimistic Indexing
176
+ #
177
+ # At index 0, does nothing. With no selection, sets index to maximum value;
178
+ # the renderer clamps to actual last row on draw.
179
+ #
180
+ # To detect actual selection changes, check bounds first:
181
+ #
182
+ #--
183
+ # SPDX-SnippetBegin
184
+ # SPDX-FileCopyrightText: 2026 Kerrick Long
185
+ # SPDX-License-Identifier: MIT-0
186
+ #++
187
+ # return if (state.selected || 0) <= 0
188
+ # state.select_previous
189
+ #
190
+ #--
191
+ # SPDX-SnippetEnd
192
+ #++
193
+ # (Native method implemented in Rust)
194
+
195
+ ##
196
+ # :method: select_first
197
+ # :call-seq: select_first() -> nil
198
+ #
199
+ # Jumps selection to the first row (index 0).
200
+ #
201
+ # To detect actual selection changes:
202
+ #
203
+ #--
204
+ # SPDX-SnippetBegin
205
+ # SPDX-FileCopyrightText: 2026 Kerrick Long
206
+ # SPDX-License-Identifier: MIT-0
207
+ #++
208
+ # return if (state.selected || 0) == 0
209
+ # state.select_first
210
+ #
211
+ #--
212
+ # SPDX-SnippetEnd
213
+ #++
214
+ # (Native method implemented in Rust)
215
+
216
+ ##
217
+ # :method: select_last
218
+ # :call-seq: select_last() -> nil
219
+ #
220
+ # Jumps selection to the last row.
221
+ #
222
+ # === Optimistic Indexing
223
+ #
224
+ # Sets index to maximum possible value. The renderer clamps to actual last
225
+ # row on draw. To get or check the real last index, track row count:
226
+ #
227
+ #--
228
+ # SPDX-SnippetBegin
229
+ # SPDX-FileCopyrightText: 2026 Kerrick Long
230
+ # SPDX-License-Identifier: MIT-0
231
+ #++
232
+ # max_index = rows.size - 1
233
+ # return if (state.selected || 0) == max_index
234
+ # state.select(max_index)
235
+ #
236
+ #--
237
+ # SPDX-SnippetEnd
238
+ #++
239
+ # (Native method implemented in Rust)
240
+
141
241
  ##
142
242
  # :singleton-method: with_selected_cell
143
243
  # :call-seq: with_selected_cell(cell) -> TableState
@@ -8,5 +8,5 @@
8
8
  module RatatuiRuby
9
9
  # The version of the ratatui_ruby gem.
10
10
  # See https://semver.org/spec/v2.0.0.html
11
- VERSION = "1.0.0-beta.1"
11
+ VERSION = "1.0.0-beta.2"
12
12
  end
data/tasks/lint.rake CHANGED
@@ -85,8 +85,10 @@ namespace :reuse do
85
85
  desc "Normalize Ruby files: frozen_string_literal at top, SPDX in #--/#++ block"
86
86
  task :normalize_ruby do
87
87
  ruby_extensions = %w[rb rake gemspec].freeze
88
+ # Exclude intentionally-formatted files
89
+ excluded_files = %w[examples/verify_website_menu/app.rb].freeze
88
90
  ruby_files = Dir.glob("**/*.{#{ruby_extensions.join(',')}}")
89
- .reject { |f| f.start_with?("vendor/", "tmp/", ".") }
91
+ .reject { |f| f.start_with?("vendor/", "tmp/", ".") || excluded_files.include?(f) }
90
92
 
91
93
  fixed_count = 0
92
94
  ruby_files.each do |file|
data/tasks/sourcehut.rake CHANGED
@@ -84,6 +84,27 @@ end
84
84
 
85
85
  if Rake::Task.task_defined?("release")
86
86
  Rake::Task["release"].enhance do
87
+ # Replace Bundler's normalized tag with semver-style for prerelease versions.
88
+ # Bundler creates tags using normalized Gem::Version (e.g., v1.0.0.pre.beta.1).
89
+ # Semver uses hyphens (e.g., v1.0.0-beta.1). We want only the semver tag.
90
+ version_content = File.read("lib/ratatui_ruby/version.rb")
91
+ version = version_content.match(/VERSION = "(.+?)"/)[1]
92
+
93
+ if version.include?("-")
94
+ normalized_tag = "v#{Gem::Version.new(version)}"
95
+ semver_tag = "v#{version}"
96
+
97
+ if normalized_tag != semver_tag
98
+ puts "Replacing normalized tag #{normalized_tag} with semver tag #{semver_tag}..."
99
+ # Delete the normalized tag locally and remotely
100
+ sh "git tag -d #{normalized_tag}"
101
+ sh "git push origin :refs/tags/#{normalized_tag}"
102
+ # Create the semver tag pointing to the same commit
103
+ sh "git tag #{semver_tag} HEAD"
104
+ sh "git push origin #{semver_tag}"
105
+ end
106
+ end
107
+
87
108
  Rake::Task["sourcehut:update_stable"].invoke
88
109
  end
89
110
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ratatui_ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0.pre.beta.1
4
+ version: 1.0.0.pre.beta.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kerrick Long
@@ -101,7 +101,7 @@ description: |2-
101
101
  Ratatui[https://ratatui.rs], a leading TUI library written in
102
102
  Rust[https://rust-lang.org]. You get native performance with the joy of Ruby.
103
103
 
104
- gem install ratatui_ruby
104
+ gem install ratatui_ruby --pre
105
105
 
106
106
  {rdoc-image:https://ratatui-ruby.dev/hero.gif}[https://www.ratatui-ruby.dev/docs/v0.10/examples/app_cli_rich_moments/README_md.html]
107
107