Running
Pick a sample or write your own program, then Run (Ctrl+Enter). Stop (Esc) ends it at once, endless loops included. Arguments is what PARSE ARG gets. Every run starts a fresh ooRexx interpreter (5.3.0, the real C++ code compiled to WebAssembly) in its own worker; ooRexx threads (START, early REPLY, .Alarm) are real threads too.
Debugging
Debug runs the program in Dom Wise's ooRexx debugger, with this page as its window. The program stops at its first clause; the highlighted line is the one it has just run.
- Step (F10, or Enter in the empty field) runs the next clause; Run (F8) goes on to the next breakpoint (the first Run in a program stops at once, as in the debugger's own windows); Break stops a running program; Exit ends it.
- Click a line number to set or clear a breakpoint, before or while debugging.
- The field under the buttons runs Rexx in the program's context:
say x, x = 5, call someRoutine.
- The stack and the variables are shown at each stop; what the program writes goes to the console, as usual. Tracing every clause is slow: a loop can take a while under Run.
Standard input and the console
- If the Standard input box is empty, input is interactive: when the program reads (
PULL, LINEIN, CHARIN, TRACE ?, rexxtry), type in the console and press Enter. Ctrl+D sends end of file. ↑ and ↓ recall earlier lines.
- If the box has text, that text is the whole input, followed by end of file.
- Colors tell the streams apart: stdoutstderrtraceyouyou, in interactive trace. Trace goes where
.traceOutput sends it (.error, unless you redirect it), but the interpreter tells the page which lines are trace (the traceback of an error included) and which are error messages, and when interactive trace is the one reading (.debugInput). Change the colors with ⚙ (Settings).
- The console understands ANSI escape sequences for colors and styles (
'1b'x || '[31m'…; see the ANSI colors sample); ESC[2J clears it.
The editor
The Rexx Parser highlights the program and checks its syntax as you type: an error is shown under the editor and its line is underlined. style picks one of the Parser's highlighting styles (auto follows the page theme); highlight turns it all off. F12 (or Ctrl+click, Cmd+click on a Mac) on a name goes to its definition: a label from a call or SIGNAL in the same code body, a ::ROUTINE, a ::CLASS from .Name, a ::METHOD or ::ATTRIBUTE from ~name (each in turn when there are several), or one of your files from ::REQUIRES; on a definition it goes to the next use. Alt+← goes back. go to… lists the labels, routines, classes and methods. find (Ctrl+F in the editor) opens a small find bar: what you type is marked everywhere in the program (whatever its case), Enter and Shift+Enter go to the next and previous match, Esc closes it and leaves the match selected; :120 there (or Ctrl+G) goes to line 120. lines shows the line numbers: by default they are shown for programs of more than 20 lines; what you choose is remembered (⚙ Settings can make it automatic again). Tab inserts two spaces. Edits to a sample are kept while the page is open.
Your files
- Every run has
/home/rexx as its current directory. Your files live there, and what a program writes there stays for the next runs. Click a file to edit it (Run then runs it); ↓ downloads it, × deletes it.
- New creates a file (a path like
lib/util.cls creates the folder too). Upload adds files (a .zip can be unpacked), Folder adds a whole folder with its subfolders, and you can also drop files or folders on the page. Download all gives everything back as a .zip.
- These files are kept in this browser, on this device, until you delete them (Clear files).
- Link folder (Chrome, Edge) mounts a folder of your computer as
/home/rexx/NAME/, read & write or read only. Edit there with your own tools and run here: the folder is read again before every run and when you come back to the page. Deleting in a linked folder always asks; nothing is ever written to a read-only one. Several folders can be linked at once. Each linked folder is also in REXX_PATH, so ::requires "lib/util.cls" finds /home/rexx/NAME/lib/util.cls without the folder's name.
- Any program can
::requires or read these files, with relative paths as usual.
Libraries
Preloaded: the extension classes (json.cls, rxregexp.cls, csvStream.cls, yaml.cls, dateparser.cls, socket.cls, streamsocket.cls, mime.cls, smtp.cls, rxftp.cls) and the Rexx Parser: ::requires "Rexx.Parser.cls", "parser/Highlighter.cls", or call highlight "-a prog.rex" and call elements "prog.rex" (see the Rexx Parser sample).
Drawing (JDOR)
ADDRESS JDOR draws: JDOR, the drawing command handler of BSF4ooRexx by Rony G. Flatscher, here on the browser's canvas. ::requires "jdor.cls" sets up the JDOR environment, an image and its window, and address jdor selects it (in each routine, as for any environment: the default one, the shell, does not exist here); call addJdorHandler "NAME" sets up another one. Then commands like newImage 300 200, color red, moveTo 10 10, fillRect 100 50, winShow draw, as documented in BSF4ooRexx's JDOR Synopsis. There is no Java here: objects that commands return say what they are (a JDOR Image (#99)), and errors read JDOR (web): .... The Drawing (JDOR) samples are Rony's, adapted to ::requires "jdor.cls" (instead of BSF4ooRexx); programs written for BSF4ooRexx also run unchanged, through this build's small BSF.CLS (just what JDOR programs use). Windows float over the page: drag them by the title bar (frameless ones anywhere), close them with × (on a frameless one it shows when the pointer is over it); they stay until the next run. loadImage and saveImage use your files; winScreenSize is the size of this page. Printing and the clipboard depend on what the browser allows.
JavaScript and the page
::requires "js.cls" gives JavaScript objects as Rexx objects. .js is the worker that runs your program (it has fetch, the browser's local database and WebSockets); .js~page is the page itself (its document, the DOM): .js~page~document~title = "Hi". Messages read properties and call methods (o~name, o~name(a, b), o~name = v); names are found whatever their case, and o["exactName"] is exact. A Promise is waited for with ~await. .js~handler(object, "MESSAGE") gives a JavaScript function that sends the message: in the worker it runs at once, so it can answer (a~sort(.js~handler(self, "COMPARE"))); in the page, which cannot wait, the call is queued and .js~runEventLoop sends the messages (see Events from the page). A Rexx class can extend a JavaScript class in the worker: .js~extend(.MyClass, base), with MyClass a subclass of JSObject, makes JavaScript call its methods where it would call the base's, and self~name:super reaches the base's own. Your Rexx objects reach JavaScript as RexxProxy objects, so JavaScript in the worker can send them messages: o.deposit(50) or o.sendMessage1("deposit", 50); in the page each call gives a Promise, and runs when your program takes events (.js~runEventLoop) or waits for JavaScript. The full reference is at the top of js.cls.
ADDRESS DOM (::requires "dom.cls") builds windows with commands, no objects needed: 'NEW "Sign up"' opens a floating panel, FIELD, BUTTON and TEXT fill it, and 'WAIT INTO ev' waits for the next event. ADDRESS FETCH (::requires "fetch.cls") does HTTP: "GET" url, then "JSON INTO data"; RC tells how it went. See the The page, the classic way samples, and the top of dom.cls and fetch.cls. Panels, like JDOR windows, stay until the next run.
Limits
There is no shell, so ADDRESS commands for one fail (ADDRESS DOM, FETCH and JDOR work, see above). Sockets reach only WebSocket servers, and fetch only servers that accept requests from other sites (CORS). Memory is the browser's. Recursion is less deep than natively (a browser worker has a smaller stack).
Privacy
Everything runs in your browser. Your programs and files are never sent anywhere: the page only downloads the interpreter and its libraries.
Keys
- Ctrl+Enter run · Esc stop · F1 this help
- Debugging: F10 step · F8 run to a breakpoint
- In the editor: Ctrl+F find · Ctrl+G go to a line · F12 go to a definition · Alt+← back
- In the console: Enter send a line · Ctrl+D end of file · ↑/↓ history