You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
883 lines
31 KiB
883 lines
31 KiB
4 years ago
|
/**
|
||
|
* Utility class that provides developers with a simple interface to
|
||
|
* prepare data that describes command's parameters and options.
|
||
|
* Copyright 2021 Anton Tarasenko
|
||
|
*------------------------------------------------------------------------------
|
||
|
* This file is part of Acedia.
|
||
|
*
|
||
|
* Acedia is free software: you can redistribute it and/or modify
|
||
|
* it under the terms of the GNU General Public License as published by
|
||
|
* the Free Software Foundation, version 3 of the License, or
|
||
|
* (at your option) any later version.
|
||
|
*
|
||
|
* Acedia is distributed in the hope that it will be useful,
|
||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
* GNU General Public License for more details.
|
||
|
*
|
||
|
* You should have received a copy of the GNU General Public License
|
||
|
* along with Acedia. If not, see <https://www.gnu.org/licenses/>.
|
||
|
*/
|
||
|
class CommandDataBuilder extends AcediaObject
|
||
|
dependson(Command);
|
||
|
|
||
|
/**
|
||
|
* `CommandDataBuilder` should be able to fill information about:
|
||
|
* 1. subcommands and their parameters;
|
||
|
* 2. options and their parameters.
|
||
|
* As far as user is concerned, the process of filling both should be
|
||
|
* identical. Therefore we will store all defined data in two ways:
|
||
|
* 1. Selected data: data about parameters for subcommand/option that is
|
||
|
* currently being filled;
|
||
|
* 2. Prepared data: data that was already filled as "selected data" then
|
||
|
* stored in these records. Whenever we want to switch to filling
|
||
|
* another subcommand/option or return already prepared data we must
|
||
|
* dump "selected data" into "prepared data" first and then return
|
||
|
* the latter.
|
||
|
*
|
||
|
* Overall, intended flow for creating a new sub-command or option is to
|
||
|
* select either, fill it with data with public methods `Param...()` into
|
||
|
* "selected data" and then copy it into "prepared data"
|
||
|
* (through a `RecordSelection()` method below).
|
||
|
*/
|
||
|
|
||
|
// "Prepared data"
|
||
|
var private array<Command.SubCommand> subcommands;
|
||
|
var private array<Command.Option> options;
|
||
|
var private bool requiresTarget;
|
||
|
// Auxiliary arrays signifying that we've started adding optional
|
||
|
// parameters into appropriate `subcommands` and `options`.
|
||
|
// All optional parameters must follow strictly after required parameters
|
||
|
// and so, after user have started adding optional parameters to
|
||
|
// subcommand/option, we prevent them from adding required ones
|
||
|
// (to that particular command/option).
|
||
|
var private array<byte> subcommandsIsOptional;
|
||
|
var private array<byte> optionsIsOptional;
|
||
|
|
||
|
// "Selected data"
|
||
|
// `false` means we have selected sub-command, `true` - option
|
||
|
var private bool selectedItemIsOption;
|
||
|
// `name` for sub-commands, `longName` for options
|
||
|
var private Text selectedItemName;
|
||
|
// Description of selected sub-command/option
|
||
|
var private Text selectedDescription;
|
||
|
// Are we filling optional parameters (`true`)? Or required ones (`false`)?
|
||
|
var private bool selectionIsOptional;
|
||
|
// Array of parameters we are currently filling (either required or optional)
|
||
|
var private array<Command.Parameter> selectedParameterArray;
|
||
|
|
||
|
protected function Constructor()
|
||
|
{
|
||
|
// Fill empty subcommand (no special key word) by default
|
||
|
SelectSubCommand(P(""));
|
||
|
}
|
||
|
|
||
|
protected function Finalizer()
|
||
|
{
|
||
|
subcommands.length = 0;
|
||
|
subcommandsIsOptional.length = 0;
|
||
|
options.length = 0;
|
||
|
optionsIsOptional.length = 0;
|
||
|
selectedParameterArray.length = 0;
|
||
|
selectedItemName = none;
|
||
|
selectedDescription = none;
|
||
|
requiresTarget = false;
|
||
|
selectedItemIsOption = false;
|
||
|
selectionIsOptional = false;
|
||
|
}
|
||
|
|
||
|
// Find index of sub-command with a given name `name` in `subcommands`.
|
||
|
// `-1` if there's not sub-command with such name.
|
||
|
// Case-sensitive.
|
||
|
private final function int FindSubCommandIndex(Text name)
|
||
|
{
|
||
|
local int i;
|
||
|
if (name == none) {
|
||
|
return -1;
|
||
|
}
|
||
|
for (i = 0; i < subcommands.length; i += 1)
|
||
|
{
|
||
|
if (name.Compare(subcommands[i].name)) {
|
||
|
return i;
|
||
|
}
|
||
|
}
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
// Find index of option with a given name `name` in `options`.
|
||
|
// `-1` if there's not sub-command with such name.
|
||
|
// Case-sensitive.
|
||
|
private final function int FindOptionIndex(Text longName)
|
||
|
{
|
||
|
local int i;
|
||
|
if (longName == none) {
|
||
|
return -1;
|
||
|
}
|
||
|
for (i = 0; i < options.length; i += 1)
|
||
|
{
|
||
|
if (longName.Compare(options[i].longName)) {
|
||
|
return i;
|
||
|
}
|
||
|
}
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
// Creates an empty selection record for subcommand or option with
|
||
|
// name (long name) `name`.
|
||
|
// Doe not check whether subcommand/option with that name already exists.
|
||
|
// Copies passed `name`, assumes that it is not `none`.
|
||
|
private final function MakeEmptySelection(Text name, bool selectedOption)
|
||
|
{
|
||
|
selectedItemIsOption = selectedOption;
|
||
|
selectedItemName = name.Copy();
|
||
|
selectedDescription = none;
|
||
|
selectedParameterArray.length = 0;
|
||
|
selectionIsOptional = false;
|
||
|
}
|
||
|
|
||
|
// Select sub-command with a given name `name` from `subcommands`.
|
||
|
// If there is no command with specified name `name` in prepared data -
|
||
|
// creates new record in selection, otherwise copies previously saved data.
|
||
|
// Automatically saves previously selected data into prepared data.
|
||
|
// Copies `name` if it has to create new record.
|
||
|
private final function SelectSubCommand(Text name)
|
||
|
{
|
||
|
local int subcommandIndex;
|
||
|
if (name == none) return;
|
||
|
if ( !selectedItemIsOption && selectedItemName != none
|
||
|
&& selectedItemName.Compare(name))
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
RecordSelection();
|
||
|
subcommandIndex = FindSubCommandIndex(name);
|
||
|
if (subcommandIndex < 0)
|
||
|
{
|
||
|
MakeEmptySelection(name, false);
|
||
|
return;
|
||
|
}
|
||
|
// Load appropriate prepared data, if it exists for
|
||
|
// sub-command with name `name`
|
||
|
selectedItemIsOption = false;
|
||
|
selectedItemName = subcommands[subcommandIndex].name;
|
||
|
selectedDescription = subcommands[subcommandIndex].description;
|
||
|
selectionIsOptional = subcommandsIsOptional[subcommandIndex] > 0;
|
||
|
if (selectionIsOptional) {
|
||
|
selectedParameterArray = subcommands[subcommandIndex].optional;
|
||
|
}
|
||
|
else {
|
||
|
selectedParameterArray = subcommands[subcommandIndex].required;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Select option with a given long name `longName` from `options`.
|
||
|
// If there is no option with specified `longName` in prepared data -
|
||
|
// creates new record in selection, otherwise copies previously saved data.
|
||
|
// Automatically saves previously selected data into prepared data.
|
||
|
// Copies `name` if it has to create new record.
|
||
|
private final function SelectOption(Text longName)
|
||
|
{
|
||
|
local int optionIndex;
|
||
|
if (longName == none) return;
|
||
|
if ( selectedItemIsOption && selectedItemName != none
|
||
|
&& selectedItemName.Compare(longName))
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
RecordSelection();
|
||
|
optionIndex = FindOptionIndex(longName);
|
||
|
if (optionIndex < 0)
|
||
|
{
|
||
|
MakeEmptySelection(longName, true);
|
||
|
return;
|
||
|
}
|
||
|
// Load appropriate prepared data, if it exists for
|
||
|
// option with long name `longName`
|
||
|
selectedItemIsOption = true;
|
||
|
selectedItemName = options[optionIndex].longName;
|
||
|
selectedDescription = options[optionIndex].description;
|
||
|
selectionIsOptional = optionsIsOptional[optionIndex] > 0;
|
||
|
if (selectionIsOptional) {
|
||
|
selectedParameterArray = options[optionIndex].optional;
|
||
|
}
|
||
|
else {
|
||
|
selectedParameterArray = options[optionIndex].required;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Saves currently selected data into prepared data.
|
||
|
private final function RecordSelection()
|
||
|
{
|
||
|
if (selectedItemName == none) {
|
||
|
return;
|
||
|
}
|
||
|
if (selectedItemIsOption) {
|
||
|
RecordSelectedOption();
|
||
|
}
|
||
|
else {
|
||
|
RecordSelectedSubCommand();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Saves selected sub-command into prepared records.
|
||
|
// Assumes that command and not an option is selected.
|
||
|
private final function RecordSelectedSubCommand()
|
||
|
{
|
||
|
local int selectedSubCommandIndex;
|
||
|
local Command.SubCommand newSubcommand;
|
||
|
if (selectedItemName == none) return;
|
||
|
|
||
|
selectedSubCommandIndex = FindSubCommandIndex(selectedItemName);
|
||
|
if (selectedSubCommandIndex < 0)
|
||
|
{
|
||
|
selectedSubCommandIndex = subcommands.length;
|
||
|
subcommands[selectedSubCommandIndex] = newSubcommand;
|
||
|
}
|
||
|
subcommands[selectedSubCommandIndex].name = selectedItemName;
|
||
|
subcommands[selectedSubCommandIndex].description = selectedDescription;
|
||
|
if (selectionIsOptional)
|
||
|
{
|
||
|
subcommands[selectedSubCommandIndex].optional = selectedParameterArray;
|
||
|
subcommandsIsOptional[selectedSubCommandIndex] = 1;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
subcommands[selectedSubCommandIndex].required = selectedParameterArray;
|
||
|
subcommandsIsOptional[selectedSubCommandIndex] = 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Saves currently selected option into prepared records.
|
||
|
// Assumes that option and not an command is selected.
|
||
|
private final function RecordSelectedOption()
|
||
|
{
|
||
|
local int selectedOptionIndex;
|
||
|
local Command.Option newOption;
|
||
|
if (selectedItemName == none) return;
|
||
|
|
||
|
selectedOptionIndex = FindOptionIndex(selectedItemName);
|
||
|
if (selectedOptionIndex < 0)
|
||
|
{
|
||
|
selectedOptionIndex = options.length;
|
||
|
options[selectedOptionIndex] = newOption;
|
||
|
}
|
||
|
options[selectedOptionIndex].longName = selectedItemName;
|
||
|
options[selectedOptionIndex].description = selectedDescription;
|
||
|
if (selectionIsOptional)
|
||
|
{
|
||
|
options[selectedOptionIndex].optional = selectedParameterArray;
|
||
|
optionsIsOptional[selectedOptionIndex] = 1;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
options[selectedOptionIndex].required = selectedParameterArray;
|
||
|
optionsIsOptional[selectedOptionIndex] = 0;
|
||
|
}
|
||
|
}
|
||
|
/**
|
||
|
* Method to use to start defining a new sub-command.
|
||
|
*
|
||
|
* Does two things:
|
||
|
* 1. Creates new sub-command with a given name (if it's missing);
|
||
|
* 2. Selects sub-command with name `name` to add parameters to.
|
||
|
*
|
||
|
* @param name Name of the sub-command user wants to define,
|
||
|
* case-sensitive. Variable will be copied.
|
||
|
* If `none` is passed, this method will do nothing.
|
||
|
* @return Returns the caller `CommandDataBuilder` to allow for
|
||
|
* method chaining.
|
||
|
*/
|
||
|
public final function CommandDataBuilder SubCommand(Text name)
|
||
|
{
|
||
|
SelectSubCommand(name);
|
||
|
return self;
|
||
|
}
|
||
|
|
||
|
// Validates names (printing errors in case of failure) for the option.
|
||
|
// Long name must be at least 2 characters long.
|
||
|
// Short name must be either:
|
||
|
// 1. exactly one character long;
|
||
|
// 2. `none`, which leads to deriving `shortName` from `longName`
|
||
|
// as a first character.
|
||
|
// Anything else will result in logging a failure and rejection of
|
||
|
// the option altogether.
|
||
|
// Returns `none` if validation failed and chosen short name otherwise
|
||
|
// (if `shortName` was used for it - it's value will be copied).
|
||
|
private final function Text.Character GetValidShortName(
|
||
|
Text longName,
|
||
|
Text shortName)
|
||
|
{
|
||
|
// Validate `longName`
|
||
|
if (longName == none) {
|
||
|
return _.text.GetInvalidCharacter();
|
||
|
}
|
||
|
if (longName.GetLength() < 2)
|
||
|
{
|
||
|
_.logger.Failure("Command" @ self.class @ "is trying to register"
|
||
|
@ "an option with a name that is way too short (<2 characters)."
|
||
|
@ "Option will be discarded:" @ longName.ToPlainString());
|
||
|
return _.text.GetInvalidCharacter();
|
||
|
}
|
||
|
// Validate `shortName`,
|
||
|
// deriving if from `longName` if necessary & possible
|
||
|
if (shortName == none)
|
||
|
{
|
||
|
return longName.GetCharacter(0);
|
||
|
}
|
||
|
if (shortName.IsEmpty() || shortName.GetLength() > 1)
|
||
|
{
|
||
|
_.logger.Failure("Command" @ self.class @ "is trying to register"
|
||
|
@ "an option with a short name that doesn't consist of just"
|
||
|
@ "one character. Option will be discarded:"
|
||
|
@ longName.ToPlainString());
|
||
|
return _.text.GetInvalidCharacter();
|
||
|
}
|
||
|
return shortName.GetCharacter(0);
|
||
|
}
|
||
|
|
||
|
// Checks that if any option record has a long/short name from a given pair of
|
||
|
// names (`longName`, `shortName`), then it also has another one.
|
||
|
//
|
||
|
// i.e. we cannot have several options with identical names:
|
||
|
// (--silent, -s) and (--sick, -s).
|
||
|
private final function bool VerifyNoOptionNamingConflict(
|
||
|
Text longName,
|
||
|
Text.Character shortName)
|
||
|
{
|
||
|
local int i;
|
||
|
// To make sure we will search through the up-to-date `options`,
|
||
|
// record selection into prepared records.
|
||
|
RecordSelection();
|
||
|
for (i = 0; i < options.length; i += 1)
|
||
|
{
|
||
|
// Is same long name, but different long names?
|
||
|
if ( !_.text.AreEqual(shortName, options[i].shortName)
|
||
|
&& longName.Compare(options[i].longName))
|
||
|
{
|
||
|
_ .logger.Warning("Command" @ self.class @ "is trying to register"
|
||
|
@ "several options with the same long name"
|
||
|
@ "\"" $ longName.ToPlainString()
|
||
|
$ "\", but different short names. This should not happen,"
|
||
|
@ "do not expect correct behavior.");
|
||
|
return true;
|
||
|
}
|
||
|
// Is same short name, but different short ones?
|
||
|
if ( _.text.AreEqual(shortName, options[i].shortName)
|
||
|
&& !longName.Compare(options[i].longName))
|
||
|
{
|
||
|
_.logger.Warning("Command" @ self.class @ "is trying to register"
|
||
|
@ "several options with the same short name"
|
||
|
@ "\"" $ _.text.CharacterToString(shortName)
|
||
|
$ "\", but different long names. This should not have happened,"
|
||
|
@ "do not expect correct behavior.");
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Method to use to start defining a new option.
|
||
|
*
|
||
|
* Does three things:
|
||
|
* 1. Checks if some of the recorded options are in conflict with given
|
||
|
* `longName` and `shortName` (already using one and only one of them).
|
||
|
* 2. Creates new option with a long and short names
|
||
|
* (if such option is missing);
|
||
|
* 3. Selects option with a long name `longName` to add parameters to.
|
||
|
*
|
||
|
* @param longName Long name of the option, case-sensitive
|
||
|
* (for using an option in form "--...").
|
||
|
* Must be at least two characters long. If passed value is either `none`
|
||
|
* or too short, method will log an error and omits this option.
|
||
|
* @param shortName Short name of the option, case-sensitive
|
||
|
* (for using an option in form "-...").
|
||
|
* Must be exactly one character. If `none` value is passed
|
||
|
* (or the argument altogether omitted) - uses first character of
|
||
|
* the `longName`.
|
||
|
* If `shortName` is not `none` and is not exactly 1 character long -
|
||
|
* logs an error and omits this option.
|
||
|
* @return Returns the caller `CommandDataBuilder` to allow for
|
||
|
* method chaining.
|
||
|
*/
|
||
|
public final function CommandDataBuilder Option(
|
||
|
Text longName,
|
||
|
optional Text shortName)
|
||
|
{
|
||
|
local int optionIndex;
|
||
|
local Text.Character shortNameAsCharacter;
|
||
|
// Unlike for `SubCommand()`, we need to ensure that option naming is
|
||
|
// correct and does not conflict with existing options
|
||
|
// (user might attempt to add two options with same long names and
|
||
|
// different short ones).
|
||
|
shortNameAsCharacter = GetValidShortName(longName, shortName);
|
||
|
if ( !_.text.IsValidCharacter(shortNameAsCharacter)
|
||
|
|| VerifyNoOptionNamingConflict(longName, shortNameAsCharacter))
|
||
|
{
|
||
|
// ^ `GetValidShortName()` and `VerifyNoOptionNamingConflict()`
|
||
|
// are responsible for logging warnings/errors
|
||
|
return self;
|
||
|
}
|
||
|
SelectOption(longName);
|
||
|
// Set short name for new options
|
||
|
optionIndex = FindOptionIndex(longName);
|
||
|
if (optionIndex < 0)
|
||
|
{
|
||
|
// We can only be here if option was created for the first time
|
||
|
RecordSelection();
|
||
|
// So now it cannot fail
|
||
|
optionIndex = FindOptionIndex(longName);
|
||
|
options[optionIndex].shortName = shortNameAsCharacter;
|
||
|
}
|
||
|
return self;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Adds description to the selected sub-command / option.
|
||
|
*
|
||
|
* Previous description is discarded (default description is empty).
|
||
|
*
|
||
|
* Does nothing if nothing is selected.
|
||
|
*
|
||
|
* @param description New description of selected sub-command / option.
|
||
|
* Variable will be copied.
|
||
|
* @return Returns the caller `CommandDataBuilder` to allow for
|
||
|
* method chaining.
|
||
|
*/
|
||
|
public final function CommandDataBuilder Describe(Text description)
|
||
|
{
|
||
|
if (selectedDescription == description) {
|
||
|
return self;
|
||
|
}
|
||
|
_.memory.Free(selectedDescription);
|
||
|
if (description != none) {
|
||
|
selectedDescription = description.Copy();
|
||
|
}
|
||
|
return self;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Makes caller builder to mark `Command.Data` under construction to require
|
||
|
* a player target.
|
||
|
*
|
||
|
* @return Returns the caller `CommandDataBuilder` to allow for
|
||
|
* method chaining.
|
||
|
*/
|
||
|
public final function CommandDataBuilder RequireTarget()
|
||
|
{
|
||
|
requiresTarget = true;
|
||
|
return self;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Any parameters added to currently selected sub-command / option after
|
||
|
* calling this method will be marked as optional.
|
||
|
*
|
||
|
* Further calls when the same sub-command / option is selected do nothing.
|
||
|
*
|
||
|
* @return Returns the caller `CommandDataBuilder` to allow for
|
||
|
* method chaining.
|
||
|
*/
|
||
|
public final function CommandDataBuilder OptionalParams()
|
||
|
{
|
||
|
if (selectionIsOptional) {
|
||
|
return self;
|
||
|
}
|
||
|
// Record all required parameters first, otherwise there would be no way
|
||
|
// to distinguish between them and optional parameters
|
||
|
RecordSelection();
|
||
|
selectionIsOptional = true;
|
||
|
selectedParameterArray.length = 0;
|
||
|
return self;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns data that has been constructed so far by
|
||
|
* the caller `CommandDataBuilder`.
|
||
|
*
|
||
|
* Does not reset progress.
|
||
|
*
|
||
|
* @return Returns the caller `CommandDataBuilder` to allow for
|
||
|
* method chaining.
|
||
|
*/
|
||
|
public final function Command.Data GetData()
|
||
|
{
|
||
|
local Command.Data newData;
|
||
|
RecordSelection();
|
||
|
newData.subcommands = subcommands;
|
||
|
newData.options = options;
|
||
|
newData.requiresTarget = requiresTarget;
|
||
|
return newData;
|
||
|
}
|
||
|
|
||
|
// Adds new parameter to selected sub-command / option
|
||
|
private final function PushParameter(Command.Parameter newParameter)
|
||
|
{
|
||
|
selectedParameterArray[selectedParameterArray.length] = newParameter;
|
||
|
}
|
||
|
|
||
|
// Fills `Command.ParameterType` struct with given values
|
||
|
// (except boolean format). Assumes `displayName != none`.
|
||
|
private final function Command.Parameter NewParameter(
|
||
|
Text displayName,
|
||
|
Command.ParameterType parameterType,
|
||
|
bool isListParameter,
|
||
|
optional Text variableName)
|
||
|
{
|
||
|
local Command.Parameter newParameter;
|
||
|
newParameter.displayName = displayName.Copy();
|
||
|
newParameter.type = parameterType;
|
||
|
newParameter.allowsList = isListParameter;
|
||
|
if (variableName != none) {
|
||
|
newParameter.variableName = variableName.Copy();
|
||
|
}
|
||
|
else {
|
||
|
newParameter.variableName = displayName;
|
||
|
}
|
||
|
return newParameter;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Adds new boolean parameter (required or optional depends on whether
|
||
|
* `RequireTarget()` call happened) to the currently selected
|
||
|
* sub-command / option.
|
||
|
*
|
||
|
* Only fails if provided `name` is `none`.
|
||
|
*
|
||
|
* @param name Name of the parameter, will be copied
|
||
|
* (as it would appear in the generated help info).
|
||
|
*
|
||
|
* @param format Preferred format of boolean values.
|
||
|
* Command parser will still accept boolean values in any form,
|
||
|
* this setting only affects how parameter will be displayed in
|
||
|
* generated help.
|
||
|
* @param variableName Name of the variable that will store this
|
||
|
* parameter's value in `AssociativeArray` after user's command input
|
||
|
* is parsed. Provided value will be copied.
|
||
|
* If left `none`, - will coincide with `name` parameter.
|
||
|
* @return Returns the caller `CommandDataBuilder` to allow for
|
||
|
* method chaining.
|
||
|
*/
|
||
|
public final function CommandDataBuilder ParamBoolean(
|
||
|
Text name,
|
||
|
optional Command.PreferredBooleanFormat format,
|
||
|
optional Text variableName)
|
||
|
{
|
||
|
local Command.Parameter newParam;
|
||
|
if (name == none) {
|
||
|
return self;
|
||
|
}
|
||
|
newParam = NewParameter(name, CPT_Boolean, false, variableName);
|
||
|
newParam.booleanFormat = format;
|
||
|
PushParameter(newParam);
|
||
|
return self;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Adds new boolean list parameter (required or optional depends on whether
|
||
|
* `RequireTarget()` call happened) to the currently selected
|
||
|
* sub-command / option.
|
||
|
*
|
||
|
* Only fails if provided `name` is `none`.
|
||
|
*
|
||
|
* @param name Name of the parameter, will be copied
|
||
|
* (as it would appear in the generated help info).
|
||
|
* @param format Preferred format of boolean values.
|
||
|
* Command parser will still accept boolean values in any form,
|
||
|
* this setting only affects how parameter will be displayed in
|
||
|
* generated help.
|
||
|
* @param variableName Name of the variable that will store this
|
||
|
* parameter's value in `AssociativeArray` after user's command input
|
||
|
* is parsed. Provided value will be copied.
|
||
|
* If left `none`, - will coincide with `name` parameter.
|
||
|
* @return Returns the caller `CommandDataBuilder` to allow for
|
||
|
* method chaining.
|
||
|
*/
|
||
|
public final function CommandDataBuilder ParamBooleanList(
|
||
|
Text name,
|
||
|
optional Command.PreferredBooleanFormat format,
|
||
|
optional Text variableName)
|
||
|
{
|
||
|
local Command.Parameter newParam;
|
||
|
if (name == none) {
|
||
|
return self;
|
||
|
}
|
||
|
newParam = NewParameter(name, CPT_Boolean, true, variableName);
|
||
|
newParam.booleanFormat = format;
|
||
|
PushParameter(newParam);
|
||
|
return self;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Adds new integer parameter (required or optional depends on whether
|
||
|
* `RequireTarget()` call happened) to the currently selected
|
||
|
* sub-command / option.
|
||
|
*
|
||
|
* Only fails if provided `name` is `none`.
|
||
|
*
|
||
|
* @param name Name of the parameter, will be copied
|
||
|
* (as it would appear in the generated help info).
|
||
|
* @param variableName Name of the variable that will store this
|
||
|
* parameter's value in `AssociativeArray` after user's command input
|
||
|
* is parsed. Provided value will be copied.
|
||
|
* If left `none`, - will coincide with `name` parameter.
|
||
|
* @return Returns the caller `CommandDataBuilder` to allow for
|
||
|
* method chaining.
|
||
|
*/
|
||
|
public final function CommandDataBuilder ParamInteger(
|
||
|
Text name,
|
||
|
optional Text variableName)
|
||
|
{
|
||
|
if (name == none) {
|
||
|
return self;
|
||
|
}
|
||
|
PushParameter(NewParameter(name, CPT_Integer, false, variableName));
|
||
|
return self;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Adds new integer list parameter (required or optional depends on whether
|
||
|
* `RequireTarget()` call happened) to the currently selected
|
||
|
* sub-command / option.
|
||
|
*
|
||
|
* Only fails if provided `name` is `none`.
|
||
|
*
|
||
|
* @param name Name of the parameter, will be copied
|
||
|
* (as it would appear in the generated help info).
|
||
|
* @param variableName Name of the variable that will store this
|
||
|
* parameter's value in `AssociativeArray` after user's command input
|
||
|
* is parsed. Provided value will be copied.
|
||
|
* If left `none`, - will coincide with `name` parameter.
|
||
|
* @return Returns the caller `CommandDataBuilder` to allow for
|
||
|
* method chaining.
|
||
|
*/
|
||
|
public final function CommandDataBuilder ParamIntegerList(
|
||
|
Text name,
|
||
|
optional Text variableName)
|
||
|
{
|
||
|
if (name == none) {
|
||
|
return self;
|
||
|
}
|
||
|
PushParameter(NewParameter(name, CPT_Integer, true, variableName));
|
||
|
return self;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Adds new numeric parameter (required or optional depends on whether
|
||
|
* `RequireTarget()` call happened) to the currently selected
|
||
|
* sub-command / option.
|
||
|
*
|
||
|
* Only fails if provided `name` is `none`.
|
||
|
*
|
||
|
* @param name Name of the parameter, will be copied
|
||
|
* (as it would appear in the generated help info).
|
||
|
* @param variableName Name of the variable that will store this
|
||
|
* parameter's value in `AssociativeArray` after user's command input
|
||
|
* is parsed. Provided value will be copied.
|
||
|
* If left `none`, - will coincide with `name` parameter.
|
||
|
* @return Returns the caller `CommandDataBuilder` to allow for
|
||
|
* method chaining.
|
||
|
*/
|
||
|
public final function CommandDataBuilder ParamNumber(
|
||
|
Text name,
|
||
|
optional Text variableName)
|
||
|
{
|
||
|
if (name == none) {
|
||
|
return self;
|
||
|
}
|
||
|
PushParameter(NewParameter(name, CPT_Number, false, variableName));
|
||
|
return self;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Adds new numeric list parameter (required or optional depends on whether
|
||
|
* `RequireTarget()` call happened) to the currently selected
|
||
|
* sub-command / option.
|
||
|
*
|
||
|
* Only fails if provided `name` is `none`.
|
||
|
*
|
||
|
* @param name Name of the parameter, will be copied
|
||
|
* (as it would appear in the generated help info).
|
||
|
* @param variableName Name of the variable that will store this
|
||
|
* parameter's value in `AssociativeArray` after user's command input
|
||
|
* is parsed. Provided value will be copied.
|
||
|
* If left `none`, - will coincide with `name` parameter.
|
||
|
* @return Returns the caller `CommandDataBuilder` to allow for
|
||
|
* method chaining.
|
||
|
*/
|
||
|
public final function CommandDataBuilder ParamNumberList(
|
||
|
Text name,
|
||
|
optional Text variableName)
|
||
|
{
|
||
|
if (name == none) {
|
||
|
return self;
|
||
|
}
|
||
|
PushParameter(NewParameter(name, CPT_Number, true, variableName));
|
||
|
return self;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Adds new text parameter (required or optional depends on whether
|
||
|
* `RequireTarget()` call happened) to the currently selected
|
||
|
* sub-command / option.
|
||
|
*
|
||
|
* Only fails if provided `name` is `none`.
|
||
|
*
|
||
|
* @param name Name of the parameter, will be copied
|
||
|
* (as it would appear in the generated help info).
|
||
|
* @param variableName Name of the variable that will store this
|
||
|
* parameter's value in `AssociativeArray` after user's command input
|
||
|
* is parsed. Provided value will be copied.
|
||
|
* If left `none`, - will coincide with `name` parameter.
|
||
|
* @return Returns the caller `CommandDataBuilder` to allow for
|
||
|
* method chaining.
|
||
|
*/
|
||
|
public final function CommandDataBuilder ParamText(
|
||
|
Text name,
|
||
|
optional Text variableName)
|
||
|
{
|
||
|
if (name == none) {
|
||
|
return self;
|
||
|
}
|
||
|
PushParameter(NewParameter(name, CPT_Text, false, variableName));
|
||
|
return self;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Adds new text list parameter (required or optional depends on whether
|
||
|
* `RequireTarget()` call happened) to the currently selected
|
||
|
* sub-command / option.
|
||
|
*
|
||
|
* Only fails if provided `name` is `none`.
|
||
|
*
|
||
|
* @param name Name of the parameter, will be copied
|
||
|
* (as it would appear in the generated help info).
|
||
|
* @param variableName Name of the variable that will store this
|
||
|
* parameter's value in `AssociativeArray` after user's command input
|
||
|
* is parsed. Provided value will be copied.
|
||
|
* If left `none`, - will coincide with `name` parameter.
|
||
|
* @return Returns the caller `CommandDataBuilder` to allow for
|
||
|
* method chaining.
|
||
|
*/
|
||
|
public final function CommandDataBuilder ParamTextList(
|
||
|
Text name,
|
||
|
optional Text variableName)
|
||
|
{
|
||
|
if (name == none) {
|
||
|
return self;
|
||
|
}
|
||
|
PushParameter(NewParameter(name, CPT_Text, true, variableName));
|
||
|
return self;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Adds new object parameter (required or optional depends on whether
|
||
|
* `RequireTarget()` call happened) to the currently selected
|
||
|
* sub-command / option.
|
||
|
*
|
||
|
* Only fails if provided `name` is `none`.
|
||
|
*
|
||
|
* @param name Name of the parameter, will be copied
|
||
|
* (as it would appear in the generated help info).
|
||
|
* @param variableName Name of the variable that will store this
|
||
|
* parameter's value in `AssociativeArray` after user's command input
|
||
|
* is parsed. Provided value will be copied.
|
||
|
* If left `none`, - will coincide with `name` parameter.
|
||
|
* @return Returns the caller `CommandDataBuilder` to allow for
|
||
|
* method chaining.
|
||
|
*/
|
||
|
public final function CommandDataBuilder ParamObject(
|
||
|
Text name,
|
||
|
optional Text variableName)
|
||
|
{
|
||
|
if (name == none) {
|
||
|
return self;
|
||
|
}
|
||
|
PushParameter(NewParameter(name, CPT_Object, false, variableName));
|
||
|
return self;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Adds new parameter for list of objects (required or optional depends on
|
||
|
* whether `RequireTarget()` call happened) to the currently selected
|
||
|
* sub-command / option.
|
||
|
*
|
||
|
* Only fails if provided `name` is `none`.
|
||
|
*
|
||
|
* @param name Name of the parameter, will be copied
|
||
|
* (as it would appear in the generated help info).
|
||
|
* @param variableName Name of the variable that will store this
|
||
|
* parameter's value in `AssociativeArray` after user's command input
|
||
|
* is parsed. Provided value will be copied.
|
||
|
* If left `none`, - will coincide with `name` parameter.
|
||
|
* @return Returns the caller `CommandDataBuilder` to allow for
|
||
|
* method chaining.
|
||
|
*/
|
||
|
public final function CommandDataBuilder ParamObjectList(
|
||
|
Text name,
|
||
|
optional Text variableName)
|
||
|
{
|
||
|
if (name == none) {
|
||
|
return self;
|
||
|
}
|
||
|
PushParameter(NewParameter(name, CPT_Object, true, variableName));
|
||
|
return self;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Adds new array parameter (required or optional depends on whether
|
||
|
* `RequireTarget()` call happened) to the currently selected
|
||
|
* sub-command / option.
|
||
|
*
|
||
|
* Only fails if provided `name` is `none`.
|
||
|
*
|
||
|
* @param name Name of the parameter, will be copied
|
||
|
* (as it would appear in the generated help info).
|
||
|
* @param variableName Name of the variable that will store this
|
||
|
* parameter's value in `AssociativeArray` after user's command input
|
||
|
* is parsed. Provided value will be copied.
|
||
|
* If left `none`, - will coincide with `name` parameter.
|
||
|
* @return Returns the caller `CommandDataBuilder` to allow for
|
||
|
* method chaining.
|
||
|
*/
|
||
|
public final function CommandDataBuilder ParamArray(
|
||
|
Text name,
|
||
|
optional Text variableName)
|
||
|
{
|
||
|
if (name == none) {
|
||
|
return self;
|
||
|
}
|
||
|
PushParameter(NewParameter(name, CPT_Array, false, variableName));
|
||
|
return self;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Adds new parameter for list of arrays (required or optional depends on
|
||
|
* whether `RequireTarget()` call happened) to the currently selected
|
||
|
* sub-command / option.
|
||
|
*
|
||
|
* Only fails if provided `name` is `none`.
|
||
|
*
|
||
|
* @param name Name of the parameter, will be copied
|
||
|
* (as it would appear in the generated help info).
|
||
|
* @param variableName Name of the variable that will store this
|
||
|
* parameter's value in `AssociativeArray` after user's command input
|
||
|
* is parsed. Provided value will be copied.
|
||
|
* If left `none`, - will coincide with `name` parameter.
|
||
|
* @return Returns the caller `CommandDataBuilder` to allow for
|
||
|
* method chaining.
|
||
|
*/
|
||
|
public final function CommandDataBuilder ParamArrayList(
|
||
|
Text name,
|
||
|
optional Text variableName)
|
||
|
{
|
||
|
if (name == none) {
|
||
|
return self;
|
||
|
}
|
||
|
PushParameter(NewParameter(name, CPT_Array, true, variableName));
|
||
|
return self;
|
||
|
}
|
||
|
|
||
|
defaultproperties
|
||
|
{
|
||
|
}
|