ratatui_ruby 1.1.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e4af7cd6e9b1850a0abe3099f29c1dbf4d9e4f01cd1782196b0948c8591d9ba3
4
- data.tar.gz: 7e68a66603d410baaad20d9267b3da083bff66a1a9c7d3dd9d0142a4b89fca9f
3
+ metadata.gz: df3052d1e97ee4b1fcb97693be22ad3f15a593f3c6fffe139e2758f2282bb44e
4
+ data.tar.gz: '01178a70dc0e6c35da3d6dedde2b5e83826f054cb930dce773e6323ecdf1e2fc'
5
5
  SHA512:
6
- metadata.gz: b3790091fe5de4276ff383caffc753012efc7d8646eb7d2d5a2467e73518dbd8584c692ffec368a374d6cf9a11981be6af0d3d51a1421e48f4afe1e528547618
7
- data.tar.gz: f63f2bbb7abf4462be09d17aabc8bdf7737853b79e4ff5d55425a2246687a23c47e5a04c19bd41405171f0e14f94749ba70e5fe07578ffcb5ffec1e248f43246
6
+ metadata.gz: 96b4aae8eb4c72cccef740f701556a86a59f11c43eb5a432c9715dbfe5f80c05002727a2cd567d16f84d995a3357810b2bbeb29c577b06fd505fd8361b213199
7
+ data.tar.gz: f833305d63b0def8e357ce8fbed452c3da62cf49afdd1d4ced9a1f1f1e181bc44fe628f8271c8be71e82440ef92a639a4cd035a010bdba3a98474fd02343ef95
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.1.0.gem
19
+ - ratatui_ruby/pkg/ratatui_ruby-1.2.0.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.1.0.gem
19
+ - ratatui_ruby/pkg/ratatui_ruby-1.2.0.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.1.0.gem
19
+ - ratatui_ruby/pkg/ratatui_ruby-1.2.0.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.1.0.gem
19
+ - ratatui_ruby/pkg/ratatui_ruby-1.2.0.gem
20
20
  sources:
21
21
  - https://git.sr.ht/~kerrick/ratatui_ruby
22
22
  tasks:
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.2.0] - 2026-01-25
22
+
23
+ ### Added
24
+
25
+ - **Inline Sync Mode**: `SyntheticEvents.inline_sync!` enables deterministic ordering of sync events with key events. When enabled, `inject_sync` routes through the native event queue and `poll_event` returns `Event::Sync` in sequence. Runtimes that need ordering guarantees (like Rooibos) should call this at startup.
26
+
27
+ ### Changed
28
+
29
+ ### Fixed
30
+
31
+ ### Removed
32
+
21
33
  ## [1.1.0] - 2026-01-25
22
34
 
23
35
  ### Added
@@ -45,6 +57,8 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
45
57
 
46
58
  ### Removed
47
59
 
60
+
61
+
48
62
  ## [1.0.0] - 2026-01-25
49
63
 
50
64
  ### Added
@@ -711,6 +725,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
711
725
  - **Testing Support**: Included `RatatuiRuby::TestHelper` and RSpec integration to make testing your TUI applications possible.
712
726
 
713
727
  [Unreleased]: https://git.sr.ht/~kerrick/ratatui_ruby/refs/HEAD
728
+ [1.2.0]: https://git.sr.ht/~kerrick/ratatui_ruby/refs/v1.2.0
714
729
  [1.1.0]: https://git.sr.ht/~kerrick/ratatui_ruby/refs/v1.1.0
715
730
  [1.0.0]: https://git.sr.ht/~kerrick/ratatui_ruby/refs/v1.0.0
716
731
  [0.10.3]: https://git.sr.ht/~kerrick/ratatui_ruby/refs/v0.10.3
@@ -1059,7 +1059,7 @@ dependencies = [
1059
1059
 
1060
1060
  [[package]]
1061
1061
  name = "ratatui_ruby"
1062
- version = "1.1.0"
1062
+ version = "1.2.0"
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.1.0"
6
+ version = "1.2.0"
7
7
  edition = "2021"
8
8
 
9
9
  [lib]
@@ -4,8 +4,15 @@
4
4
  use magnus::{Error, IntoValue, TryConvert, Value};
5
5
  use std::cell::RefCell;
6
6
 
7
+ /// Wrapper enum for test events - includes crossterm events and our Sync event.
8
+ #[derive(Debug, Clone)]
9
+ enum TestEvent {
10
+ Crossterm(ratatui::crossterm::event::Event),
11
+ Sync,
12
+ }
13
+
7
14
  thread_local! {
8
- static EVENT_QUEUE: RefCell<Vec<ratatui::crossterm::event::Event>> = const { RefCell::new(Vec::new()) };
15
+ static EVENT_QUEUE: RefCell<Vec<TestEvent>> = const { RefCell::new(Vec::new()) };
9
16
  }
10
17
 
11
18
  use ratatui::crossterm::event::{KeyCode, KeyModifiers, MediaKeyCode, ModifierKeyCode};
@@ -107,12 +114,13 @@ pub fn all_key_codes() -> magnus::RHash {
107
114
  pub fn inject_test_event(event_type: String, data: magnus::RHash) -> Result<(), Error> {
108
115
  let ruby = magnus::Ruby::get().unwrap();
109
116
  let event = match event_type.as_str() {
110
- "key" => parse_key_event(data, &ruby)?,
111
- "mouse" => parse_mouse_event(data, &ruby)?,
112
- "resize" => parse_resize_event(data, &ruby)?,
113
- "paste" => parse_paste_event(data, &ruby)?,
114
- "focus_gained" => ratatui::crossterm::event::Event::FocusGained,
115
- "focus_lost" => ratatui::crossterm::event::Event::FocusLost,
117
+ "key" => TestEvent::Crossterm(parse_key_event(data, &ruby)?),
118
+ "mouse" => TestEvent::Crossterm(parse_mouse_event(data, &ruby)?),
119
+ "resize" => TestEvent::Crossterm(parse_resize_event(data, &ruby)?),
120
+ "paste" => TestEvent::Crossterm(parse_paste_event(data, &ruby)?),
121
+ "focus_gained" => TestEvent::Crossterm(ratatui::crossterm::event::Event::FocusGained),
122
+ "focus_lost" => TestEvent::Crossterm(ratatui::crossterm::event::Event::FocusLost),
123
+ "sync" => TestEvent::Sync,
116
124
  _ => {
117
125
  return Err(Error::new(
118
126
  ruby.exception_arg_error(),
@@ -317,7 +325,7 @@ pub fn poll_event(ruby: &magnus::Ruby, timeout_val: Option<f64>) -> Result<Value
317
325
  });
318
326
 
319
327
  if let Some(e) = event {
320
- return handle_event(e);
328
+ return handle_test_event(e);
321
329
  }
322
330
 
323
331
  let is_test_mode = crate::terminal::with_query(|q| q.is_test_mode()).unwrap_or(false);
@@ -334,7 +342,7 @@ pub fn poll_event(ruby: &magnus::Ruby, timeout_val: Option<f64>) -> Result<Value
334
342
  {
335
343
  let event = ratatui::crossterm::event::read()
336
344
  .map_err(|e| Error::new(ruby.exception_runtime_error(), e.to_string()))?;
337
- handle_event(event)
345
+ handle_crossterm_event(event)
338
346
  } else {
339
347
  Ok(ruby.qnil().into_value_with(ruby))
340
348
  }
@@ -342,11 +350,18 @@ pub fn poll_event(ruby: &magnus::Ruby, timeout_val: Option<f64>) -> Result<Value
342
350
  // Blocking: wait indefinitely for an event
343
351
  let event = ratatui::crossterm::event::read()
344
352
  .map_err(|e| Error::new(ruby.exception_runtime_error(), e.to_string()))?;
345
- handle_event(event)
353
+ handle_crossterm_event(event)
354
+ }
355
+ }
356
+
357
+ fn handle_test_event(event: TestEvent) -> Result<Value, Error> {
358
+ match event {
359
+ TestEvent::Crossterm(e) => handle_crossterm_event(e),
360
+ TestEvent::Sync => handle_sync_event(),
346
361
  }
347
362
  }
348
363
 
349
- fn handle_event(event: ratatui::crossterm::event::Event) -> Result<Value, Error> {
364
+ fn handle_crossterm_event(event: ratatui::crossterm::event::Event) -> Result<Value, Error> {
350
365
  match event {
351
366
  ratatui::crossterm::event::Event::Key(key) => handle_key_event(key),
352
367
  ratatui::crossterm::event::Event::Mouse(event) => handle_mouse_event(event),
@@ -357,6 +372,13 @@ fn handle_event(event: ratatui::crossterm::event::Event) -> Result<Value, Error>
357
372
  }
358
373
  }
359
374
 
375
+ fn handle_sync_event() -> Result<Value, Error> {
376
+ let ruby = magnus::Ruby::get().unwrap();
377
+ let hash = ruby.hash_new();
378
+ hash.aset(ruby.to_symbol("type"), ruby.to_symbol("sync"))?;
379
+ Ok(hash.into_value_with(&ruby))
380
+ }
381
+
360
382
  fn media_key_to_string(m: MediaKeyCode) -> &'static str {
361
383
  MEDIA_KEY_MAPPINGS
362
384
  .iter()
@@ -48,8 +48,28 @@ module RatatuiRuby
48
48
  module SyntheticEvents
49
49
  @queue = [] #: Array[Event]
50
50
  @mutex = Mutex.new
51
+ @inline_sync = false #: bool
51
52
 
52
53
  class << self
54
+ ##
55
+ # Enables inline sync mode for deterministic event ordering.
56
+ #
57
+ # Call once at startup. Cannot be disabled.
58
+ #
59
+ # When enabled, +inject_sync+ routes through the native event queue
60
+ # and +poll_event+ returns +Event::Sync+ like any other event.
61
+ # This ensures sync events are processed in sequence with key events.
62
+ #
63
+ # Runtimes that need ordering guarantees (like Rooibos) should call
64
+ # this before entering their event loop.
65
+ def inline_sync!
66
+ @inline_sync = true
67
+ end
68
+
69
+ def inline_sync? # :nodoc:
70
+ @inline_sync
71
+ end
72
+
53
73
  ##
54
74
  # Pushes an event to the synthetic queue.
55
75
  #
@@ -89,8 +89,13 @@ module RatatuiRuby
89
89
  when RatatuiRuby::Event::FocusLost
90
90
  RatatuiRuby.inject_test_event("focus_lost", {})
91
91
  when RatatuiRuby::Event::Sync
92
- # Sync events use the engine-level synthetic queue
93
- RatatuiRuby::SyntheticEvents.push(event)
92
+ if RatatuiRuby::SyntheticEvents.inline_sync?
93
+ # Route through native queue for deterministic ordering with key events
94
+ RatatuiRuby.inject_test_event("sync", {})
95
+ else
96
+ # Default 1.0 behavior: use the engine-level synthetic queue
97
+ RatatuiRuby::SyntheticEvents.push(event)
98
+ end
94
99
  else
95
100
  raise ArgumentError, "Unknown event type: #{event.class}"
96
101
  end
@@ -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.1.0"
11
+ VERSION = "1.2.0"
12
12
  end
data/lib/ratatui_ruby.rb CHANGED
@@ -409,6 +409,8 @@ module RatatuiRuby
409
409
  Event::FocusGained.new.freeze
410
410
  when :focus_lost
411
411
  Event::FocusLost.new.freeze
412
+ when :sync
413
+ Event::Sync.new.freeze
412
414
  else
413
415
  # Return None for unknown event types
414
416
  Event::None.new.freeze
@@ -12,7 +12,10 @@ module RatatuiRuby
12
12
  # Used primarily for testing and the andThen-like integration pattern.
13
13
  module SyntheticEvents
14
14
  @queue: Array[Event]
15
+ @inline_sync: bool
15
16
 
17
+ def self.inline_sync!: () -> void
18
+ def self.inline_sync?: () -> bool
16
19
  def self.push: (Event event) -> void
17
20
  def self.pop: () -> Event?
18
21
  def self.clear: () -> void
data/tasks/sourcehut.rake CHANGED
@@ -68,6 +68,18 @@ namespace :sourcehut do
68
68
  abort "Fatal: Version mismatch! 'lib/ratatui_ruby/version.rb' says #{tag_name}, but the latest git tag is #{latest_tag}."
69
69
  end
70
70
 
71
+ # Get current stable version (if stable branch exists)
72
+ stable_version_str = `git show stable:lib/ratatui_ruby/version.rb 2>/dev/null`.match(/VERSION = "(.+?)"/)&.[](1)
73
+ if stable_version_str
74
+ stable_version = Gem::Version.new(stable_version_str)
75
+ new_version = Gem::Version.new(version)
76
+
77
+ if new_version <= stable_version
78
+ puts "Skipping stable update: #{version} is not newer than current stable #{stable_version_str}"
79
+ next
80
+ end
81
+ end
82
+
71
83
  puts "Updating stable branch to point to #{tag_name}..."
72
84
  # Resolve the tag to a commit hash (peel annotated tags)
73
85
  # This renders a commit SHA that can be pushed to a branch head
@@ -77,8 +89,8 @@ namespace :sourcehut do
77
89
  sh "git branch -f stable #{commit_sha}"
78
90
 
79
91
  # Push the commit to remote stable branch
80
- # This creates 'stable' if it doesn't exist, or fast-forwards it.
81
- sh "git push origin #{commit_sha}:stable"
92
+ # Force-push because stable is reset to each release, not fast-forwarded.
93
+ sh "git push --force origin #{commit_sha}:stable"
82
94
  end
83
95
  end
84
96
 
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.1.0
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kerrick Long