diff --git a/changelog.md b/changelog.md
index f5f9eac01820dd4aeda98be12c5606a012873828..16c31605a364c2b92adb08154dc8c8f7fd8b3b13 100644
--- a/changelog.md
+++ b/changelog.md
@@ -14,6 +14,7 @@
 * `CHG` only search first file by `require`
 * `CHG` no longer ignore file names case in Windows
 * `CHG` watching library changes
+* `CHG` completion: improve misspelling results
 * `FIX` runtime errors
 * `FIX` hint: may show param-2 as `self`
 
diff --git a/script/core/matchkey.lua b/script/core/matchkey.lua
index 8397749604227a844f65a44c98f7461e7f0769cf..eb67dac67da9c08a6dbb4e097b09ae1498219659 100644
--- a/script/core/matchkey.lua
+++ b/script/core/matchkey.lua
@@ -1,25 +1,44 @@
+local lowers = {}
+local uppers = {}
+for c in ('abcdefghijklmnopqrstuvwxyz'):gmatch '.' do
+    lowers[c] = true
+    uppers[c:upper()] = true
+end
+
 ---@param input string
 ---@param other string
----@param fast  boolean
----@return boolean isMatch
----@return number  deviation
-return function (input, other, fast)
-    if input == other then
-        return true, 0
+local function isValidFirstChar(input, other)
+    local first = input:sub(1, 1):upper()
+    if first == other:sub(1, 1):upper() then
+        return true
     end
-    if input == '' then
-        return true, 0
+    local pos, char = other:find(first, 2, true)
+    if not pos and uppers[first] then
+        -- word after symbol?
+        if other:find('%A' .. first:lower(), 2) then
+            return true
+        end
     end
-    if #input > #other then
-        return false, 0
+    if not char then
+        return false
+    end
+    -- symbol?
+    if not uppers[char] then
+        return true
+    end
+    -- word boundary?
+    local beforeChar = other:sub(pos - 1, pos - 1)
+    if not uppers[beforeChar] then
+        return true
     end
+    return false
+end
+
+local function isAlmostSame(input, other)
     local lMe = input:lower()
     local lOther = other:lower()
     if lMe == lOther:sub(1, #lMe) then
-        return true, 0
-    end
-    if fast and input:sub(1, 1) ~= other:sub(1, 1) then
-        return false, 0
+        return true
     end
     local chars = {}
     for i = 1, #lOther do
@@ -31,8 +50,35 @@ return function (input, other, fast)
         if chars[c] and chars[c] > 0 then
             chars[c] = chars[c] - 1
         else
-            return false, 0
+            return false
         end
     end
+    return true
+end
+
+---@param input string
+---@param other string
+---@param fast  boolean
+---@return boolean isMatch
+---@return number  deviation
+return function (input, other, fast)
+    if input == other then
+        return true, 0
+    end
+    if input == '' then
+        return true, 0
+    end
+    if #input > #other then
+        return false, 0
+    end
+    if fast and input:sub(1, 1) ~= other:sub(1, 1) then
+        return false, 0
+    end
+    if not isValidFirstChar(input, other) then
+        return false, 0
+    end
+    if not isAlmostSame(input, other) then
+        return false, 0
+    end
     return true, 1
 end
diff --git a/test/completion/common.lua b/test/completion/common.lua
index f2bbe542a89ab35a8ba4c0bb29f4e78e14fa1acf..b3a2a36ae2ed38a4a046b249241b08ac07c2abca 100644
--- a/test/completion/common.lua
+++ b/test/completion/common.lua
@@ -4,6 +4,7 @@ local config = require 'config'
 config.set('Lua.completion.callSnippet',    'Both')
 config.set('Lua.completion.keywordSnippet', 'Both')
 config.set('Lua.completion.workspaceWord',  false)
+config.set('Lua.completion.showWord',       'Enable')
 
 TEST [[
 local zabcde
@@ -215,14 +216,6 @@ loc$
         label = 'local function',
         kind = define.CompletionItemKind.Snippet,
     },
-    {
-        label = 'collectgarbage(opt, ...)',
-        kind = define.CompletionItemKind.Function,
-    },
-    {
-        label = 'collectgarbage(opt, ...)',
-        kind = define.CompletionItemKind.Snippet,
-    },
 }
 
 IgnoreFunction = true
@@ -1443,22 +1436,6 @@ end
         label = 'type',
         kind = define.CompletionItemKind.Event,
     },
-    {
-        label = 'return',
-        kind = define.CompletionItemKind.Event,
-    },
-    {
-        label = 'deprecated',
-        kind = define.CompletionItemKind.Event,
-    },
-    {
-        label = 'meta',
-        kind = define.CompletionItemKind.Event,
-    },
-    {
-        label = 'diagnostic',
-        kind = define.CompletionItemKind.Event,
-    }
 }
 
 TEST [[