Browse Source

Add alias support into "help" command

pull/8/head
Anton Tarasenko 2 years ago
parent
commit
4d8bb3d09c
  1. 324
      sources/Commands/BuiltInCommands/ACommandHelp.uc

324
sources/Commands/BuiltInCommands/ACommandHelp.uc

@ -20,15 +20,35 @@
class ACommandHelp extends Command class ACommandHelp extends Command
dependson(LoggerAPI); dependson(LoggerAPI);
// 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;
var LoggerAPI.Definition testMsg; var LoggerAPI.Definition testMsg;
var public const int TSPACE, TCOMMAND_NAME_FALLBACK, TPLUS; var public const int TSPACE, TCOMMAND_NAME_FALLBACK, TPLUS;
var public const int TOPEN_BRACKET, TCLOSE_BRACKET, TCOLUMN_SPACE; var public const int TOPEN_BRACKET, TCLOSE_BRACKET, TCOLON_SPACE;
var public const int TKEY, TDOUBLE_KEY, TCOMMA_SPACE, TBOOLEAN, TINDENT; var public const int TKEY, TDOUBLE_KEY, TCOMMA_SPACE, TBOOLEAN, TINDENT;
var public const int TBOOLEAN_TRUE_FALSE, TBOOLEAN_ENABLE_DISABLE; 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;
protected function Constructor()
{
super.Constructor();
if (class'Aliases_Feature'.static.GetEnabledInstance() != none) {
ReloadCommandAliases();
}
_.environment.OnFeatureEnabled(self).connect = HandleFeatureEnabled;
}
protected function Finalizer()
{
_.memory.Free(commandToAliasesMap);
commandToAliasesMap = none;
}
protected function BuildData(CommandDataBuilder builder) protected function BuildData(CommandDataBuilder builder)
{ {
@ -37,7 +57,11 @@ protected function BuildData(CommandDataBuilder builder)
builder.OptionalParams() builder.OptionalParams()
.ParamTextList(P("commands")) .ParamTextList(P("commands"))
.Describe(P("Displays information about all specified commands.")); .Describe(P("Displays information about all specified commands."));
builder.Option(P("list")) builder.Option(P("aliases"))
.Describe(P("When displaying available commands, specifying this flag"
@ "will additionally make command to display all of their available"
@ "aliases."))
.Option(P("list"))
.Describe(P("Display available commands. Optionally command groups can" .Describe(P("Display available commands. Optionally command groups can"
@ "be specified and then only commands from such groups will be" @ "be specified and then only commands from such groups will be"
@ "listed. Otherwise all commands will be displayed.")) @ "listed. Otherwise all commands will be displayed."))
@ -55,7 +79,9 @@ protected function Executed(Command.CallData callData, EPlayer callerPlayer)
if (options.HasKey(P("list"))) if (options.HasKey(P("list")))
{ {
commandGroupsToDisplay = options.GetArrayListBy(P("/list/groups")); commandGroupsToDisplay = options.GetArrayListBy(P("/list/groups"));
DisplayCommandLists(commandGroupsToDisplay); DisplayCommandLists(
commandGroupsToDisplay,
options.HasKey(P("aliases")));
_.memory.Free(commandGroupsToDisplay); _.memory.Free(commandGroupsToDisplay);
} }
// Help pages. // Help pages.
@ -71,7 +97,98 @@ protected function Executed(Command.CallData callData, EPlayer callerPlayer)
} }
} }
private final function DisplayCommandLists(ArrayList commandGroupsToDisplay) private final function HandleFeatureEnabled(Feature enabledFeature)
{
if (enabledFeature == none) return;
if (enabledFeature.class != class'Aliases_Feature') return;
ReloadCommandAliases();
}
private final function ReloadCommandAliases()
{
local int i;
local Text aliasValue;
local array<Text> availableAliases;
local BaseAliasSource commandAliasSource;
local MutableText commandName, subcommandName;
_.memory.Free(commandToAliasesMap);
commandToAliasesMap = _.collections.EmptyHashTable();
commandAliasSource = _.alias.GetCommandSource();
if (commandAliasSource == none) {
return;
}
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]);
commandName.FreeSelf();
subcommandName.FreeSelf();
aliasValue.FreeSelf();
}
_.memory.FreeMany(availableAliases);
commandAliasSource.FreeSelf();
}
private final function ParseCommandNames(
BaseText source,
out MutableText commandName,
out MutableText subcommandName)
{
local Parser valueParser;
if (source == none) {
return;
}
if (subcommandName != none) {
subcommandName.FreeSelf();
}
valueParser = source.Parse();
subcommandName = valueParser
.MUntil(commandName, _.text.GetCharacter("."))
.MatchS(".")
.GetRemainderM();
_.memory.Free(valueParser);
}
// Assumes that `commandToAliasesMap` and its arguments are not `none`
private final function InsertIntoMap(
BaseText commandName,
BaseText subcommandName,
BaseText alias)
{
local Text commandKey, subcommandKey;
local HashTable subcommandToAliasesMap;
local ArrayList aliasesArray;
commandKey = commandName.LowerCopy();
subcommandKey = subcommandName.LowerCopy();
subcommandToAliasesMap = commandToAliasesMap.GetHashTable(commandKey);
if (subcommandToAliasesMap == none) {
subcommandToAliasesMap = _.collections.EmptyHashTable();
}
commandToAliasesMap.SetItem(commandKey, subcommandToAliasesMap);
aliasesArray = subcommandToAliasesMap.GetArrayList(subcommandKey);
if (aliasesArray == none) {
aliasesArray = _.collections.EmptyArrayList();
}
subcommandToAliasesMap.SetItem(subcommandKey, aliasesArray);
if (aliasesArray.Find(alias) < 0) {
aliasesArray.AddItem(alias);
}
// Cleaning up local references to collections and keys
subcommandToAliasesMap.FreeSelf();
aliasesArray.FreeSelf();
commandKey.FreeSelf();
subcommandKey.FreeSelf();
}
private final function DisplayCommandLists(
ArrayList commandGroupsToDisplay,
bool displayAliases)
{ {
local int i; local int i;
local array<Text> commandNames, groupsNames; local array<Text> commandNames, groupsNames;
@ -82,10 +199,8 @@ private final function DisplayCommandLists(ArrayList commandGroupsToDisplay)
if (commandsFeature == none) { if (commandsFeature == none) {
return; return;
} }
if (commandGroupsToDisplay == none) if (commandGroupsToDisplay == none) {
{
groupsNames = commandsFeature.GetGroupsNames(); groupsNames = commandsFeature.GetGroupsNames();
DisplayCommandsNamesArray(commandsFeature, commandNames);
} }
else else
{ {
@ -109,7 +224,10 @@ private final function DisplayCommandLists(ArrayList commandGroupsToDisplay)
else { else {
callerConsole.WriteLine(groupsNames[i]); callerConsole.WriteLine(groupsNames[i]);
} }
DisplayCommandsNamesArray(commandsFeature, commandNames); DisplayCommandsNamesArray(
commandsFeature,
commandNames,
displayAliases);
_.memory.FreeMany(commandNames); _.memory.FreeMany(commandNames);
} }
} }
@ -118,7 +236,8 @@ private final function DisplayCommandLists(ArrayList commandGroupsToDisplay)
private final function DisplayCommandsNamesArray( private final function DisplayCommandsNamesArray(
Commands_Feature commandsFeature, Commands_Feature commandsFeature,
array<Text> commandsNamesArray) array<Text> commandsNamesArray,
bool displayAliases)
{ {
local int i; local int i;
local Command nextCommand; local Command nextCommand;
@ -131,21 +250,104 @@ private final function DisplayCommandsNamesArray(
continue; continue;
} }
nextData = nextCommand.BorrowData(); nextData = nextCommand.BorrowData();
callerConsole.UseColor(_.color.textEmphasis) callerConsole
.UseColorOnce(_.color.textEmphasis)
.Write(nextData.name) .Write(nextData.name)
.ResetColor() .Write(T(TCOLON_SPACE))
.Write(T(TCOLUMN_SPACE))
.WriteLine(nextData.summary); .WriteLine(nextData.summary);
if (displayAliases) {
DisplayCommandAliases(nextData.name);
}
_.memory.Free(nextCommand); _.memory.Free(nextCommand);
} }
} }
private final function DisplayCommandAliases(BaseText commandName)
{
local CollectionIterator iter;
local Text commandKey;
local Text nextSubCommand;
local ArrayList nextAliasesArray;
local HashTable subCommandToAliasesMap;
if (commandName == none) return;
if (commandToAliasesMap == none) return;
commandKey = commandName.LowerCopy();
subCommandToAliasesMap = commandToAliasesMap.GetHashTable(commandName);
commandKey.FreeSelf();
if (subCommandToAliasesMap == none) {
return;
}
//callerConsole.WriteBlock(T(TALIASES));
// Display aliases to command itself first
nextAliasesArray = subCommandToAliasesMap.GetArrayList(T(TEMPTY));
DisplayAliasesArray(commandName, none, nextAliasesArray);
_.memory.Free(nextAliasesArray);
// Then aliases to all of its subcommands, in no particular order
iter = subCommandToAliasesMap.Iterate();
while (!iter.HasFinished())
{
nextSubCommand = Text(iter.Getkey()); // cannot be `none`
if (nextSubCommand.IsEmpty())
{
nextSubCommand.FreeSelf();
iter.Next();
continue;
}
nextAliasesArray = ArrayList(iter.Get());
DisplayAliasesArray(commandName, nextSubCommand, nextAliasesArray);
_.memory.Free(nextAliasesArray);
_.memory.Free(nextSubCommand);
iter.Next();
}
iter.FreeSelf();
}
private final function DisplayAliasesArray(
BaseText commandName,
BaseText subcommandName,
ArrayList aliasesArray)
{
local int i;
local Text nextAlias;
if (commandName == none) return;
if (aliasesArray == none) return;
callerConsole
.Write(T(TALIASES_FOR))
.Write(T(TSPACE))
.UseColorOnce(_.color.TextEmphasis)
.Write(commandName);
if (subcommandName != none)
{
callerConsole
.Write(T(TSPACE))
.UseColorOnce(_.color.TextEmphasis)
.Write(subCommandName);
}
callerConsole.Write(T(TCOLON_SPACE));
for (i = 0; i < aliasesArray.GetLength(); i += 1)
{
if (i > 0) {
callerConsole.Write(T(TCOMMA_SPACE));
}
nextAlias = aliasesArray.GetText(i);
callerConsole.UseColorOnce(_.color.TextNeutral).Write(nextAlias);
nextAlias.FreeSelf();
}
callerConsole.WriteBlock();
}
private final function DisplayCommandHelpPages(ArrayList commandList) private final function DisplayCommandHelpPages(ArrayList commandList)
{ {
local int i; local int i;
local Text nextCommandName; local Text nextCommandName, nextCommandValue;
local Command nextCommand; local Command nextCommand;
local Commands_Feature commandsFeature; local Commands_Feature commandsFeature;
local MutableText parsedCommandName, parsedSubcommandName;
commandsFeature = commandsFeature =
Commands_Feature(class'Commands_Feature'.static.GetEnabledInstance()); Commands_Feature(class'Commands_Feature'.static.GetEnabledInstance());
if (commandsFeature == none) { if (commandsFeature == none) {
@ -160,24 +362,50 @@ private final function DisplayCommandHelpPages(ArrayList commandList)
// 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
nextCommandName = commandList.GetText(i); nextCommandName = commandList.GetText(i);
nextCommand = commandsFeature.GetCommand(nextCommandName); 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); _.memory.Free(nextCommandName);
if (nextCommand == none) {
continue; continue;
} }
if (i > 0) { if (i > 0) {
callerConsole.WriteLine(T(TSEPARATOR)); callerConsole.WriteLine(T(TSEPARATOR));
} }
if (parsedSubcommandName == none) {
PrintHelpPage(nextCommand.BorrowData()); PrintHelpPage(nextCommand.BorrowData());
}
else
{
PrintHelpPageFor(
nextCommand.BorrowData(),
nextCommandName,
parsedSubcommandName);
}
_.memory.Free(nextCommand); _.memory.Free(nextCommand);
_.memory.Free(parsedSubcommandName);
_.memory.Free(nextCommandName);
parsedSubcommandName = none;
} }
} }
// Following methods are mostly self-explanatory // Following methods are mostly self-explanatory
private final function PrintHelpPage(Command.Data data) private final function PrintHelpPage(Command.Data data)
{ {
local Text commandNameUpperCase; local Text commandNameLowerCase, commandNameUpperCase;
// Get capitalized command name // Get capitalized command name
commandNameUpperCase = data.name.UpperCopy(); commandNameUpperCase = data.name.UpperCopy();
// Print header: name + basic info // Print header: name + basic info
@ -192,32 +420,80 @@ private final function PrintHelpPage(Command.Data data)
callerConsole.WriteLine(T(TCMD_WITHOUT_TARGET)); callerConsole.WriteLine(T(TCMD_WITHOUT_TARGET));
} }
// Print commands and options // Print commands and options
PrintCommands(data); commandNameLowerCase = data.name.LowerCopy();
PrintCommands(data, commandNameLowerCase, none);
commandNameLowerCase.FreeSelf();
PrintOptions(data); PrintOptions(data);
// Clean up // Clean up
callerConsole.ResetColor().Flush(); callerConsole.ResetColor().Flush();
} }
private final function PrintCommands(Command.Data data) private final function PrintHelpPageFor(
Command.Data data,
BaseText commandAlias,
BaseText usedSubcommand)
{
local Text commandNameLowerCase, commandNameUpperCase;
// Get capitalized command name
commandNameUpperCase = commandAlias.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));
}
else {
callerConsole.WriteLine(T(TCMD_WITHOUT_TARGET));
}
// Print commands and options
commandNameLowerCase = commandAlias.LowerCopy();
PrintCommands(data, commandNameLowerCase, usedSubcommand);
commandNameLowerCase.FreeSelf();
PrintOptions(data);
// Clean up
callerConsole.ResetColor().Flush();
}
private final function PrintCommands(
Command.Data data,
BaseText commandName,
BaseText filterSubcommandName)
{ {
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)
PrintSubCommand(subCommands[i], data.name); {
if ( filterSubcommandName == none
|| filterSubcommandName.Compare(subCommands[i].name))
{
PrintSubCommand(
subCommands[i],
commandName,
filterSubcommandName != none);
}
} }
} }
private final function PrintSubCommand( private final function PrintSubCommand(
SubCommand subCommand, SubCommand subCommand,
BaseText commandName) BaseText commandName,
bool skipSubcommandName)
{ {
// Command + parameters // Command + parameters
// Command name + sub command name // Command name + sub command name
callerConsole.UseColor(_.color.textEmphasis) callerConsole.UseColor(_.color.textEmphasis)
.Write(commandName) .Write(commandName)
.Write(T(TSPACE)); .Write(T(TSPACE));
if (subCommand.name != none && !subCommand.name.IsEmpty()) { if ( !skipSubcommandName
&& subCommand.name != none
&& !subCommand.name.IsEmpty())
{
callerConsole.Write(subCommand.name).Write(T(TSPACE)); callerConsole.Write(subCommand.name).Write(T(TSPACE));
} }
callerConsole.UseColor(_.color.textDefault); callerConsole.UseColor(_.color.textDefault);
@ -351,7 +627,7 @@ defaultproperties
stringConstants(5) = "--" stringConstants(5) = "--"
TCOMMA_SPACE = 6 TCOMMA_SPACE = 6
stringConstants(6) = ", " stringConstants(6) = ", "
TCOLUMN_SPACE = 7 TCOLON_SPACE = 7
stringConstants(7) = ": " stringConstants(7) = ": "
TINDENT = 8 TINDENT = 8
stringConstants(8) = " " stringConstants(8) = " "
@ -377,4 +653,8 @@ defaultproperties
stringConstants(18) = "{$TextHeader List of registered commands}" stringConstants(18) = "{$TextHeader List of registered commands}"
TEMPTY_GROUP = 19 TEMPTY_GROUP = 19
stringConstants(19) = "Empty group" stringConstants(19) = "Empty group"
TALIASES_FOR = 20
stringConstants(20) = "Aliases for"
TEMPTY = 21
stringConstants(21) = ""
} }
Loading…
Cancel
Save