Ver Fonte

Fixed autocomplete flickering while typing

Simon Lübeß há 3 anos atrás
pai
commit
c2c7431620

+ 53 - 65
IDE/src/ui/AutoComplete.bf

@@ -1597,70 +1597,22 @@ namespace IDE.ui
 			    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)
-		{	
+		{
 			if (filter.Length == 0)
 				return true;
 
-			char8* entryPtr = entry.Ptr;
-			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)
+			if (filter.Length > entry.Length)
 				return false;
-			int initialLen = initialStrP - (char8*)&initialStr;
-			return (initialLen >= filterLen) && (String.Compare(&initialStr, filterLen, filterPtr, filterLen, true) == 0);
 
-			//*(initialStrP++) = 0;
-			//return strnicmp(filter, initialStr, filterLen) == 0;
+			int score = 0;
+			uint8[256] matches = ?;
+
+			return fts_fuzzy_match(filter.CStr(), entry.CStr(), ref score, &matches, matches.Count);
 		}
 
         void UpdateData(String selectString, bool changedAfterInfo)
@@ -1718,7 +1670,7 @@ namespace IDE.ui
                     for (int i < mAutoCompleteListWidget.mFullEntryList.Count)
                     {
                         var entry = mAutoCompleteListWidget.mFullEntryList[i];
-                        //if (String.Compare(entry.mEntryDisplay, 0, curString, 0, curString.Length, true) == 0)
+
 						if (DoesFilterMatch(entry.mEntryDisplay, curString))
                         {
 							mAutoCompleteListWidget.mEntryList.Add(entry);
@@ -1876,6 +1828,7 @@ namespace IDE.ui
 
 		public void UpdateInfo(String info)
 		{
+			List<uint8> matchIndices = new:ScopedAlloc! .(256);
 			for (var entryView in info.Split('\n'))
 			{
 				StringView entryType = StringView(entryView);
@@ -1886,13 +1839,35 @@ namespace IDE.ui
 					entryDisplay = StringView(entryView, tabPos + 1);
 					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;
-				int docPos = entryDisplay.IndexOf('\x03');
+				int docPos = matches.IndexOf('\x03');
 				if (docPos != -1)
 				{
-					documentation = StringView(entryDisplay, docPos + 1);
-					entryDisplay = StringView(entryDisplay, 0, docPos);
+					documentation = StringView(matches, docPos + 1);
+					matches = StringView(matches, 0, docPos);
 				}
 
 				StringView entryInsert = default;
@@ -1915,15 +1890,27 @@ namespace IDE.ui
 				case "select":
 				default:
 				    {
-						if ((!documentation.IsEmpty) && (mAutoCompleteListWidget != null))
+						if (((!documentation.IsEmpty) || (!matchIndices.IsEmpty)) && (mAutoCompleteListWidget != null))
 						{
 							while (entryIdx < mAutoCompleteListWidget.mEntryList.Count)
 							{
 								let entry = mAutoCompleteListWidget.mEntryList[entryIdx];
 								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);
+
 									break;
 								}
 								entryIdx++;
@@ -2017,6 +2004,7 @@ namespace IDE.ui
 					entryDisplay = StringView(entryView, tabPos + 1);
 					entryType = StringView(entryType, 0, tabPos);
 				}
+
 				StringView matches = default;
 				int matchesPos = entryDisplay.IndexOf('\x02');
 				matchIndices.Clear();
@@ -2027,7 +2015,7 @@ namespace IDE.ui
 
 					for(var sub in matches.Split(','))
 					{
-						if(sub == "X")
+						if(sub.StartsWith('X'))
 							break;
 
 						var result = int64.Parse(sub, .HexNumber);

+ 8 - 0
IDEHelper/BeefProj.toml

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

+ 1 - 1
IDEHelper/Compiler/BfAutoComplete.cpp

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

+ 0 - 4
IDEHelper/Compiler/BfCompiler.cpp

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

+ 1 - 1
IDEHelper/IDEHelper.vcxproj

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

+ 6 - 1
IDEHelper/IDEHelper.vcxproj.filters

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

+ 6 - 0
IDEHelper/Compiler/FtsFuzzyMatch.h → IDEHelper/third_party/FtsFuzzyMatch.h

@@ -47,6 +47,7 @@ namespace fts {
     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
 namespace fts {
@@ -245,6 +246,11 @@ 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_H