Chapters

  1. Introduction
  2. Structure
  3. Packaging
  4. Logging
  5. Configuration
  6. Debugging EXEs
  7. Handling errors
  8. Testing
  9. Documentation
  10. Make
  11. Providing help
  12. Scheduled Tasks
  13. Windows Services
  14. Windows Event Log
  15. Windows Registry
  16. Creating SetUp.exe
  17. Regular Expressions
  18. Acre
  19. GUI
  20. Git

Appendices

  1. Windows environment vars
  2. User commands
  3. aplcores & WS integrity
  4. Development environment
  5. Special characters

Misc

User commands are a great way to make utilities available to the developer without cluttering the workspace. They also allow you to have one code base for several Dyalog installations. Since its introduction they have proven to be be indispensable.

Whether you want to write your own user commands or to make use of any third-party user commands like those available from the APL wiki for download [1], you need to consider your options for how to integrate non-Dyalog user commands into your development environment.

The default folder depends on your version of Dyalog of course, but you can always find out from a running instance of Dyalog APL:

      '"',(2⎕NQ # 'GetEnvironment' 'Dyalog'),'\SALT\spice\"'
"C:\Program Files\Dyalog\Dyalog APL-64 16.0 Unicode\SALT\spice\"

The above is the default folder for the 64-bit Unicode version of Dyalog 16.0 for all Dyalog user commands available within that version.

If you want to keep life simple the obvious choice seems to be this folder: you just copy your user command into this folder and it becomes available straight away.

Simple may it be, but this is not recommended:

For these reasons you are advised to use a different folder.

Let's assume that you have a folder C:\MyUserCommands that's supposed to hold all non-Dyalog user commands.

Via the Options > Configure command you can select the User Commands dialog and add that folder to the search path; remember to press the Add button once you have browsed to the right directory.

If you use several versions of Dyalog in parallel then you are advised not to add that folder via the configuration dialog box in each of those versions.

Instead we recommend writing an APL function that adds the folder to all versions of Dyalog currently installed. See the chapter The Windows Registry where this scenario is used as an example.

Where two user commands share the same name, the last definition wins. You can achieve this just by having a user command Foo in two different scripts in different folders with the same group name, or no group name at all!

In other words, the full name of a user command is compiled by the group name (say foo) and the user-command name (say goo): ]foo.goo. However, as long as there is only one user command goo this will do nicely:

      ]goo

Group names are not only useful to avoid name clashes, they also allow user commands to be, well, grouped in a sensible way. Whether you should add your own user commands to any of the groups Dyalog comes with is a diffult question to answer. There are pros and cons:

Note that once you've copied a new user command into that folder it is available straight away, even in instances of Dyalog that are already running.

However, auto-complete does not know about the new user command until it was called for the first time in an already running instance. You can at any time execute ]ureset to make sure that even auto-complete knows about it.

In case you change an existing user command, for example by modifying the parsing rules, you must execute ]ureset in order to get access to the changes from any instance of Dyalog that has already been running by then.

It's not difficult to write your own user commands, and there is an example script available that makes that easy and straightforward. However, if your user command is not too simple consider developing it as an independent application, living in a particular namespace (let's assume Foo) in a particular workspace (let's assume Goo).

Then write a user command that creates a namespace local to the function in the user command script, copy the namespace Foo from the workspace Goo into that local namespace and finally run the required function. Make sure the workspace is a sibling of the user command script.

This approach has the advantage that you can develop and test your user commands independently from the user command framework.

This is particularly important because changing a user command script from the Tracer is a bit dangerous; you will see more aplcores than under normal circumstances. On the other hand it is difficult to execute the user command without the user command framework calling it: you need those arguments and sometimes even variables that live in the parent (##).

We therefore recommend you ensure no function in Foo relies on anything provided by the user-command framework. Instead, the calling function (Run in your user command) must pass such values as arguments to any functions in Foo called by Run.

That makes it easy to test all the public functions in Foo. Of course you should have proper test cases for them.

The following code is a simple example that assumes the following conditions:

:Namespace  Foo
      ⎕IO←1 ⋄ ⎕ML←1

    ∇ r←List
      r←⎕NS''
      r.Name←'Foo'
      r.Desc←'Does this and that'
      r.Group←'Cookbook'
      r.Parse←'1 -verbose'
    ∇

    ∇ r←Run(Cmd Args);verbose;ref;path;arg
      ref←⎕NS''
      verbose←Args.Switch'verbose'
      path←⊃1 ⎕NPARTS ##.SourceFile
      arg←⊃Args.Arguments
      :Trap 11
          'Foo'ref.⎕CY path,'\Goo'
      :Else
          'Copy operation for "Foo" in "Goo" failed' ⎕Signal 11
      :EndTrap
      r←ref.Foo.Run arg verbose
    ∇

    ∇ r←Help Cmd
      r←⊂'Help for "Foo".'
      r,←⊂'This user command ...'
      r←,[0.5]r
    ∇

:EndNamespace

Notes:

The workspace Goo can be tested independently from the user command framework, and the workspace Goo might well hold test cases for the functions in Foo.


Footnotes

  1. Dyalog user commands from the APL wiki http://aplwiki.com//CategoryDyalogUserCommands