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 class ACommandHelp extends Command
dependson(LoggerAPI); 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. // that uses sub-command names as keys and returns `ArrayList` of aliases.
var private HashTable commandToAliasesMap; 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 TBOOLEAN_ON_OFF, TBOOLEAN_YES_NO;
var public const int TOPTIONS, TCMD_WITH_TARGET, TCMD_WITHOUT_TARGET; 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 TSEPARATOR, TLIST_REGIRESTED_CMDS, TEMPTY_GROUP;
var public const int TALIASES_FOR, TEMPTY; var public const int TALIASES_FOR, TEMPTY, TDOT;
protected function Constructor() protected function Constructor()
{ {
local Feature preenabledInstance;
super.Constructor(); super.Constructor();
if (class'Aliases_Feature'.static.GetEnabledInstance() != none) { // We need to update aliases map every time aliases feature is reenabled
ReloadCommandAliases(); _.environment.OnFeatureEnabled(self).connect = FillCommandToAliasesMap;
} // If `Aliases_Feature` is already enabled - read its command aliases now
_.environment.OnFeatureEnabled(self).connect = HandleFeatureEnabled; preenabledInstance = class'Aliases_Feature'.static.GetEnabledInstance();
FillCommandToAliasesMap(Aliases_Feature(preenabledInstance));
_.memory.Free(preenabledInstance);
} }
protected function Finalizer() protected function Finalizer()
@ -71,8 +75,9 @@ protected function BuildData(CommandDataBuilder builder)
protected function Executed(Command.CallData callData, EPlayer callerPlayer) protected function Executed(Command.CallData callData, EPlayer callerPlayer)
{ {
local HashTable parameters, options;; local HashTable parameters, options;
local ArrayList commandsToDisplay, commandGroupsToDisplay; local ArrayList commandsToDisplay, commandGroupsToDisplay;
parameters = callData.parameters; parameters = callData.parameters;
options = callData.options; options = callData.options;
// Print command list if "--list" option was specified // 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 == none) return;
if (enabledFeature.class != class'Aliases_Feature') return; if (enabledFeature.class != class'Aliases_Feature') return;
commandAliasSource = _.alias.GetCommandSource();
if (commandAliasSource == none) return;
ReloadCommandAliases(); // Drop map built by previous aliases (if it was even build up until now)
}
private final function ReloadCommandAliases()
{
local int i;
local Text aliasValue;
local array<Text> availableAliases;
local BaseAliasSource commandAliasSource;
local MutableText commandName, subcommandName;
_.memory.Free(commandToAliasesMap); _.memory.Free(commandToAliasesMap);
commandToAliasesMap = _.collections.EmptyHashTable(); commandToAliasesMap = _.collections.EmptyHashTable();
commandAliasSource = _.alias.GetCommandSource(); // Construct a command -> alias map by iterating over aliases
if (commandAliasSource == none) {
return;
}
availableAliases = commandAliasSource.GetAllAliases(); availableAliases = commandAliasSource.GetAllAliases();
for (i = 0; i < availableAliases.length; i += 1) for (i = 0; i < availableAliases.length; i += 1)
{ {
aliasValue = _.alias.ResolveCommand(availableAliases[i]); aliasValue = _.alias.ResolveCommand(availableAliases[i]);
ParseCommandNames(aliasValue, commandName, subcommandName); ParseCommandNames(aliasValue, commandName, subcommandName);
InsertIntoMap(commandName, subcommandName, availableAliases[i]); aliasValue.FreeSelf();
InsertIntoAliasesMap(commandName, subcommandName, availableAliases[i]);
commandName.FreeSelf(); commandName.FreeSelf();
subcommandName.FreeSelf(); subcommandName.FreeSelf();
aliasValue.FreeSelf();
} }
// Clean up
_.memory.FreeMany(availableAliases); _.memory.FreeMany(availableAliases);
commandAliasSource.FreeSelf(); 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( private final function ParseCommandNames(
BaseText source, BaseText source,
out MutableText commandName, out MutableText commandName,
@ -148,14 +156,14 @@ private final function ParseCommandNames(
} }
valueParser = source.Parse(); valueParser = source.Parse();
subcommandName = valueParser subcommandName = valueParser
.MUntil(commandName, _.text.GetCharacter(".")) .MUntil(commandName, T(TDOT).GetCharacter(0))
.MatchS(".") .Match(T(TDOT))
.GetRemainderM(); .GetRemainderM();
_.memory.Free(valueParser); _.memory.Free(valueParser);
} }
// Assumes that `commandToAliasesMap` and its arguments are not `none` // Assumes that `commandToAliasesMap` and its arguments are not `none`.
private final function InsertIntoMap( private final function InsertIntoAliasesMap(
BaseText commandName, BaseText commandName,
BaseText subcommandName, BaseText subcommandName,
BaseText alias) BaseText alias)
@ -224,7 +232,7 @@ private final function DisplayCommandLists(
else { else {
callerConsole.WriteLine(groupsNames[i]); callerConsole.WriteLine(groupsNames[i]);
} }
DisplayCommandsNamesArray( PrintCommandsNamesArray(
commandsFeature, commandsFeature,
commandNames, commandNames,
displayAliases); displayAliases);
@ -232,9 +240,10 @@ private final function DisplayCommandLists(
} }
} }
_.memory.FreeMany(groupsNames); _.memory.FreeMany(groupsNames);
commandsFeature.FreeSelf();
} }
private final function DisplayCommandsNamesArray( private final function PrintCommandsNamesArray(
Commands_Feature commandsFeature, Commands_Feature commandsFeature,
array<Text> commandsNamesArray, array<Text> commandsNamesArray,
bool displayAliases) bool displayAliases)
@ -256,13 +265,13 @@ private final function DisplayCommandsNamesArray(
.Write(T(TCOLON_SPACE)) .Write(T(TCOLON_SPACE))
.WriteLine(nextData.summary); .WriteLine(nextData.summary);
if (displayAliases) { if (displayAliases) {
DisplayCommandAliases(nextData.name); PrintCommandAliases(nextData.name);
} }
_.memory.Free(nextCommand); _.memory.Free(nextCommand);
} }
} }
private final function DisplayCommandAliases(BaseText commandName) private final function PrintCommandAliases(BaseText commandName)
{ {
local CollectionIterator iter; local CollectionIterator iter;
local Text commandKey; local Text commandKey;
@ -279,10 +288,9 @@ private final function DisplayCommandAliases(BaseText commandName)
if (subCommandToAliasesMap == none) { if (subCommandToAliasesMap == none) {
return; return;
} }
//callerConsole.WriteBlock(T(TALIASES));
// Display aliases to command itself first // Display aliases to command itself first
nextAliasesArray = subCommandToAliasesMap.GetArrayList(T(TEMPTY)); nextAliasesArray = subCommandToAliasesMap.GetArrayList(T(TEMPTY));
DisplayAliasesArray(commandName, none, nextAliasesArray); PrintAliasesArray(commandName, none, nextAliasesArray);
_.memory.Free(nextAliasesArray); _.memory.Free(nextAliasesArray);
// Then aliases to all of its subcommands, in no particular order // Then aliases to all of its subcommands, in no particular order
iter = subCommandToAliasesMap.Iterate(); iter = subCommandToAliasesMap.Iterate();
@ -296,7 +304,7 @@ private final function DisplayCommandAliases(BaseText commandName)
continue; continue;
} }
nextAliasesArray = ArrayList(iter.Get()); nextAliasesArray = ArrayList(iter.Get());
DisplayAliasesArray(commandName, nextSubCommand, nextAliasesArray); PrintAliasesArray(commandName, nextSubCommand, nextAliasesArray);
_.memory.Free(nextAliasesArray); _.memory.Free(nextAliasesArray);
_.memory.Free(nextSubCommand); _.memory.Free(nextSubCommand);
iter.Next(); iter.Next();
@ -304,7 +312,7 @@ private final function DisplayCommandAliases(BaseText commandName)
iter.FreeSelf(); iter.FreeSelf();
} }
private final function DisplayAliasesArray( private final function PrintAliasesArray(
BaseText commandName, BaseText commandName,
BaseText subcommandName, BaseText subcommandName,
ArrayList aliasesArray) ArrayList aliasesArray)
@ -343,95 +351,100 @@ private final function DisplayAliasesArray(
private final function DisplayCommandHelpPages(ArrayList commandList) private final function DisplayCommandHelpPages(ArrayList commandList)
{ {
local int i; local int i;
local Text nextCommandName, nextCommandValue; local bool printedSomething;
local Text nextUserProvidedName;
local MutableText referredSubcommand;
local Command nextCommand; 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 arguments were empty - at least display our own help page
if (commandList == none) if (commandList == none)
{ {
PrintHelpPage(BorrowData()); PrintHelpPageFor(BorrowData().name, none, BorrowData());
return; return;
} }
// Otherwise - print help for specified commands // Otherwise - print help for specified commands
for (i = 0; i < commandList.GetLength(); i += 1) for (i = 0; i < commandList.GetLength(); i += 1)
{ {
// Try normal command name nextUserProvidedName = commandList.GetText(i);
nextCommandName = commandList.GetText(i); nextCommand = GetCommandFromUserProvidedName(
nextCommand = commandsFeature.GetCommand(nextCommandName); nextUserProvidedName,
// Try command alias referredSubcommand);
if (nextCommand == none) 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
{ {
if (printedSomething) {
callerConsole.WriteLine(T(TSEPARATOR));
}
PrintHelpPageFor( PrintHelpPageFor(
nextCommand.BorrowData(), nextUserProvidedName,
nextCommandName, referredSubcommand,
parsedSubcommandName); nextCommand.BorrowData());
printedSomething = true;
} }
_.memory.Free(nextCommand); _.memory.Free(nextCommand);
_.memory.Free(parsedSubcommandName); _.memory.Free(nextUserProvidedName);
_.memory.Free(nextCommandName); _.memory.Free(referredSubcommand);
parsedSubcommandName = none; // `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 // Returns `Command` based on the name, given by user.
private final function PrintHelpPage(Command.Data data) // `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; local Command result;
// Get capitalized command name local Text commandAliasValue;
commandNameUpperCase = data.name.UpperCopy(); local Commands_Feature commandsFeature;
// Print header: name + basic info local MutableText parsedCommandName;
callerConsole.UseColor(_.color.textHeader)
.Write(commandNameUpperCase) // Clear `out` parameter no matter what
.UseColor(_.color.textDefault); if (referredSubcommand != none)
commandNameUpperCase.FreeSelf(); {
if (data.requiresTarget) { referredSubcommand.FreeSelf();
callerConsole.WriteLine(T(TCMD_WITH_TARGET)); referredSubcommand = none;
} }
else { // Try accessing (check availability of) `Commands_Feature`
callerConsole.WriteLine(T(TCMD_WITHOUT_TARGET)); commandsFeature =
Commands_Feature(class'Commands_Feature'.static.GetEnabledInstance());
if (commandsFeature == none) {
return none;
} }
// Print commands and options // Try getting command using `nextUserProvidedName` as a literal name
commandNameLowerCase = data.name.LowerCopy(); result = commandsFeature.GetCommand(nextUserProvidedName);
PrintCommands(data, commandNameLowerCase, none); if (result != none)
commandNameLowerCase.FreeSelf(); {
PrintOptions(data); commandsFeature.FreeSelf();
// Clean up return result;
callerConsole.ResetColor().Flush(); }
// 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( private final function PrintHelpPageFor(
Command.Data data,
BaseText commandAlias, BaseText commandAlias,
BaseText usedSubcommand) BaseText referredSubcommand,
Command.Data commandData)
{ {
local Text commandNameLowerCase, commandNameUpperCase; local Text commandNameLowerCase, commandNameUpperCase;
// Get capitalized command name // Get capitalized command name
@ -441,7 +454,7 @@ private final function PrintHelpPageFor(
.Write(commandNameUpperCase) .Write(commandNameUpperCase)
.UseColor(_.color.textDefault); .UseColor(_.color.textDefault);
commandNameUpperCase.FreeSelf(); commandNameUpperCase.FreeSelf();
if (data.requiresTarget) { if (commandData.requiresTarget) {
callerConsole.WriteLine(T(TCMD_WITH_TARGET)); callerConsole.WriteLine(T(TCMD_WITH_TARGET));
} }
else { else {
@ -449,9 +462,9 @@ private final function PrintHelpPageFor(
} }
// Print commands and options // Print commands and options
commandNameLowerCase = commandAlias.LowerCopy(); commandNameLowerCase = commandAlias.LowerCopy();
PrintCommands(data, commandNameLowerCase, usedSubcommand); PrintCommands(commandData, commandNameLowerCase, referredSubcommand);
commandNameLowerCase.FreeSelf(); commandNameLowerCase.FreeSelf();
PrintOptions(data); PrintOptions(commandData);
// Clean up // Clean up
callerConsole.ResetColor().Flush(); callerConsole.ResetColor().Flush();
} }
@ -459,23 +472,21 @@ private final function PrintHelpPageFor(
private final function PrintCommands( private final function PrintCommands(
Command.Data data, Command.Data data,
BaseText commandName, BaseText commandName,
BaseText filterSubcommandName) BaseText referredSubcommand)
{ {
local int i; local int i;
local array<SubCommand> subCommands; local array<SubCommand> subCommands;
if (filterSubcommandName != none && filterSubcommandName.IsEmpty()) {
filterSubcommandName = none;
}
subCommands = data.subCommands; subCommands = data.subCommands;
for (i = 0; i < subCommands.length; i += 1) for (i = 0; i < subCommands.length; i += 1)
{ {
if ( filterSubcommandName == none if ( referredSubcommand == none
|| filterSubcommandName.Compare(subCommands[i].name)) || referredSubcommand.Compare(subCommands[i].name))
{ {
PrintSubCommand( PrintSubCommand(
subCommands[i], subCommands[i],
commandName, commandName,
filterSubcommandName != none); referredSubcommand != none);
} }
} }
} }
@ -657,4 +668,6 @@ defaultproperties
stringConstants(20) = "Aliases for" stringConstants(20) = "Aliases for"
TEMPTY = 21 TEMPTY = 21
stringConstants(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 * `Executed()` is called first, whenever command is executed and
* `ExecuteFor()` is called only for targeted commands, once for each * `ExecuteFor()` is called only for targeted commands, once for each
* targeted player. * targeted player.
* Copyright 2021 - 2022 Anton Tarasenko * Copyright 2021-2022 Anton Tarasenko
*------------------------------------------------------------------------------ *------------------------------------------------------------------------------
* This file is part of Acedia. * This file is part of Acedia.
* *
@ -605,7 +605,6 @@ public final function Text GetGroupName()
return commandData.group.LowerCopy(); return commandData.group.LowerCopy();
} }
// TODO: use `SharedRef` instead
/** /**
* Returns `Command.Data` struct that describes caller `Command`. * 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 given `Command.Data`. While it's meant to be allocated for
* a `self.ParseWith()` call and deallocated right after, it can be reused * a `self.ParseWith()` call and deallocated right after, it can be reused
* without deallocation. * without deallocation.
* Copyright 2021 - 2022 Anton Tarasenko * Copyright 2021-2022 Anton Tarasenko
*------------------------------------------------------------------------------ *------------------------------------------------------------------------------
* This file is part of Acedia. * This file is part of Acedia.
* *

2
sources/Commands/Commands.uc

@ -1,6 +1,6 @@
/** /**
* Config object for `Commands_Feature`. * Config object for `Commands_Feature`.
* Copyright 2021 Anton Tarasenko * Copyright 2021-2022 Anton Tarasenko
*------------------------------------------------------------------------------ *------------------------------------------------------------------------------
* This file is part of Acedia. * 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 * parse their arguments into standard Acedia collection. It also allows to
* manage them (and specify limitation on how they can be called) in a * manage them (and specify limitation on how they can be called) in a
* centralized manner. * centralized manner.
* Copyright 2021 - 2022 Anton Tarasenko * Copyright 2021-2022 Anton Tarasenko
*------------------------------------------------------------------------------ *------------------------------------------------------------------------------
* This file is part of Acedia. * 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 * Object for parsing what converting textual description of a group of
* players into array of `EPlayer`s. Depends on the game context. * 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. * This file is part of Acedia.
* *

Loading…
Cancel
Save