Add commandlets

This commit is contained in:
Magnus Norddahl 2025-01-07 06:12:31 +01:00
commit 5491aecd5f
8 changed files with 298 additions and 23 deletions

View file

@ -0,0 +1,123 @@
#include "commandlet.h"
#include "lightmapcmd.h"
#include "version.h"
void CommandletGroup::AddGroup(std::unique_ptr<CommandletGroup> group)
{
Groups.Push(std::move(group));
}
void CommandletGroup::AddCommand(std::unique_ptr<Commandlet> command)
{
Commands.Push(std::move(command));
}
/////////////////////////////////////////////////////////////////////////////
RootCommandlet::RootCommandlet()
{
AddGroup<LightmapCmdletGroup>();
}
void RootCommandlet::RunCommand()
{
FArgs args = *Args;
args.RemoveArg(0);
if (args.NumArgs() > 0 && stricmp(args.GetArg(0), "help") == 0)
{
args.RemoveArg(0);
PrintDetailHelp(this, args);
}
else
{
RunCommand(this, args, {});
}
}
void RootCommandlet::RunCommand(CommandletGroup* group, FArgs args, const FString prefix)
{
if (args.NumArgs() > 0 && args.GetArg(0)[0] != '-')
{
const char* arg = args.GetArg(0);
for (auto& cmd : group->Commands)
{
if (stricmp(arg, cmd->GetLongFormName().GetChars()) == 0)
{
args.RemoveArg(0);
cmd->OnCommand(args);
return;
}
}
for (auto& subgroup : group->Groups)
{
if (stricmp(arg, subgroup->GetLongFormName().GetChars()) == 0)
{
args.RemoveArg(0);
RunCommand(subgroup.get(), args, prefix + arg + " ");
return;
}
}
Printf("Unknown command " TEXTCOLOR_ORANGE "%s\n", arg);
}
else
{
Printf("Syntax: " TOOLNAMELOWERCASE TEXTCOLOR_ORANGE " <command> " TEXTCOLOR_CYAN "[options]" TEXTCOLOR_NORMAL " - Run command\n");
Printf("Syntax: " TOOLNAMELOWERCASE " help " TEXTCOLOR_CYAN "[options]" TEXTCOLOR_NORMAL " - Get help list of commands\n");
Printf("Syntax: " TOOLNAMELOWERCASE " help " TEXTCOLOR_ORANGE "<command> " TEXTCOLOR_CYAN "[options]" TEXTCOLOR_NORMAL " - Get help about a specific command\n");
}
}
void RootCommandlet::PrintDetailHelp(CommandletGroup* group, FArgs args)
{
if (args.NumArgs() > 0 && args.GetArg(0)[0] != '-')
{
const char* arg = args.GetArg(0);
for (auto& cmd : group->Commands)
{
if (stricmp(arg, cmd->GetLongFormName().GetChars()) == 0)
{
cmd->OnPrintHelp();
return;
}
}
for (auto& subgroup : group->Groups)
{
if (stricmp(arg, subgroup->GetLongFormName().GetChars()) == 0)
{
args.RemoveArg(0);
PrintDetailHelp(subgroup.get(), args);
return;
}
}
Printf("Unknown command " TEXTCOLOR_ORANGE "%s\n", arg);
}
else
{
PrintCommandList(this, {});
}
}
void RootCommandlet::PrintCommandList(CommandletGroup* group, const FString prefix)
{
if (group != this)
{
FString description = group->GetShortDescription();
Printf("%s:\n", description.GetChars());
}
for (auto& cmdlet : group->Commands)
{
FString longname = prefix + cmdlet->GetLongFormName();
FString description = cmdlet->GetShortDescription();
while (longname.Len() < 20)
longname.AppendCharacter(' ');
Printf(TEXTCOLOR_ORANGE "%s " TEXTCOLOR_NORMAL "%s\n", longname.GetChars(), description.GetChars());
}
for (auto& subgroup : group->Groups)
{
PrintCommandList(subgroup.get(), prefix + subgroup->GetLongFormName() + " ");
}
}

View file

@ -0,0 +1,69 @@
#pragma once
#include <memory>
#include "templates.h"
#include "zstring.h"
#include "printf.h"
#include "m_argv.h"
class Commandlet
{
public:
virtual ~Commandlet() = default;
virtual void OnCommand(FArgs args) = 0;
virtual void OnPrintHelp() = 0;
const FString& GetLongFormName() const { return LongFormName; }
const FString& GetShortDescription() const { return ShortDescription; }
protected:
void SetLongFormName(FString name) { LongFormName = std::move(name); }
void SetShortDescription(FString desc) { ShortDescription = std::move(desc); }
private:
FString LongFormName;
FString ShortDescription;
};
class CommandletGroup
{
public:
void AddGroup(std::unique_ptr<CommandletGroup> group);
void AddCommand(std::unique_ptr<Commandlet> command);
template<typename T>
void AddGroup() { AddGroup(std::make_unique<T>()); }
template<typename T>
void AddCommand() { AddCommand(std::make_unique<T>()); }
const FString& GetLongFormName() const { return LongFormName; }
const FString& GetShortDescription() const { return ShortDescription; }
protected:
void SetLongFormName(FString name) { LongFormName = std::move(name); }
void SetShortDescription(FString desc) { ShortDescription = std::move(desc); }
private:
FString LongFormName;
FString ShortDescription;
TArray<std::unique_ptr<CommandletGroup>> Groups;
TArray<std::unique_ptr<Commandlet>> Commands;
friend class RootCommandlet;
};
class RootCommandlet : public CommandletGroup
{
public:
RootCommandlet();
void RunCommand();
private:
void RunCommand(CommandletGroup* group, FArgs args, const FString prefix);
void PrintCommandList(CommandletGroup* group, const FString prefix);
void PrintDetailHelp(CommandletGroup* group, FArgs args);
};

View file

@ -0,0 +1,47 @@
#include "lightmapcmd.h"
LightmapCmdletGroup::LightmapCmdletGroup()
{
SetLongFormName("lightmap");
SetShortDescription("Lightmapper commands");
AddCommand<LightmapBuildCmdlet>();
AddCommand<LightmapDeleteCmdlet>();
}
/////////////////////////////////////////////////////////////////////////////
LightmapBuildCmdlet::LightmapBuildCmdlet()
{
SetLongFormName("build");
SetShortDescription("Build lightmap lump");
}
void LightmapBuildCmdlet::OnCommand(FArgs args)
{
Printf("Baking LIGHTMAP lump!\n");
}
void LightmapBuildCmdlet::OnPrintHelp()
{
Printf(TEXTCOLOR_ORANGE "lightmap build " TEXTCOLOR_CYAN "[map name]" TEXTCOLOR_NORMAL " - Bakes all the lightmap lights and stores the result in a LIGHTMAP lump\n");
}
/////////////////////////////////////////////////////////////////////////////
LightmapDeleteCmdlet::LightmapDeleteCmdlet()
{
SetLongFormName("delete");
SetShortDescription("Delete lightmap lump");
}
void LightmapDeleteCmdlet::OnCommand(FArgs args)
{
Printf("Deleting LIGHTMAP lump!\n");
}
void LightmapDeleteCmdlet::OnPrintHelp()
{
Printf(TEXTCOLOR_ORANGE "lightmap delete " TEXTCOLOR_CYAN "[map name]" TEXTCOLOR_NORMAL " - Deletes the LIGHTMAP lump\n");
}

View file

@ -0,0 +1,26 @@
#pragma once
#include "commandlet.h"
class LightmapCmdletGroup : public CommandletGroup
{
public:
LightmapCmdletGroup();
};
class LightmapBuildCmdlet : public Commandlet
{
public:
LightmapBuildCmdlet();
void OnCommand(FArgs args) override;
void OnPrintHelp() override;
};
class LightmapDeleteCmdlet : public Commandlet
{
public:
LightmapDeleteCmdlet();
void OnCommand(FArgs args) override;
void OnPrintHelp() override;
};