diff --git a/CMakeLists.txt b/CMakeLists.txt index 0fff61f16..7d1ebde9c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2930,6 +2930,7 @@ if(GTEST_FOUND OR DOWNLOAD_GTEST) compression.cpp csv.cpp datafile.cpp + editor.cpp fs.cpp git_revision.cpp hash.cpp diff --git a/src/game/editor/quick_actions.h b/src/game/editor/quick_actions.h index cfba08e4b..a2425ca50 100644 --- a/src/game/editor/quick_actions.h +++ b/src/game/editor/quick_actions.h @@ -134,7 +134,7 @@ REGISTER_QUICK_ACTION( ALWAYS_FALSE, ALWAYS_FALSE, DEFAULT_BTN, - "[HOME] Restore map focus.") + "[Home] Restore map focus.") REGISTER_QUICK_ACTION( Proof, "Proof", diff --git a/src/test/editor.cpp b/src/test/editor.cpp new file mode 100644 index 000000000..4a5b72db0 --- /dev/null +++ b/src/test/editor.cpp @@ -0,0 +1,103 @@ +#include + +#include + +bool is_letter(char c) { return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); } + +bool IsValidEditorTooltip(const char *pTooltip, char *pErrorMsg, int ErrorMsgSize) +{ + pErrorMsg[0] = '\0'; + char aHotkey[512]; + aHotkey[0] = '\0'; + + if(pTooltip[0] == '[') + { + str_copy(aHotkey, pTooltip + 1); + const char *pHotkeyEnd = str_find(aHotkey, "]"); + if(!pHotkeyEnd) + { + str_copy(pErrorMsg, "tooltip missing closing square bracket", ErrorMsgSize); + return false; + } + aHotkey[pHotkeyEnd - aHotkey] = '\0'; + + for(int i = 0; aHotkey[i]; i++) + { + bool ExpectLowerCase = true; + if(i == 0) + { + ExpectLowerCase = false; + } + else if(!is_letter(aHotkey[i - 1])) + { + // the first character of a word should be uppercase + ExpectLowerCase = false; + } + + bool IsLower = aHotkey[i] >= 'a' && aHotkey[i] <= 'z'; + bool IsUpper = aHotkey[i] >= 'A' && aHotkey[i] <= 'Z'; + + if(ExpectLowerCase && IsUpper) + { + str_format(pErrorMsg, ErrorMsgSize, "expected character '%c' at index %d to be lower case", aHotkey[i], i + 1); + return false; + } + if(!ExpectLowerCase && IsLower) + { + str_format(pErrorMsg, ErrorMsgSize, "expected character '%c' at index %d to be upper case", aHotkey[i], i + 1); + return false; + } + } + } + + const char *pParenthesis = str_find(pTooltip, "("); + if(pParenthesis) + { + const char *pHotkey = str_find_nocase(pParenthesis, "ctrl"); + if(!pHotkey) + pHotkey = str_find_nocase(pParenthesis, "shift"); + if(!pHotkey) + pHotkey = str_find_nocase(pParenthesis, "home"); + + if(pHotkey) + { + int Offset = pHotkey - pTooltip; + str_format(pErrorMsg, ErrorMsgSize, "found hotkey at offset %d. Hotkeys must be defined at the start.", Offset); + return false; + } + } + + if(!str_endswith(pTooltip, ".")) + { + str_copy(pErrorMsg, "tooltip has to end with a dot", ErrorMsgSize); + return false; + } + return true; +} + +void AssertTooltip(const char *pTooltip) +{ + char aError[512]; + bool IsValid = IsValidEditorTooltip(pTooltip, aError, sizeof(aError)); + if(!IsValid) + { + dbg_msg("test", "Invalid tooltip: %s", pTooltip); + dbg_msg("test", "ERROR: %s", aError); + } + EXPECT_TRUE(IsValid); +} + +TEST(Editor, QuickActionNames) +{ + char aError[512]; + EXPECT_TRUE(IsValidEditorTooltip("hello world.", aError, sizeof(aError))); + EXPECT_TRUE(IsValidEditorTooltip("[Ctrl+H] hello world.", aError, sizeof(aError))); + EXPECT_FALSE(IsValidEditorTooltip("[Ctrl+H hello world.", aError, sizeof(aError))); + EXPECT_FALSE(IsValidEditorTooltip("[ctrl+h] hello world.", aError, sizeof(aError))); + EXPECT_FALSE(IsValidEditorTooltip("hello world", aError, sizeof(aError))); + EXPECT_FALSE(IsValidEditorTooltip("hello world (Ctrl+H).", aError, sizeof(aError))); + +#define REGISTER_QUICK_ACTION(name, text, callback, disabled, active, button_color, description) AssertTooltip(description); +#include +#undef REGISTER_QUICK_ACTION +}