//////////////////////////////////////////////////////////// // // 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 KnownCommands; // Prototypes whose command name matches this line. // TArray 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; };