Files
integration/Source/Integration/SlashCommand.h
2026-05-26 18:20:35 -04:00

122 lines
4.1 KiB
C++

////////////////////////////////////////////////////////////
//
// SlashCommand.h
//
// A command line plus a cursor, exposed to blueprint.
//
////////////////////////////////////////////////////////////
#pragma once
#include "Containers/Array.h"
#include "Containers/Set.h"
#include "Containers/UnrealString.h"
#include "Containers/StringFwd.h"
#include "Common.h"
#include "SlashCommand.generated.h"
////////////////////////////////////////////////////////////
//
// UlxSlashCommand
//
// Holds a command line (a string the user has typed) together
// with a cursor marking the current position within it. This
// is the object that wraps Unreal's FParse facilities so that
// blueprint can parse a typed command piece by piece, with the
// cursor advancing as each token is consumed.
//
////////////////////////////////////////////////////////////
UCLASS(BlueprintType)
class UlxSlashCommand : public UObject
{
GENERATED_BODY()
private:
// The full command line that we are parsing.
//
FString CommandLine;
// The current parse position: an index into CommandLine.
//
int32 Cursor = 0;
// Known command names that have been registered while exploring
// possible parses for this line.
//
TSet<FString> KnownCommands;
// Prototypes whose command name matches this line.
//
TArray<FString> MatchingPrototypes;
// Skip leading whitespace at the cursor, then read characters up
// to (but not including) the next whitespace. The token is
// returned as a view into CommandLine, and the cursor is advanced
// past it.
//
// Returns an empty view if there is no nonwhitespace input left.
//
FStringView FetchToken();
public:
// Construct a slash command from a command line string.
// The cursor starts at the beginning.
//
UFUNCTION(BlueprintCallable)
static UlxSlashCommand* MakeSlashCommand(const FString& CommandLine);
// Return true if the string is a slash followed by one or more
// alphanumeric characters, and nothing else (e.g. "/foo").
//
static bool IsSlashCommand(const FString& Command);
// Reset the cursor to the start, then read the first token and
// check whether it matches the given literal, case-insensitively.
// The command name is recorded in KnownCommands either way. If it
// matched, the prototype is added to MatchingPrototypes. The token
// is consumed either way. Returns Success if it matched, Error
// otherwise.
//
UFUNCTION(BlueprintCallable, meta = (ExpandEnumAsExecs = "ReturnValue"))
ElxSuccessOrError CheckCommand(const FString& Literal, const FString& Prototype);
// Read the next whitespace-delimited word from the command line.
//
// This is the blueprint-callable form of FetchToken: it returns
// the token as an FString. Returns Error (with an empty Result)
// if there is no nonwhitespace input left, Success otherwise.
//
UFUNCTION(BlueprintCallable, meta = (ExpandEnumAsExecs = "ReturnValue"))
ElxSuccessOrError ReadToken(FString& Result);
// Read the next token and interpret it as an integer, using C++
// number syntax (optional sign; decimal, 0x hex, or leading-0
// octal). The whole token must be valid; "12abc" is rejected.
// Returns Error (with Result 0) on failure, Success otherwise.
//
UFUNCTION(BlueprintCallable, meta = (ExpandEnumAsExecs = "ReturnValue"))
ElxSuccessOrError ReadInteger(int32& Result);
// Read the next token and interpret it as a floating-point number,
// using C++ number syntax (optional sign, digits, dot, e/E
// exponent, trailing f). The whole token must be valid; "12abc"
// is rejected. Returns Error (with Result 0) on failure, Success
// otherwise.
//
UFUNCTION(BlueprintCallable, meta = (ExpandEnumAsExecs = "ReturnValue"))
ElxSuccessOrError ReadFloat(double& Result);
// Read the rest of the command line, from the cursor to the end,
// trimmed of leading and trailing whitespace. The cursor is
// advanced to the end. Always returns Success.
//
UFUNCTION(BlueprintCallable, meta = (ExpandEnumAsExecs = "ReturnValue"))
ElxSuccessOrError ReadRest(FString& Result);
// Return a user-facing error message describing why parsing failed.
//
UFUNCTION(BlueprintCallable)
FString GetErrorMessage() const;
};