User Commands User Guide
User Commands User Guide
User Guide
Unless stated otherwise, all examples in this document assume that ⎕IO ⎕ML ← 1
No part of this publication may be reproduced in any form by any means without the
prior written permission of Dyalog Limited.
Dyalog Limited makes no representations or warranties with respect to the contents
hereof and specifically disclaims any implied warranties of merchantability or fitness
for any particular purpose. Dyalog Limited reserves the right to revise this publication
without notification.
email: support@[Link]
[Link]
TRADEMARKS:
Array Editor is copyright of [Link]
Raspberry Pi is a trademark of the Raspberry Pi Foundation.
Oracle®, JavaScript™ and Java™ are registered trademarks of Oracle and/or its
affiliates.
UNIX® is a registered trademark in the U.S. and other countries, licensed exclusively
through X/Open Company Limited.
Linux® is the registered trademark of Linus Torvalds in the U.S. and other countries.
Windows® is a registered trademark of Microsoft Corporation in the U.S. and other
countries.
macOS® and OS X® (operating system software) are registered trademarks of Apple
Inc. in the U.S. and other countries.
All other trademarks and copyrights are acknowledged.
User Commands User Guide
Contents
1 About This Document 1
1.1 Audience 1
1.2 Conventions 1
2 Introduction 3
2.1 Cache File 3
2.1.1 Defining the UCMDCACHEFILE Environment Variable 4
3 Using User Commands 6
3.1 Installation 6
3.2 Directory Structure 6
3.3 Implementation 6
3.3.1 Customising the Implementation 7
3.4 File Format 8
3.5 Groups 8
3.6 Syntax in Dyalog Sessions 9
3.7 Running User Commands 10
3.7.1 Arguments 10
3.7.2 Modifiers and Modifier Values 11
3.7.3 Errors when Running a User Command 11
4 Creating User Commands 12
4.1 Basic Definition 12
4.2 The List Function 13
4.2.1 Name 14
4.2.2 Group 14
4.2.3 Parse 15
4.3 The Run Function 16
4.3.1 Defining Multiple Levels of Help 16
4.4 The Help Function 18
4.5 Modifiers 19
4.5.1 Default Modifier Values 20
4.6 Arguments 21
4.6.1 Default Argument Values 21
4.6.2 Arguments Including Space Characters 22
4.6.3 Minimum Number of Arguments 22
4.6.4 Maximum Number of Arguments 22
4.6.5 Long Arguments 22
4.6.6 Summary of Argument Specification in the Parser 23
4.7 Saving Custom User Commands 23
4.8 Detecting New Custom User Commands 24
A SAMPLES Group 26
revision 20240129_250 i
User Commands User Guide
A.1 ]UCMDHelp 26
A.2 ]UCMDNoParsing 26
A.3 ]UCMDParsing 27
B Example User Commands 28
B.1 Example: Basic User Command Definition 28
B.2 Example: Cross-Operating System Definition 29
B.3 Example: Optional Arguments 32
B.4 Example: The Parse Variable 35
B.5 Example: Debugging a User Command 37
Index 41
revision 20240129_250 ii
User Commands User Guide
1.1 Audience
It is assumed that the reader has a reasonable understanding of Dyalog.
For information on the resources available to help develop your Dyalog knowledge,
see [Link]
1.2 Conventions
Unless explicitly stated otherwise, all examples in Dyalog documentation assume that
⎕IO and ⎕ML are both 1.
revision 20240129_250 1
User Commands User Guide
A full list of the platforms on which Dyalog version 19.0 is supported is available at
[Link] Although the Dyalog
programming language is identical on all platforms, differences do exist in the way
some functionality is implemented and in the tools and interfaces that are available.
Differences in behaviour between operating systems are identified with the following
icons (representing macOS, Linux, Microsoft Windows and UNIX respectively):
revision 20240129_250 2
User Commands User Guide
2 Introduction
User commands are tools that are available at any time, in any workspace, as
extensions to the Dyalog development environment. The text-based implementation
of user commands allows development tools to be easily shared between users, and
the ability to create custom user commands in addition to the predefined user
commands that are supplied with Dyalog means that it is simple to write utility tools
for your environment that can be easily issued to an entire development team.
User commands are entered in an APL Session by starting an input line with a ]
character, for example:
]ToHex 250+⍳5
FB FC FD FE FF
revision 20240129_250 3
User Commands User Guide
The default name for the cache file uses the following syntax: UserCommand
<UcmdMajor><UcmdMinor>.<DyalogMajor><DyalogMinor><U|C><bits>.cache. For
example, the cache file for the user command framework v2.5, which accompanies
Dyalog v19.0, on a 64-bit Unicode system, would be [Link].
The name and location of the cache file can be changed from its default by setting the
UCMDCACHEFILE environment variable.
revision 20240129_250 4
User Commands User Guide
8. Click OK to create the new environment variable and exit the New User
Variable dialog box.
9. Click OK to exit the Environment Variables dialog box.
10. Click OK to exit the System Properties window.
11. Close the System window.
1. Open a shell.
2. At the command prompt, enter:
UCMDCACHEFILE=[UCMDCACHEFILE] dyalog
revision 20240129_250 5
User Commands User Guide
This chapter introduces some of the concepts that underpin user commands in
Dyalog.
3.1 Installation
A set of predefined user commands is installed automatically with Dyalog.
Although the spice directory can be moved, it must always remain directly
beneath the SALT directory and must not be renamed.
3.3 Implementation
When an input line in a Session starts with a ] character, Dyalog looks for the function
⎕[Link]:
revision 20240129_250 6
User Commands User Guide
l if this function exists, then it is called with the rest of the input line as the right
argument and a reference to calling space as the left argument.
l if this function does not exist, then user commands are disabled.
This implementation means that application code can invoke user commands by
calling ⎕[Link] directly.
Dyalog Ltd reserves the right to change the implementation of the user
command framework.
EXAMPLE
The following command is entered while in a namespace:
]<ucmd> <-myModifier>=<value>
Dyalog's interpreter preserves this exactly and makes the following call:
⎕THIS ⎕[Link] '<ucmd> <-myModifier>=<value>'
⎕[Link] converts this into a call to the user command framework; the functions
defined for <ucmd> are actioned with the <-myModifier> modifier applied with a
value of <value> and the result is displayed in the Session.
EXAMPLE
The result of <ucmd> is assigned to a variable called <variable>:
]<variable>←<ucmd> <–myModifier>=<value>
Dyalog's interpreter preserves this exactly and makes the following call:
⎕THIS ⎕[Link] '<variable>←<ucmd> <–myModifier>=<value>'
⎕[Link] converts this into a call to the user command framework; the functions
defined for <ucmd> are actioned with the <-myModifier> modifier applied with a
value of <value> and the result is assigned to <variable>.
If <variable> was not included then the result of <ucmd> would be discarded and
not shown in the Session, although any non-result output generated would be
displayed.
revision 20240129_250 7
User Commands User Guide
By default, double-clicking on a .dyalog file opens that file using the standalone
editor.
Files with the .dyalog extension are Unicode text files. This means that they can store
any text that uses Unicode characters. This format includes most of the world's
languages and the Dyalog character set, and is supported by many software
applications. By using text files as a storage mechanism, user commands and other
tools written using Dyalog can be combined with industry-standard tools for source
code management.
3.5 Groups
User commands with common features can be grouped together under a single
name. These groups have no effect on the functionality of the individual user
commands but enable related user commands to be gathered together for ease of
reference and provide a means of sorting and classifying user commands that can be
very useful as the number of user commands increases.
User command names must be unique within a group but do not have to be unique
across all groups. This means that groups allow a systematic naming convention for
user commands that perform similar functions on different types of APL object, for
example, the predefined user command ][Link] compares two files,
][Link] compares two arrays and ][Link] compares two functions.
Although a user command can have the same name as its group (or another
group), Dyalog Ltd does not recommend this as it can introduce ambiguity to a
user reading the code.
revision 20240129_250 8
User Commands User Guide
When running (or asking for help on) a user command, the group name can be
prefixed to the user command name, separated by a . character; this group name
prefix is mandatory if the user command name is not unique across all groups.
Every user command must be in a group, and every group must comprise at least one
user command.
revision 20240129_250 9
User Commands User Guide
The names of user commands and groups are not case-sensitive although their
arguments, modifiers and modifier values might be. The convention used in
this document is that group names are shown in UPPERCASE and user
command names are shown in Upper CamelCase.
For information on the precise syntax for each user command, the arguments that
can be supplied to it and the modifiers that it can take, enter ]<ucmd> -? or ]Help
]<ucmd> in a Dyalog Session.
When running a user command, the name of that command must be entered in full.
The names of user commands are not case-sensitive although their arguments,
modifiers and modifier values might be.
3.7.1 Arguments
Some user commands can accept (or require) one or more arguments. To see a list of
the possible arguments for a user command, enter ]<ucmd> -? or ]Help
]<ucmd> in a Dyalog Session.
For example, the behaviour of the user command ]CD depends on the argument
supplied when calling it. If it is run with no argument, then it returns the current
working directory – this is equivalent to entering cd on the command line of a
Microsoft Windows operating system or pwd in UNIX. However, if a single argument
specifying the full path to a directory is supplied, then the user command changes the
current working directory to be the one specified by the argument.
revision 20240129_250 10
User Commands User Guide
When running a user command with a specified modifier, the name of the modifier
does not always need to be entered in full as long as enough of the modifier's name is
entered for it to be interpreted unambiguously. For example, if a user command has a
modifier called -version and does not have any other modifiers starting with the
letter v then the function can be successfully called with modifiers -version, -vers,
-v, and so on.
Multiple modifiers can be included in a user command call – in this situation they
must be separated by a space character. The order in which they are specified is
irrelevant.
revision 20240129_250 11
User Commands User Guide
revision 20240129_250 12
User Commands User Guide
The script for Dyalog's predefined user commands can be a useful starting
point when creating a new user command. The location of an existing user
command's script can be found in the following ways:
l ]UVersion <ucmd> returns the script location for the specified user
command
l ]ULoad <ucmd> loads the script for the specified user command into
the active workspace and returns the script location.
l ]<ucmd> -? returns the script location for the specified user command
if ]UDebug is on.
User commands are defined by three specific APL functions (along with any additional
functions needed for the particular purpose of the user command). The three
functions must be called:
l List – for information on the List function, see Section 4.2.
l Run – for information on the Run function, see Section 4.3.
l Help – for information on the Help function, see Section 4.4.
These functions are wrapped together in a namespace (the order in which the
functions are specified within the namespace is not important). A single namespace
can host multiple user commands, but must only have one instance of each of the
three functions irrespective of how many user commands it contains. (Although a
class can be used instead of a namespace, a namespace is the recommended
approach.)
See Appendix A for some sample user commands that demonstrate the use of
multiple levels of help and parsing user command lines. See Appendix B for
some examples of user commands wrapped in a namespace – these show how
the List, Help and Run functions are defined.
revision 20240129_250 13
User Commands User Guide
l Group – the name of the group to which the command belongs (see
Section 4.2.2)
l Parse – parsing information for the framework (see Section 4.2.3)
4.2.1 Name
User commands must have unique names within a group (names can be replicated
across different groups if required). They must be valid APL identifier names (for more
information on legal names, see the Dyalog Programming Reference Guide).
Modifiers must have unique names within the user command but do not have to be
unique within the superset of user commands. Modifier names are case-sensitive;
Dyalog recommends using lowercase characters only.
The names of user commands and modifiers cannot contain space characters.
When naming a modifier, avoid the names arguments, delim, propagate, swd
and switch as these names are used by the parser.
4.2.2 Group
Every user command must be a member of a group (but can only be a member of one
group). In addition:
l the user commands for a single group do not all need to be defined within a
single namespace/.dyalog file
l a single namespace/.dyalog file can include user commands for several
different groups
l user command names must be unique within a group but do not have to be
unique across all groups (however, custom user commands should not be given
the same name as any of the predefined user commands within the SALT
group).
revision 20240129_250 14
User Commands User Guide
4.2.3 Parse
If the Parse variable for a user command is empty, then the Run function's second
argument will comprise everything following the command name. By setting the
Parse variable to non-empty values, the user command framework is able to handle
arguments and modifiers. For more information on modifiers and modifier values, see
Section 4.5. For more information on arguments, see Section 4.6.
The following general rules apply when processing a call to a user command:
l user commands take 0 or more arguments and 0 or more modifiers
l individual arguments and modifiers are separated by space characters
l arguments and modifiers can be specified in any order
l arguments can be optional or mandatory
l modifiers are identified by a preceding - character
l modifier values are identified by a preceding = character
l modifier names are case-sensitive
l individual arguments and modifier values can be delimited by single or double
quotes to allow leading/trailing/internal space characters or to allow
arguments that have a leading - character.
The user command framework verifies that these rules have been adhered to before
creating a new namespace. It then populates this namespace with a variable called
Arguments (containing all the arguments) and a variable for each of the modifiers
with names matching those of the modifiers. Other manipulation tools are also added
to the namespace, for example, the Switch function – see Section 4.5.1. This
namespace is passed to the Run function (see Section 4.3) as its second argument.
If the Parse variable defined in a user command's List function is empty, then the
user command will accept anything; the entire character vector is the argument.
If the Parse variable defined in a user command's List function is not empty, then it
must describe the number of arguments and the modifiers used. The number of
arguments is a simple number and the list of modifiers must include, for each
modifier, its name, whether it accepts a value and, optionally, any restrictions for that
value.
revision 20240129_250 15
User Commands User Guide
The specific defined help information that is presented to a user when requesting
help in a Dyalog Session is dependent on the level of help requested. This level is
defined to be 1 less than the number of ? characters entered after the - character;
for example, ]<ucmd> -?? returns the information defined for level 1 of the <ucmd>
user command.
As with the predefined user commands, increasingly detailed levels of information
can be provided for custom user commands. If multiple levels of help are defined,
then Dyalog Ltd recommends including information to that effect in each level, for
example, the information that is displayed in response to a ]<ucmd> -?? request
should state that more detailed information is available if ]<ucmd> -??? is entered.
Any valid Dyalog algorithmic syntax can be used in the Help function to define
different levels of help, for example, control structures or branching. Optionally, the
different levels of help can be cumulative so that, for example, ]<ucmd> -???
returns the help information for levels 0 and 1 as well as the help for level 2.
The following code fragment is an example showing how separate (non-cumulative)
levels of help can be defined within the Help function:
∇ r←level Help Cmd
:Select level
:Case 0
r←⊂'This is basic help.'
:Case 1
r←⊂'This is level 1 help.'
:Case 2
r←⊂'This is level 2 help.'
:Else
revision 20240129_250 16
User Commands User Guide
In this case:
l ]<ucmd> -? gives This is basic help.
l ]<ucmd> -?? gives This is level 1 help.
l ]<ucmd> -??? gives This is level 2 help.
l ]<ucmd> -???? gives This is level 3 help.
l ]<ucmd> -????? gives This is level 3 help.
The :Else control structure in the code fragment ensures that requests for
higher levels of help than are defined return the highest-defined level rather
than generating an error message.
The following code fragment is an example showing how cumulative levels of help can
be defined within the Help function:
∇ r←level Help Cmd
r←⊂'This is basic help.'
r,←⊂'This is level 1 help.'
r,←⊂'This is level 2 help.'
r,←⊂'This is level 3 help.'
r←((1+level)⌊≢r)↑r
∇
revision 20240129_250 17
User Commands User Guide
In these cases:
l ]<ucmd> -? gives
This is basic help.
l ]<ucmd> -?? gives
This is basic help.
This is level 1 help.
l ]<ucmd> -??? gives
This is basic help.
This is level 1 help.
This is level 2 help.
l ]<ucmd> -???? gives
This is basic help.
This is level 1 help.
This is level 2 help.
This is level 3 help.
l ]<ucmd> -????? gives
This is basic help.
This is level 1 help.
This is level 2 help.
This is level 3 help.
Entering ]Help ]<ucmd> in a Dyalog Session always presents the user with
the same level of help as ]<ucmd> -? even if there are multiple levels of help
defined.
If ]UDebug is on, then the Help function returns an enhanced set of information by
default:
revision 20240129_250 18
User Commands User Guide
]<GROUPNAME>.<commandname>
4.5 Modifiers
Modifiers enable a user command to apply filters and rules so that an entirely new
(similar) user command does not need to be written. The user command framework
allows you to define the modifiers that your user command will accept. The rules
when defining each modifier in the Parse variable are:
l If a modifier accepts characters in a set, then the Parse variable includes the
modifier and possible values with the ∊ character as a separator. For example:
-<modifier name>∊<set of characters>
so -XYZ∊abc012 means that the modifier -XYZ can accept any number and
combination of characters in the set abc012, such as ab2a0b.
l If a modifier accepts specific character vectors, then the Parse variable
includes the modifier and possible values with the = character as a separator
and the character vectors separated by space characters. For example:
-<modifier name>=<charvec1> <charvec2> <charvec3>
so -XYZ=abc 012 means that the modifier -XYZ can accept either abc or 012
as a modifier value.
l If a modifier accepts any character vector, then the Parse variable includes
the modifier and a = character with nothing after it. For example:
-<modifier name>=
so -XYZ= means that the modifier -XYZ can accept any value.
For each of these three rules, enclosing the separator character within square
brackets means that specification of modifier values is optional. For example,-XYZ
[=] means that the modifier -XYZ can be specified without a value but will accept
any value.
revision 20240129_250 19
User Commands User Guide
Approach 1: Assign a default value to the modifier using the ":" character as the
separator:
List[i].Parse←'-X:123'
With this approach, the default value is reported only if the modifier is not used; a
value of 1 is reported if the modifier is used but no value is specified.
Approach 2: Test whether the modifier value is 0 and, if it is, then set it to the
required default value.
For example:
:if X≡0 ⋄ X←'123' ⋄ :endif
Approach 3: Define the default value using the dyadic form of the Switch function
(automatically defined in the namespace that is passed to the Run function (see
Section 4.3) as its second argument).
Given the name of a modifier as a right argument:
l monadic Switch returns:
o 0 if an invalid modifier name is specified
o 0 if the modifier is not specified and no default value has been set for
that modifier
o 1 if the modifier is specified without a modifier value
revision 20240129_250 20
User Commands User Guide
4.6 Arguments
Unlike modifiers, arguments do not have names. However, as arguments must be
specified in a particular order and each have a specific purpose, they should be given
an appropriate name in the Help function to make their purpose clear.
The number of arguments that a user command can take is specified in the Parse
variable (see Section 4.2.3 – this explains the rules for determining the value to
specify there).
where a is the second argument supplied to the Run function, that is the
arguments/modifiers supplied to the user command (see Section 4.3). In this example,
the first three arguments have their default values set to 0 if they are optional
arguments; if they are mandatory then any value specified here is ignored.
revision 20240129_250 21
User Commands User Guide
If the user command ]NewID accepts 3 arguments, firstname, surname and address,
then Parse should be set to '3' and the user command is run as follows:
]NewID Morten Kromberg 'Dyalog Ltd'
revision 20240129_250 22
User Commands User Guide
The long argument L can be appended to the maximum number of arguments S (see
Section 4.6.4) to specify that any additional arguments after the maximum number
has been supplied should be merged into the last one supplied. For example, if '3SL'
is specified, then 0, 1, 2 or 3 arguments can be supplied when calling the user
command but any more than this will be merged with the third argument. This means
that:
]cmd a1 a2 a3 a4 a5 a6
runs the user command cmd with three arguments: a1, a2 and 'a3 a4 a5 a6'.
revision 20240129_250 23
User Commands User Guide
permissions issues with accessing custom commands beneath this directory and there
is always the possibility that Dyalog Ltd might issue a user command with the same
filename as your custom user command at a future date.
The custom user command directory must be added to the user command search
path to enable the user commands within it to be detected. To do this, use the
]Settings user command to set the cmddir global parameter to the full path and
name of the directory (for more information enter ]Settings -? in a Session). The
new directory is added to the start of the list of directories, making it the first one
searched.
When adding a new directory to the list of directories searched by the user
command framework, you must precede its path with a , character.
If the cmddir global parameter includes multiple directories, then the user
command framework searches the directories in the order listed (starting from
the left) and retrieves the first user command it finds with the specified name.
To see the list of directories (and the order in which they are searched), enter
]Settings cmddir.
If the ]UNew user command is used to create and save a new user command, then its
location is automatically added to the list of directories searched.
revision 20240129_250 24
User Commands User Guide
revision 20240129_250 25
User Commands User Guide
A SAMPLES Group
The SAMPLES group contains user commands that demonstrate the use of multiple
levels of help and parsing user command lines.
The user commands in this group are not like those in other groups; they do not
provide any useful functionality but their code can be examined to assist with
understanding when creating custom user commands. This can be achieved by
opening them in any text editor, for example, Microsoft Notepad.
A.1 ]UCMDHelp
An example of a custom user command that defines multiple levels of help
information in the Help function, selectable by the number of question marks
supplied by the user, for example, ]<ucmd> -???.
To open the code for this user command in the Editor:
]ULoad UCMDHelp
Namespace #.HelpExample now contains source for
][Link] from <full path>\SALT\study\[Link]
)ED HelpExample
A.2 ]UCMDNoParsing
An example of a custom user command that does not use parsing; the argument is
the entire character vector after the command name.
revision 20240129_250 26
User Commands User Guide
A.3 ]UCMDParsing
An example of a custom user command that uses parsing; the character vector after
the command name is parsed and turned into a namespace containing the arguments
(tokenised) and each of the identified modifiers.
To open the code for this user command in the Editor:
]ULoad UCMDParsing
Namespace #.anyname now contains source for ][Link]
from <full path>\SALT\study\[Link]
)ED anyname
revision 20240129_250 27
User Commands User Guide
The examples in this appendix have been created to illustrate different aspects
of user commands. This means that they do not necessarily follow an efficient
workflow process or best coding practice.
revision 20240129_250 28
User Commands User Guide
In this example:
l The List function sets the four variables Desc, Name, Group and Parse to
'Time example Script', 'Time', 'TimeGrp' and '' respectively.
l The Run function only needs to call ⎕TS so the command name and any
supplied arguments are ignored. This function also formats the time into a
user-friendly format.
l The Help function identifies that there is only one user command in the
namespace (there is only one user command name, Time, defined) and returns
the appropriate information for that user command.
Running this user command in a Dyalog Session returns three numbers; these three
numbers are the current time, indicating the hour (according to the 24 hour clock),
the number of minutes past the hour and the number of seconds elapsed
respectively.
]Time -?
────────────────────────────────────────────────────────────
][Link]
]Time (no arguments)
revision 20240129_250 29
User Commands User Guide
:EndIf
∇
∇ r←Help Cmd;which
which←'Time' 'UTC'⍳⊂Cmd
r←which⊃']Time (no arguments)' ']UTC (no arguments)'
∇
∇ r←Zulu date
⍝ Use .NET to retrieve UTC info
r←[Link] date
∇
:EndNamespace
revision 20240129_250 30
User Commands User Guide
In this example:
l The List function is amended to allow for two function definitions in the four
variable definitions:
o Desc is set to to 'Show local time' 'Show UTC time' (two
values, therefore the first applies to the first user command and the
second applies to the second user command)
o Name is set to 'Time' 'UTC' (two values, therefore the first applies to
the first user command and the second applies to the second user
command)
o Group is set to ⊂TimeGrp (only one value so applied to both user
commands)
o Parse is set to '' (only one value so applied to both user commands)
l The Run function is amended to use the Cmd argument to determine which
user command is being run (any further supplied arguments are still ignored).
The operating system on which the Dyalog Session is being run is then
identified; this determines whether to use the current system time or the APL
system function ⎕TS. For example, if the UTC user command is being run on a
Microsoft Windows operating system, then the Run function calls the Zulu
function. The Run function also formats the resulting time into a more user-
friendly format irrespective of the operating system and user command.
l The Help function is amended to enable it to identify that there are two user
commands in the namespace (there are two user command names, Time and
UTC, defined) and return the appropriate information according to which name
is specified.
l The Zulu function is added to retrieve the UTC time through a .NET call – this
function is only called if the Run function identifies that the Dyalog Session is
running on a Microsoft Windows operating system and the ]UTC user
command is specified.
After changing the code but before running these user commands, the
]UReset user command should be run to force a cache file update (otherwise
the code changes will not be detected).
The Time and UTC user commands can now be run from a Dyalog Session:
]TimeGrp -?
TIMEGRP:
Time Show local time in a city
UTC Show UTC time
]Time -?
────────────────────────────────────────────────────────────
][Link]
revision 20240129_250 31
User Commands User Guide
revision 20240129_250 32
User Commands User Guide
⎕USING←'System'
dt←[Link]
:Select Cmd
:Case 'UTC'
dt←Zulu dt
:Case 'Time'
:If 0≠⍴city←Args~' '
offset←CityTimeOffset city
'Unknown city'⎕SIGNAL 11⍴⍨⍬≡offset
diff←⎕NEW TimeSpan(3↑offset)
dt←(Zulu dt)+diff
:EndIf
:EndSelect
r←(r⍳' ')↓r←⍕dt
∇
∇ r←Help Cmd;which
which←'Time' 'UTC'⍳⊂Cmd
r←which⊃']Time [city]' ']UTC (no arguments)'
∇
∇ r←Zulu date
⍝ Use .NET to retrieve UTC info
r←[Link] date
∇
∇ r←CityTimeOffset city;lcity;cities;ix;offsets
cities←'l.a.' 'montreal' 'copenhagen' 'sydney'
offsets←¯8 ¯5 1 10
r←⍬ ⍝ Assume no match
lcity←(819⌶)city ⍝ Name to lowercase
ix←cities⍳⊂lcity ⍝ Find city in cities
:If ix≤⍴cities ⍝ If present,
r←ix⌷offsets ⍝ return the offset
:EndIf ⍝ [else return ⍬]
∇
:EndNamespace
In this example:
l The List function has one small amendment to the description of the Desc
variable for the first user command.
l The Run function still uses the Cmd argument to determine which user
command is being run; different actions are taken according to which is
specified. If the Cmd argument is UTC then the function proceeds as before.
However, if the Cmd argument is Time then the function now takes the second
revision 20240129_250 33
User Commands User Guide
The Time and UTC user commands can now be run from a Dyalog Session:
]Time -?
────────────────────────────────────────────────────────────
][Link]
]Time [city]
(indicating that the current time in Los Angeles, ignoring daylight saving time, is 04:17
and 51 seconds)
]Time l.x.
* Command Execution Failed: Unknown city
revision 20240129_250 34
User Commands User Guide
]UTC -?
────────────────────────────────────────────────────────────
][Link]
]UTC (no arguments)
(indicating that the local co-ordinated universal time is 6:08 and 30 seconds)
]TimeGrp -?
TIMEGRP:
Time Show local time in a city
UTC Show UTC time
For more information on the Parse variable, see Section 4.2.3. For more
information on modifiers and modifier values, see Section 4.5. For more
information on arguments, see Section 4.6.
A new user command called Number is required to display either the age of the
specified person or to convert a decimal number into its Hexadecimal equivalent. The
necessary functions are defined in a namespace called number:
:Namespace number
⎕ML ⎕IO←1 ⍝ set to avoid inheriting external values
∇ r←List
r←⎕NS¨1⍴⊂''
r.(Group Parse Name Desc)←⊂'AgeHex' '' 'Number' 'Gives age
or Hexadecimal format'
∇
∇ r←Run(Cmd Args);N;H;alph;Name;Names
r←⍬
Names←[Link]
:For Name :In Names
:Select Name
revision 20240129_250 35
User Commands User Guide
:Case 'Fiona'
r,←40
:Case 'Andy'
r,←51
:Else
:If ∧/Name∊⎕D ⍝ If all digits...
N←⌈16⍟(⍎Name)
H←(N⍴16)⊤(⍎Name)
alph←'0123456789ABCDEF'
r,←⊂alph[⎕IO+H]
:Else
r,←⊂'Unrecognised Name'
:EndIf
:EndSelect
:EndFor
∇
∇ r←Help Cmd
r←'Enter either a person''s name to return their age or a
number to return the Hexadecimal equivalent'
∇
:EndNamespace
In this example, the Parse variable is empty – this means that the Run function takes
everything following the command name as a simple character vector. However, if a
valid name is entered with the expectation of having that person's age returned, then
an error message is generated:
]Number Fiona
* Command Execution Failed: SYNTAX ERROR
The same error message is generated if a decimal number is entered with the
expectation of its Hexadecimal equivalent being returned:
]Number 42
* Command Execution Failed: SYNTAX ERROR
This error arises because the user command is expecting a namespace as its input and
instead it is receiving a simple character vector.
These errors arise because the Args parameter in the Run function is a simple
character vector rather than a namespace; this is due to the empty Parse variable.
Populating the Parse variable means that the Args parameter becomes a
namespace.
revision 20240129_250 36
User Commands User Guide
For this example, the only changes that will be made to the user command's
code are to its Parse variable definition.
To enable the user command to perform the necessary namespace conversion, the
Parse variable is changed from '' to '2S' – this means that the user command can
accept 0, 1 or 2 arguments but no more (for more information on this, see
Section 4.6.4).
]Number 42
2A
]Number 42 42
2A 2A
]Number 42 42 42
* Command Execution Failed: too many arguments
]Number 42 Fiona
2A 40
Changing the Parse variable again, this time from '2S' to '2L', means that 2
arguments must be supplied; if more than this are supplied then the first argument is
taken as specified and the rest are merged together to become the second argument
(for more information on this, see Section 4.6.5).
]Number 42
* Command Execution Failed: too few arguments
]Number 42 42
2A 2A
]Number 42 42 42
2A Unrecognised Name
]Number 42 Fiona
2A 40
revision 20240129_250 37
User Commands User Guide
A user command can be debugged by tracing through ⎕[Link] (see Section 3.3).
However, a more convenient method is to instruct the framework to suspend on the
first line of the Run or Help function – tracing/debugging can then proceed from
there. To do this, debugging mode must be switched on:
]UDebug on
Was OFF
To progress through the Run function, enter the Trace command (<TC>).
You can now trace and debug the code in the namespace.
revision 20240129_250 38
User Commands User Guide
The Trace window shows that, in the number namespace, the Parse variable is set to
2S. This means that the Args variable is a namespace. The namespace contains a
number of variables, one of which is Arguments:
]Disp Args
⎕SE.[Namespace]
Args.⎕NL 2
Arguments
SwD
_1
_2
]Disp [Link]
┌→─┬────┐
│42│Andy│
└─→┴───→┘
This shows that the Arguments variable is a vector comprising two character vectors.
Enter the Edit command (<ED>) to open the namespace definition in the Edit window
and change the Parse variable from '2S' to '2L'. Save the changes and repeatedly
enter the Escape command (<EP>) until you are no longer tracing through code. Then
enter:
]Number 42 Andy 8 9 10 –
This shows that the Arguments variable is still a vector comprising two character
vectors. However, the second of the two character vectors now includes everything
after the first argument in the call to the user command.
Press the <ED> key combination to open the namespace definition in the Edit window
and change the Parse variable from '2L' to '2S -true'. The '-true' means that
the parser now accepts a modifier called -true that does not accept a modifier value
but can only be present or absent (see Section 3.7.2). Save the changes and
repeatedly hit <EP> until you are no longer tracing through code. Then enter:
]Number 42 Andy –
Args.⎕NL 2
Arguments
revision 20240129_250 39
User Commands User Guide
SwD
_1
_2
true
This shows an additional variable, true, created with the same name as the modifier
that was included in the Parse variable. However, when calling the ]Number user
command, this on/off modifier was not specified. Therefore:
[Link]
0
To see the effect of calling the ]Number user command with this modifier specified:
)reset
]Number 42 Andy -true –
[Link]
1
revision 20240129_250 40
User Commands User Guide
Index
A E
B G
C H
revision 20240129_250 41
User Commands User Guide
Syntax 11
P
Parse variable 15
R
Run function 16
Running user commands 10
S
UCMDCACHEFILE Environment
Variable 4
User command groups
(predefined)
SAMPLES 26
User commands (predefined)
]UCMDHelp 26
]UCMDNoParsing 26
]UCMDParsing 27
revision 20240129_250 42