From c7b1a6f53e75218bb9956004680a6cdbea137a59 Mon Sep 17 00:00:00 2001 From: Adam Date: Sun, 16 May 2021 13:23:17 -0400 Subject: [PATCH] Allowed for optional boolean to better match filenames. (#180) --- data/core/common.lua | 16 ++++++------ src/api/system.c | 59 ++++++++++++++++++++++++++++++++------------ 2 files changed, 51 insertions(+), 24 deletions(-) diff --git a/data/core/common.lua b/data/core/common.lua index 5f6e8bc9..05f91111 100644 --- a/data/core/common.lua +++ b/data/core/common.lua @@ -58,10 +58,10 @@ local function compare_score(a, b) return a.score > b.score end -local function fuzzy_match_items(items, needle) +local function fuzzy_match_items(items, needle, files) local res = {} for _, item in ipairs(items) do - local score = system.fuzzy_match(tostring(item), needle) + local score = system.fuzzy_match(tostring(item), needle, files) if score then table.insert(res, { text = item, score = score }) end @@ -74,11 +74,11 @@ local function fuzzy_match_items(items, needle) end -function common.fuzzy_match(haystack, needle) +function common.fuzzy_match(haystack, needle, files) if type(haystack) == "table" then - return fuzzy_match_items(haystack, needle) + return fuzzy_match_items(haystack, needle, files) end - return system.fuzzy_match(haystack, needle) + return system.fuzzy_match(haystack, needle, files) end @@ -86,16 +86,16 @@ function common.fuzzy_match_with_recents(haystack, recents, needle) if needle == "" then local recents_ext = {} for i = 2, #recents do - table.insert(recents_ext, recents[i]) + table.insert(recents_ext, recents[i]) end table.insert(recents_ext, recents[1]) - local others = common.fuzzy_match(haystack, "") + local others = common.fuzzy_match(haystack, "", true) for i = 1, #others do table.insert(recents_ext, others[i]) end return recents_ext else - return fuzzy_match_items(haystack, needle) + return fuzzy_match_items(haystack, needle, true) end end diff --git a/src/api/system.c b/src/api/system.c index 1b15a2ec..89c037c2 100644 --- a/src/api/system.c +++ b/src/api/system.c @@ -517,27 +517,54 @@ static int f_exec(lua_State *L) { static int f_fuzzy_match(lua_State *L) { - const char *str = luaL_checkstring(L, 1); - const char *ptn = luaL_checkstring(L, 2); + size_t strLen, ptnLen; + const char *str = luaL_checklstring(L, 1, &strLen); + const char *ptn = luaL_checklstring(L, 2, &ptnLen); + bool files = false; + if (lua_gettop(L) > 2 && lua_isboolean(L,3)) + files = lua_toboolean(L, 3); + int score = 0; int run = 0; - - while (*str && *ptn) { - while (*str == ' ') { str++; } - while (*ptn == ' ') { ptn++; } - if (tolower(*str) == tolower(*ptn)) { - score += run * 10 - (*str != *ptn); - run++; - ptn++; - } else { - score -= 10; - run = 0; + + // Match things *backwards*. This allows for better matching on filenames than the above + // function. For example, in the lite project, opening "renderer" has lib/font_render/build.sh + // as the first result, rather than src/renderer.c. Clearly that's wrong. + if (files) { + const char* strEnd = str + strLen - 1; + const char* ptnEnd = ptn + ptnLen - 1; + while (strEnd >= str && ptnEnd >= ptn) { + while (*strEnd == ' ') { strEnd--; } + while (*ptnEnd == ' ') { ptnEnd--; } + if (tolower(*strEnd) == tolower(*ptnEnd)) { + score += run * 10 - (*strEnd != *ptnEnd); + run++; + ptnEnd--; + } else { + score -= 10; + run = 0; + } + strEnd--; } - str++; + if (ptnEnd >= ptn) { return 0; } + } else { + while (*str && *ptn) { + while (*str == ' ') { str++; } + while (*ptn == ' ') { ptn++; } + if (tolower(*str) == tolower(*ptn)) { + score += run * 10 - (*str != *ptn); + run++; + ptn++; + } else { + score -= 10; + run = 0; + } + str++; + } + if (*ptn) { return 0; } } - if (*ptn) { return 0; } - lua_pushnumber(L, score - (int) strlen(str)); + lua_pushnumber(L, score - (int)strLen); return 1; }