Merge pull request #1507 from ddnet/chat-command-autocomplete

Autocomplete chat commands (fixes #1504)
This commit is contained in:
Dennis Felsing 2019-03-21 19:12:52 +01:00 committed by GitHub
commit 05f927b8ca
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 150 additions and 64 deletions

View file

@ -32,9 +32,19 @@ CChat::CChat()
// reset the container indices, so the text containers can be deleted on reset // reset the container indices, so the text containers can be deleted on reset
m_aLines[i].m_TextContainerIndex = -1; m_aLines[i].m_TextContainerIndex = -1;
} }
#define CHAT_COMMAND(name, params, flags, callback, userdata, help) RegisterCommand(name, params, flags, help);
#include <game/server/ddracechat.h>
m_Commands.sort_range();
OnReset(); OnReset();
} }
void CChat::RegisterCommand(const char *pName, const char *pParams, int flags, const char *pHelp)
{
m_Commands.add_unsorted(CCommand{pName, pParams});
}
void CChat::OnWindowResize() void CChat::OnWindowResize()
{ {
for(int i = 0; i < MAX_LINES; i++) for(int i = 0; i < MAX_LINES; i++)
@ -294,6 +304,73 @@ bool CChat::OnInput(IInput::CEvent Event)
str_copy(m_aCompletionBuffer, m_Input.GetString()+m_PlaceholderOffset, min(static_cast<int>(sizeof(m_aCompletionBuffer)), m_PlaceholderLength+1)); str_copy(m_aCompletionBuffer, m_Input.GetString()+m_PlaceholderOffset, min(static_cast<int>(sizeof(m_aCompletionBuffer)), m_PlaceholderLength+1));
} }
if(m_aCompletionBuffer[0] == '/')
{
CCommand *pCompletionCommand = 0;
const size_t NumCommands = m_Commands.size();
if(m_ReverseTAB)
m_CompletionChosen = (m_CompletionChosen-1 + 2*NumCommands)%(2*NumCommands);
else
m_CompletionChosen = (m_CompletionChosen+1)%(2*NumCommands);
const char *pCommandStart = m_aCompletionBuffer+1;
for(size_t i = 0; i < 2*NumCommands; ++i)
{
int SearchType;
int Index;
if(m_ReverseTAB)
{
SearchType = ((m_CompletionChosen-i +2*NumCommands)%(2*NumCommands))/NumCommands;
Index = (m_CompletionChosen-i + NumCommands )%NumCommands;
}
else
{
SearchType = ((m_CompletionChosen+i)%(2*NumCommands))/NumCommands;
Index = (m_CompletionChosen+i)%NumCommands;
}
auto &Command = m_Commands[Index];
if(str_comp_nocase_num(Command.pName, pCommandStart, str_length(pCommandStart)) == 0)
{
pCompletionCommand = &Command;
m_CompletionChosen = Index+SearchType*NumCommands;
break;
}
}
// insert the command
if(pCompletionCommand)
{
char aBuf[256];
// add part before the name
str_copy(aBuf, m_Input.GetString(), min(static_cast<int>(sizeof(aBuf)), m_PlaceholderOffset+1));
// add the command
str_append(aBuf, "/", sizeof(aBuf));
str_append(aBuf, pCompletionCommand->pName, sizeof(aBuf));
// add separator
const char *pSeparator = pCompletionCommand->pParams[0] == '\0' ? "" : " ";
str_append(aBuf, pSeparator, sizeof(aBuf));
if(*pSeparator)
str_append(aBuf, pSeparator, sizeof(aBuf));
// add part after the name
str_append(aBuf, m_Input.GetString()+m_PlaceholderOffset+m_PlaceholderLength, sizeof(aBuf));
m_PlaceholderLength = str_length(pSeparator)+str_length(pCompletionCommand->pName)+1;
m_OldChatStringLength = m_Input.GetLength();
m_Input.Set(aBuf); // TODO: Use Add instead
m_Input.SetCursorOffset(m_PlaceholderOffset+m_PlaceholderLength);
m_InputUpdate = true;
}
}
else
{
// find next possible name // find next possible name
const char *pCompletionString = 0; const char *pCompletionString = 0;
@ -371,6 +448,7 @@ bool CChat::OnInput(IInput::CEvent Event)
m_InputUpdate = true; m_InputUpdate = true;
} }
} }
}
else else
{ {
// reset name completion process // reset name completion process

View file

@ -60,6 +60,17 @@ class CChat : public CComponent
int m_PlaceholderOffset; int m_PlaceholderOffset;
int m_PlaceholderLength; int m_PlaceholderLength;
struct CCommand
{
const char *pName;
const char *pParams;
bool operator <(const CCommand &Other) const { return str_comp(pName, Other.pName) < 0; }
bool operator <=(const CCommand &Other) const { return str_comp(pName, Other.pName) <= 0; }
bool operator ==(const CCommand &Other) const { return str_comp(pName, Other.pName) == 0; }
};
sorted_array<CCommand> m_Commands;
bool m_ReverseTAB; bool m_ReverseTAB;
struct CHistoryEntry struct CHistoryEntry
@ -85,14 +96,11 @@ public:
CChat(); CChat();
bool IsActive() const { return m_Mode != MODE_NONE; } bool IsActive() const { return m_Mode != MODE_NONE; }
void AddLine(int ClientID, int Team, const char *pLine); void AddLine(int ClientID, int Team, const char *pLine);
void EnableMode(int Team); void EnableMode(int Team);
void Say(int Team, const char *pLine); void Say(int Team, const char *pLine);
void SayChat(const char *pLine); void SayChat(const char *pLine);
void RegisterCommand(const char *pName, const char *pParams, int flags, const char *pHelp);
virtual void OnWindowResize(); virtual void OnWindowResize();
virtual void OnReset(); virtual void OnReset();