Utilities for Dyalog Developers
Vector 15:1, page 138
Transcribed from the printed issue; not yet reviewed. Read it in the PDF of the issue, page 138
One thing I missed when I first started working with Dyalog APL under Windows after many years of STSC/Manugistics mainframe APL, was User Commands.
In an attempt to fill the gap left by Dyalog’s lack of a User Command Processor, I have developed a technique to run user-written commands from within the ⎕SE namespace, (normally from the toolbar or menu bar or PF key) without having to save them permanently in the "session namespace" (⎕SE).
Overview¶
I have a workspace called SE.DWS which is always loaded when I first start the development version of Dyalog APL. This WS copies a very few utility functions into ⎕SE, sets up my session Toolbar, session Menu, PF keys, dynamic page width, an external variable (to act as an APL dedicated "clipboard") and then loads any requested workspace (either named in a command line parameter or as the workspace selected via File Manager).
The most important function added to the ⎕SE namespace is Ucmd. This takes a character string as a right argument and an optional left argument (which will be explained later).
∇ r←{ltarg}Ucmd
string;niladic;bo;cmd;arg;bin;file;wsid;namespace;tempns
[1] ⍝Emulate STSC_s r←⎕UCMD string
[2] bo←∧\string≠' ' ⍝Must use space delimiter
[3] cmd←bo/string
[4] niladic←∧/bo
[5] arg←1↓(~bo)/string
[6] ⍝Copy command to local namespace "tempns"
[7] namespace←'tempns'
[8] bin←namespace ⎕NS''
[9] wsid←(2 ⎕NQ'.' 510 'DYALOG'),'\ws\ucmd\',cmd
[10] copyinto
[11] ⍝run main function in cmd with correct valence
[12] :If 2=⎕NC'ltarg' ⋄ ⍎'r←ltarg tempns.',cmd,' arg'
[13] :ElseIf ~niladic ⋄ ⍎'r←tempns.',cmd,' arg'
[14] :Else ⋄ ⍎'r←tempns.',cmd
[15] :End
∇
The string consists of the name of the command to be processed and any arguments. (For example Fns a* where Fns is the command and a* the argument. Note that the case of the function name is important.)
Ucmd parses its arguments and then creates a temporary (i.e. localised) namespace called ⎕SE.tempns.
Ucmd then locates a workspace with the same name as the command from a standard known location. (I use the value of Dyalog’s configuration parameter DYALOG as the root and add to this the extra path required to locate the Ucmd utility workspaces. e.g. C:\DYALOG73\ws\ucmd\Fns.dws. Note that the case of the function name, now used as the workspace name, is unimportant here.)
Ucmd then copies into the ⎕SE.tempns namespace the contents of a workspace it just found. It then runs a function with the same name (and case) as the command with the supplied argument.
This means that a single workspace (say FNS.DWS) could contain several different function commands (say FNS, Fns, FnS, fns etc.). I use this technique to call several different cover functions to a basic command. (i.e. to list the functions in the current namespace; list functions in the ROOT namespace; list functions in the namespace putting the result in the clipboard; list all functions matching a set of criteria read from the calling window…..)
I have set up my Toolbar, PF keys and Menus to support calling the Ucmd function in a number of different ways:
a) Single click menu item. This calls the command directly, if appropriate, using the "currently selected object" as an argument. Due to limited space on the menu bar, only the most useful commands are supported in this manner. e.g.:
- NSfind – To locate all occurrences of the current object in the current namespace.
- Latest – To list all functions modified today.
- Fns - To list all fns in the current namespace.
- Vars - To list all vars in the current namespace.
- Put1 – Adds a copy of the "currently selected object" to the "APL Clipboard".
- GetAll – Fixes all objects held in the "APL Clipboard" into the current namespace.
b) Select a command from a drop-down list, getting any required parameters via a window. e.g.:
- FNS – Input pattern-matching selection criteria of function (and operator) names, and name of namespace to search and then list all functions (and operators) found.
- VARS - as for FNS but on variables.
- OBS – as for FNS but on other objects.
- COMP - Input the (fully qualified) names and locations (default to the current workspace) of the objects to be compared.
- WSCOMP - Input the name of a workspace to compare to the current workspace, and list differences found at the object name level.
- WSFIND - Locate the text in the workspace/namespace, with full control over what and how the search is performed (e.g. ignore case, in comments only).
- GETCLIP - Store the results of the last command in the (supplied) named variable.
- TREENS - List the namespace/GUI object tree structure from the (supplied) named node (default #).
- COPYUTILS - Copy from the named workspace the named function (and all other functions it calls) into the current namespace.
c) Press a PF key to perform standard requests. e.g.:
Lists all variables starting with dbx_ (i.e. Causeway panel definitions).
NOTE. The results of the commands are often "unformed" (e.g. a simple text matrix, with one item per row). This is what would be stored by GETCLIP above. However, when actioned from the Toolbar or Menu bar, the results displayed in the session are always "formatted" (e.g. a long list would be "folded" into several columns across the page, the number of columns depending on ⎕PW (which in turn is dynamically linked to the width of the session window). The function ⎕SE.Show performs this action.
Recap: the command
results in the contents of workspace C:\dyalog73\ws\ucmd\fns.dws being copied into temporary namespace ⎕SE.tempns. It then executes the following string:
Upon completion, the local namespace is removed when the parent function Ucmd is exited.
I have placed a zipped file containing my most up to date UCMD directory (..\ws\ucmd\*.*) including the all important SE.DWS on the Vector web site; access is via the Contents page listing for this edition of Vector. Once unzipped and stored under your Dyalog directory, (you will need to add the UCMD directory to your WSPATH,) then the action of )LOAD SE should modify your current session making all the Ucmd utilities available.
Notes¶
There is no need to save your modified session, as SE is designed to modify it each time it is loaded. Take special care not to overwrite your default session with the modified one (I have overwritten DEF_UK.DSE more than once!).
If you ever use file manager to select a workspace to run under Dyalog, the REGEDIT file SE.REG, can be used to modify your registry so that Dyalog automatically loads the SE workspace before loading the selected workspace. The file supplied is for Windows 3.x and will need to be modified for your correct paths. I am unable to supply a Win95/NT version of this file, so you will need to modify the appropiate registry entry by hand (via the program REGEDIT.EXE).