RBScriptConsole
This is a sample project that shows how you can integrate RBScripts into your Realbasic application. RBScript gives you the power of the Realbasic language on runtime, enabling the user to enhance your applications.
Download class and sample project
http://www.belle-nuit.com/download/RBScriptConsoleApp.sit.hqx
http://www.belle-nuit.com/download/RBScriptConsoleProject.sit.hqx
The project was written in RB 4.0, but it should work in 3.5, too. It does not use any plugins.
Introduction
An RBScript is a source text written in a subset of RealBasic which can be edited on Runtime. The Script is precompiled before running and executed. The script has always a main function and can have functions, sub methods and classes when they are defined before they are used. The code for a script is mainly three steps:
- You create a new instance of RBScript
- You set the source (and may precompile it)
- You run the script
The script communicates with the host application through events
- the Input event with a string asks the host for parameters
- the Print event returns a string to the host
To reply to the events, you either have to make the RBScript an instance of the window or you have to subclass the RBScript. In our example, we will do both.
All interaction always works through strings, so RBScripts may not be very efficient if you work with a lot of numbers.
Enhancing Interaction with the Host by dispatching Input and Print
Have a look at the ConsoleScript class.
The Input event has to parse the prompt string. In our case, it uses the first word to dispatch the prompt.
- "_var " will return the value of a variable (persistant through executions)
- "_argc" will return the count of arguments (like in command line programs)
- "_argv" will return the nth argument
- In all other cases the prompt will be sent to the host to ask the user
In the case of the command line arguments, the ConsoleScript class can answer directly, because the argument property has been set before the run. In the other cases a custom event GetVariable and Input will be called.
You will see that I work a lot with events. You could be tented to create directly a property of the targeting listbox to get the value of the variable, but in this case the ConsoleScript class must know about the DataListBox class. If you work in events, the links will be made in the window and the ConsoleScript class is self contained, eg portable.
If you take a look at the Print event, it is quite the same kind of dispatch. In fact, in communication the Input event is something like a function, because it returns a value, and Print more a Sub.
Writing a private header to hide the dispatch
writing input("_var h") is not very readable in the script code. So in the most case, you want to write a private header, which is always set before the source. This private header is defined in the constructor method and defines the RBScript methods
- function argc() as integer
- function argv(v as integer) as string
- function get(key as string) as string
- sub set(key as string, value as string)
You note that this is also more readable for the user because he can directly deal with the type of variables he needs. input("_argc) returns a string, but argc() returns an integer.
You may want to write all functions which are often needed in your application as a private header, so the user can call them directly and does not have to deal with the input() function.
Handling Errors
Compiler Errors and Runtime Errors are returned with the Print event. You may note that they also return the line number, the line and the error message, so the user can debug the code better.
You may want to send these errors to another target, if you do not use a console but it is always good to give a feedback to the user.
Main Window
The main window has four sections:
- Script List: A list of script which you can edit and execute
- Script Source: The source text of the active script
- Console: A console which handles input and print
- Variables: A list of global variables
Script List / Source
The idea is that you can write the Scripts in different parts and that you can have more than one version. Only the active script is executed, but it can include other scripts.
There are two compiler directives which can be used
- #name defines the name of the script in the script list
- #include includes the text of another script into the script
You do not have to bother about duplicate includes. The including is recursive, but it will not include a script two times (see the resolve method of the datalistbox).
You can create new scripts (command-N) and duplicate scripts (command-D). Basic document handling is implemented: You can save the project to a folder (one file per script with the scriptname as filename), you can open and create new projects. The console will always ask you if you want to save the project on quit.
The script names are conventional, but should not use spaces.
ConsoleField / ConsoleInput
The consolefield class simulates what could be a console.It sends the print events to an editfield and accepts commands between the scripts.
The following commands are implemented:
- clear (equivalent to command-0) clears the console editfield
- close closes the current project
- get key gets the value of the persistant value with the name key
- help returns a list of valid commands
- quit quits the application
- run arguments (equivalent to command-R) runs the active script. You can optionally add arguments, which the script can ask for with the argc/argv functions
- source prints the source of the last run script to the console
- set key value sets the value of a persistant variable
Like in the Win32 console, you can use arrow up and down to go through the history of recent commands.
Commands are finalized with return or enter.
The code in the ConsoleField class is set that you can select text wherever you want, but you cannot cut or edit text in the output part.
The ConsoleInput window is necessary to handle Input events during a script. The only possibility in RealBasic to having a code waiting for user input is to use the ShowModal method. The problem is that the ShowModal can be used for the active window, but the window must be hidden to make the code continue. If you make this with the Main window, you have big flickering. So I made a modal window of only the size of the consolefield. (I first tried a plain rect window, but it was not modal enough, you could still click on the Main window.) It still flickers, but much less.
Terms of use / Disclaimer
© Belle Nuit Montage / Matthias Bürcher March 2002. All rights reserved. Written in Switzerland.
This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Comments please to matti@belle-nuit.com
The latest version is available at http//www.belle-nuit.com/
History
15.3.02 version 1.0