Skip to content

Instantly share code, notes, and snippets.

@tompng
Created January 19, 2024 17:07
Show Gist options
  • Save tompng/5ed3b7fb6e2ca02b48f93941189a751b to your computer and use it in GitHub Desktop.
Save tompng/5ed3b7fb6e2ca02b48f93941189a751b to your computer and use it in GitHub Desktop.
ruby interactive shell that uses `ruby -c`
class TemrinationChecker
def initialize
@prelaunched = nil
@code = ''
@current = new_session
end
def new_session
IO.popen(['ruby', '-c'], 'r+', err: [:child, :out])
end
def session
@prelaunched ||= new_session
@current
end
def reset_session
@current.close
@current = @prelaunched || new_session
@prelaunched = new_session
@code = ''
end
def check(code)
verbose, $VERBOSE = $VERBOSE, nil
begin
RubyVM::InstructionSequence.compile(code)
return true
rescue SyntaxError
end
reset_session unless code.start_with? @code
session.write code.byteslice(@code.bytesize..)
@code = code
if session.wait_readable(0.01)
reset_session
true
else
false
end
ensure
$VERBOSE = verbose
end
end
checker = TemrinationChecker.new
require 'reline'
loop do
begin
input = Reline.readmultiline 'irb> ' do |code|
checker.check(code)
end
rescue Interrupt
next
end
begin
break unless input
res = eval(input)
puts "=> #{res.inspect}"
rescue SystemExit
break
rescue Exception => e
puts e
puts e.backtrace
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment