aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Clason <c.clason@uni-graz.at>2024-08-03 13:04:47 +0200
committerChristian Clason <c.clason@uni-graz.at>2024-08-03 14:14:42 +0200
commit3b58d93aaeaea363ff1066fc791f5d8af1946218 (patch)
treee68ee09a74dbe8c1ee46aaac2399e3e4d9ec8af4
parent37910f270341d8b36f2f26b6d628274b85e2522b (diff)
downloadrneovim-3b58d93aaeaea363ff1066fc791f5d8af1946218.tar.gz
rneovim-3b58d93aaeaea363ff1066fc791f5d8af1946218.tar.bz2
rneovim-3b58d93aaeaea363ff1066fc791f5d8af1946218.zip
docs(filetype): consolidate comments in dev_vimpatch.txt
-rw-r--r--runtime/doc/dev_vimpatch.txt51
-rw-r--r--runtime/lua/vim/filetype.lua30
2 files changed, 42 insertions, 39 deletions
diff --git a/runtime/doc/dev_vimpatch.txt b/runtime/doc/dev_vimpatch.txt
index a36b2a613b..9a2380b162 100644
--- a/runtime/doc/dev_vimpatch.txt
+++ b/runtime/doc/dev_vimpatch.txt
@@ -308,41 +308,54 @@ used in new documentation:
FILETYPE DETECTION *dev-vimpatch-filetype*
Nvim's filetype detection behavior matches Vim, but is implemented as part of
-|vim.filetype| (see $VIMRUNTIME/lua/vim/filetype.lua).
+|vim.filetype| (see `$VIMRUNTIME/lua/vim/filetype.lua`). The logic is encoded in
+three tables, listed in order of precedence (the first match is returned):
+1. `filename` for literal full path or basename lookup;
+2. `pattern` for matching filenames or paths against |lua-patterns|, optimized
+ for fast lookup;
+3. `extension` for literal extension lookup.
-Prefer explicit filenames/extensions over patterns, especially for case
+Logic that requires checking file contents or buffer variables is implemented
+in `$VIMRUNTIME/lua/vim/filetype/detect.lua`.
+
+When porting filetype patches from Vim, keep the following in mind:
+
+Prefer explicit filenames or extensions over patterns, especially for case
insensitive matches (see https://github.com/neovim/neovim/pull/29800): >
"*[mM]akefile" regex -> "makefile", "Makefile" filenames
"*.js\c" regex -> "js", "jS", "Js", "jS" extensions
Pattern matching has several differences:
-- It is done using explicit Lua patterns (without implicit anchoring) instead
+- It is done using explicit Lua patterns without implicit anchoring instead
of Vim regexes: >
"*/debian/changelog" -> "/debian/changelog$"
"*/bind/db.*" -> "/bind/db%."
<
- Filetype patterns are grouped by their parent pattern to improve matching
- performance. For this to work properly, parent pattern should:
- - Match at least the same set of strings as filetype patterns inside it.
- But not too much more.
- - Be fast to match.
+ performance: If the parent pattern does not match, skip testing all child
+ patterns. Note that unlike leaf patterns, parent patterns do not have
+ special matching behaviour if they contain a `/`.
When adding a new filetype with pattern matching, consider the following:
- If there is already a group with appropriate parent pattern, use it.
- - If there can be a fast and specific enough pattern to group at least
- 3 filetype patterns, add it as a separate grouped entry.
+ - If there can be a fast and specific enough pattern to group at least 3
+ filetype patterns, add it as a separate grouped entry.
- Good new parent pattern should be:
- - Fast. Good rule of thumb is that it should be a short explicit string
- (i.e. no quantifiers or character sets).
- - Specific. Good rules of thumb (from best to worst):
- - Full directory name (like "/etc/", "/log/").
- - Part of a rare enough directory name (like "/conf", "git/").
- - String reasonably rarely used in real full paths (like "nginx").
+ New parent patterns should be
+ - fast: rule of thumb is that it should be a short explicit string
+ (i.e. no quantifiers or character sets);
+ - specific: rules of thumb, in order:
+ - full directory name (e.g., `"/etc/"`, `"/log/"`);
+ - part of a rare enough directory name (e.g., `"/conf"`, `"git/"`);
+ - string rarely used in real full paths (e.g., `"nginx"`).
Example:
- - Filetype pattern: ".*/etc/a2ps/.*%.cfg"
- - Good parent: "/etc/"; "%.cfg$"
- - Bad parent: "%." - fast, not specific; "/a2ps/.*%." - slow, specific
+ - Filetype pattern: `".*/etc/a2ps/.*%.cfg"`
+ - Good parents: `"/etc/"` or `"%.cfg$"`
+ - Bad parents: `"%."` (fast but not specific) or `"/a2ps/.*%."` (specific
+ but slow)
+
+ When modifying an existing regular pattern, make sure that it still fits its
+ group.
vim:tw=78:ts=8:noet:ft=help:norl:
diff --git a/runtime/lua/vim/filetype.lua b/runtime/lua/vim/filetype.lua
index 4192645acb..71a49445de 100644
--- a/runtime/lua/vim/filetype.lua
+++ b/runtime/lua/vim/filetype.lua
@@ -174,9 +174,15 @@ end
-- luacheck: push no unused args
-- luacheck: push ignore 122
--- Filetypes based on file extension
+-- Filetype detection logic is encoded in three tables:
+-- 1. `extension` for literal extension lookup
+-- 2. `filename` for literal full path or basename lookup;
+-- 3. `pattern` for matching filenames or paths against Lua patterns,
+-- optimized for fast lookup.
+-- See `:h dev-vimpatch-filetype` for guidance when porting Vim filetype patches.
+
---@diagnostic disable: unused-local
---- @type vim.filetype.mapping
+---@type vim.filetype.mapping
local extension = {
-- BEGIN EXTENSION
['8th'] = '8th',
@@ -273,8 +279,6 @@ local extension = {
cfm = 'cf',
cfi = 'cf',
hgrc = 'cfg',
- -- Extension match does not conflict with specific patterns such as '.*/etc/a2ps/.*%.cfg', etc.,
- -- as it is done after those are tried to match
cfg = detect.cfg,
cfG = detect.cfg,
cFg = detect.cfg,
@@ -1418,7 +1422,7 @@ local extension = {
-- END EXTENSION
}
---- @type vim.filetype.mapping
+---@type vim.filetype.mapping
local filename = {
-- BEGIN FILENAME
['a2psrc'] = 'a2ps',
@@ -1884,21 +1888,7 @@ local detect_muttrc = starsetf('muttrc', { parent = 'utt' })
local detect_neomuttrc = starsetf('neomuttrc', { parent = 'utt' })
local detect_xkb = starsetf('xkb', { parent = '/usr/' })
---- Table of filetype pattern matching rules grouped by their parent pattern.
----
---- Every filetype pattern match is prefaced with a matching of its parent pattern.
---- If there is no match, skip all matching inside group.
---- Note that unlike leaf patterns, parent patterns do not have special matching behaviour if they
---- contain a `/`.
----
---- When modifying an existing regular pattern, make sure that it still fits its group.
----
---- Vim regexes are converted into explicit Lua patterns (without implicit anchoring):
---- '*/debian/changelog' -> '/debian/changelog$'
---- '*/bind/db.*' -> '/bind/db%.'
----
---- See more info in `:h dev-vimpatch-filetype`.
---- @type table<string,vim.filetype.mapping>
+---@type table<string,vim.filetype.mapping>
local pattern = {
-- BEGIN PATTERN
['/debian/'] = {