A: Command Arguments

Scott Waldron Updated by Scott Waldron

Adding Arguments

Our first command does not require any input from the user other than pressing the Run button. Commands are usually more useful if we can collect some information from the user. Let's create a new function that takes some parameters. Go back to the rule script record, go to the Editor tab, and enter the following script after the cmdFirstCommand function.

/**
Command function demonstrating parameter type prefixed names.
*/
def cmdSecondCommand(strArgOne, intArgTwo, dateArgThree, boolArgFour) {
return string.Format(
$$
You entered:
A string with the value of {0},
a number with the value of {1},
a date with the value of {2},
a bool (true/false) with the value of {3}.
$$, strArgOne, intArgTwo, dateArgThree, boolArgFour);
}

Those funny $$bunch of stuff here$$ are simply a type of string delimiter that can be used to enter multi-line strings. in Dino, all the following lines of code would be semantically identical:

var x = 'This is a string';
var x = "This is a string";
var x = $$This is a string$$;

It may seem odd to have so many types of delimiters. Doing so allows us to create strings that contain the other delimiters within. For example, HTML nearly always uses the double quote mark to contain attribute values. By using the $$ delimiters, we can easily embed the "" marks without escaping them.

var html =
$$
<div class="outer">
<h2>Hello World</h2>
</div>
$$;

After entering the script and saving the record, go back to the Commands tab and create the command record highlighted in the second row in the following screenshot:

Now let's go back to the System Log list page and run our second command from the Actions and Links menu there. When we run it, we should get a dialog popup that looks like this, called the argument collection dialog:

Wait, we have a normal textbox, a textbox with a zero already in it, a date picker, and a checkbox! How did that happen?

Command Function Argument Types

Since Dino is a dynamically typed language, this section should really be called Function Argument "Types", because Trestle simply uses naming convention and type inference based on the name of the parameter. Here are the type prefixes that Trestle recognizes. This is a Trestle-specific extension; Dino itself makes no assumptions about the type of the argument from the way that it is named.

  • str (strOne, strSomeString, strName) – string
  • txt (txtNotes, txtDescription) – string, renders as long text input (textarea) control
  • int (intX, intNumDays) – int (32-bit integer)
  • long (longX, longY) – long (64-bit integer)
  • num (numX, numPercent) – double (floating point number)
  • bool (boolAllRecords, boolExcludeEmpty) – Boolean (true/false)
  • date (dateFrom, dateThru) – DateTime, but renders as date only
  • dateTime (dateTimeTestedOn, dateTimeExactDate) – DateTime, renders as date and time
  • time (timeFrom, timeThru) – DateTime, but renders as time only control
  • file (fileUpload, fileAttachment) – Trestle IFile interface type, renders as file upload control

When Trestle renders the parameter collection popup, it automatically labels the controls as you would expect, e.g. strArgOne becomes Arg One, numArgTwo becomes Arg Two, etc.

Ok, enter some values in those controls, then press the Run button. You should get back a popup with a message reflecting all the values you entered:

Command Function Argument Defaults

The Dino language allows function parameters to have a default value. Providing a default value for a parameter in a standard Dino function looks like this:

def foo(x, y, z=1) {
return (x + y) * z;
}

// call site...
var value = foo(3, 4); // z arg left off
assert(value == 7); // ok
value = foo(3, 4, 2); // z arg included
assert(value == 14); // ok

This is fine for standard functions, but with command functions, we want more control over the default values, and it would also be nice to provide meta information like selection lists, help strings, and the like. This is handled in command functions with a parameter declaration section. This section uses the $$ delimiters. Enter the following into the Dino Cookbook script:

/**
Command function demonstrating parameter declaration section.
*/
def cmdThirdCommand(strArgOne, intArgTwo, dateArgThree, boolArgFour) {
$$
<param name="strArgOne"
value="Hello, World"
help="Enter a message here" />
<param name="intArgTwo"
value="5"
selections="1,2,3,4,5,6,7,8,9,10"
help="Select a value between 1 and 10" />
<param name="dateArgThree"
value="2000-01-01"
help="Enter a past date" />
<param name="boolArgFour"
value="true"
help="Check the box if you want it to be true" />
$$


return string.Format(
$$
You entered:
A string with the value of {0},
a number with the value of {1},
a date with the value of {2},
a bool (true/false) with the value of {3}.
$$, strArgOne, intArgTwo, dateArgThree, boolArgFour);
}

After entering the code, don't forget to go to the Commands tab and add the corresponding command record.

This function is identical to cmdSecondCommand, except that we have added the parameter declaration section. This section must show up on the first line following the function declaration (the first line of code of the function which contains the name and parameters), inside the first curly brace that starts the function contents. Here are the requirements for this section:

  • It must begin on the first line after the opening curly brace.
  • It must begin with a $$ on a line by itself.
  • For each function parameter:
    • Enter an XML-style element that opens with <param
    • Enter a name attribute, e.g. name="strMyArg" (required)
    • Enter a value attribute, if you want to provide a default, e.g. value="3"
    • Enter a help attribute, if you want to show a help string
    • Enter a display attribute, if you want to label the parameter yourself
    • Enter a selections attribute, if you want to show a drop-down list
      • selections="abc,def,123,Hello World"
      • Selections inside the value string are comma-separated.
    • Enter a multiple="true" attribute/value if you are showing selections (or a file input) and want the user to be able to make more than one selection.
    • Close the element with />
  • It is NOT required that you have a param element for each parameter. Only those parameters that you want to affect need to be included.
  • The format of the <param /> element itself does not matter. All attributes may be on the same line, or it may be formatted to be more readable, as we have done above.
  • It must end with $$ on a line by itself. Do not include a semicolon!

Advanced Parameter Declarations

So far, the default arguments we provided in the parameter declaration section were all hard-coded, there is no way to change the values that appear when the argument collection popup appears. For example, our number selection list for numArgTwo will always show the values 1 through 10. It would be nice if we could respond to the environment to provide things like default values and selection lists, and Trestle does allow for that.

The value, help, and selections attributes of the param default element can get their values from a no-parameter function that is defined in Dino. A no-parameter function is one that takes no arguments:

def noParams() {
return "This function takes no arguments.";
}

Enter the following into the Dino Cookbook.

private var _callCount = 0;

private def _getNumberSelections() {
var nums = list[int]();
repeat i _callCount + 1 {
nums.Add(i);
}

return nums;
}

private def _getNumberValue() {
return _callCount;
}

private def _getNumberHelp() {
return string.Format('Select a number between 0 and {0}', _callCount);
}

/**
Command function demonstrating dynamic parameter defaults.
*/
def cmdFourthCommand(strArgOne, intArgTwo, dateArgThree, boolArgFour) {
$$
<param name="strArgOne"
value="Hello, World"
help="Enter a message here" />
<param name="intArgTwo"
value="_getNumberValue()"
selections="_getNumberSelections()"
help="_getNumberHelp()"
/>
<param name="dateArgThree"
value="2000-01-01"
help="Enter a past date" />
<param name="boolArgFour"
value="true"
help="Check the box if you want it to be true" />
$$

//
// Increment the script-level counter variable.
//
_callCount++;

return string.Format(
$$
You entered:
A string with the value of {0},
a number with the value of {1},
a date with the value of {2},
a bool (true/false) with the value of {3}.
$$, strArgOne, intArgTwo, dateArgThree, boolArgFour);
}

After this, go to the Commands tab, add the command record, then go to the System Log list page to run the command.

Pay attention to the Arg Two dropdown list. It should have a single entry with a 0, and the selected value should also be set to 0. Press the Run button.

Now, instead of pressing the Close button, choose the Run Again button. You should see that our selections and our default value for Arg Two have changed. We now have two items in our drop-down list, and the default value is 1.

This happens because every time we run the cmdFourthCommand function, we are incrementing a counter variable, and then using that to populate the drop-down list when it is displayed. This is obviously a useless and contrived example, but we will be demonstrating far more useful examples of this behavior.

Aside: Script-Level Variable Lifetime

What is the lifetime of a script-level variable like _callCount in our example? Script-level variables are any variable or constant declared outside of a function body. Their value will last until the script record is modified and saved. At the point of saving, the variable will be reset to its declared value, in this case, 0. Keep in mind also that script-level variables are shared state, that is, every user who is running this script is accessing the same one. We'll see how to get around this limitation later in Storing the User's Previous Entries.

How did we do?

A: Host and Target

A: Creating/Running a Command

Contact