AutoHotkey Homepage AutoHotkey Community
Let's help each other out
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

embedded ruby for ahk

 
Post new topic   Reply to topic    AutoHotkey Community Forum Index -> Scripts & Functions
View previous topic :: View next topic  
Author Message
savage



Joined: 02 Jul 2004
Posts: 206

PostPosted: Thu Jul 03, 2008 4:12 am    Post subject: embedded ruby for ahk Reply with quote

I've wanted to be able to embed a ruby interpreter in AHK for ages and I finally got it working a bit ago.

Code:

;Internal definitions
rb_handle = 0

rb_Eval(code)
{
    local ret
    ret := DllCall("msvcrt-ruby18\rb_eval_string","str",code,"cdecl uint")
    if( ErrorLevel != 0 )
    {
        Msgbox, Error running: `n %code% `n Possible syntax error?
        exit
    }
    ;Msgbox, %code% `n %ret% : %errorlevel%
    return ret
}

rb_ToString(val)
{
    local v, str
    v := val
    str := DllCall("msvcrt-ruby18\rb_string_value_cstr","Uint *",v,"cdecl str")
    ;Msgbox, tostring %str% : %errorlevel%
    return str
}

rb_EvalStr(code)
{
    return rb_ToString(rb_Eval(code))
}

;Load the library and setup the interpreter
    rb_handle := DllCall("LoadLibrary","str","msvcrt-ruby18.dll","Uint")
    DllCall("msvcrt-ruby18\ruby_init")
    DllCall("msvcrt-ruby18\ruby_init_loadpath","cdecl")
    DllCall("msvcrt-ruby18\ruby_script","str","embedded","cdecl")

;Some internal code for a cleaner callin
code =
(
module AHK
  @last_error = nil
  @env = Object.new
  def AHK.run(&block)
    @last_error = nil
    @env.instance_eval(&block).to_s
  rescue Exception => e
    @last_error = e
  end

  def AHK.load(path)
    @last_error = nil
    Kernel.load(path).to_s
  rescue Exception => e
    @last_error = e
  end

  def AHK.require(lib)
    @last_error = nil
    Kernel.require(lib).to_s
  rescue Exception => e
    @last_error = e
  end

  def AHK.error?
    (!@last_error.nil?).to_s
  end

  def AHK.pretty_error
    "#{@last_error.class}: #{@last_error.message}\n#{@last_error.backtrace.join("\n")}"
  end
end
)
rb_Eval(code)

;Evaluate a string of code, and return the results as a string
RubyEval(code)
{
    c := "AHK.run {" . code . "}"
    ;Msgbox, %c%
    ret := rb_EvalStr(c)
    if( rb_EvalStr("AHK.error?") == "true" )
    {
        error := rb_EvalStr("begin; AHK.pretty_error; rescue => e; e.message; end")
        MsgBox, %error%
        exit
    }
    return ret
}

;Load a ruby file
RubyLoad(path)
{
    ret := rb_EvalStr("AHK.load('" . path . "')")
    if( rb_EvalStr("AHK.error?") == "true" )
    {
        error := rb_EvalStr("begin; AHK.pretty_error; rescue => e; e.message; end")
        MsgBox, %error%
        exit
    }
    return ret
}

;Require a ruby library
RubyRequire(lib)
{
    ret := rb_EvalStr("AHK.require('" . path . "')")
    if( rb_EvalStr("AHK.error?") == "true" )
    {
        error := rb_EvalStr("begin; AHK.pretty_error; rescue => e; e.message; end")
        MsgBox, %error%
        exit
    }
    return ret
}

;Finalize the interpreter and drop the library
RubyFinalize()
{
    DllCall("msvcrt-ruby18\ruby_finalize")
    DllCall("FreeLibrary","UInt",rb_handle)
}



Usage is quite simple. Just #include the file and use RubyEval, RubyLoad, and RubyRequire to your hearts content. Just remember to call RubyFinalize() on exit so that the interpreter can be cleaned up. It RubyEval uses instance_eval on a persistent object so you can use instance variables between invocations of RubyEval.

Pointless Example!
Code:

RubyEval("@a = '" . A_ScriptDir . "'")
ret := RubyEval("@a.scan(/./).join(""\n""))
Msgbox, %ret%


You of course need to have ruby installed and on your PATH. Also, as you can see from that short example, quotes can be a bit of a pain to deal with. I'd recommend writing most code in a seperate file and loading it, then using RubyEval to interact with it.
_________________
<enormous animated gif>
Back to top
View user's profile Send private message AIM Address
Display posts from previous:   
Post new topic   Reply to topic    AutoHotkey Community Forum Index -> Scripts & Functions All times are GMT
Page 1 of 1

 
Jump to:  
You can post new topics in this forum
You can reply to topics in this forum


Powered by phpBB © 2001, 2005 phpBB Group