Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 2 additions & 31 deletions demo/exec
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,11 @@
require "bundler/setup"
require "bubbletea"

class EditorFinishedMessage < Bubbletea::Message
attr_reader :error

def initialize(error = nil)
super()

@error = error
end
end

class ExecDemo
include Bubbletea::Model

def initialize
@altscreen_active = false
@error = nil
end

def init
Expand All @@ -39,38 +28,20 @@ class ExecDemo

return [self, cmd]
when "e"
return [self, open_editor]
editor = ENV["EDITOR"] || "vim"
return [self, Bubbletea.exec(-> { system(editor) })]
when "ctrl+c", "q"
return [self, Bubbletea.quit]
end

when EditorFinishedMessage
if message.error
@error = message.error
return [self, Bubbletea.quit]
end
end

[self, nil]
end

def view
return "Error: #{@error}\n" if @error

"Press 'e' to open your EDITOR.\nPress 'a' to toggle the altscreen\nPress 'q' to quit.\n"
end

private

def open_editor
lambda do
editor = ENV["EDITOR"] || "vim"
system(editor)
EditorFinishedMessage.new
rescue StandardError => e
EditorFinishedMessage.new(e.message)
end
end
end

Bubbletea.run(ExecDemo.new)
14 changes: 14 additions & 0 deletions lib/bubbletea/commands.rb
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,16 @@ def initialize(text)
class SuspendCommand < Command
end

class ExecCommand < Command
attr_reader :callable, :message

def initialize(callable, message: nil)
super()
@callable = callable
@message = message
end
end

class << self
def quit
QuitCommand.new
Expand Down Expand Up @@ -122,5 +132,9 @@ def puts(text)
def suspend
SuspendCommand.new
end

def exec(callable, message: nil)
ExecCommand.new(callable, message: message)
end
end
end
23 changes: 23 additions & 0 deletions lib/bubbletea/runner.rb
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,9 @@ def process_command(command)
when SuspendCommand
suspend_process

when ExecCommand
exec_process(command)

when Proc
Thread.new do
result = command.call
Expand Down Expand Up @@ -286,6 +289,9 @@ def execute_command_sync(command)
when SuspendCommand
suspend_process

when ExecCommand
exec_process(command)

when Proc
result = command.call
return unless result
Expand Down Expand Up @@ -360,6 +366,23 @@ def suspend_process
handle_message(ResumeMessage.new)
end

def exec_process(command)
@program.disable_mouse if @options[:mouse_cell_motion] || @options[:mouse_all_motion]
@program.show_cursor
@program.stop_input_reader
@program.exit_raw_mode

command.callable.call

@program.enter_raw_mode
@program.hide_cursor
@program.start_input_reader
@program.enable_mouse_cell_motion if @options[:mouse_cell_motion]
@program.enable_mouse_all_motion if @options[:mouse_all_motion]

handle_message(command.message) if command.message
end

def render
return if @options[:without_renderer]
return unless @renderer_id
Expand Down
35 changes: 35 additions & 0 deletions test/runner_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -160,4 +160,39 @@ def setup
it "process nil command" do
@runner.__send__(:process_command, nil)
end

it "process exec command calls callable" do
called = false
callable = -> { called = true }

program = Object.new
[:disable_mouse, :show_cursor, :stop_input_reader, :exit_raw_mode, :enter_raw_mode, :hide_cursor, :start_input_reader].each do |method|
program.define_singleton_method(method) { nil }
end

@runner.instance_variable_set(:@program, program)

cmd = Bubbletea.exec(callable)
@runner.__send__(:process_command, cmd)

assert called
end

it "process exec command dispatches message" do
called = false
callable = -> { called = true }

program = Object.new
[:disable_mouse, :show_cursor, :stop_input_reader, :exit_raw_mode, :enter_raw_mode, :hide_cursor, :start_input_reader].each do |method|
program.define_singleton_method(method) { nil }
end

@runner.instance_variable_set(:@program, program)

cmd = Bubbletea.exec(callable, message: :exec_done)
@runner.__send__(:process_command, cmd)

assert called
assert_includes @model.messages, :exec_done
end
end
Loading