The REXX interpreter before you is the first public release of a port of Bill Vlachoudis' BRexx version 1.3 to BeOS, with a number of improvements and additions by myself, most notably the support of application scripting.
Note that this port is very different from David Feugey's straight port of version 2.0, which was posted to BeWare recently.
Documentation for the original version can be found in the hlp directory, which contains the following text documents:
There is also a full hypertext manual, for version 1.3. Please refer to this manual and the above text files for all documentation about REXX in general and BRexx in particular.
Installation instructions and information about the many changes and additions for version 1.3.2 (the BeOS version) are described below.
Installation of BRexx is not too difficult.
First open a Terminal window and change to the directory into which BRexx was unzipped:(or wherever it is). Now type:
This causes all the programs and libraries to be compiled and linked, and installed in the proper location. It then will run the test script called squares.rexx to verify that the installation completed correctly. For those who want to customize their installation, and who are curious about where things will go, please examine the makefile.
One of the main functions of REXX as a language is to interact with a "host environment". Usually the host environment is the command shell, and BRexx version 1.3 is no exception. See the relevant manual section for details. In fact BRexx has a particularly simple way of retrieving output from shell commands.
The traditional way of selecting a host environment is by using the address construct, for example:
The BeOS version can also interact with other environments, most notably any application that is running under the BeOS. An example BRexx script might have:
These two lines would set the window title of the first NetPositive window to "This is a different title". Equivalently, from the command line, we could have just typed:
where we needed to escape the inner level of double-quotes.
One can also get information from an application. For example:
The variable result is a special variable reserved for the purpose of returning results from commands addressed to some environment.
Generally, applications may return several lines worth of results. This is solved in the BeOS version by extending the functionality of the result variable: it is in fact a compound variable, with result.0 containing the number of lines of results, and each result line stored in result.i with i ranging from 1 to result.0. Simple commands usually return a single line, and the value of result is the same as that of result.1.
Moreover, BeOS applications return results in the form of BMessages which may contain a variety of data types in fields which may have names. In order to find out precisely what it is that the application is returning, the result compound variable has some additional fields, result.name.i and result.type.i. As an example, we list the full set of "suites" that is supported by NetPositive:
rx - "address 'NetPositive' 'getsuites'; do i = 1 to result.0; say result.name.i result.type.i result.i; end" suites B_STRING_TYPE suite/vnd.Be-application suites B_STRING_TYPE suite/vnd.Be-handler messages B_PROPERTY_INFO_TYPE property commands specifiers -------------------------------------------------------------------------------- Window INDEX REV.INDEX Window NAME Looper INDEX REV.INDEX Looper ID Looper NAME Name B_GET_PROPERTY DIRECT Window B_COUNT_PROPERTIES DIRECT Loopers B_GET_PROPERTY DIRECT Windows B_GET_PROPERTY DIRECT Looper B_COUNT_PROPERTIES DIRECT messages B_PROPERTY_INFO_TYPE property commands specifiers -------------------------------------------------------------------------------- Suites B_GET_PROPERTY DIRECT Messenger B_GET_PROPERTY DIRECT InternalName B_GET_PROPERTY DIRECT error B_INT32_TYPE 0
In the above, various "properties" are listed, with names such as "suites", "messages", and "error", with types such as "B_STRING_TYPE" and "B_INT32_TYPE". The "messages" property has a result.i that contains several lines of text.
The implementation of BeOS-native scripting in BRexx is based on the source code for a public domain utility called hey, written by Atilla Mezzei. The documentation (adapted for its usage inside BRexx) has further details and examples.
In the previous section I showed examples of what I call "BeOS-native scripting", i.e. scripting that uses the BeOS built-in scripting facilities. As nice as it is to have scripting facilities built into just about every application written on the BeOS, it is in the end not very useful, unless the application writer puts in one or more suites that deal with the application's internals. After all, it is cute to be able change the title of a document window, but that change goes on behind the back of the application itself: the application does not know the title changed, and won't be able to save the project with the changed title.
In addition, when the application has several windows open, and when each window has a complicated user interface with several elements (called a "View" in BeOS parlance) each of which may be divided up in more elements, then it can be quite annoying to do the simplest of things:
Also, the number of "verbs" allowed is limited to the following set: getsuites, get, set, execute, count, create, delete, quit, save and load. Admittedly, one can get pretty far with these. For example, in order to draw a rectangle in some application, one might need to do something like this:
It would clearly be better if one could more directly express to an application what it is that one wants:
Although there is more to the story than that, this is clearly a much more user-friendly way of scripting an application. The BeOS version of BRexx therefore implements an alternative way to script applications. The drawback of this approach is that application writers need to implement this way of scripting in their applications. Since they need to implement some form of scripting anyway, this is not a big problem in principle. In practice, of course, it is only useful if all application writers implement the same way of scripting.
In order to facilitate this way of scripting, BRexx comes with a shared library, called libPortManager.so, which does all the work needed. The program Squares is supplied as an example application, controlled by the accompanying script squares.rexx.
With BRexx comes an application called PortManager. PortManager is started up automatically when needed, and stays around until the system is restarted. It keeps a list of "ports" around, that allow BRexx to communicate directly with an application, rather than through a series of detours through the application, its windows and the views inside of views in the windows. BRexx first checks to see if a given port exists in the list maintained by PortManager and if no such port exists, BRexx checks if it is the name of an application (one can bypass the PortManager list by prefixing the application name with a colon).
Other than that, PortManager and the PortManager class are only of interest to developers wanting to implement this type of scripting into their applications.
The PortManager class implements everything needed for this type of scripting: it handles the interaction with the PortManager application, it does most of the work involved in scripting, and it also provides a function that will add a BeOS-native scripting suite, so that the program can also be scripted without BRexx (using hey for example).
In order to use the class, one includes the PortManager.h header file in ones application. It is located in the PortLib directory of the BRexx distribution. One links with the libPortManager.so shared library, which during installation is copied to /boot/home/config/lib.
Many thanks to Atilla Mezzei for hey module, Chris Herborth and Dominic Giampaolo for various discusions, Marvin Weinstein for extensive beta-testing, and to Eric Shepherd for his simple TextEditor (part of the sample-code directory of the optional folder) from which a number of things were stolen. Because of this, I am obliged to include the following copyright notice and disclaimer.
Parts of this code are subject to the following:
Copyright 1991-1999, Be Incorporated. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Other parts of this code are freeware or public domain, as indicated in their respective documentation. As to myself, I assume no warranties of any kind.