-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
vim.glob.to_lpeg doesn't always work as expected #28931
Comments
Patch with added tests for a particular glob with which I discovered the issue: diff --git a/test/functional/lua/glob_spec.lua b/test/functional/lua/glob_spec.lua
index 56cd4c9bb..383e66d33 100644
--- a/test/functional/lua/glob_spec.lua
+++ b/test/functional/lua/glob_spec.lua
@@ -223,6 +223,17 @@ describe('glob', function()
eq(true, match('{[0-9],[a-z]}', '0'))
eq(true, match('{[0-9],[a-z]}', 'a'))
eq(false, match('{[0-9],[a-z]}', 'A'))
+
+ -- glob is from willRename filter in typescript-language-server
+ -- https://github.com/typescript-language-server/typescript-language-server/blob/b224b878652438bcdd639137a6b1d1a6630129e4/src/lsp-server.ts#L266
+ eq(true, match('**/*.{ts,js,jsx,tsx,mjs,mts,cjs,cts}', 'test.js'))
+ eq(true, match('**/*.{ts,js,jsx,tsx,mjs,mts,cjs,cts}', 'test.ts'))
+ eq(true, match('**/*.{ts,js,jsx,tsx,mjs,mts,cjs,cts}', 'test.mts'))
+ eq(true, match('**/*.{ts,js,jsx,tsx,mjs,mts,cjs,cts}', 'test.mjs'))
+ eq(true, match('**/*.{ts,js,jsx,tsx,mjs,mts,cjs,cts}', 'test.cjs'))
+ eq(true, match('**/*.{ts,js,jsx,tsx,mjs,mts,cjs,cts}', 'test.cts'))
+ eq(true, match('**/*.{ts,js,jsx,tsx,mjs,mts,cjs,cts}', 'test.jsx'))
+ eq(true, match('**/*.{ts,js,jsx,tsx,mjs,mts,cjs,cts}', 'test.tsx'))
end)
end)
end) Only last 2 cases do not match. Not sure if I'll be able to figure out how to fix that myself. |
I didn't write the lpeg grammar, I merely moved it into the current file. It was added by @nojnhuh in #23788. I spent some time poking around; this seems to be a problem with greedy matching the first option in the list. -- this fails
eq(true, match('**/*.{ts,tsx}', 'test.tsx'))
-- this succeeds
eq(true, match('**/*.{tsx,ts}', 'test.tsx'))
-- this also succeeds
eq(true, match('**/*.{tsx,ts}', 'test.ts')) I have no idea how to fix this using purely lpeg. Intuitively I want to take the list of items inside the |
I'm very sure why this happens. It's because vim.glob simply translates regex |
This change fixes an issue where glob patterns like `{a,ab}` would not match `ab` because the first option `a` matches, then the end of the string is expected but `b` is found, and LPeg does not backtrack to try the next option `ab` which would match. The fix here is to also append the rest of the pattern to the generated LPeg pattern for each option. This changes a glob `{a,ab}` from being parsed as ("a" or "ab") "end of string" to ("a" "end of string" or "ab" "end of string") Here, matching against `ab` would try the first option, fail to match, then proceed to the next option, and match. The sacrifice this change makes is dropping support for nested `{}` conditions, which VSCode doesn't seem to support or test AFAICT. Fixes neovim#28931 Co-authored-by: Sergey Slipchenko <[email protected]>
This change fixes an issue where glob patterns like `{a,ab}` would not match `ab` because the first option `a` matches, then the end of the string is expected but `b` is found, and LPeg does not backtrack to try the next option `ab` which would match. The fix here is to also append the rest of the pattern to the generated LPeg pattern for each option. This changes a glob `{a,ab}` from being parsed as ("a" or "ab") "end of string" to ("a" "end of string" or "ab" "end of string") Here, matching against `ab` would try the first option, fail to match, then proceed to the next option, and match. The sacrifice this change makes is dropping support for nested `{}` conditions, which VSCode doesn't seem to support or test AFAICT. Fixes #28931 Co-authored-by: Sergey Slipchenko <[email protected]>
Problem
Group conditions do not properly work when there are multiple groups starting with the same substring and the shorter one appears earlier.
For example,
vim.glob.to_lpeg('**/*.{tsx,ts}'):match('test.tsx')
matches, butvim.glob.to_lpeg('**/*.{ts,tsx}'):match('test.tsx')
doesn'tSteps to reproduce
nvim --clean
:lua=vim.glob.to_lpeg('**/*.{tsx,ts}'):match('test.tsx')
(returns 9):lua=vim.glob.to_lpeg('**/*.{ts,tsx}'):match('test.tsx')
(returns nil)Expected behavior
Both of the globs match.
Neovim version (nvim -v)
v0.11.0-dev-57+gcd48b72b6
Vim (not Nvim) behaves the same?
n/a
Operating system/version
Arch Linux
Terminal name/version
kitty 0.34.1
$TERM environment variable
xterm-kitty
Installation
build from repo
The text was updated successfully, but these errors were encountered: