53
edits
(Polished...) |
|||
Line 1: | Line 1: | ||
== Overview == | == Overview == | ||
User commands | User commands play a crucial role for Dyalog APL developers. Dyalog comes with a rich set of user commands, but independent parties also develop and maintain user commands. This article discusses how and where to install third-party user commands, and how to load them into <syntaxhighlight lang=apl inline>⎕SE</syntaxhighlight>. | ||
== Prerequisite Knowledge == | |||
Dyalog | This article assumes that you are familiar with the concept of Dyalog user commands, and understand what a user command script is, along with its specific features and properties. | ||
If you are new to these topics, it is recommended to first study Dyalog's [https://www.dyalog.com/documentation_182.htm "User Commands User Guide"]. | |||
== Installing user command == | |||
* | Dyalog installs its own set of user commands into <syntaxhighlight lang=apl inline>[DYALOG]/SALT/spice</syntaxhighlight>. Installing third-party user commands into this folder comes with both advantages and disadvantages. | ||
Advantages of installing into the <syntaxhighlight lang=apl inline>[DYALOG]/SALT/spice</syntaxhighlight> folder: | |||
* User commands cannot be modified by ordinary users; admin rights are required | |||
* Every version of Dyalog has its own set of user commands | * Every version of Dyalog has its own set of user commands | ||
On the other hand, installing user commands in a different folder, such as <syntaxhighlight lang=apl inline>MyUCMDs/</syntaxhighlight>, has its own advantages: | |||
* | * Users have write permission to this folder, making updates easier | ||
* Anything installed into this folder will be available in all installed versions of Dyalog APL | * Anything installed into this folder will be available in all installed versions of Dyalog APL | ||
* Each user has their own <syntaxhighlight lang=apl inline>MyUCMDs/</syntaxhighlight> folder, which can be seen as an advantage or disadvantage based on individual preferences | |||
Both the <syntaxhighlight lang=apl inline>SALT/spice</syntaxhighlight> folder and the <syntaxhighlight lang=apl inline>MyUCMDs/</syntaxhighlight> folder are scanned for user command scripts at startup. | |||
== | == Location of the MyUCMDs/ folder == | ||
The | The location of the MyUCMDs/ folder depends on the operating system used: | ||
* | * On Windows it's usually <syntaxhighlight lang=apl inline>C:\Users\<username>\Documents\</syntaxhighlight> | ||
* | * On Linux it is <syntaxhighlight lang=apl inline>/home/<username>/</syntaxhighlight> | ||
* On Mac OS it is <syntaxhighlight lang=apl inline>/Users/<username>/</syntaxhighlight> | |||
Note that <syntaxhighlight lang=apl inline>MyUCMDs/</syntaxhighlight> is created by the Dyalog APL installer | Note that <syntaxhighlight lang=apl inline>MyUCMDs/</syntaxhighlight> is created by the Dyalog APL installer on Windows, but you need to manually create it on non-Windows platforms before version 19.0. | ||
If you have [https://github.com/aplteam/Tatin Tatin] installed, or you are using version 19.0 or later (those come with Tatin | If you have [https://github.com/aplteam/Tatin Tatin] installed, or you are using version 19.0 or later (those come with Tatin) then you can call this Tatin API function: | ||
<syntaxhighlight lang=apl> | <syntaxhighlight lang=apl> | ||
⎕se.Tatin.GetMyUCMDsFolder' | ⎕se.Tatin.GetMyUCMDsFolder'' ⍝ Windows | ||
C:\Users\ | C:\Users\<username>\Documents\MyUCMDs | ||
</syntaxhighlight> | </syntaxhighlight> | ||
== Availability of user commands == | == Availability of user commands == | ||
Once a user command script is moved into | Once a user command script is moved into the <syntaxhighlight lang=apl inline>MyUCMDs/</syntaxhighlight> folder (or a sub-folder of it), the user command becomes available across all versions of APL. | ||
For simple user commands where all the code resides in the script itself, this is the end of the process. However, if a user command relies on a larger set of code files that need to be loaded into <syntaxhighlight lang=apl inline>⎕SE</syntaxhighlight> for execution, additional steps are required. | |||
The user command script could of course check whether the code is already available in <syntaxhighlight lang=apl inline>⎕SE</syntaxhighlight> and if not load it, and that would work just fine. | |||
== User commands with an API == | == User commands with an API == | ||
It has become increasingly popular to add an API to user commands. For example, the Dyalog APL project manager Cider offers a rich set of user commands: | |||
For example, the Dyalog APL project manager | |||
<syntaxhighlight lang=apl> | <syntaxhighlight lang=apl> | ||
Line 91: | Line 94: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
If you want to use any of | If you want to use any of the API functions without the need of first calling one of the Cider user commands (that would force the user command loading the code into <syntaxhighlight lang=apl inline>⎕SE</syntaxhighlight>), then you have to make sure that the code is loaded by other means, ideally at an early stage: as part of the bootstrapping process. | ||
== setup.dyalog in MyUCMDs/ == | == Introducing setup.dyalog in MyUCMDs/ == | ||
To address this, a script named <syntaxhighlight lang=apl inline>setup.dyalog</syntaxhighlight> is introduced in the <syntaxhighlight lang=apl inline>MyUCMDs/</syntaxhighlight> folder. When Dyalog encounters this script, it checks for the presence of a function called <syntaxhighlight lang=apl inline>Setup</syntaxhighlight> and executes it. | |||
Notes: | Notes: | ||
* The name | * The script name must be lowercase to ensure compatibility with non-Windows platforms | ||
* The script can be a class or a namespace | * The script can be a class or a namespace | ||
* The | * The <syntaxhighlight lang=apl inline>Setup</syntaxhighlight> function must accept a right argument | ||
* The function <syntaxhighlight lang=apl inline>Setup</syntaxhighlight> must return a result | * The function <syntaxhighlight lang=apl inline>Setup</syntaxhighlight> must return a result | ||
=== There is no setup.dyalog yet === | === There is no setup.dyalog yet === | ||
Line 157: | Line 159: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Note that this also checks the version of Dyalog APL and whether it's "Classic" or not. | Note that this also checks the version of Dyalog APL and whether it's "Classic" or not. Please customize the script to fit your specific needs. Ensure to modify the <syntaxhighlight lang=apl inline>IfAtLeastVersion</syntaxhighlight> function, if necessary. | ||
If your user command is not a Tatin package then this will do. | If your user command is not a Tatin package then this will do. | ||
Line 163: | Line 165: | ||
=== There is already a setup.dyalog === | === There is already a setup.dyalog === | ||
Copy the functions <syntaxhighlight lang=apl inline>IfAtLeastVersion</syntaxhighlight>, <syntaxhighlight lang=apl inline>GetMyUCMDsFolder</syntaxhighlight> and <syntaxhighlight lang=apl inline>LoadMyUserCommand</syntaxhighlight> from above into your own <syntaxhighlight lang=apl inline>setup.dyalog</syntaxhighlight> script | Copy the functions <syntaxhighlight lang=apl inline>IfAtLeastVersion</syntaxhighlight>, <syntaxhighlight lang=apl inline>GetMyUCMDsFolder</syntaxhighlight> and <syntaxhighlight lang=apl inline>LoadMyUserCommand</syntaxhighlight> from above into your own <syntaxhighlight lang=apl inline>setup.dyalog</syntaxhighlight> script. | ||
Make sure that <syntaxhighlight lang=apl inline>LoadMyUserCommand</syntaxhighlight> is called from your <syntaxhighlight lang=apl inline>Setup</syntaxhighlight> function. | |||
This makes sure that the API of your user command is available right after instantiating Dyalog APL. | This makes sure that the API of your user command is available right after instantiating Dyalog APL. | ||
Line 192: | Line 196: | ||
* Usually <syntaxhighlight lang=apl inline>LoadDependencies</syntaxhighlight> loads packages into <syntaxhighlight lang=apl inline>#</syntaxhighlight> in case no second argument is specified, but because the folder was specified as an alias (<syntaxhighlight lang=apl inline>[MyUCMDs]</syntaxhighlight>) the function knows that this is about a user command, and therefore the default target for the load operation is <syntaxhighlight lang=apl inline>⎕SE</syntaxhighlight> rather than <syntaxhighlight lang=apl inline>#</syntaxhighlight>. | * Usually <syntaxhighlight lang=apl inline>LoadDependencies</syntaxhighlight> loads packages into <syntaxhighlight lang=apl inline>#</syntaxhighlight> in case no second argument is specified, but because the folder was specified as an alias (<syntaxhighlight lang=apl inline>[MyUCMDs]</syntaxhighlight>) the function knows that this is about a user command, and therefore the default target for the load operation is <syntaxhighlight lang=apl inline>⎕SE</syntaxhighlight> rather than <syntaxhighlight lang=apl inline>#</syntaxhighlight>. | ||
* The user command script <syntaxhighlight lang=apl inline>MyUserCommand.dyalog</syntaxhighlight> is moved to the top of the folder hosting the user command, here <syntaxhighlight lang=apl inline>[MyUCMDs]/MyUserCommand</syntaxhighlight> | * The user command script <syntaxhighlight lang=apl inline>MyUserCommand.dyalog</syntaxhighlight> is moved to the top of the folder hosting the user command by <syntaxhighlight lang=apl inline>]Tatin.Installpackages</syntaxhighlight>, here <syntaxhighlight lang=apl inline>[MyUCMDs]/MyUserCommand</syntaxhighlight> | ||
=== Loading all such user commands === | === Loading all such user commands === | ||
If you want to make sure that all user commands that are Tatin packages are loaded into <syntaxhighlight lang=apl inline>⎕SE</syntaxhighlight> at an early stage add this to your <syntaxhighlight lang=apl inline>setup.dyalog</syntaxhighlight> script and make sure that it is called by your <syntaxhighlight lang=apl inline>Setup</syntaxhighlight> function: | If you want to make sure that all user commands that are Tatin packages are loaded into <syntaxhighlight lang=apl inline>⎕SE</syntaxhighlight> at an early stage then add this code to your <syntaxhighlight lang=apl inline>setup.dyalog</syntaxhighlight> script and make sure that it is called by your <syntaxhighlight lang=apl inline>Setup</syntaxhighlight> function: | ||
<syntaxhighlight lang=apl> | <syntaxhighlight lang=apl> | ||
r←path LoadUserCommandPackages debug;home;name;res;folders;folder;F | r←path LoadUserCommandPackages debug;home;name;res;folders;folder;F | ||
⍝ This loads Tatin packages that are user commands installed in | ⍝ This loads Tatin packages that are user commands installed in "path" | ||
r←'' | r←'' | ||
F←⎕SE._Tatin.FilesAndDirs | F←⎕SE._Tatin.FilesAndDirs | ||
:If 0<≢folders←F.ListDirs path | :If 0<≢folders←F.ListDirs path | ||
:For folder :In folders | :For folder :In folders | ||
:If F.IsFile folder,'/apl-buildlist.json' | :If F.IsFile folder,'/apl-buildlist.json' | ||
name←2⊃⎕NPARTS folder | name←2⊃⎕NPARTS folder | ||
:Trap (~debug)/0 | :Trap (~debug)/0 | ||
Line 223: | Line 227: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
== Conclusion == | |||
* Every user command that relies on code that is not part of the user command script as such should check whether that code is already in <syntaxhighlight lang=apl inline>⎕SE</syntaxhighlight> and load it into <syntaxhighlight lang=apl inline>⎕SE</syntaxhighlight> if not | |||
* There are good reasons to load all user commands, packaged or otherwise, at an early stage as part of the Dyalog bootstrapping process | |||
* If you have specific user commands that consume a significant amount of memory and are infrequently executed, you can request Dyalog to introduce a mechanism that allows a package to indicate its preference for loading its own code. | |||
[[Category:Articles]][[Category:Tutorials]][[Category:Dyalog APL examples]] | [[Category:Articles]][[Category:Tutorials]][[Category:Dyalog APL examples]] |