Your library is your paradise
Last Updated on 2023-10-10, 21:43 (GMT+0200)
Update 14-07-2021
I just tried SQLcl latest version 21.2. First results: The registering of my custom commands with below library doesn’t work anymore. Could be my bad, in which I’ll try to fix it, could be something in SQLcl. I don’t know yet, have to investigate as soon as I have the time. For now: Either don’t use this library, or stick to 21.1.1 until the root cause is fixed.
Update 08-10-2021
The above mentioned problem was not due to my code, so the library can be safely used. It’s caused by new stuff inside SQLcl.
So, if you run javascript code and only receive one of these messages:
“!ScriptCommand.1!”
“JS Language engine not found”
The quickest way to solve it is to install JDK. (Or better yet: GraalVM. See next update.)
Update 14-04-2022
On 07-04-2022 version 22.1 of SQLcl was released which ends support for Java 8.
So, as of that version Java 11 is the minimum version. As of that version no separate JRE is supplied anymore, so you will need to install a JDK anyway.
Problem: Nashorn is depricated in Java 11 and removed in Java 15, so that implies that using JavaScript in SQLcl will is approaching the end.
However, instead of using a JDK we can use GraalVM which continues to support JavaScript.
The people behind SQLcl have promoted the use of GraalVM on Social media, so that implies it’s supported as well.
I will soon do a short blog post about how I let SQLcl use GraalVM (Spoiler: it’s simple).
You can find GraalVM here: https://www.oracle.com/downloads/graalvm-downloads.html
I’m currently using the latest and greatest: “GraalVM Enterprise Edition 22 version 22.0.0.2 For Java Version 17”
Update 22-04-2022
The library had some changes.
First and foremost: There was a bug due to a terribly wrong use of a global variable which could lead to a custom command suddenly not being recognized fater a couple of succesful executions.
This has been fixed.
Furthermore, I made a better distinction between code meant to be called and code meant for internal use inside the library.
Soon (I hope, available time is a factor) I will create a GitHub repo for this and other scripts, making it a lot easier for me to push new versions and for you to download them.
Update 23-112022
The scripts and libraries can now be found on GitHub.
I hope to add more in the future. I have a bunch of scripts I use, but that need to be made more robust before handing it to others.
https://github.com/erikvanroon/SQLcl
So far, in the previous post and the one before that, we have seen what is necessary to register some Javascript as a custom command in SQLcl.
To be honest, with all the complexity that is needed, I would be surprised if anybody made it to here.
I am very enthusiastic about the scripting possibilities in SQLcl, but if registering a very simple script with a handful of lines requires more than a screen full of extra code just to be able to make it available as a custom command, I can imagine not a lot of people wanting to go there.
I myself copied the extra code from one script to the next, until I got sick and tired of it.
So, with the wise words of the Dutch medieval Philosopher Desiderius Erasmus in mind “Your library is your paradise” I turned the code I had so far into a library.
Below I will first explain how to use the library and what it does.
Then after that, if you just want a simple way to register custom commands, you can go about your business again while I discuss some aspects of the library itself.
Go straight to
How to load the library into your script
The functionality of the library
– Adding registration functionality to the script
– Just running the script without registering
– Syntax of running the script for registration as custom command
– Registering as custom command
– Registering as custom command with default name
– Controlling the amount of feedback of the register process
– Unregistering a command without re-registering
The listing of the library
Remarks about the code of the library
– Internal/external use
– Feedback
– Arguments
– Default functions
– runCommand
How to load the library into your script
Because this library is introduced to reduce the complexity of the code we need to add to register a command, it would be pretty silly if loading the library would be complex.
So don’t worry, it’s not.
Just save the code of the library (see below) to a file and use the “load” command to load it into your script.
The code in the library is implemented as functions of the object “registration”.
So, that would IMHO be a nice name for the library.
But I also like to be able to recognize by the name that a script is a library and not a directly executable script.
Of course I could use a different extension, but I prefer to use a prefix “ELib_”, where ELib stands for Erik’s Library (or EvROCS Library, but that is the same).
So, if I save the code in a file “d:\ELib\ELib_registration.js” then I can load the library in any script by adding this to the start of it:
1 |
load("d:/ELib/ELib_registration.js"); |
Getting all that functionality into your script has never been this easy.
Of course it’s up to you if you would like to add a bit more complexity to make the path a bit more dynamic.
I personally like to have the location of my library scripts in a substitution variable so if I go to a different customer and have to put them in a different place I only have to change the one variable and everything works again.
But , as I’ve said, that comes with a bit of extra complexity because then you need to add a little bit of code to get the value from that substitution variable.
Do what and as you like.
Go Back to topThe functionality of the library
For your scripts, the most important functionality in the library is the function “registration.runCommand”.
If you add a call to this function to the end of your script and provide it the main-code function as parameter, you can either just execute the script or register it as a custom command. If you register it you can choose any command name you like or not choose a command name in which case the default command name “cctest” (for Custom Command Test) will be used, which can be useful during development of the script.
Also, when registering you can choose the amount of feedback (information) messages that will be put on screen.
NOTE:
Up until now, in previous posts, in the code I showed you, my “MainCode” function had a parameter for the “args” array.
This was because when the script was just executed the out-of-the-box ‘array’ args had to be used, but when the script was registered as a custom command, a custom created array with the arguments that are parsed from the command line had to be used.
Now, when a script is registered as a custom command the library still puts the command line arguments of the execution of the command in a custom array, but the custom array is called “args”, so the code of the script can just refer to the args array, no matter whether it’s executed as script or as custom command. So, the MainCode function no longer needs the parameter for the array containing the arguments.
The registration.runCommand function takes up to 3 parameters: functionToExecute, beginEvent, endEvent.
In the first parameter “functionToExecute” you should pass the name of the function expression that is the main code of the script.
Parameters “beginEvent” and “endEvent” are optional. If you need some begin- or endEvent functionality, you can pass in the names of the respective function expressions here. If you don’t, ‘empty’ function expressions that don’t do anything will be used.
Adding registration functionality to the script
If we want to be able to register this script
1 2 3 4 5 6 7 8 9 10 |
"use strict"; // Report each argument value function mainCode () { for (var i=0; i < args.length; i++) { ctx.write ("Argument " + i + " is: " + args[i] + "\n"); } } mainCode(); |
It would have to be changed into
1 2 3 4 5 6 7 8 9 10 11 12 |
"use strict"; load ("D:/Elib/ELib_registration.js"); //Or wherever the library is // Report each argument value function mainCode () { for (var i=0; i < args.length; i++) { ctx.write ("Argument " + i + " is: " + args[i] + "\n"); } } registration.runCommand (mainCode); |
In the new version, line 2 is added to load the library, and the call of function MainCode on line 10 in the original was changed into what is line 12 in the new version.
And that’s all.
That’s a lot less code to add isn’t it?
And it supplies some extra possibilities too.
Let’s have a look at what happens when we run this script.
Go Back to topJust running the script without registering
If the script is saved as “listargs.js” and executed, for example like this:
1 |
script listargs.js a b "between b and c" c d |
the exact same behavior can be seen with or without the change we described above.
“So?” I hear you say. “What’s the use?”.
Well, this is just so you can still choose to simply execute the script without registering it.
But you do now have the option to register it too if you want to.
That is what we’ll do next…….
Syntax of running the script for registration as custom command
If we want to register the functionality of the script as a custom command, we need to execute it with some special parameters
1 |
script FileName.js -cmdReg [Custom_Command_name] [-all | -minimal | -silent] |
In the following sections I will try to explain what these parameters mean and what the result of using them is.
Go Back to topRegistering as custom command
To tell the script we don’t want to execute it but to register it as a custom command a parameter is used
This parameter is “-cmdReg” and has to be the first parameter.
This parameter can then be followed by the name you want to use for the custom command.
This means that if I want to register this script as custom command “erik” I could just run:
1 |
script listargs.js -cmdReg erik |
After which I have added a command “erik” with the functionality from the script, so I can run
1 |
erik a b "between b and c" c d |
Notice that when registering the command some feedback is put on screen:
- A message that an attempt is going to be made to unregister the command, because it may already exist after a previous registration
- A message that the command has not been found, so it has not been unregistered
If the command had been found, the message would say that the command has been unregistered - A message that the command has been registered
We will see later how the amount of this feedback can be reduced if you want to.
Go Back to topRegistering as custom command with default name
As you can see in the general syntax, the parameter for the name of the custom command is optional.
That implies that you can register a script as a custom command without supplying a name for the command !?!
Correct. You can.
If no command name is supplied the library will register the functionality using the default name ” ccTest” (Where the “cc” stands for “Custom Command”).
Maybe this is not of any importance to you, but I like this in cases where I’m altering the functionality of existing commands. I can change the script and register it with the default name. Then I can run the command cctest and still have the original command available for comparison of the results.
As I said: maybe you don’t care. Fine. Don’t use it. But it’s there if you want.
By the way, if you would like to use a different default name you can obviously just change it in the library.
Go Back to topControlling the amount of feedback of the register process
By default registering a custom command using this library gives some feedback on screen.
It can be useful to see that indeed an attempt was made to unregister previous instances of the command, that it has actually been unregistered or that no previous instances of the command were found, and that the command eventually was successfully registered.
But once you have a stable script that you just want to register via for example your login.sql, you may not want these messages for, let’s say, 10 commands to scroll over your screen when you connect.
Of course you could simply set termout off while registering your commands. But that suppresses any errors too.
The registration functionality in the library has the option to reduce or completely suppress the positive, succesful feedback, while allowing all problems to go to screen after all.
At the end of the registration statement as we’ve seen above one of 3 parameter values kan be added to control the amount of feedback
These parameter values are:
- -all
Shows all feedback. This is the default. Behavior will be as we’ve seen so far.
. - -minimal
Only displays the confirmation that the command has been registered
. - -silent
Does not display any of the normal feedback
.
So if the command “erik” we’ve registered before would be registered with the “-minimal” parameter like this
1 |
script listargs.js -cmdReg erik -minimal |
the feedback would look like this
Doing this with the 10 command registrations in your login.sql would just show a clean list of 10 “Command xxx has been registered” remarks.
If even that is too much for you, you can just use “-silent” instead of “-minimal”.
These feedback parameters also work if no command name is supplied after “-cmdReg”.
1 |
script listargs.js -cmdReg -minimal |
Will also work.
Go Back to topUnregistering a command without re-registering
Unregistering a custom command is built into the library and is automatically done just before a new version of that command is registered.
This means that unregistering is a fixed part of registering.
There will probably not be a lot of use cases for when you would like to explicitly unregister a command if it’s not just to get rid of it before registering a new version.
If you’re just not interested in the command anymore, you would normally probably just leave the command where it is and remove the registering of the command from your login.sql. Then next time you run SQLcl it will be gone, and until then you just don’t use the command. You’re not interested in it anymore, after all.
But just in case you found the perfect use case to clean up a custom command, you can.
In fact there are two ways to do that.
Option 1
If you have any script that contains the changes I described to add the registration functionality (loading the library and executing registration.runCommand), then that script can be used to unregister any custom command that has been registered before.
Just execute the script with the ” cmdUnReg” parameter followed by the name of the command you wish to unregister.
1 |
script listargs.js -cmdUnReg AnyCommandYouWantToDrop |
Here too you can leave out the command name to unregister the command with the default name (cctest).
1 |
script listargs.js -cmdUnReg |
To be absolutely clear: this does not, I repeat: not(!!), unregister whatever code is in that script file “listargs.js”, but it unregisters the command that is explicitly typed after “-cmdUnreg” or if no command is typed there, the default command “cctest”.
Option 2
If you do this manual unregistering regularly, you may want to just create a simple dedicated script for that.
That script can be as simple as
1 2 3 4 5 6 7 8 9 10 |
"use strict"; load ("D:/Elib/ELib_registration.js"); if (args.length == 1) { registration.unregisterCommand (); } else { registration.unregisterCommand (args[1]); } |
Save that code in a file called unreg.js and then unregistering a command can be done like this
1 |
script unreg.js AnyCommandYouWantToDrop |
Or to unregister the default command cctest
1 |
script unreg.js |
The listing of the library
Okay, we now all know how the stuff works and how it should be used.
All that is left is the library itself.
Here it is:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 |
/* ------------------------------------------------------------------------- -- -- -- _/_/_/_/ _/_/_/ _/_/ _/_/_/ _/_/_/ -- -- _/ _/ _/ _/ _/ _/ _/ _/ _/ -- -- _/_/_/ _/ _/ _/_/_/ _/ _/ _/ _/_/ -- -- _/ _/ _/ _/ _/ _/ _/ _/ _/ -- -- _/_/_/_/ _/ _/ _/ _/_/ _/_/_/ _/_/_/ -- -- -- ------------------------------------------------------------------------- ========================================================================================== Library with functionality for registering/unregistering custom commands in SQLcl Note: The "LibLocal**.***" functionality is, as the name implies, primarily meant for use inside this library. Some of it *might* be useful and usable outside too, but if you do, you're on your own. ========================================================================================== Instructions: Change your script - At the top of the script you may want to register as a command first of all load this library Suppose you saved the library script as "ELib_registration.js" in "D:\ELib\", then: load ("D:/ELib/ELib_registration.js") - At the bottom, add the "registration.runCommand" function. supply the function expression holding the main code of your script as value to the first parameter If a beginEvent and/or endEvent are needed, supply the corresponding function expressions from your script to the second and third parameter. Remove the execution of the function executing the main code. So, if the function with the main code is called "maincode()" and no beginEvent or endEvent is needed this should be added registration.runCommand (mainCode); Execute the script - Executing the script without parameters or with parameters, but the first one is not -cmdReg or -cmdUnReg will just execute the the function holding the main code. So the script is executed without being registered as a custom command. script FileName.jc param1 param2 param3 Registering the script as a custom command - For registration the general syntax is: script FileName.js -cmdReg [Custom_Command_name] [-all | -minimal | -silent] Examples: script FileName.js -cmdReg MyCommand => Will register the functionality as custom command "MyCommand" script FileName.js -cmdReg => Will register the functionality as default custom command "cctest" The examples above can be extended with one more parameter which controls the amount of feedback that is given on screen by the registration functionality. Valid values for this parameter are: - all : The default. All feed back will be put on screen - minimal : Only the succesful registration message is put on screen - silent : No feedback is put on screen Errors are always shown. Unregistering a command - a command is automatically unregistered just before it is registered, to clean up old versions of the command If a manual unregister of a custom command is desired, do either one of the following: - execute an (any) existing script that has been prepared for registration as described above (load this library and execute the registration.runCommand function) Supply parameters: First parameter : "-cmdUnReg" Second parameter : name of the command that has to be unregistered, or empty to unregsiter the default command "cctest" script FileName.js -cmdUnReg MyCommand - Create a script and save it into a file for instance called "unreg.js" In the file: Just load this libarary and then execute: if (args.length == 1) { registration.unregisterCommand (); } else { registration.unregisterCommand (args[1]); } Now a command can be unregistered by executing script unreg.js MyCommand Or simply script unreg.js to unregister the default "command cctest" ========================================================================================== */ "use strict"; var registration = {}; //Object containing all 'Public' functionality var LibLocalRegUnreg = {}; //Object containing all functionality for internal use in this library LibLocalRegUnreg.jRegUnregCollectors = Java.type("java.util.stream.Collectors") ; LibLocalRegUnreg.jRegUnregSQLCommand = Java.type("oracle.dbtools.raptor.newscriptrunner.SQLCommand") ; LibLocalRegUnreg.jRegUnregCommandRegistry = Java.type("oracle.dbtools.raptor.newscriptrunner.CommandRegistry"); LibLocalRegUnreg.jRegUnregCommandListener = Java.type("oracle.dbtools.raptor.newscriptrunner.CommandListener"); // Predefined Feedback Levels LibLocalRegUnreg.RegUnregFeedbackWantedAll = 0 ; LibLocalRegUnreg.RegUnregFeedbackWantedMinimal = 50 ; LibLocalRegUnreg.RegUnregFeedbackWantedSilent = 100; // Message Priority Levels LibLocalRegUnreg.RegUnregMsgLevelInfo = 25 ; LibLocalRegUnreg.RegUnregMsgLevelImportant = 75 ; LibLocalRegUnreg.RegUnregMsgLevelCritical = 1000; // Set defaults for Feedback level and Name to use for the custom command LibLocalRegUnreg.defaultCommandName = "ccTest" ; LibLocalRegUnreg.RegUnregFeedbackWantedLevel = LibLocalRegUnreg.RegUnregFeedbackWantedAll; LibLocalRegUnreg.replaceArgsWithCustomArgs = function (matcher) { args = []; while (matcher.find()) { //args.push(matcher.group()); args.push(matcher.group(3) != null ? matcher.group(3) : matcher.group(2)); } } LibLocalRegUnreg.feedback = function (line, fblevel) { if (fblevel >= LibLocalRegUnreg.RegUnregFeedbackWantedLevel) { ctx.write (line + "\n"); } } LibLocalRegUnreg.commandArguments = function(cmdLine) { var jPattern = Java.type("java.util.regex.Pattern"); var pattern = jPattern.compile('("([^"]*)")|([^ ]+)'); var matcher = pattern.matcher(cmdLine.trim()); LibLocalRegUnreg.replaceArgsWithCustomArgs (matcher); } LibLocalRegUnreg.feedbackParameter = function (feedbackParam) { var validFeedbackParam = true; if (feedbackParam.equalsIgnoreCase("-silent")) { // No feedback other than critical messages wanted LibLocalRegUnreg.RegUnregFeedbackWantedLevel = LibLocalRegUnreg.RegUnregFeedbackWantedSilent; } else if (feedbackParam.equalsIgnoreCase("-minimal")) { // Only reasonably important messages wanted LibLocalRegUnreg.RegUnregFeedbackWantedLevel = LibLocalRegUnreg.RegUnregFeedbackWantedMinimal; } else if (feedbackParam.equalsIgnoreCase("-all")) { // All possible messages wanted LibLocalRegUnreg.RegUnregFeedbackWantedLevel = LibLocalRegUnreg.RegUnregFeedbackWantedAll; } else { // The value in the parameter is not a valid feedback parameter value validFeedbackParam = false; } return validFeedbackParam; } registration.unregisterCommand = function (cmdName) { if (cmdName != undefined && cmdName != "undefined") { var RegUnregCommandName = cmdName; } else { var RegUnregCommandName = LibLocalRegUnreg.defaultCommandName ; } // Get the current list of listeners var listeners = LibLocalRegUnreg.jRegUnregCommandRegistry.getListeners(ctx.getBaseConnection(), ctx).get(LibLocalRegUnreg.jRegUnregSQLCommand.StmtSubType.G_S_FORALLSTMTS_STMTSUBTYPE); var commandFound = false; // remove all commands registered with LibLocalRegUnreg.jRegUnregCommandRegistry.addForAllStmtsListener LibLocalRegUnreg.jRegUnregCommandRegistry.removeListener(LibLocalRegUnreg.jRegUnregSQLCommand.StmtSubType.G_S_FORALLSTMTS_STMTSUBTYPE); // clear the general (no-connection) cache and the connection specific cache LibLocalRegUnreg.jRegUnregCommandRegistry.clearCaches(null, ctx); LibLocalRegUnreg.jRegUnregCommandRegistry.clearCaches(ctx.getBaseConnection(), ctx); // get the list of listeners that have not been removed, if any var remainingListeners = LibLocalRegUnreg.jRegUnregCommandRegistry.getListeners(ctx.getBaseConnection(), ctx).get(LibLocalRegUnreg.jRegUnregSQLCommand.StmtSubType.G_S_FORALLSTMTS_STMTSUBTYPE) .stream().map(function(l) l.getClass()).collect(LibLocalRegUnreg.jRegUnregCollectors.toSet()); // re-register all commands except for the one we are trying to unregister and any remaining (not removed) listener classes for (var i in listeners) { if (listeners.get(i).toString().equalsIgnoreCase(RegUnregCommandName)) { // This is the command we are trying to unregister, so don't re-register, remember we found it for feedback later commandFound = true; } else if (!remainingListeners.contains(listeners.get(i).getClass())) { // It is not one of the listener classes that couldn't be removed, so re-register it LibLocalRegUnreg.jRegUnregCommandRegistry.addForAllStmtsListener(listeners.get(i).getClass()); } } // Report whether the command has actually been unregistered if (commandFound) { LibLocalRegUnreg.feedback ("Command " + RegUnregCommandName + " has been UNRegistered" , LibLocalRegUnreg.RegUnregMsgLevelInfo); } else { LibLocalRegUnreg.feedback ("Command " + RegUnregCommandName + " was not found, hence could not be UNRegistered" , LibLocalRegUnreg.RegUnregMsgLevelInfo); } } LibLocalRegUnreg.registerCommand = function (cmdName, functionToExecute, beginEvent, endEvent) { if (cmdName != undefined && cmdName != "undefined") { var RegUnregCommandName = cmdName; } else { var RegUnregCommandName = LibLocalRegUnreg.defaultCommandName ; } // Determine if a beginEvent is supplied, and if not define it as an 'empty' function if (beginEvent == undefined || beginEvent == "undefined") { beginEvent = function(conn, ctx, cmd) {}; } // Determine if an endEvent is supplied, and if not define it as an 'empty' function if (endEvent == undefined || endEvent == "undefined") { endEvent = function(conn, ctx, cmd) {} } // Define a handleEvent. If no functionToExecute is supplied define it as an 'empty' function if (functionToExecute == undefined || functionToExecute == "undefined") { var handleEvent = function(conn, ctx, cmd) {} } else { var handleEvent = function(conn, ctx, cmd) { LibLocalRegUnreg.commandArguments (cmd.getSql()); if (args != null && typeof args[0] != "undefined" && args[0].equalsIgnoreCase(RegUnregCommandName)) { functionToExecute(); return true; } return false; } } // Define a custom toString method as a function that returns the name of the custom command var customToString = function() { // to be able to identify this dynamically created class when unregistering return RegUnregCommandName; } // Extend the listener with the above methods var customCommandToRegister = Java.extend(LibLocalRegUnreg.jRegUnregCommandListener, { handleEvent : handleEvent, beginEvent : beginEvent, endEvent : endEvent, toString : customToString } ); // Unregister the custom command if it has been registered before LibLocalRegUnreg.feedback ("Trying to unregister Command " + RegUnregCommandName + " in case it has been registered before...." , LibLocalRegUnreg.RegUnregMsgLevelInfo); registration.unregisterCommand (RegUnregCommandName); // Register the custom command LibLocalRegUnreg.jRegUnregCommandRegistry.addForAllStmtsListener(customCommandToRegister.class); LibLocalRegUnreg.feedback ("Command " + RegUnregCommandName + " has been registered" , LibLocalRegUnreg.RegUnregMsgLevelImportant); } registration.runCommand = function (functionToExecute, beginEvent, endEvent) { var paramCount = args.length - 1; var cmdName; // if first parameter is -cmdReg (case INsensitive) then register the CommandListener // if first parameter is -cmdUnReg (case INsensitive) then UNregister the CommandListener // otherwise just run the script if (paramCount >= 1 && args[1].equalsIgnoreCase("-cmdReg")) { // Parameter requesting registration of a command // Set feedback level and/or command name, if they were provided through the parameters // If there is a second parameter and it is one of the feedback parameters, set the global feedback level accordingly // otherwise, // the second parameter contains the requested name of the custom command, so set *that* global variable // in this case, check if there is a third parameter and if so, if it's one of the feedback parameters if (paramCount >= 2) { if (!LibLocalRegUnreg.feedbackParameter(args[2])) { cmdName = args[2]; if (paramCount >= 3 ) { // Now we are not interested in the return value of the function. // If it's not a feedback parameter, it'll just be ignored and feedback level remains on its default LibLocalRegUnreg.feedbackParameter(args[3]); } } } LibLocalRegUnreg.registerCommand(cmdName, functionToExecute, beginEvent, endEvent); } else if (paramCount >= 1 && args[1].equalsIgnoreCase("-cmdUnReg")) { // Parameter requesting UNregistration of a command // If there is a parameter it contains the name of the command to be unregistered. // Otherwise, the command with the default name is to be unregistered if (paramCount >= 1) { cmdName = args[1]; } registration.unregisterCommand(cmdName); } else { // NO Parameter requesting registration of the command encountered, so just run the script functionToExecute(); } } |
Remarks about the code of the library
Overall the library is just an implementation of what I’ve discussed about registering and unregistering in previous posts, so I won’t repeat all that I’ve said there.
I will only highlight some stuff that is specific for this library.
Internal/external use
Most of what’s in the library is for internal use only.
The library declares two objects with functions.
- LibLocalRegUnreg
- registration
The functionality in object LibLocalRegUnreg is primarily meant for use inside the library.
You might look at the code and come to the conclusion you can use it elsewhere too.
That could even be true, but I did not develop it with such use in mind, so there are no guaranties whatsoever.
The functionality in object registration is what’s meant for use by “the outside world”.
The registration.runCommand function is really the only one that is supposed to be called from outside.
The registration.unregisterCommand command is an exception to this rule. It shouldn’t be necessary to call that from outside this library, but if you want to, you can. See the unregistering of commands.
Feedback
The LibLocalRegUnreg.feedback on line 133 writes the messages to screen conditionally.
Only messages with a level equal or higher than the feedback level that was requested through the -all/-minimal/-silent parameter are actually written to screen. Others are ignored
Arguments
The LibLocalRegUnreg.commandArguments function on line 140 is the one that parses the command line for executions of the custom command it then calls the LibLocalRegUnreg.replaceArgsWithCustomArgs function to write the parameter values in that call to a custom “args” array.
Go Back to topDefault functions
In the registration.runCommand function all three parameters, for the function to be executed, the begin event and the end event, can be empty.
For each of those, if the parameter is empty, an ‘empty’ function doing nothing is used (See internal function LibLocalRegUnreg.registerCommand, Line 227, 232 and 237).
Yes, this means that it is possible to register a command with only no-op functions for handleEvent and beginEvent and endEvent.
So registering a command that does absolutely completely totally nothing.
Is this a problem? I don’t think so.
Would that be a stupid thing to do? Absolutely.
Do I think you’re stupid? Not at all.
So in conclusion: I don’t think this is a problem, and preventing it does not justify adding extra complexity to the library.
Go Back to toprunCommand
On line 276. the function registration.runCommand handles the running of the script either normally or in registration/unregistration mode.
If the first parameter used when executing the script is neither “-cmdReg” nor “-cmdUnReg” then the main code function of the script is executed.
If it’s “cmdUnReg” the unregistration functionality is executed.
If it’s “cmdReg” the registration functionality is executed.
I hope this library will be as useful to you as it has been to me so far. This blog does not have the -silent parameter set, so feel free to comment.
Love to hear if it’s useful. Don’t love to but definitely want to hear if you have any criticism.
Reacties
Your library is your paradise — Geen reacties
HTML tags allowed in your comment: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">