From c9167b83913625e57b161e6f7d6b8c89decdc89d Mon Sep 17 00:00:00 2001 From: Marco Roth Date: Tue, 17 Feb 2026 16:50:54 +0100 Subject: [PATCH] Add `rbs-inline` --- .github/workflows/main.yml | 3 + Gemfile | 1 + Gemfile.lock | 29 +++-- Rakefile | 18 +++ sig/bubbletea.rbs | 5 +- sig/bubbletea/commands.rbs | 80 +++++++++++++ sig/bubbletea/messages.rbs | 230 +++++++++++++++++++++++++++++++++++++ sig/bubbletea/model.rbs | 55 +++++++++ sig/bubbletea/runner.rbs | 56 +++++++++ sig/bubbletea/version.rbs | 5 + 10 files changed, 470 insertions(+), 12 deletions(-) create mode 100644 sig/bubbletea/commands.rbs create mode 100644 sig/bubbletea/messages.rbs create mode 100644 sig/bubbletea/model.rbs create mode 100644 sig/bubbletea/runner.rbs create mode 100644 sig/bubbletea/version.rbs diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 7b40d01..03f345d 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -44,5 +44,8 @@ jobs: - name: Run tests run: bundle exec rake test + # - name: Run steep check + # run: bundle exec steep check + - name: Run rubocop run: bundle exec rubocop diff --git a/Gemfile b/Gemfile index dc34129..2acd029 100644 --- a/Gemfile +++ b/Gemfile @@ -20,4 +20,5 @@ gem "maxitest", "~> 7.0" gem "rake", "~> 13.0" gem "rake-compiler", "~> 1.3" gem "rake-compiler-dock" +gem "rbs-inline", "~> 0.13.0" gem "rubocop" diff --git a/Gemfile.lock b/Gemfile.lock index 074eb6e..f9eac23 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -10,17 +10,17 @@ GEM ast (2.4.3) date (3.5.1) erb (6.0.1) - glamour (0.2.1) - glamour (0.2.1-aarch64-linux-gnu) - glamour (0.2.1-aarch64-linux-musl) - glamour (0.2.1-arm-linux-gnu) - glamour (0.2.1-arm-linux-musl) - glamour (0.2.1-arm64-darwin) - glamour (0.2.1-x86-linux-gnu) - glamour (0.2.1-x86-linux-musl) - glamour (0.2.1-x86_64-darwin) - glamour (0.2.1-x86_64-linux-gnu) - glamour (0.2.1-x86_64-linux-musl) + glamour (0.2.2) + glamour (0.2.2-aarch64-linux-gnu) + glamour (0.2.2-aarch64-linux-musl) + glamour (0.2.2-arm-linux-gnu) + glamour (0.2.2-arm-linux-musl) + glamour (0.2.2-arm64-darwin) + glamour (0.2.2-x86-linux-gnu) + glamour (0.2.2-x86-linux-musl) + glamour (0.2.2-x86_64-darwin) + glamour (0.2.2-x86_64-linux-gnu) + glamour (0.2.2-x86_64-linux-musl) harmonica (0.1.0) io-console (0.8.2) irb (1.16.0) @@ -63,6 +63,12 @@ GEM rake-compiler (1.3.1) rake rake-compiler-dock (1.11.0) + rbs (3.10.3) + logger + tsort + rbs-inline (0.13.0) + prism (>= 0.29) + rbs (>= 3.8.0) rdoc (7.0.2) erb psych (>= 4.0.0) @@ -116,6 +122,7 @@ DEPENDENCIES rake (~> 13.0) rake-compiler (~> 1.3) rake-compiler-dock + rbs-inline (~> 0.13.0) rubocop BUNDLED WITH diff --git a/Rakefile b/Rakefile index 66628b5..a7304b7 100644 --- a/Rakefile +++ b/Rakefile @@ -166,4 +166,22 @@ rescue LoadError => e end end +task :rbs_inline do + require "open3" + + command = "bundle exec rbs-inline --opt-out --output=sig/ lib/" + + _stdout, stderr, status = Open3.capture3(command) + + puts "Running `#{command}`" + + if stderr.strip.include?("🎉 Generated 0 RBS files under sig/") + puts "RBS files in sig/ are up to date" + exit status.exitstatus + else + puts "RBS files in sig/ are not up to date" + exit 1 + end +end + task default: [:test, :rubocop, :compile] diff --git a/sig/bubbletea.rbs b/sig/bubbletea.rbs index c14ad42..aaa5f1d 100644 --- a/sig/bubbletea.rbs +++ b/sig/bubbletea.rbs @@ -1,3 +1,6 @@ +# Generated from lib/bubbletea.rb with RBS::Inline + module Bubbletea - VERSION: String + class Error < StandardError + end end diff --git a/sig/bubbletea/commands.rbs b/sig/bubbletea/commands.rbs new file mode 100644 index 0000000..dc1d66c --- /dev/null +++ b/sig/bubbletea/commands.rbs @@ -0,0 +1,80 @@ +# Generated from lib/bubbletea/commands.rb with RBS::Inline + +module Bubbletea + class Command + end + + class QuitCommand < Command + end + + class BatchCommand < Command + attr_reader commands: untyped + + def initialize: (untyped commands) -> untyped + end + + class TickCommand < Command + attr_reader duration: untyped + + attr_reader callback: untyped + + def initialize: (untyped duration) ?{ (?) -> untyped } -> untyped + end + + class SendMessage < Command + attr_reader message: untyped + + attr_reader delay: untyped + + def initialize: (untyped message, ?delay: untyped) -> untyped + end + + class SequenceCommand < Command + attr_reader commands: untyped + + def initialize: (untyped commands) -> untyped + end + + class EnterAltScreenCommand < Command + end + + class ExitAltScreenCommand < Command + end + + class SetWindowTitleCommand < Command + attr_reader title: untyped + + def initialize: (untyped title) -> untyped + end + + class PutsCommand < Command + attr_reader text: untyped + + def initialize: (untyped text) -> untyped + end + + class SuspendCommand < Command + end + + def self.quit: () -> untyped + + def self.batch: (*untyped commands) -> untyped + + def self.tick: (untyped duration) ?{ (?) -> untyped } -> untyped + + def self.send_message: (untyped message, ?delay: untyped) -> untyped + + def self.sequence: (*untyped commands) -> untyped + + def self.none: () -> untyped + + def self.enter_alt_screen: () -> untyped + + def self.exit_alt_screen: () -> untyped + + def self.set_window_title: (untyped title) -> untyped + + def self.puts: (untyped text) -> untyped + + def self.suspend: () -> untyped +end diff --git a/sig/bubbletea/messages.rbs b/sig/bubbletea/messages.rbs new file mode 100644 index 0000000..2e112af --- /dev/null +++ b/sig/bubbletea/messages.rbs @@ -0,0 +1,230 @@ +# Generated from lib/bubbletea/messages.rb with RBS::Inline + +module Bubbletea + class Message + end + + class KeyMessage < Message + KEY_NULL: ::Integer + + KEY_CTRL_A: ::Integer + + KEY_CTRL_B: ::Integer + + KEY_CTRL_C: ::Integer + + KEY_CTRL_D: ::Integer + + KEY_CTRL_E: ::Integer + + KEY_CTRL_F: ::Integer + + KEY_CTRL_G: ::Integer + + KEY_CTRL_H: ::Integer + + KEY_TAB: ::Integer + + KEY_CTRL_J: ::Integer + + KEY_CTRL_K: ::Integer + + KEY_CTRL_L: ::Integer + + KEY_ENTER: ::Integer + + KEY_CTRL_N: ::Integer + + KEY_CTRL_O: ::Integer + + KEY_CTRL_P: ::Integer + + KEY_CTRL_Q: ::Integer + + KEY_CTRL_R: ::Integer + + KEY_CTRL_S: ::Integer + + KEY_CTRL_T: ::Integer + + KEY_CTRL_U: ::Integer + + KEY_CTRL_V: ::Integer + + KEY_CTRL_W: ::Integer + + KEY_CTRL_X: ::Integer + + KEY_CTRL_Y: ::Integer + + KEY_CTRL_Z: ::Integer + + KEY_ESC: ::Integer + + KEY_BACKSPACE: ::Integer + + KEY_RUNES: ::Integer + + KEY_UP: ::Integer + + KEY_DOWN: ::Integer + + KEY_RIGHT: ::Integer + + KEY_LEFT: ::Integer + + KEY_HOME: ::Integer + + KEY_END: ::Integer + + KEY_PGUP: ::Integer + + KEY_PGDOWN: ::Integer + + KEY_DELETE: ::Integer + + KEY_INSERT: ::Integer + + KEY_F1: ::Integer + + KEY_F2: ::Integer + + KEY_F3: ::Integer + + KEY_F4: ::Integer + + KEY_F5: ::Integer + + KEY_F6: ::Integer + + KEY_F7: ::Integer + + KEY_F8: ::Integer + + KEY_F9: ::Integer + + KEY_F10: ::Integer + + KEY_F11: ::Integer + + KEY_F12: ::Integer + + KEY_SHIFT_TAB: ::Integer + + KEY_SPACE: ::Integer + + attr_reader key_type: untyped + + attr_reader runes: untyped + + attr_reader alt: untyped + + attr_reader name: untyped + + def initialize: (key_type: untyped, ?runes: untyped, ?alt: untyped, ?name: untyped) -> untyped + + private + + def lookup_key_name: () -> untyped + + public + + def to_s: () -> untyped + + def char: () -> untyped + + def ctrl?: () -> untyped + + def runes?: () -> untyped + + def space?: () -> untyped + + def enter?: () -> untyped + + def backspace?: () -> untyped + + def tab?: () -> untyped + + def esc?: () -> untyped + + def up?: () -> untyped + + def down?: () -> untyped + + def left?: () -> untyped + + def right?: () -> untyped + end + + class MouseMessage < Message + BUTTON_NONE: ::Integer + + BUTTON_LEFT: ::Integer + + BUTTON_MIDDLE: ::Integer + + BUTTON_RIGHT: ::Integer + + BUTTON_WHEEL_UP: ::Integer + + BUTTON_WHEEL_DOWN: ::Integer + + ACTION_PRESS: ::Integer + + ACTION_RELEASE: ::Integer + + ACTION_MOTION: ::Integer + + attr_reader x: untyped + + attr_reader y: untyped + + attr_reader button: untyped + + attr_reader action: untyped + + attr_reader shift: untyped + + attr_reader alt: untyped + + attr_reader ctrl: untyped + + def initialize: (x: untyped, y: untyped, button: untyped, action: untyped, ?shift: untyped, ?alt: untyped, ?ctrl: untyped) -> untyped + + def press?: () -> untyped + + def release?: () -> untyped + + def motion?: () -> untyped + + def wheel?: () -> untyped + + def left?: () -> untyped + + def right?: () -> untyped + + def middle?: () -> untyped + end + + class WindowSizeMessage < Message + attr_reader width: untyped + + attr_reader height: untyped + + def initialize: (width: untyped, height: untyped) -> untyped + end + + class FocusMessage < Message + end + + class BlurMessage < Message + end + + class QuitMessage < Message + end + + class ResumeMessage < Message + end + + def self.parse_event: (untyped hash) -> untyped +end diff --git a/sig/bubbletea/model.rbs b/sig/bubbletea/model.rbs new file mode 100644 index 0000000..62e19b3 --- /dev/null +++ b/sig/bubbletea/model.rbs @@ -0,0 +1,55 @@ +# Generated from lib/bubbletea/model.rb with RBS::Inline + +module Bubbletea + # Model module that provides the Elm Architecture interface. + # Include this module in your model class and implement: + # - init: Returns [model, command] - initial state and optional command + # - update(message): Returns [model, command] - new state and optional command + # - view: Returns String - the current view to render + # + # Example: + # class Counter + # include Bubbletea::Model + # + # attr_reader :count + # + # def initialize + # @count = 0 + # end + # + # def init + # [self, nil] + # end + # + # def update(message) + # case message + # when Bubbletea::KeyMessage + # case message.to_s + # when "q", "ctrl+c" + # [self, Bubbletea.quit] + # when "up", "k" + # @count += 1 + # [self, nil] + # when "down", "j" + # @count -= 1 + # [self, nil] + # else + # [self, nil] + # end + # else + # [self, nil] + # end + # end + # + # def view + # "Count: #{@count}\n\nPress up/down to change, q to quit" + # end + # end + module Model + def init: () -> untyped + + def update: (untyped _message) -> untyped + + def view: () -> untyped + end +end diff --git a/sig/bubbletea/runner.rbs b/sig/bubbletea/runner.rbs new file mode 100644 index 0000000..6b0e69f --- /dev/null +++ b/sig/bubbletea/runner.rbs @@ -0,0 +1,56 @@ +# Generated from lib/bubbletea/runner.rb with RBS::Inline + +module Bubbletea + # Runner manages the event loop and coordinates between the model and the terminal + class Runner + attr_reader options: untyped + + DEFAULT_OPTIONS: untyped + + def initialize: (untyped model, **untyped options) -> untyped + + def run: () -> untyped + + def send: (untyped message) -> untyped + + private + + def setup_terminal: () -> untyped + + def cleanup_terminal: () -> untyped + + def setup_resize_handler: () -> untyped + + def restore_resize_handler: () -> untyped + + def update_terminal_size: () -> untyped + + def run_loop: () -> untyped + + def check_resize: () -> untyped + + def process_pending_messages: () -> untyped + + def handle_message: (untyped message) -> untyped + + def process_command: (untyped command) -> untyped + + def execute_command_sync: (untyped command) -> untyped + + def execute_sequence_sync: (untyped commands) -> untyped + + def execute_batch_sync: (untyped commands) -> untyped + + def schedule_tick: (untyped tick_command) -> untyped + + def schedule_delayed_message: (untyped send_command) -> untyped + + def process_ticks: () -> untyped + + def suspend_process: () -> untyped + + def render: () -> untyped + end + + def self.run: (untyped model, **untyped options) -> untyped +end diff --git a/sig/bubbletea/version.rbs b/sig/bubbletea/version.rbs new file mode 100644 index 0000000..de82eea --- /dev/null +++ b/sig/bubbletea/version.rbs @@ -0,0 +1,5 @@ +# Generated from lib/bubbletea/version.rb with RBS::Inline + +module Bubbletea + VERSION: ::String +end