Browse Source

Fix command classes formatting

pull/8/head
Anton Tarasenko 2 years ago
parent
commit
187e69eedc
  1. 237
      sources/Commands/BuiltInCommands/ACommandHelp.uc
  2. 3
      sources/Commands/Command.uc
  3. 2
      sources/Commands/CommandParser.uc
  4. 2
      sources/Commands/Commands.uc
  5. 2
      sources/Commands/Commands_Feature.uc
  6. 2
      sources/Commands/PlayersParser.uc

237
sources/Commands/BuiltInCommands/ACommandHelp.uc

@ -20,7 +20,7 @@
class ACommandHelp extends Command
dependson(LoggerAPI);
// For each key (given by lower case command name) stores another `HashMap`
// For each key (given by lower case command name) stores another `HashMap`
// that uses sub-command names as keys and returns `ArrayList` of aliases.
var private HashTable commandToAliasesMap;
@ -33,15 +33,19 @@ var public const int TBOOLEAN_TRUE_FALSE, TBOOLEAN_ENABLE_DISABLE;
var public const int TBOOLEAN_ON_OFF, TBOOLEAN_YES_NO;
var public const int TOPTIONS, TCMD_WITH_TARGET, TCMD_WITHOUT_TARGET;
var public const int TSEPARATOR, TLIST_REGIRESTED_CMDS, TEMPTY_GROUP;
var public const int TALIASES_FOR, TEMPTY;
var public const int TALIASES_FOR, TEMPTY, TDOT;
protected function Constructor()
{
local Feature preenabledInstance;
super.Constructor();
if (class'Aliases_Feature'.static.GetEnabledInstance() != none) {
ReloadCommandAliases();
}
_.environment.OnFeatureEnabled(self).connect = HandleFeatureEnabled;
// We need to update aliases map every time aliases feature is reenabled
_.environment.OnFeatureEnabled(self).connect = FillCommandToAliasesMap;
// If `Aliases_Feature` is already enabled - read its command aliases now
preenabledInstance = class'Aliases_Feature'.static.GetEnabledInstance();
FillCommandToAliasesMap(Aliases_Feature(preenabledInstance));
_.memory.Free(preenabledInstance);
}
protected function Finalizer()
@ -71,8 +75,9 @@ protected function BuildData(CommandDataBuilder builder)
protected function Executed(Command.CallData callData, EPlayer callerPlayer)
{
local HashTable parameters, options;;
local HashTable parameters, options;
local ArrayList commandsToDisplay, commandGroupsToDisplay;
parameters = callData.parameters;
options = callData.options;
// Print command list if "--list" option was specified
@ -97,42 +102,45 @@ protected function Executed(Command.CallData callData, EPlayer callerPlayer)
}
}
private final function HandleFeatureEnabled(Feature enabledFeature)
// If instance of the `Aliases_Feature` is passed as an argument (allowing this
// method to be used as a slot for `OnFeatureEnabled` signal) and
// `commandAliasSource` is available - empties current `commandToAliasesMap`
// and refills it with available command aliases.
private final function FillCommandToAliasesMap(Feature enabledFeature)
{
local int i;
local Text aliasValue;
local array<Text> availableAliases;
local BaseAliasSource commandAliasSource;
local MutableText commandName, subcommandName;
if (enabledFeature == none) return;
if (enabledFeature.class != class'Aliases_Feature') return;
commandAliasSource = _.alias.GetCommandSource();
if (commandAliasSource == none) return;
ReloadCommandAliases();
}
private final function ReloadCommandAliases()
{
local int i;
local Text aliasValue;
local array<Text> availableAliases;
local BaseAliasSource commandAliasSource;
local MutableText commandName, subcommandName;
// Drop map built by previous aliases (if it was even build up until now)
_.memory.Free(commandToAliasesMap);
commandToAliasesMap = _.collections.EmptyHashTable();
commandAliasSource = _.alias.GetCommandSource();
if (commandAliasSource == none) {
return;
}
// Construct a command -> alias map by iterating over aliases
availableAliases = commandAliasSource.GetAllAliases();
for (i = 0; i < availableAliases.length; i += 1)
{
aliasValue = _.alias.ResolveCommand(availableAliases[i]);
ParseCommandNames(aliasValue, commandName, subcommandName);
InsertIntoMap(commandName, subcommandName, availableAliases[i]);
aliasValue.FreeSelf();
InsertIntoAliasesMap(commandName, subcommandName, availableAliases[i]);
commandName.FreeSelf();
subcommandName.FreeSelf();
aliasValue.FreeSelf();
}
// Clean up
_.memory.FreeMany(availableAliases);
commandAliasSource.FreeSelf();
}
// Breaks command name as it is intended to be specified in command aliases
// ("<command>" or "<command>.<subcommand>") into command and subcommand,
// returning both as `out` parameters.
private final function ParseCommandNames(
BaseText source,
out MutableText commandName,
@ -148,14 +156,14 @@ private final function ParseCommandNames(
}
valueParser = source.Parse();
subcommandName = valueParser
.MUntil(commandName, _.text.GetCharacter("."))
.MatchS(".")
.MUntil(commandName, T(TDOT).GetCharacter(0))
.Match(T(TDOT))
.GetRemainderM();
_.memory.Free(valueParser);
}
// Assumes that `commandToAliasesMap` and its arguments are not `none`
private final function InsertIntoMap(
// Assumes that `commandToAliasesMap` and its arguments are not `none`.
private final function InsertIntoAliasesMap(
BaseText commandName,
BaseText subcommandName,
BaseText alias)
@ -224,7 +232,7 @@ private final function DisplayCommandLists(
else {
callerConsole.WriteLine(groupsNames[i]);
}
DisplayCommandsNamesArray(
PrintCommandsNamesArray(
commandsFeature,
commandNames,
displayAliases);
@ -232,9 +240,10 @@ private final function DisplayCommandLists(
}
}
_.memory.FreeMany(groupsNames);
commandsFeature.FreeSelf();
}
private final function DisplayCommandsNamesArray(
private final function PrintCommandsNamesArray(
Commands_Feature commandsFeature,
array<Text> commandsNamesArray,
bool displayAliases)
@ -256,13 +265,13 @@ private final function DisplayCommandsNamesArray(
.Write(T(TCOLON_SPACE))
.WriteLine(nextData.summary);
if (displayAliases) {
DisplayCommandAliases(nextData.name);
PrintCommandAliases(nextData.name);
}
_.memory.Free(nextCommand);
}
}
private final function DisplayCommandAliases(BaseText commandName)
private final function PrintCommandAliases(BaseText commandName)
{
local CollectionIterator iter;
local Text commandKey;
@ -279,10 +288,9 @@ private final function DisplayCommandAliases(BaseText commandName)
if (subCommandToAliasesMap == none) {
return;
}
//callerConsole.WriteBlock(T(TALIASES));
// Display aliases to command itself first
nextAliasesArray = subCommandToAliasesMap.GetArrayList(T(TEMPTY));
DisplayAliasesArray(commandName, none, nextAliasesArray);
PrintAliasesArray(commandName, none, nextAliasesArray);
_.memory.Free(nextAliasesArray);
// Then aliases to all of its subcommands, in no particular order
iter = subCommandToAliasesMap.Iterate();
@ -296,7 +304,7 @@ private final function DisplayCommandAliases(BaseText commandName)
continue;
}
nextAliasesArray = ArrayList(iter.Get());
DisplayAliasesArray(commandName, nextSubCommand, nextAliasesArray);
PrintAliasesArray(commandName, nextSubCommand, nextAliasesArray);
_.memory.Free(nextAliasesArray);
_.memory.Free(nextSubCommand);
iter.Next();
@ -304,7 +312,7 @@ private final function DisplayCommandAliases(BaseText commandName)
iter.FreeSelf();
}
private final function DisplayAliasesArray(
private final function PrintAliasesArray(
BaseText commandName,
BaseText subcommandName,
ArrayList aliasesArray)
@ -343,95 +351,100 @@ private final function DisplayAliasesArray(
private final function DisplayCommandHelpPages(ArrayList commandList)
{
local int i;
local Text nextCommandName, nextCommandValue;
local bool printedSomething;
local Text nextUserProvidedName;
local MutableText referredSubcommand;
local Command nextCommand;
local Commands_Feature commandsFeature;
local MutableText parsedCommandName, parsedSubcommandName;
commandsFeature =
Commands_Feature(class'Commands_Feature'.static.GetEnabledInstance());
if (commandsFeature == none) {
return;
}
// If arguments were empty - at least display our own help page
if (commandList == none)
{
PrintHelpPage(BorrowData());
PrintHelpPageFor(BorrowData().name, none, BorrowData());
return;
}
// Otherwise - print help for specified commands
for (i = 0; i < commandList.GetLength(); i += 1)
{
// Try normal command name
nextCommandName = commandList.GetText(i);
nextCommand = commandsFeature.GetCommand(nextCommandName);
// Try command alias
if (nextCommand == none)
{
nextCommandValue = _.alias.ResolveCommand(nextCommandName);
ParseCommandNames(
nextCommandValue,
parsedCommandName,
parsedSubcommandName);
nextCommand = commandsFeature.GetCommand(parsedCommandName);
_.memory.Free(nextCommandValue);
_.memory.Free(parsedCommandName);
}
if (nextCommand == none)
{
_.memory.Free(nextCommandName);
continue;
}
if (i > 0) {
callerConsole.WriteLine(T(TSEPARATOR));
}
if (parsedSubcommandName == none) {
PrintHelpPage(nextCommand.BorrowData());
}
else
nextUserProvidedName = commandList.GetText(i);
nextCommand = GetCommandFromUserProvidedName(
nextUserProvidedName,
referredSubcommand);
if (nextCommand != none)
{
if (printedSomething) {
callerConsole.WriteLine(T(TSEPARATOR));
}
PrintHelpPageFor(
nextCommand.BorrowData(),
nextCommandName,
parsedSubcommandName);
nextUserProvidedName,
referredSubcommand,
nextCommand.BorrowData());
printedSomething = true;
}
_.memory.Free(nextCommand);
_.memory.Free(parsedSubcommandName);
_.memory.Free(nextCommandName);
parsedSubcommandName = none;
_.memory.Free(nextUserProvidedName);
_.memory.Free(referredSubcommand);
// `referredSubcommand` is passed as an `out` parameter on
// every iteration, so we need to prevent the possibility of its value
// being used.
// NOTE: `nextCommand` and `nextUserProvidedName` are just
// rewritten.
referredSubcommand = none;
}
}
// Following methods are mostly self-explanatory
private final function PrintHelpPage(Command.Data data)
// Returns `Command` based on the name, given by user.
// `referredSubcommand` is always overwritten (freed if non-`none` value
// is passed) and is used to return name of the subcommand for returned
// `Command` that is specified by `nextUserProvidedName` (only relevant for
// aliases that refer to a particular subcommand).
private final function Command GetCommandFromUserProvidedName(
BaseText nextUserProvidedName,
out MutableText referredSubcommand)
{
local Text commandNameLowerCase, commandNameUpperCase;
// Get capitalized command name
commandNameUpperCase = data.name.UpperCopy();
// Print header: name + basic info
callerConsole.UseColor(_.color.textHeader)
.Write(commandNameUpperCase)
.UseColor(_.color.textDefault);
commandNameUpperCase.FreeSelf();
if (data.requiresTarget) {
callerConsole.WriteLine(T(TCMD_WITH_TARGET));
local Command result;
local Text commandAliasValue;
local Commands_Feature commandsFeature;
local MutableText parsedCommandName;
// Clear `out` parameter no matter what
if (referredSubcommand != none)
{
referredSubcommand.FreeSelf();
referredSubcommand = none;
}
else {
callerConsole.WriteLine(T(TCMD_WITHOUT_TARGET));
// Try accessing (check availability of) `Commands_Feature`
commandsFeature =
Commands_Feature(class'Commands_Feature'.static.GetEnabledInstance());
if (commandsFeature == none) {
return none;
}
// Print commands and options
commandNameLowerCase = data.name.LowerCopy();
PrintCommands(data, commandNameLowerCase, none);
commandNameLowerCase.FreeSelf();
PrintOptions(data);
// Clean up
callerConsole.ResetColor().Flush();
// Try getting command using `nextUserProvidedName` as a literal name
result = commandsFeature.GetCommand(nextUserProvidedName);
if (result != none)
{
commandsFeature.FreeSelf();
return result;
}
// On failure - try resolving it as an alias
commandAliasValue = _.alias.ResolveCommand(nextUserProvidedName);
ParseCommandNames(commandAliasValue, parsedCommandName, referredSubcommand);
result = commandsFeature.GetCommand(parsedCommandName);
// Empty subcommand name from the alias is essentially no subcommand name
if (referredSubcommand != none && referredSubcommand.IsEmpty())
{
referredSubcommand.FreeSelf();
referredSubcommand = none;
}
_.memory.Free(commandAliasValue);
_.memory.Free(parsedCommandName);
commandsFeature.FreeSelf();
return result;
}
private final function PrintHelpPageFor(
Command.Data data,
BaseText commandAlias,
BaseText usedSubcommand)
BaseText referredSubcommand,
Command.Data commandData)
{
local Text commandNameLowerCase, commandNameUpperCase;
// Get capitalized command name
@ -441,7 +454,7 @@ private final function PrintHelpPageFor(
.Write(commandNameUpperCase)
.UseColor(_.color.textDefault);
commandNameUpperCase.FreeSelf();
if (data.requiresTarget) {
if (commandData.requiresTarget) {
callerConsole.WriteLine(T(TCMD_WITH_TARGET));
}
else {
@ -449,9 +462,9 @@ private final function PrintHelpPageFor(
}
// Print commands and options
commandNameLowerCase = commandAlias.LowerCopy();
PrintCommands(data, commandNameLowerCase, usedSubcommand);
PrintCommands(commandData, commandNameLowerCase, referredSubcommand);
commandNameLowerCase.FreeSelf();
PrintOptions(data);
PrintOptions(commandData);
// Clean up
callerConsole.ResetColor().Flush();
}
@ -459,23 +472,21 @@ private final function PrintHelpPageFor(
private final function PrintCommands(
Command.Data data,
BaseText commandName,
BaseText filterSubcommandName)
BaseText referredSubcommand)
{
local int i;
local array<SubCommand> subCommands;
if (filterSubcommandName != none && filterSubcommandName.IsEmpty()) {
filterSubcommandName = none;
}
subCommands = data.subCommands;
for (i = 0; i < subCommands.length; i += 1)
{
if ( filterSubcommandName == none
|| filterSubcommandName.Compare(subCommands[i].name))
if ( referredSubcommand == none
|| referredSubcommand.Compare(subCommands[i].name))
{
PrintSubCommand(
subCommands[i],
commandName,
filterSubcommandName != none);
referredSubcommand != none);
}
}
}
@ -657,4 +668,6 @@ defaultproperties
stringConstants(20) = "Aliases for"
TEMPTY = 21
stringConstants(21) = ""
TDOT = 22
stringConstants(22) = "."
}

3
sources/Commands/Command.uc

@ -6,7 +6,7 @@
* `Executed()` is called first, whenever command is executed and
* `ExecuteFor()` is called only for targeted commands, once for each
* targeted player.
* Copyright 2021 - 2022 Anton Tarasenko
* Copyright 2021-2022 Anton Tarasenko
*------------------------------------------------------------------------------
* This file is part of Acedia.
*
@ -605,7 +605,6 @@ public final function Text GetGroupName()
return commandData.group.LowerCopy();
}
// TODO: use `SharedRef` instead
/**
* Returns `Command.Data` struct that describes caller `Command`.
*

2
sources/Commands/CommandParser.uc

@ -3,7 +3,7 @@
* a given `Command.Data`. While it's meant to be allocated for
* a `self.ParseWith()` call and deallocated right after, it can be reused
* without deallocation.
* Copyright 2021 - 2022 Anton Tarasenko
* Copyright 2021-2022 Anton Tarasenko
*------------------------------------------------------------------------------
* This file is part of Acedia.
*

2
sources/Commands/Commands.uc

@ -1,6 +1,6 @@
/**
* Config object for `Commands_Feature`.
* Copyright 2021 Anton Tarasenko
* Copyright 2021-2022 Anton Tarasenko
*------------------------------------------------------------------------------
* This file is part of Acedia.
*

2
sources/Commands/Commands_Feature.uc

@ -3,7 +3,7 @@
* parse their arguments into standard Acedia collection. It also allows to
* manage them (and specify limitation on how they can be called) in a
* centralized manner.
* Copyright 2021 - 2022 Anton Tarasenko
* Copyright 2021-2022 Anton Tarasenko
*------------------------------------------------------------------------------
* This file is part of Acedia.
*

2
sources/Commands/PlayersParser.uc

@ -1,7 +1,7 @@
/**
* Object for parsing what converting textual description of a group of
* players into array of `EPlayer`s. Depends on the game context.
* Copyright 2021 Anton Tarasenko
* Copyright 2021-2022 Anton Tarasenko
*------------------------------------------------------------------------------
* This file is part of Acedia.
*

Loading…
Cancel
Save