mirror of
https://github.com/ddnet/ddnet.git
synced 2024-11-10 01:58:19 +00:00
Look at command under cursor not at the end of the line
This commit is contained in:
parent
54977d5745
commit
6b0b49e414
|
@ -3155,6 +3155,38 @@ const char *str_find(const char *haystack, const char *needle)
|
|||
return 0;
|
||||
}
|
||||
|
||||
bool str_delimiters_around_offset(const char *haystack, const char *delim, int offset, int *start, int *end)
|
||||
{
|
||||
bool found = true;
|
||||
const char *search = haystack;
|
||||
const int delim_len = str_length(delim);
|
||||
*start = 0;
|
||||
while(str_find(search, delim))
|
||||
{
|
||||
const char *test = str_find(search, delim) + delim_len;
|
||||
int distance = test - haystack;
|
||||
if(distance > offset)
|
||||
break;
|
||||
|
||||
*start = distance;
|
||||
search = test;
|
||||
}
|
||||
if(search == haystack)
|
||||
found = false;
|
||||
|
||||
if(str_find(search, delim))
|
||||
{
|
||||
*end = str_find(search, delim) - haystack;
|
||||
}
|
||||
else
|
||||
{
|
||||
*end = str_length(haystack);
|
||||
found = false;
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
const char *str_rchr(const char *haystack, char needle)
|
||||
{
|
||||
return strrchr(haystack, needle);
|
||||
|
|
|
@ -1605,6 +1605,21 @@ const char *str_find_nocase(const char *haystack, const char *needle);
|
|||
*/
|
||||
const char *str_find(const char *haystack, const char *needle);
|
||||
|
||||
/*
|
||||
Function: str_delimiters_around_offset
|
||||
Parameters:
|
||||
haystack - String to search in
|
||||
needle - String to search for
|
||||
|
||||
Returns:
|
||||
true if both delimiters were found
|
||||
false if a delimiter is missing (it uses haystart start and end as fallback)
|
||||
|
||||
Remarks:
|
||||
- The strings are treated as zero-terminated strings.
|
||||
*/
|
||||
bool str_delimiters_around_offset(const char *haystay, const char *delim, int offset, int *start, int *end);
|
||||
|
||||
/**
|
||||
* Finds the last occurrence of a character
|
||||
*
|
||||
|
|
|
@ -322,19 +322,19 @@ void CGameConsole::CInstance::PossibleCommandsCompleteCallback(int Index, const
|
|||
CGameConsole::CInstance *pInstance = (CGameConsole::CInstance *)pUser;
|
||||
if(pInstance->m_CompletionChosen == Index)
|
||||
{
|
||||
char aCurrent[512];
|
||||
str_truncate(aCurrent, sizeof(aCurrent), pInstance->m_aCompletionBuffer, pInstance->m_CompletionCommandStart);
|
||||
char aBefore[512];
|
||||
str_truncate(aBefore, sizeof(aBefore), pInstance->m_aCompletionBuffer, pInstance->m_CompletionCommandStart);
|
||||
char aBuf[512];
|
||||
str_format(aBuf, sizeof(aBuf), "%s%s", aCurrent, pStr);
|
||||
str_format(aBuf, sizeof(aBuf), "%s%s%s", aBefore, pStr, pInstance->m_aCompletionBuffer + pInstance->m_CompletionCommandEnd);
|
||||
pInstance->m_Input.Set(aBuf);
|
||||
pInstance->m_Input.SetCursorOffset(str_length(pStr) + pInstance->m_CompletionCommandStart);
|
||||
}
|
||||
}
|
||||
|
||||
const char *CGameConsole::CInstance::GetCommand(const char *pInput) const
|
||||
void CGameConsole::CInstance::GetCommand(const char *pInput, char *pCmd, size_t CmdSize)
|
||||
{
|
||||
while(str_find(pInput, ";"))
|
||||
pInput = str_find(pInput, ";") + 1;
|
||||
return pInput;
|
||||
str_delimiters_around_offset(pInput, ";", m_Input.GetCursorOffset(), &m_CompletionCommandStart, &m_CompletionCommandEnd);
|
||||
str_truncate(pCmd, CmdSize, pInput + m_CompletionCommandStart, m_CompletionCommandEnd - m_CompletionCommandStart);
|
||||
}
|
||||
|
||||
static void StrCopyUntilSpace(char *pDest, size_t DestSize, const char *pSrc)
|
||||
|
@ -458,12 +458,12 @@ bool CGameConsole::CInstance::OnInput(const IInput::CEvent &Event)
|
|||
|
||||
if(!m_Searching)
|
||||
{
|
||||
const char *pSearch = GetCommand(m_aCompletionBuffer);
|
||||
m_CompletionCommandStart = pSearch - m_aCompletionBuffer;
|
||||
char aSearch[128];
|
||||
GetCommand(m_aCompletionBuffer, aSearch, sizeof(aSearch));
|
||||
|
||||
// command completion
|
||||
const bool UseTempCommands = m_Type == CGameConsole::CONSOLETYPE_REMOTE && m_pGameConsole->Client()->RconAuthed() && m_pGameConsole->Client()->UseTempRconCommands();
|
||||
int CompletionEnumerationCount = m_pGameConsole->m_pConsole->PossibleCommands(pSearch, m_CompletionFlagmask, UseTempCommands);
|
||||
int CompletionEnumerationCount = m_pGameConsole->m_pConsole->PossibleCommands(aSearch, m_CompletionFlagmask, UseTempCommands);
|
||||
if(m_Type == CGameConsole::CONSOLETYPE_LOCAL || m_pGameConsole->Client()->RconAuthed())
|
||||
{
|
||||
if(CompletionEnumerationCount)
|
||||
|
@ -472,7 +472,7 @@ bool CGameConsole::CInstance::OnInput(const IInput::CEvent &Event)
|
|||
m_CompletionChosen = 0;
|
||||
m_CompletionChosen = (m_CompletionChosen + Direction + CompletionEnumerationCount) % CompletionEnumerationCount;
|
||||
m_CompletionArgumentPosition = 0;
|
||||
m_pGameConsole->m_pConsole->PossibleCommands(pSearch, m_CompletionFlagmask, UseTempCommands, PossibleCommandsCompleteCallback, this);
|
||||
m_pGameConsole->m_pConsole->PossibleCommands(aSearch, m_CompletionFlagmask, UseTempCommands, PossibleCommandsCompleteCallback, this);
|
||||
}
|
||||
else if(m_CompletionChosen != -1)
|
||||
{
|
||||
|
@ -597,8 +597,10 @@ bool CGameConsole::CInstance::OnInput(const IInput::CEvent &Event)
|
|||
|
||||
// find the current command
|
||||
{
|
||||
char aCmd[128];
|
||||
GetCommand(GetString(), aCmd, sizeof(aCmd));
|
||||
char aBuf[IConsole::CMDLINE_LENGTH];
|
||||
StrCopyUntilSpace(aBuf, sizeof(aBuf), GetCommand(GetString()));
|
||||
StrCopyUntilSpace(aBuf, sizeof(aBuf), aCmd);
|
||||
|
||||
const IConsole::CCommandInfo *pCommand = m_pGameConsole->m_pConsole->GetCommandInfo(aBuf, m_CompletionFlagmask,
|
||||
m_Type != CGameConsole::CONSOLETYPE_LOCAL && m_pGameConsole->Client()->RconAuthed() && m_pGameConsole->Client()->UseTempRconCommands());
|
||||
|
@ -1128,7 +1130,9 @@ void CGameConsole::OnRender()
|
|||
Info.m_pOffsetChange = &pConsole->m_CompletionRenderOffsetChange;
|
||||
Info.m_Width = Screen.w;
|
||||
Info.m_TotalWidth = 0.0f;
|
||||
Info.m_pCurrentCmd = pConsole->GetCommand(pConsole->m_aCompletionBuffer);
|
||||
char aCmd[128];
|
||||
pConsole->GetCommand(pConsole->m_aCompletionBuffer, aCmd, sizeof(aCmd));
|
||||
Info.m_pCurrentCmd = aCmd;
|
||||
|
||||
TextRender()->SetCursor(&Info.m_Cursor, InitialX - Info.m_Offset, InitialY + RowHeight + 2.0f, FONT_SIZE, TEXTFLAG_RENDER | TEXTFLAG_STOP_AT_END);
|
||||
Info.m_Cursor.m_LineWidth = std::numeric_limits<float>::max();
|
||||
|
|
|
@ -70,6 +70,7 @@ class CGameConsole : public CComponent
|
|||
float m_CompletionRenderOffsetChange;
|
||||
int m_CompletionArgumentPosition;
|
||||
int m_CompletionCommandStart = 0;
|
||||
int m_CompletionCommandEnd = 0;
|
||||
|
||||
char m_aUser[32];
|
||||
bool m_UserGot;
|
||||
|
@ -114,7 +115,20 @@ class CGameConsole : public CComponent
|
|||
void Dump() REQUIRES(!m_BacklogPendingLock);
|
||||
|
||||
const char *GetString() const { return m_Input.GetString(); }
|
||||
void GetCommand(char *pBuf, size_t Size) const;
|
||||
/**
|
||||
* Gets the command at the current cursor including surrounding spaces.
|
||||
* Commands are split by semicolons.
|
||||
*
|
||||
* So if the current console input is for example "hello; world ;foo"
|
||||
* ^
|
||||
* and the cursor is here -------------/
|
||||
* The result would be " world "
|
||||
*
|
||||
* @param pInput the console input line
|
||||
* @param pCmd the command the cursor is at
|
||||
* @param CmdSize size of the pCmd buffer
|
||||
*/
|
||||
void GetCommand(const char *pInput, char *pCmd, size_t CmdSize);
|
||||
static void PossibleCommandsCompleteCallback(int Index, const char *pStr, void *pUser);
|
||||
static void PossibleArgumentsCompleteCallback(int Index, const char *pStr, void *pUser);
|
||||
|
||||
|
|
|
@ -4,6 +4,62 @@
|
|||
|
||||
#include <game/gamecore.h>
|
||||
|
||||
TEST(Str, StrDelim)
|
||||
{
|
||||
int Start, End;
|
||||
// 0123456
|
||||
// 01234567891111111
|
||||
str_delimiters_around_offset("123;123456789;aaa", ";", 5, &Start, &End);
|
||||
EXPECT_EQ(Start, 4);
|
||||
EXPECT_EQ(End, 13);
|
||||
|
||||
str_delimiters_around_offset("123;123", ";", 1, &Start, &End);
|
||||
EXPECT_EQ(Start, 0);
|
||||
EXPECT_EQ(End, 3);
|
||||
|
||||
str_delimiters_around_offset("---foo---bar---baz---hello", "---", 1, &Start, &End);
|
||||
EXPECT_EQ(Start, 0);
|
||||
EXPECT_EQ(End, 0);
|
||||
|
||||
str_delimiters_around_offset("---foo---bar---baz---hello", "---", 2, &Start, &End);
|
||||
EXPECT_EQ(Start, 0);
|
||||
EXPECT_EQ(End, 0);
|
||||
|
||||
str_delimiters_around_offset("---foo---bar---baz---hello", "---", 3, &Start, &End);
|
||||
EXPECT_EQ(Start, 3);
|
||||
EXPECT_EQ(End, 6);
|
||||
|
||||
str_delimiters_around_offset("---foo---bar---baz---hello", "---", 4, &Start, &End);
|
||||
EXPECT_EQ(Start, 3);
|
||||
EXPECT_EQ(End, 6);
|
||||
|
||||
str_delimiters_around_offset("---foo---bar---baz---hello", "---", 9, &Start, &End);
|
||||
EXPECT_EQ(Start, 9);
|
||||
EXPECT_EQ(End, 12);
|
||||
|
||||
str_delimiters_around_offset("---foo---bar---baz---hello", "---", 22, &Start, &End);
|
||||
EXPECT_EQ(Start, 21);
|
||||
EXPECT_EQ(End, 26);
|
||||
|
||||
str_delimiters_around_offset("foo;;;;bar;;;;;;", ";", 2, &Start, &End);
|
||||
EXPECT_EQ(Start, 0);
|
||||
EXPECT_EQ(End, 3);
|
||||
|
||||
str_delimiters_around_offset("foo;;;;bar;;;;;;", ";", 3, &Start, &End);
|
||||
EXPECT_EQ(Start, 0);
|
||||
EXPECT_EQ(End, 3);
|
||||
|
||||
bool Found = str_delimiters_around_offset("foo;;;;bar;;;;;;", ";", 4, &Start, &End);
|
||||
EXPECT_EQ(Found, true);
|
||||
EXPECT_EQ(Start, 4);
|
||||
EXPECT_EQ(End, 4);
|
||||
|
||||
Found = str_delimiters_around_offset("", ";", 4, &Start, &End);
|
||||
EXPECT_EQ(Found, false);
|
||||
EXPECT_EQ(Start, 0);
|
||||
EXPECT_EQ(End, 0);
|
||||
}
|
||||
|
||||
TEST(Str, StrIsNum)
|
||||
{
|
||||
EXPECT_EQ(str_isnum('/'), false);
|
||||
|
|
Loading…
Reference in a new issue