1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-08 03:28:20 +02:00

Fixed autocomplete flickering while typing

This commit is contained in:
Simon Lübeß 2021-12-15 11:01:14 +01:00
parent 2a446afc73
commit c2c7431620
7 changed files with 75 additions and 72 deletions

View file

@ -1597,70 +1597,22 @@ namespace IDE.ui
mInvokeWidget.mIgnoreMove += ignoreMove ? 1 : -1; mInvokeWidget.mIgnoreMove += ignoreMove ? 1 : -1;
} }
// IDEHelper/third_party/FtsFuzzyMatch.h
[CallingConvention(.Stdcall), CLink]
static extern bool fts_fuzzy_match(char8* pattern, char8* str, ref int outScore, uint8* matches, int maxMatches);
bool DoesFilterMatch(String entry, String filter) bool DoesFilterMatch(String entry, String filter)
{ {
if (filter.Length == 0) if (filter.Length == 0)
return true; return true;
char8* entryPtr = entry.Ptr; if (filter.Length > entry.Length)
char8* filterPtr = filter.Ptr;
int filterLen = (int)filter.Length;
int entryLen = (int)entry.Length;
bool hasUnderscore = false;
bool checkInitials = filterLen > 1;
for (int i = 0; i < (int)filterLen; i++)
{
char8 c = filterPtr[i];
if (c == '_')
hasUnderscore = true;
else if (filterPtr[i].IsLower)
checkInitials = false;
}
if (hasUnderscore)
//return strnicmp(filter, entry, filterLen) == 0;
return (entryLen >= filterLen) && (String.Compare(entryPtr, filterLen, filterPtr, filterLen, true) == 0);
char8[256] initialStr;
char8* initialStrP = &initialStr;
//String initialStr;
bool prevWasUnderscore = false;
for (int entryIdx = 0; entryIdx < entryLen; entryIdx++)
{
char8 entryC = entryPtr[entryIdx];
if (entryC == '_')
{
prevWasUnderscore = true;
continue;
}
if ((entryIdx == 0) || (prevWasUnderscore) || (entryC.IsUpper) || (entryC.IsDigit))
{
/*if (strnicmp(filter, entry + entryIdx, filterLen) == 0)
return true;*/
if ((entryLen - entryIdx >= filterLen) && (String.Compare(entryPtr + entryIdx, filterLen, filterPtr, filterLen, true) == 0))
return true;
if (checkInitials)
*(initialStrP++) = entryC;
}
prevWasUnderscore = false;
if (filterLen == 1)
break; // Don't check inners for single-character case
}
if (!checkInitials)
return false; return false;
int initialLen = initialStrP - (char8*)&initialStr;
return (initialLen >= filterLen) && (String.Compare(&initialStr, filterLen, filterPtr, filterLen, true) == 0);
//*(initialStrP++) = 0; int score = 0;
//return strnicmp(filter, initialStr, filterLen) == 0; uint8[256] matches = ?;
return fts_fuzzy_match(filter.CStr(), entry.CStr(), ref score, &matches, matches.Count);
} }
void UpdateData(String selectString, bool changedAfterInfo) void UpdateData(String selectString, bool changedAfterInfo)
@ -1718,7 +1670,7 @@ namespace IDE.ui
for (int i < mAutoCompleteListWidget.mFullEntryList.Count) for (int i < mAutoCompleteListWidget.mFullEntryList.Count)
{ {
var entry = mAutoCompleteListWidget.mFullEntryList[i]; var entry = mAutoCompleteListWidget.mFullEntryList[i];
//if (String.Compare(entry.mEntryDisplay, 0, curString, 0, curString.Length, true) == 0)
if (DoesFilterMatch(entry.mEntryDisplay, curString)) if (DoesFilterMatch(entry.mEntryDisplay, curString))
{ {
mAutoCompleteListWidget.mEntryList.Add(entry); mAutoCompleteListWidget.mEntryList.Add(entry);
@ -1876,6 +1828,7 @@ namespace IDE.ui
public void UpdateInfo(String info) public void UpdateInfo(String info)
{ {
List<uint8> matchIndices = new:ScopedAlloc! .(256);
for (var entryView in info.Split('\n')) for (var entryView in info.Split('\n'))
{ {
StringView entryType = StringView(entryView); StringView entryType = StringView(entryView);
@ -1887,12 +1840,34 @@ namespace IDE.ui
entryType = StringView(entryType, 0, tabPos); entryType = StringView(entryType, 0, tabPos);
} }
StringView matches = default;
int matchesPos = entryDisplay.IndexOf('\x02');
matchIndices.Clear();
if (matchesPos != -1)
{
matches = StringView(entryDisplay, matchesPos + 1);
entryDisplay = StringView(entryDisplay, 0, matchesPos);
for(var sub in matches.Split(','))
{
if(sub.StartsWith('X'))
break;
var result = int64.Parse(sub, .HexNumber);
Debug.Assert((result case .Ok(let value)) && value <= uint8.MaxValue);
// TODO(FUZZY): we could save start and length instead of single chars
matchIndices.Add((uint8)result.Value);
}
}
StringView documentation = default; StringView documentation = default;
int docPos = entryDisplay.IndexOf('\x03'); int docPos = matches.IndexOf('\x03');
if (docPos != -1) if (docPos != -1)
{ {
documentation = StringView(entryDisplay, docPos + 1); documentation = StringView(matches, docPos + 1);
entryDisplay = StringView(entryDisplay, 0, docPos); matches = StringView(matches, 0, docPos);
} }
StringView entryInsert = default; StringView entryInsert = default;
@ -1915,15 +1890,27 @@ namespace IDE.ui
case "select": case "select":
default: default:
{ {
if ((!documentation.IsEmpty) && (mAutoCompleteListWidget != null)) if (((!documentation.IsEmpty) || (!matchIndices.IsEmpty)) && (mAutoCompleteListWidget != null))
{ {
while (entryIdx < mAutoCompleteListWidget.mEntryList.Count) while (entryIdx < mAutoCompleteListWidget.mEntryList.Count)
{ {
let entry = mAutoCompleteListWidget.mEntryList[entryIdx]; let entry = mAutoCompleteListWidget.mEntryList[entryIdx];
if ((entry.mEntryDisplay == entryDisplay) && (entry.mEntryType == entryType)) if ((entry.mEntryDisplay == entryDisplay) && (entry.mEntryType == entryType))
{ {
if (entry.mDocumentation == null) if (!matchIndices.IsEmpty)
{
if (entry.mMatchIndices == null)
entry.mMatchIndices = new:(mAutoCompleteListWidget.[Friend]mAlloc) List<uint8>(matchIndices.GetEnumerator());
else
{
entry.mMatchIndices.Clear();
entry.mMatchIndices.AddRange(matchIndices);
}
}
if ((!documentation.IsEmpty) && entry.mDocumentation == null)
entry.mDocumentation = new:(mAutoCompleteListWidget.[Friend]mAlloc) String(documentation); entry.mDocumentation = new:(mAutoCompleteListWidget.[Friend]mAlloc) String(documentation);
break; break;
} }
entryIdx++; entryIdx++;
@ -2017,6 +2004,7 @@ namespace IDE.ui
entryDisplay = StringView(entryView, tabPos + 1); entryDisplay = StringView(entryView, tabPos + 1);
entryType = StringView(entryType, 0, tabPos); entryType = StringView(entryType, 0, tabPos);
} }
StringView matches = default; StringView matches = default;
int matchesPos = entryDisplay.IndexOf('\x02'); int matchesPos = entryDisplay.IndexOf('\x02');
matchIndices.Clear(); matchIndices.Clear();
@ -2027,7 +2015,7 @@ namespace IDE.ui
for(var sub in matches.Split(',')) for(var sub in matches.Split(','))
{ {
if(sub == "X") if(sub.StartsWith('X'))
break; break;
var result = int64.Parse(sub, .HexNumber); var result = int64.Parse(sub, .HexNumber);

View file

@ -508,3 +508,11 @@ Path = "X86Target.h"
[[ProjectFolder.Items]] [[ProjectFolder.Items]]
Type = "Source" Type = "Source"
Path = "X86XmmInfo.cpp" Path = "X86XmmInfo.cpp"
[[ProjectFolder.Items]]
Type = "Folder"
Name = "third_party"
[[ProjectFolder.Items.Items]]
Type = "Source"
Path = "third_party/FtsFuzzyMatch.h"

View file

@ -7,7 +7,7 @@
#include "BfResolvedTypeUtils.h" #include "BfResolvedTypeUtils.h"
#define FTS_FUZZY_MATCH_IMPLEMENTATION #define FTS_FUZZY_MATCH_IMPLEMENTATION
#include "FtsFuzzyMatch.h" #include "../third_party/FtsFuzzyMatch.h"
#pragma warning(disable:4996) #pragma warning(disable:4996)

View file

@ -8007,9 +8007,7 @@ void BfCompiler::GenerateAutocompleteInfo()
} }
std::sort(entries.begin(), entries.end(), [](AutoCompleteEntry* lhs, AutoCompleteEntry* rhs) std::sort(entries.begin(), entries.end(), [](AutoCompleteEntry* lhs, AutoCompleteEntry* rhs)
{ {
// TODO(FUZZY): SORT BY Score
return lhs->mScore > rhs->mScore; return lhs->mScore > rhs->mScore;
//return stricmp(lhs->mDisplay, rhs->mDisplay) < 0;
}); });
String docString; String docString;
@ -8024,8 +8022,6 @@ void BfCompiler::GenerateAutocompleteInfo()
autoCompleteResultString += '@'; autoCompleteResultString += '@';
autoCompleteResultString += String(entry->mDisplay); autoCompleteResultString += String(entry->mDisplay);
// TODO(FUZZY): OUTPUT
// TODO(FUZZY): this is not really efficient
autoCompleteResultString += "\x02"; autoCompleteResultString += "\x02";
for (int i = 0; i < 256; i++) for (int i = 0; i < 256; i++)
{ {

View file

@ -400,7 +400,7 @@
<ClInclude Include="Compiler\BfUtil.h" /> <ClInclude Include="Compiler\BfUtil.h" />
<ClInclude Include="Compiler\BfVarDeclChecker.h" /> <ClInclude Include="Compiler\BfVarDeclChecker.h" />
<ClInclude Include="Compiler\CeMachine.h" /> <ClInclude Include="Compiler\CeMachine.h" />
<ClInclude Include="Compiler\FtsFuzzyMatch.h" /> <ClInclude Include="third_party\FtsFuzzyMatch.h" />
<ClInclude Include="Compiler\MemReporter.h" /> <ClInclude Include="Compiler\MemReporter.h" />
<ClInclude Include="DbgMiniDump.h" /> <ClInclude Include="DbgMiniDump.h" />
<ClInclude Include="Debugger.h" /> <ClInclude Include="Debugger.h" />

View file

@ -24,6 +24,9 @@
<Filter Include="Beef"> <Filter Include="Beef">
<UniqueIdentifier>{83b97406-2f83-49ad-bbbc-3ff70ecda6bb}</UniqueIdentifier> <UniqueIdentifier>{83b97406-2f83-49ad-bbbc-3ff70ecda6bb}</UniqueIdentifier>
</Filter> </Filter>
<Filter Include="third_party">
<UniqueIdentifier>{d36777f2-b326-4a8c-84a3-5c2f39153f75}</UniqueIdentifier>
</Filter>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="Compiler\BfAst.cpp"> <ClCompile Include="Compiler\BfAst.cpp">
@ -399,6 +402,8 @@
<ClInclude Include="Compiler\CeMachine.h"> <ClInclude Include="Compiler\CeMachine.h">
<Filter>Compiler</Filter> <Filter>Compiler</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="Compiler\FtsFuzzyMatch.h" /> <ClInclude Include="third_party\FtsFuzzyMatch.h">
<Filter>third_party</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
</Project> </Project>

View file

@ -47,6 +47,7 @@ namespace fts {
static bool fuzzy_match(char const* pattern, char const* str, int& outScore, uint8_t* matches, int maxMatches); static bool fuzzy_match(char const* pattern, char const* str, int& outScore, uint8_t* matches, int maxMatches);
} }
BF_EXPORT bool BF_CALLTYPE fts_fuzzy_match(char const* pattern, char const* str, int& outScore, uint8_t* matches, int maxMatches);
#ifdef FTS_FUZZY_MATCH_IMPLEMENTATION #ifdef FTS_FUZZY_MATCH_IMPLEMENTATION
namespace fts { namespace fts {
@ -245,6 +246,11 @@ namespace fts {
} }
} // namespace fts } // namespace fts
BF_EXPORT bool BF_CALLTYPE fts_fuzzy_match(char const* pattern, char const* str, int& outScore, uint8_t* matches, int maxMatches)
{
return fts::fuzzy_match(pattern, str, outScore, matches, maxMatches);
}
#endif // FTS_FUZZY_MATCH_IMPLEMENTATION #endif // FTS_FUZZY_MATCH_IMPLEMENTATION
#endif // FTS_FUZZY_MATCH_H #endif // FTS_FUZZY_MATCH_H