mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-03-22 23:30:14 +00:00
feat: add Tab autocomplete for slash commands in chat input
Pressing Tab while typing a slash command cycles through all matching commands (e.g. /em<Tab> → /emote, /emote<Tab> → /emote again). Unambiguous matches append a trailing space. Repeated Tab presses cycle forward through all matches. History navigation (Up/Down) resets the autocomplete session.
This commit is contained in:
parent
68251b647d
commit
c14b338a92
2 changed files with 69 additions and 1 deletions
|
|
@ -54,6 +54,11 @@ private:
|
|||
std::vector<std::string> chatSentHistory_;
|
||||
int chatHistoryIdx_ = -1; // -1 = not browsing history
|
||||
|
||||
// Tab-completion state for slash commands
|
||||
std::string chatTabPrefix_; // prefix captured on first Tab press
|
||||
std::vector<std::string> chatTabMatches_; // matching command list
|
||||
int chatTabMatchIdx_ = -1; // active match index (-1 = inactive)
|
||||
|
||||
// Chat tabs
|
||||
int activeChatTab_ = 0;
|
||||
struct ChatTab {
|
||||
|
|
|
|||
|
|
@ -1770,8 +1770,70 @@ void GameScreen::renderChatWindow(game::GameHandler& gameHandler) {
|
|||
self->chatInputMoveCursorToEnd = false;
|
||||
}
|
||||
|
||||
// Tab: slash-command autocomplete
|
||||
if (data->EventFlag == ImGuiInputTextFlags_CallbackCompletion) {
|
||||
if (data->BufTextLen > 0 && data->Buf[0] == '/') {
|
||||
// Split buffer into command word and trailing args
|
||||
std::string fullBuf(data->Buf, data->BufTextLen);
|
||||
size_t spacePos = fullBuf.find(' ');
|
||||
std::string word = (spacePos != std::string::npos) ? fullBuf.substr(0, spacePos) : fullBuf;
|
||||
std::string rest = (spacePos != std::string::npos) ? fullBuf.substr(spacePos) : "";
|
||||
|
||||
// Normalize to lowercase for matching
|
||||
std::string lowerWord = word;
|
||||
for (auto& ch : lowerWord) ch = static_cast<char>(std::tolower(static_cast<unsigned char>(ch)));
|
||||
|
||||
static const std::vector<std::string> kCmds = {
|
||||
"/afk", "/away", "/cast", "/chathelp", "/clear",
|
||||
"/dance", "/do", "/dnd", "/e", "/emote",
|
||||
"/follow", "/g", "/guild", "/guildinfo",
|
||||
"/gmticket", "/grouploot", "/i", "/instance",
|
||||
"/invite", "/j", "/join", "/kick",
|
||||
"/l", "/leave", "/local", "/me",
|
||||
"/p", "/party", "/r", "/raid",
|
||||
"/raidwarning", "/random", "/reply", "/roll",
|
||||
"/s", "/say", "/setloot", "/shout",
|
||||
"/stopattack", "/stopfollow", "/t", "/time",
|
||||
"/trade", "/uninvite", "/w", "/whisper",
|
||||
"/who", "/wts", "/wtb", "/y", "/yell", "/zone"
|
||||
};
|
||||
|
||||
// New session if prefix changed
|
||||
if (self->chatTabMatchIdx_ < 0 || self->chatTabPrefix_ != lowerWord) {
|
||||
self->chatTabPrefix_ = lowerWord;
|
||||
self->chatTabMatches_.clear();
|
||||
for (const auto& cmd : kCmds) {
|
||||
if (cmd.size() >= lowerWord.size() &&
|
||||
cmd.compare(0, lowerWord.size(), lowerWord) == 0)
|
||||
self->chatTabMatches_.push_back(cmd);
|
||||
}
|
||||
self->chatTabMatchIdx_ = 0;
|
||||
} else {
|
||||
// Cycle forward through matches
|
||||
++self->chatTabMatchIdx_;
|
||||
if (self->chatTabMatchIdx_ >= static_cast<int>(self->chatTabMatches_.size()))
|
||||
self->chatTabMatchIdx_ = 0;
|
||||
}
|
||||
|
||||
if (!self->chatTabMatches_.empty()) {
|
||||
std::string match = self->chatTabMatches_[self->chatTabMatchIdx_];
|
||||
// Append trailing space when match is unambiguous
|
||||
if (self->chatTabMatches_.size() == 1 && rest.empty())
|
||||
match += ' ';
|
||||
std::string newBuf = match + rest;
|
||||
data->DeleteChars(0, data->BufTextLen);
|
||||
data->InsertChars(0, newBuf.c_str());
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Up/Down arrow: cycle through sent message history
|
||||
if (data->EventFlag == ImGuiInputTextFlags_CallbackHistory) {
|
||||
// Any history navigation resets autocomplete
|
||||
self->chatTabMatchIdx_ = -1;
|
||||
self->chatTabMatches_.clear();
|
||||
|
||||
const int histSize = static_cast<int>(self->chatSentHistory_.size());
|
||||
if (histSize == 0) return 0;
|
||||
|
||||
|
|
@ -1802,7 +1864,8 @@ void GameScreen::renderChatWindow(game::GameHandler& gameHandler) {
|
|||
|
||||
ImGuiInputTextFlags inputFlags = ImGuiInputTextFlags_EnterReturnsTrue |
|
||||
ImGuiInputTextFlags_CallbackAlways |
|
||||
ImGuiInputTextFlags_CallbackHistory;
|
||||
ImGuiInputTextFlags_CallbackHistory |
|
||||
ImGuiInputTextFlags_CallbackCompletion;
|
||||
if (ImGui::InputText("##ChatInput", chatInputBuffer, sizeof(chatInputBuffer), inputFlags, inputCallback, this)) {
|
||||
sendChatMessage(gameHandler);
|
||||
// Close chat input on send so movement keys work immediately.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue