How to call one Ruby script from another

edited August 2013 in Ruby Scripting

Two questions:

1) How do I call one .lym script from another one? I tried the following: Make one .lym script with this inside:

module Test
  include RBA
  p "Hello World"
end

and another .lym script with this inside:

module Test2
  include RBA
  Test
end

When I run "Test" I get "Hello World". When I run "Test2" I get nothing..

2) Same question, but how do I pass values to the "child" script and receive a result back from the "child" script?

Thanks!

Comments

  • edited August 2013

    Hi David,

    the "module" is just a namespace, not a function that you can call. You can do the following:

    File1.rb:
    module Test
      def Test.foo 
        puts "Inside foo"
      end
    end
    
    File2.lym:
    load "File1.rb"
    module Test
      puts "Now calling foo from File 1:"
      foo 
    end
    

    I'd recommend to take a look into a good Ruby book to learn more about modules, functions etc.

    Please note, that "load" can only load plain Ruby (text) files, not .lym files - they are a KLayout speciality.

    Regards,

    Matthias

  • edited November -1

    Thanks. I thought "module" was KLayout specific but didn't realize it is from Ruby.

    After reading your reply I realized how little Ruby I know and I was just flying by the seat of my pants.

    So I read a Ruby book this weekend, almost in its entirety :) and while I can't say I understood everything, at least now have a much better handle on things.

    Quick note that may be helpful for future readers: To pass variables you do it the standard Ruby way (which I didn't know, but below are a few examples, hopefully it helps someone)

    This is the calling .lym file:

    module MyMacro
        include RBA
    
        load "NumberAdder.rb"
        na = NumberAdder.new("An initialization string",10) # 10 is some initialization parameter that may be needed when creating a new NumberAdder object - just here to demonstrate the principle
        na.addTwoNumbers(1,2)
        na.getInitializationString
    
    end
    

    And this is the .rb file that is being referred to. Saved as “NumberAdder.rb”

    class NumberAdder
    
        def initialize(initStr,initNum)
            @initStr, @initNum = initStr, initNum # variables defined when the object is created. You can use these later.
        end
    
        def addTwoNumbers(num1,num2)
            p num1+num2 # prints out the sum of two numbers
        end
    
        def getInitializationString
            # Gets that string we passed when we first instanced our NumberAdder
            p "The string was: " + @initStr 
        end
    
    end
    

    When you run the first script, the output should be:

    3
    “The string was: An initialization string”
    
  • edited November -1

    Hi David,

    thank you for the note.

    Actually, defining classes and using them in the top-level context is even more the "Ruby-way" :-)

    Matthias

  • edited November -1

    This is working, to call .rb scripts.

    However now I want to call an .lym script.

    For example, I have one code that makes a button on the toolbar as shown next. Then I have a second .lym code (not shown) that I want to just run when the toolbar button is pressed.

    module CustomToolbarButtons
    
      include RBA
    
      a = RBA::Action.new
      a.title = "New"
      #a.icon = 'C:\filepath\TheIcon.png'
      a.on_triggered do
        load 'C:\filepath\RunMe.rb'
        param_to_pass = 5;
        b = RunMe.new(param_to_pass)
      end
    
      # install the action at the right end of the toolbar with a separator
      menu = RBA::Application.instance.main_window.menu
      menu.insert_separator("@toolbar.end", "name")
      menu.insert_item("@toolbar.end", "my_action", a)
    
    end
    

    This works fine if RunMe.rb is an .rb file. But if I'm trying to actuate an .lym file when I press the button and I change this:

        load 'C:\filepath\RunMe.rb'
        param_to_pass = 5;
        b = RunMe.new(param_to_pass)
    

    to this:

        load 'C:\filepath\RunMeLymFile.lym'
    

    (so, no parameters to pass this time -- I just want to run it), then it doesn't work. Is there a way to do this?

    Lastly, how do I get rid of the non-portable filepaths such as

    a.icon = 'C:\filepath\TheIcon.png'
    

    and replace it with some relative path? e.g. to the "macros" directory? I tried putting TheIcon.png in $: (where the macros directory is indeed listed for me) and $KLAYOUT_PATH, and changing the string to refer there, but am perhaps not using it right. Can you provide an example?

    Thanks!

  • edited October 2013

    Hi David,

    ".lym" files are not native ruby, hence you cannot load them with Ruby's "load". The idea behind ".lym" is to provide meta-information for integration into the application. They are intended for the entry-point scripts and provide information about menu binding or the interpreter to use (once I support other languages beside Ruby).

    Libraries or utility modules which are called from those script should be provided as plain Ruby files (*.rb) and can be loaded by the interpreter (i.e. through "load"). Such files are supported in the IDE as well, but can't be bound to a menu for example. That is an exclusive right of ".lym" which provides the meta-information for doing so.

    To load a ruby file relative to "$:" you can just use "require 'file'" which will locate and load "file.rb". In order to use some file path relative to the current script's location, you can use "File.dirname($0)" as the directory for the file. $0 is the path of the script currently executed. Using the current script as for the base path is the most convenient method and allows you to store the auxiliary files along with the script.

    Regards,

    Matthias

Sign In or Register to comment.