[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[FR-devel] FXIrb (Windows problem solved: blocking pipes)
From: |
Marco Frailis |
Subject: |
[FR-devel] FXIrb (Windows problem solved: blocking pipes) |
Date: |
Fri, 27 Dec 2002 18:57:14 +0100 (CET) |
Hi,
I've seen that some month ago there was an attempt to embed irb into
FreeRIDE, so maybe some of you is interested to this topic. FXIrb is a
widget which embeds irb and has been developed by Gilles Filippini
(http://www.rubygarden.org/ruby?FXIrb). On Windows platform it
freezes because of blocking pipes, that is, when a thread does "gets" on
one hand of a pipe and on the other hand of the pipe nothing has been put
yet, than the thread continues to wait something, blocking also the
scheduling of other threads (on Linux it simply goes into sleep status
until something is put on the pipe, so the other threads can go on). Maybe
this is a problem only of ruby compilded by Visual C++.
I've done a little workaround to let it work on both platforms
I 've also added the commands history (using up/down arrows) and a
widget behaviour more similar to a terminal. So here it is the code:
-----------------------------------------------------------------
#! /usr/bin/env ruby
# TODO
# - handle user input redirection
# - ^D
# - readline
require "fox"
require "irb"
require "singleton"
include Fox
STDOUT.sync = true
module IOEmulate # Named after RubyWin's IOEmulate module
def gets
return FXIrb.instance.gets
end
def p(obj)
return FXIrb.instance.write(obj.to_s + "\n")
end
def putc(ch)
FXIrb.instance.write("" << ch)
end
end
include IOEmulate
class FXIRBInputMethod < IRB::StdioInputMethod
attr_reader :line_no
def initialize
super
@history = 1
end
def gets
print @prompt
str = IOEmulate.gets
if /^exit/ =~ str
exit
end
@line_no += 1
@history = @line_no + 1
@address@hidden = str
end
def prevCmd
@history -= 1 unless @history <= 1
return @history
end
def nextCmd
@history += 1 unless @history >= @line_no
return @history
end
end
module IRB
def IRB.start_in_fxirb(im)
# IRB.initialize(nil)
# IRB.parse_opts
# IRB.load_modules
IRB.setup(nil)
irb = Irb.new(nil, im)
@CONF[:IRB_RC].call(irb.context) if @CONF[:IRB_RC]
@CONF[:MAIN_CONTEXT] = irb.context
trap("SIGINT") do
irb.signal_handle
end
catch(:IRB_EXIT) do
irb.eval_input
end
print "\n"
end
end
class FXIrb < FXText
include Singleton
include Responder
attr_reader :input
def FXIrb.init(p, tgt, sel, opts)
unless @__instance__
Thread.critical = true
begin
@__instance__ ||= new(p, tgt, sel, opts)
ensure
Thread.critical = false
end
end
return @__instance__
end
def initialize(p, tgt, sel, opts)
FXMAPFUNC(SEL_KEYRELEASE, 0, "onKeyRelease")
FXMAPFUNC(SEL_KEYPRESS, 0, "onKeyPress")
FXMAPFUNC(SEL_LEFTBUTTONPRESS,0,"onLeftBtnPress")
FXMAPFUNC(SEL_MIDDLEBUTTONPRESS,0,"onMiddleBtnPress")
super
setFont(FXFont.new(FXApp.instance,"-misc-fixed-medium-r-semicondensed-*-*-120-*-*-c-*-iso8859-1"))
end
def create
super
setFocus
# IRB initialization
@inputAdded = false
@input = IO.pipe
$> = self
@im = FXIRBInputMethod.new
@irb = Thread.new {
IRB.start_in_fxirb(@im)
}
end
def onKeyRelease(sender, sel, event)
case event.code
when Fox::KEY_Return, Fox::KEY_KP_Enter
newLineEntered
end
return 1
end
def onKeyPress(sender,sel,event)
case event.code
when Fox::KEY_Up,Fox::KEY_KP_Up
if @im.line_no>0
removeText(@anchor, address@hidden)
write(@im.line(@im.prevCmd).chop)
end
when Fox::KEY_Down,Fox::KEY_KP_Down
if @im.line_no>0
removeText(@anchor, address@hidden)
write(@im.line(@im.nextCmd).chop)
end
when Fox::KEY_Left,Fox::KEY_KP_Left
if getCursorPos > @anchor
super
end
when Fox::KEY_Delete,Fox::KEY_KP_Delete,Fox::KEY_BackSpace
if getCursorPos > @anchor
super
end
else
super
end
end
def onLeftBtnPress(sender,sel,event)
pos=getPosAt(event.win_x,event.win_y)
if pos >= @anchor
super
end
end
def onMiddleBtnPress(sender,sel,event)
pos=getPosAt(event.win_x,event.win_y)
if pos >= @anchor
super
end
end
def newLineEntered
processCommandLine(extractText(@anchor, address@hidden))
end
def processCommandLine(cmd)
@input[1].puts cmd
@inputAdded = true
@irb.run
end
def sendCommand(cmd)
setCursorPos(getLength)
makePositionVisible(getLength) unless isPosVisible(getLength)
cmd += "\n"
appendText(cmd)
processCommandLine(cmd)
end
def write(obj)
str = obj.to_s
appendText(str)
setCursorPos(getLength)
makePositionVisible(getLength) unless isPosVisible(getLength)
return str.length
end
def gets
@anchor = getLength
if address@hidden
Thread.stop
end
@inputAdded = false
return @input[0].gets
end
end
# Stand alone run
if __FILE__ == $0
application = FXApp.new("FXIrb", "ruby")
application.threadsEnabled = true
Thread.abort_on_exception = true
application.init(ARGV)
window = FXMainWindow.new(application, "FXIrb", nil, nil, DECOR_ALL, 0,0,
580, 600)
FXIrb.init(window, nil, 0, LAYOUT_FILL_X|LAYOUT_FILL_Y|TEXT_OVERSTRIKE)
application.create
window.show(PLACEMENT_SCREEN)
application.run
end