aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--runtime/doc/dev_vimpatch.txt36
-rw-r--r--runtime/lua/vim/filetype.lua1115
2 files changed, 641 insertions, 510 deletions
diff --git a/runtime/doc/dev_vimpatch.txt b/runtime/doc/dev_vimpatch.txt
index d6e4ced054..6d450424c5 100644
--- a/runtime/doc/dev_vimpatch.txt
+++ b/runtime/doc/dev_vimpatch.txt
@@ -302,4 +302,40 @@ used in new documentation:
- `{Only when compiled with ...}`: the vast majority of features have been
made non-optional (see https://github.com/neovim/neovim/wiki/Introduction)
+==============================================================================
+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).
+
+Pattern matching has several differences:
+- 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.
+
+ 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.
+
+ 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").
+
+ Example:
+ - Filetype pattern: ".*/etc/a2ps/.*%.cfg"
+ - Good parent: "/etc/"; "%.cfg$"
+ - Bad parent: "%." - fast, not specific; "/a2ps/.*%." - slow, specific
+
vim:tw=78:ts=8:noet:ft=help:norl:
diff --git a/runtime/lua/vim/filetype.lua b/runtime/lua/vim/filetype.lua
index 834eb9e89c..b497485b53 100644
--- a/runtime/lua/vim/filetype.lua
+++ b/runtime/lua/vim/filetype.lua
@@ -4,12 +4,13 @@ local fn = vim.fn
local M = {}
--- @alias vim.filetype.mapfn fun(path:string,bufnr:integer, ...):string?, fun(b:integer)?
---- @alias vim.filetype.maptbl [string|vim.filetype.mapfn, {priority:integer}]
+--- @alias vim.filetype.mapopts { parent: string, priority: number }
+--- @alias vim.filetype.maptbl [string|vim.filetype.mapfn, vim.filetype.mapopts]
--- @alias vim.filetype.mapping.value string|vim.filetype.mapfn|vim.filetype.maptbl
--- @alias vim.filetype.mapping table<string,vim.filetype.mapping.value>
--- @param ft string|vim.filetype.mapfn
---- @param opts? {priority:integer}
+--- @param opts? vim.filetype.mapopts
--- @return vim.filetype.maptbl
local function starsetf(ft, opts)
return {
@@ -26,6 +27,9 @@ local function starsetf(ft, opts)
end
end,
{
+ -- Allow setting "parent" to be reused in closures, but don't have default as it will be
+ -- assigned later from grouping
+ parent = opts and opts.parent,
-- Starset matches should have lowest priority by default
priority = (opts and opts.priority) or -math.huge,
},
@@ -1735,497 +1739,556 @@ local filename = {
}
-- Re-use closures as much as possible
-local detect_apache = starsetf('apache')
-local detect_muttrc = starsetf('muttrc')
-local detect_neomuttrc = starsetf('neomuttrc')
+local detect_apache_diretc = starsetf('apache', { parent = '/etc/' })
+local detect_apache_dotconf = starsetf('apache', { parent = '%.conf' })
+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%.'
---- @type vim.filetype.mapping
+--- @type table<string,vim.filetype.mapping>
local pattern = {
-- BEGIN PATTERN
- ['/etc/a2ps/.*%.cfg$'] = 'a2ps',
- ['/etc/a2ps%.cfg$'] = 'a2ps',
- ['/usr/share/alsa/alsa%.conf$'] = 'alsaconf',
- ['/etc/asound%.conf$'] = 'alsaconf',
- ['/etc/apache2/sites%-.*/.*%.com$'] = 'apache',
- ['/etc/httpd/.*%.conf$'] = 'apache',
- ['/etc/apache2/.*%.conf'] = detect_apache,
- ['/etc/apache2/conf%..*/'] = detect_apache,
- ['/etc/apache2/mods%-.*/'] = detect_apache,
- ['/etc/apache2/sites%-.*/'] = detect_apache,
- ['^access%.conf'] = detect_apache,
- ['^apache%.conf'] = detect_apache,
- ['^apache2%.conf'] = detect_apache,
- ['^httpd%.conf'] = detect_apache,
- ['^srm%.conf'] = detect_apache,
- ['/etc/httpd/conf%..*/'] = detect_apache,
- ['/etc/httpd/conf%.d/.*%.conf'] = detect_apache,
- ['/etc/httpd/mods%-.*/'] = detect_apache,
- ['/etc/httpd/sites%-.*/'] = detect_apache,
- ['/etc/proftpd/.*%.conf'] = starsetf('apachestyle'),
- ['/etc/proftpd/conf%..*/'] = starsetf('apachestyle'),
- ['^proftpd%.conf'] = starsetf('apachestyle'),
- ['asterisk/.*%.conf'] = starsetf('asterisk'),
- ['asterisk.*/.*voicemail%.conf'] = starsetf('asteriskvm'),
- ['/%.aptitude/config$'] = 'aptconf',
- ['^[mM]akefile%.am$'] = 'automake',
- ['/bind/db%.'] = starsetf('bindzone'),
- ['/named/db%.'] = starsetf('bindzone'),
- ['/build/conf/.*%.conf$'] = 'bitbake',
- ['/meta/conf/.*%.conf$'] = 'bitbake',
- ['/meta%-.*/conf/.*%.conf$'] = 'bitbake',
- ['%.blade%.php$'] = 'blade',
- ['^bzr_log%.'] = 'bzr',
- ['enlightenment/.*%.cfg$'] = 'c',
- ['/%.cabal/config$'] = 'cabalconfig',
- ['/cabal/config$'] = 'cabalconfig',
- ['^cabal%.project%.'] = starsetf('cabalproject'),
- ['/%.calendar/'] = starsetf('calendar'),
- ['/share/calendar/.*/calendar%.'] = starsetf('calendar'),
- ['/share/calendar/calendar%.'] = starsetf('calendar'),
- ['^sgml%.catalog'] = starsetf('catalog'),
- ['/etc/defaults/cdrdao$'] = 'cdrdaoconf',
- ['/etc/cdrdao%.conf$'] = 'cdrdaoconf',
- ['/etc/default/cdrdao$'] = 'cdrdaoconf',
- ['hgrc$'] = 'cfg',
- ['%.[Cc][Ff][Gg]$'] = {
- detect.cfg,
- -- Decrease priority to avoid conflicts with more specific patterns
- -- such as '.*/etc/a2ps/.*%.cfg', '.*enlightenment/.*%.cfg', etc.
- { priority = -1 },
+ ['/debian/'] = {
+ ['/debian/changelog$'] = 'debchangelog',
+ ['/debian/control$'] = 'debcontrol',
+ ['/debian/copyright$'] = 'debcopyright',
+ ['/debian/patches/'] = detect.dep3patch,
},
- ['^[cC]hange[lL]og'] = starsetf(detect.changelog),
- ['%.%.ch$'] = 'chill',
- ['/etc/translate%-shell$'] = 'clojure',
- ['%.cmake%.in$'] = 'cmake',
- -- */cmus/rc and */.cmus/rc
- ['/%.?cmus/rc$'] = 'cmusrc',
- -- */cmus/*.theme and */.cmus/*.theme
- ['/%.?cmus/.*%.theme$'] = 'cmusrc',
- ['/%.cmus/autosave$'] = 'cmusrc',
- ['/%.cmus/command%-history$'] = 'cmusrc',
- ['/etc/hostname%.'] = starsetf('config'),
- ['^crontab%.'] = starsetf('crontab'),
- ['/etc/cron%.d/'] = starsetf('crontab'),
- ['^%.cshrc'] = detect.csh,
- ['^%.login'] = detect.csh,
- ['^cvs%d+$'] = 'cvs',
- ['%.[Dd][Aa][Tt]$'] = detect.dat,
- ['/debian/patches/'] = detect.dep3patch,
- ['/etc/dnsmasq%.d/'] = starsetf('dnsmasq'),
- ['^Containerfile%.'] = starsetf('dockerfile'),
- ['^Dockerfile%.'] = starsetf('dockerfile'),
- ['/etc/yum%.repos%.d/'] = starsetf('dosini'),
- ['^drac%.'] = starsetf('dracula'),
- ['/debian/changelog$'] = 'debchangelog',
- ['/debian/control$'] = 'debcontrol',
- ['/debian/copyright$'] = 'debcopyright',
- ['/etc/apt/sources%.list%.d/.*%.list$'] = 'debsources',
- ['/etc/apt/sources%.list$'] = 'debsources',
- ['/etc/apt/sources%.list%.d/.*%.sources$'] = 'deb822sources',
- ['^dictd.*%.conf$'] = 'dictdconf',
- ['/etc/DIR_COLORS$'] = 'dircolors',
- ['/etc/dnsmasq%.conf$'] = 'dnsmasq',
- ['^php%.ini%-'] = 'dosini',
- ['/%.aws/config$'] = 'confini',
- ['/%.aws/credentials$'] = 'confini',
- ['/etc/yum%.conf$'] = 'dosini',
- ['/lxqt/.*%.conf$'] = 'dosini',
- ['/screengrab/.*%.conf$'] = 'dosini',
- ['/bpython/config$'] = 'dosini',
- ['/mypy/config$'] = 'dosini',
- ['/flatpak/repo/config$'] = 'dosini',
- ['lvs$'] = 'dracula',
- ['lpe$'] = 'dracula',
- ['/dtrace/.*%.d$'] = 'dtrace',
- ['esmtprc$'] = 'esmtprc',
- ['Eterm/.*%.cfg$'] = 'eterm',
- ['s6.*/up$'] = 'execline',
- ['s6.*/down$'] = 'execline',
- ['s6.*/run$'] = 'execline',
- ['s6.*/finish$'] = 'execline',
- ['^s6%-'] = 'execline',
- ['^[a-zA-Z0-9].*Dict$'] = detect.foam,
- ['^[a-zA-Z0-9].*Dict%.'] = detect.foam,
- ['^[a-zA-Z].*Properties$'] = detect.foam,
- ['^[a-zA-Z].*Properties%.'] = detect.foam,
- ['Transport%.'] = detect.foam,
- ['/constant/g$'] = detect.foam,
- ['/0/'] = detect.foam,
- ['/0%.orig/'] = detect.foam,
- ['/%.fvwm/'] = starsetf('fvwm'),
- ['fvwmrc'] = starsetf(detect.fvwm_v1),
- ['fvwm95.*%.hook$'] = starsetf(detect.fvwm_v1),
- ['fvwm2rc'] = starsetf(detect.fvwm_v2),
- ['/tmp/lltmp'] = starsetf('gedcom'),
- ['/etc/gitconfig%.d/'] = starsetf('gitconfig'),
- ['/gitolite%-admin/conf/'] = starsetf('gitolite'),
- ['^tmac%.'] = starsetf('nroff'),
- ['/%.gitconfig%.d/'] = starsetf('gitconfig'),
- ['%.git/'] = {
- detect.git,
- -- Decrease priority to run after simple pattern checks
- { priority = -1 },
+ ['/etc/'] = {
+ ['/etc/a2ps/.*%.cfg$'] = 'a2ps',
+ ['/etc/a2ps%.cfg$'] = 'a2ps',
+ ['/etc/asound%.conf$'] = 'alsaconf',
+ ['/etc/apache2/sites%-.*/.*%.com$'] = 'apache',
+ ['/etc/httpd/.*%.conf$'] = 'apache',
+ ['/etc/apache2/.*%.conf'] = detect_apache_diretc,
+ ['/etc/apache2/conf%..*/'] = detect_apache_diretc,
+ ['/etc/apache2/mods%-.*/'] = detect_apache_diretc,
+ ['/etc/apache2/sites%-.*/'] = detect_apache_diretc,
+ ['/etc/httpd/conf%..*/'] = detect_apache_diretc,
+ ['/etc/httpd/conf%.d/.*%.conf'] = detect_apache_diretc,
+ ['/etc/httpd/mods%-.*/'] = detect_apache_diretc,
+ ['/etc/httpd/sites%-.*/'] = detect_apache_diretc,
+ ['/etc/proftpd/.*%.conf'] = starsetf('apachestyle'),
+ ['/etc/proftpd/conf%..*/'] = starsetf('apachestyle'),
+ ['/etc/cdrdao%.conf$'] = 'cdrdaoconf',
+ ['/etc/default/cdrdao$'] = 'cdrdaoconf',
+ ['/etc/defaults/cdrdao$'] = 'cdrdaoconf',
+ ['/etc/translate%-shell$'] = 'clojure',
+ ['/etc/hostname%.'] = starsetf('config'),
+ ['/etc/cron%.d/'] = starsetf('crontab'),
+ ['/etc/apt/sources%.list%.d/.*%.sources$'] = 'deb822sources',
+ ['/etc/apt/sources%.list%.d/.*%.list$'] = 'debsources',
+ ['/etc/apt/sources%.list$'] = 'debsources',
+ ['/etc/DIR_COLORS$'] = 'dircolors',
+ ['/etc/dnsmasq%.conf$'] = 'dnsmasq',
+ ['/etc/dnsmasq%.d/'] = starsetf('dnsmasq'),
+ ['/etc/yum%.conf$'] = 'dosini',
+ ['/etc/yum%.repos%.d/'] = starsetf('dosini'),
+ ['/etc/gitconfig%.d/'] = starsetf('gitconfig'),
+ ['/etc/gitconfig$'] = 'gitconfig',
+ ['/etc/gitattributes$'] = 'gitattributes',
+ ['/etc/group$'] = 'group',
+ ['/etc/group%-$'] = 'group',
+ ['/etc/group%.edit$'] = 'group',
+ ['/etc/gshadow%-$'] = 'group',
+ ['/etc/gshadow%.edit$'] = 'group',
+ ['/etc/gshadow$'] = 'group',
+ ['/etc/grub%.conf$'] = 'grub',
+ ['/etc/host%.conf$'] = 'hostconf',
+ ['/etc/hosts%.allow$'] = 'hostsaccess',
+ ['/etc/hosts%.deny$'] = 'hostsaccess',
+ ['/etc/initng/.*/.*%.i$'] = 'initng',
+ ['/etc/libao%.conf$'] = 'libao',
+ ['/etc/.*limits%.conf$'] = 'limits',
+ ['/etc/.*limits%.d/.*%.conf$'] = 'limits',
+ ['/etc/limits$'] = 'limits',
+ ['/etc/logcheck/.*%.d.*/'] = starsetf('logcheck'),
+ ['/etc/login%.access$'] = 'loginaccess',
+ ['/etc/login%.defs$'] = 'logindefs',
+ ['/etc/aliases$'] = 'mailaliases',
+ ['/etc/mail/aliases$'] = 'mailaliases',
+ ['/etc/man%.conf$'] = 'manconf',
+ ['/etc/conf%.modules$'] = 'modconf',
+ ['/etc/modprobe%.'] = starsetf('modconf'),
+ ['/etc/modules%.conf$'] = 'modconf',
+ ['/etc/modules$'] = 'modconf',
+ ['/etc/modutils/'] = starsetf(function(path, bufnr)
+ if fn.executable(fn.expand(path)) ~= 1 then
+ return 'modconf'
+ end
+ end),
+ ['/etc/Muttrc%.d/'] = starsetf('muttrc'),
+ ['/etc/nanorc$'] = 'nanorc',
+ ['/etc/nginx/'] = 'nginx',
+ ['/etc/pam%.conf$'] = 'pamconf',
+ ['/etc/pam%.d/'] = starsetf('pamconf'),
+ ['/etc/passwd%-$'] = 'passwd',
+ ['/etc/shadow$'] = 'passwd',
+ ['/etc/shadow%.edit$'] = 'passwd',
+ ['/etc/passwd$'] = 'passwd',
+ ['/etc/passwd%.edit$'] = 'passwd',
+ ['/etc/shadow%-$'] = 'passwd',
+ ['/etc/pinforc$'] = 'pinfo',
+ ['/etc/protocols$'] = 'protocols',
+ ['/etc/sensors%.d/[^.]'] = starsetf('sensors'),
+ ['/etc/sensors%.conf$'] = 'sensors',
+ ['/etc/sensors3%.conf$'] = 'sensors',
+ ['/etc/services$'] = 'services',
+ ['/etc/serial%.conf$'] = 'setserial',
+ ['/etc/udev/cdsymlinks%.conf$'] = 'sh',
+ ['/etc/profile$'] = detect.sh,
+ ['/etc/slp%.conf$'] = 'slpconf',
+ ['/etc/slp%.reg$'] = 'slpreg',
+ ['/etc/slp%.spi$'] = 'slpspi',
+ ['/etc/sudoers%.d/'] = starsetf('sudoers'),
+ ['/etc/ssh/ssh_config%.d/.*%.conf$'] = 'sshconfig',
+ ['/etc/ssh/sshd_config%.d/.*%.conf$'] = 'sshdconfig',
+ ['/etc/sudoers$'] = 'sudoers',
+ ['/etc/sysctl%.conf$'] = 'sysctl',
+ ['/etc/sysctl%.d/.*%.conf$'] = 'sysctl',
+ ['/etc/systemd/.*%.conf%.d/.*%.conf$'] = 'systemd',
+ ['/etc/systemd/system/.*%.d/.*%.conf$'] = 'systemd',
+ ['/etc/systemd/system/.*%.d/%.#'] = 'systemd',
+ ['/etc/systemd/system/%.#'] = 'systemd',
+ ['/etc/config/'] = starsetf(detect.uci),
+ ['/etc/udev/udev%.conf$'] = 'udevconf',
+ ['/etc/udev/permissions%.d/.*%.permissions$'] = 'udevperm',
+ ['/etc/updatedb%.conf$'] = 'updatedb',
+ ['/etc/init/.*%.conf$'] = 'upstart',
+ ['/etc/init/.*%.override$'] = 'upstart',
+ ['/etc/xinetd%.conf$'] = 'xinetd',
+ ['/etc/xinetd%.d/'] = starsetf('xinetd'),
+ ['/etc/blkid%.tab%.old$'] = 'xml',
+ ['/etc/blkid%.tab$'] = 'xml',
+ ['/etc/xdg/menus/.*%.menu$'] = 'xml',
+ ['/etc/zprofile$'] = 'zsh',
+ },
+ ['/log/'] = {
+ ['/log/auth%.crit$'] = 'messages',
+ ['/log/auth%.err$'] = 'messages',
+ ['/log/auth%.info$'] = 'messages',
+ ['/log/auth%.log$'] = 'messages',
+ ['/log/auth%.notice$'] = 'messages',
+ ['/log/auth%.warn$'] = 'messages',
+ ['/log/auth$'] = 'messages',
+ ['/log/cron%.crit$'] = 'messages',
+ ['/log/cron%.err$'] = 'messages',
+ ['/log/cron%.info$'] = 'messages',
+ ['/log/cron%.log$'] = 'messages',
+ ['/log/cron%.notice$'] = 'messages',
+ ['/log/cron%.warn$'] = 'messages',
+ ['/log/cron$'] = 'messages',
+ ['/log/daemon%.crit$'] = 'messages',
+ ['/log/daemon%.err$'] = 'messages',
+ ['/log/daemon%.info$'] = 'messages',
+ ['/log/daemon%.log$'] = 'messages',
+ ['/log/daemon%.notice$'] = 'messages',
+ ['/log/daemon%.warn$'] = 'messages',
+ ['/log/daemon$'] = 'messages',
+ ['/log/debug%.crit$'] = 'messages',
+ ['/log/debug%.err$'] = 'messages',
+ ['/log/debug%.info$'] = 'messages',
+ ['/log/debug%.log$'] = 'messages',
+ ['/log/debug%.notice$'] = 'messages',
+ ['/log/debug%.warn$'] = 'messages',
+ ['/log/debug$'] = 'messages',
+ ['/log/kern%.crit$'] = 'messages',
+ ['/log/kern%.err$'] = 'messages',
+ ['/log/kern%.info$'] = 'messages',
+ ['/log/kern%.log$'] = 'messages',
+ ['/log/kern%.notice$'] = 'messages',
+ ['/log/kern%.warn$'] = 'messages',
+ ['/log/kern$'] = 'messages',
+ ['/log/lpr%.crit$'] = 'messages',
+ ['/log/lpr%.err$'] = 'messages',
+ ['/log/lpr%.info$'] = 'messages',
+ ['/log/lpr%.log$'] = 'messages',
+ ['/log/lpr%.notice$'] = 'messages',
+ ['/log/lpr%.warn$'] = 'messages',
+ ['/log/lpr$'] = 'messages',
+ ['/log/mail%.crit$'] = 'messages',
+ ['/log/mail%.err$'] = 'messages',
+ ['/log/mail%.info$'] = 'messages',
+ ['/log/mail%.log$'] = 'messages',
+ ['/log/mail%.notice$'] = 'messages',
+ ['/log/mail%.warn$'] = 'messages',
+ ['/log/mail$'] = 'messages',
+ ['/log/messages%.crit$'] = 'messages',
+ ['/log/messages%.err$'] = 'messages',
+ ['/log/messages%.info$'] = 'messages',
+ ['/log/messages%.log$'] = 'messages',
+ ['/log/messages%.notice$'] = 'messages',
+ ['/log/messages%.warn$'] = 'messages',
+ ['/log/messages$'] = 'messages',
+ ['/log/news/news%.crit$'] = 'messages',
+ ['/log/news/news%.err$'] = 'messages',
+ ['/log/news/news%.info$'] = 'messages',
+ ['/log/news/news%.log$'] = 'messages',
+ ['/log/news/news%.notice$'] = 'messages',
+ ['/log/news/news%.warn$'] = 'messages',
+ ['/log/news/news$'] = 'messages',
+ ['/log/syslog%.crit$'] = 'messages',
+ ['/log/syslog%.err$'] = 'messages',
+ ['/log/syslog%.info$'] = 'messages',
+ ['/log/syslog%.log$'] = 'messages',
+ ['/log/syslog%.notice$'] = 'messages',
+ ['/log/syslog%.warn$'] = 'messages',
+ ['/log/syslog$'] = 'messages',
+ ['/log/user%.crit$'] = 'messages',
+ ['/log/user%.err$'] = 'messages',
+ ['/log/user%.info$'] = 'messages',
+ ['/log/user%.log$'] = 'messages',
+ ['/log/user%.notice$'] = 'messages',
+ ['/log/user%.warn$'] = 'messages',
+ ['/log/user$'] = 'messages',
+ },
+ ['/systemd/'] = {
+ ['/%.config/systemd/user/%.#'] = 'systemd',
+ ['/%.config/systemd/user/.*%.d/%.#'] = 'systemd',
+ ['/%.config/systemd/user/.*%.d/.*%.conf$'] = 'systemd',
+ ['/systemd/.*%.automount$'] = 'systemd',
+ ['/systemd/.*%.dnssd$'] = 'systemd',
+ ['/systemd/.*%.link$'] = 'systemd',
+ ['/systemd/.*%.mount$'] = 'systemd',
+ ['/systemd/.*%.netdev$'] = 'systemd',
+ ['/systemd/.*%.network$'] = 'systemd',
+ ['/systemd/.*%.nspawn$'] = 'systemd',
+ ['/systemd/.*%.path$'] = 'systemd',
+ ['/systemd/.*%.service$'] = 'systemd',
+ ['/systemd/.*%.slice$'] = 'systemd',
+ ['/systemd/.*%.socket$'] = 'systemd',
+ ['/systemd/.*%.swap$'] = 'systemd',
+ ['/systemd/.*%.target$'] = 'systemd',
+ ['/systemd/.*%.timer$'] = 'systemd',
+ },
+ ['/usr/'] = {
+ ['/usr/share/alsa/alsa%.conf$'] = 'alsaconf',
+ ['/usr/.*/gnupg/options%.skel$'] = 'gpg',
+ ['/usr/share/upstart/.*%.conf$'] = 'upstart',
+ ['/usr/share/upstart/.*%.override$'] = 'upstart',
+ ['/usr/share/X11/xkb/compat/'] = detect_xkb,
+ ['/usr/share/X11/xkb/geometry/'] = detect_xkb,
+ ['/usr/share/X11/xkb/keycodes/'] = detect_xkb,
+ ['/usr/share/X11/xkb/symbols/'] = detect_xkb,
+ ['/usr/share/X11/xkb/types/'] = detect_xkb,
+ },
+ ['/var/'] = {
+ ['/var/backups/group%.bak$'] = 'group',
+ ['/var/backups/gshadow%.bak$'] = 'group',
+ ['/var/backups/passwd%.bak$'] = 'passwd',
+ ['/var/backups/shadow%.bak$'] = 'passwd',
+ },
+ ['/conf'] = {
+ ['/%.aptitude/config$'] = 'aptconf',
+ ['/build/conf/.*%.conf$'] = 'bitbake',
+ ['/meta%-.*/conf/.*%.conf$'] = 'bitbake',
+ ['/meta/conf/.*%.conf$'] = 'bitbake',
+ ['/%.cabal/config$'] = 'cabalconfig',
+ ['/cabal/config$'] = 'cabalconfig',
+ ['/%.aws/config$'] = 'confini',
+ ['/bpython/config$'] = 'dosini',
+ ['/flatpak/repo/config$'] = 'dosini',
+ ['/mypy/config$'] = 'dosini',
+ ['^${XDG_CONFIG_HOME}/git/config$'] = 'gitconfig',
+ ['%.git/config%.worktree$'] = 'gitconfig',
+ ['%.git/config$'] = 'gitconfig',
+ ['%.git/modules/.*/config$'] = 'gitconfig',
+ ['%.git/modules/config$'] = 'gitconfig',
+ ['%.git/worktrees/.*/config%.worktree$'] = 'gitconfig',
+ ['/%.config/git/config$'] = 'gitconfig',
+ ['/gitolite%-admin/conf/'] = starsetf('gitolite'),
+ ['/%.i3/config$'] = 'i3config',
+ ['/i3/config$'] = 'i3config',
+ ['/supertux2/config$'] = 'lisp',
+ ['/%.mplayer/config$'] = 'mplayerconf',
+ ['/neofetch/config%.conf$'] = 'sh',
+ ['/%.ssh/config$'] = 'sshconfig',
+ ['/%.sway/config$'] = 'swayconfig',
+ ['/sway/config$'] = 'swayconfig',
+ ['/%.cargo/config$'] = 'toml',
+ ['/%.bundle/config$'] = 'yaml',
+ },
+ ['/%.'] = {
+ ['/%.aws/credentials$'] = 'confini',
+ ['/%.gitconfig%.d/'] = starsetf('gitconfig'),
+ ['/%.gnupg/gpg%.conf$'] = 'gpg',
+ ['/%.gnupg/options$'] = 'gpg',
+ ['/%.icewm/menu$'] = 'icemenu',
+ ['/%.libao$'] = 'libao',
+ ['/%.pinforc$'] = 'pinfo',
+ ['/%.cargo/credentials$'] = 'toml',
+ ['/%.init/.*%.override$'] = 'upstart',
+ },
+ ['calendar/'] = {
+ ['/%.calendar/'] = starsetf('calendar'),
+ ['/share/calendar/.*/calendar%.'] = starsetf('calendar'),
+ ['/share/calendar/calendar%.'] = starsetf('calendar'),
+ },
+ ['cmus/'] = {
+ -- */cmus/*.theme and */.cmus/*.theme
+ ['/%.?cmus/.*%.theme$'] = 'cmusrc',
+ -- */cmus/rc and */.cmus/rc
+ ['/%.?cmus/rc$'] = 'cmusrc',
+ ['/%.cmus/autosave$'] = 'cmusrc',
+ ['/%.cmus/command%-history$'] = 'cmusrc',
+ },
+ ['git/'] = {
+ ['%.git/'] = {
+ detect.git,
+ -- Decrease priority to run after simple pattern checks
+ { priority = -1 },
+ },
+ ['^${XDG_CONFIG_HOME}/git/attributes$'] = 'gitattributes',
+ ['%.git/info/attributes$'] = 'gitattributes',
+ ['/%.config/git/attributes$'] = 'gitattributes',
+ ['^${XDG_CONFIG_HOME}/git/ignore$'] = 'gitignore',
+ ['%.git/info/exclude$'] = 'gitignore',
+ ['/%.config/git/ignore$'] = 'gitignore',
+ },
+ ['bash'] = {
+ ['^%.bash[_%-]aliases$'] = detect.bash,
+ ['^%.bash[_%-]history$'] = detect.bash,
+ ['^%.bash[_%-]logout$'] = detect.bash,
+ ['^%.bash[_%-]profile$'] = detect.bash,
+ ['^bash%-fc[%-%.]'] = detect.bash,
+ },
+ ['%.cfg'] = {
+ ['enlightenment/.*%.cfg$'] = 'c',
+ ['Eterm/.*%.cfg$'] = 'eterm',
+ ['baseq[2-3]/.*%.cfg$'] = 'quake',
+ ['id1/.*%.cfg$'] = 'quake',
+ ['quake[1-3]/.*%.cfg$'] = 'quake',
+ ['/tex/latex/.*%.cfg$'] = 'tex',
+ },
+ ['%.conf'] = {
+ ['^proftpd%.conf'] = starsetf('apachestyle'),
+ ['^access%.conf'] = detect_apache_dotconf,
+ ['^apache%.conf'] = detect_apache_dotconf,
+ ['^apache2%.conf'] = detect_apache_dotconf,
+ ['^httpd%.conf'] = detect_apache_dotconf,
+ ['^srm%.conf'] = detect_apache_dotconf,
+ ['asterisk/.*%.conf'] = starsetf('asterisk'),
+ ['asterisk.*/.*voicemail%.conf'] = starsetf('asteriskvm'),
+ ['^dictd.*%.conf$'] = 'dictdconf',
+ ['/lxqt/.*%.conf$'] = 'dosini',
+ ['/screengrab/.*%.conf$'] = 'dosini',
+ ['^${GNUPGHOME}/gpg%.conf$'] = 'gpg',
+ ['/boot/grub/grub%.conf$'] = 'grub',
+ ['^lilo%.conf'] = starsetf('lilo'),
+ ['^named.*%.conf$'] = 'named',
+ ['^rndc.*%.conf$'] = 'named',
+ ['/openvpn/.*/.*%.conf$'] = 'openvpn',
+ ['/%.ssh/.*%.conf$'] = 'sshconfig',
+ ['^%.?tmux.*%.conf$'] = 'tmux',
+ ['^%.?tmux.*%.conf'] = { 'tmux', { priority = -1 } },
+ ['/%.config/upstart/.*%.conf$'] = 'upstart',
+ ['/%.config/upstart/.*%.override$'] = 'upstart',
+ ['/%.init/.*%.conf$'] = 'upstart',
+ ['/xorg%.conf%.d/.*%.conf$'] = detect.xfree86_v4,
+ },
+ ['sst%.meta'] = {
+ ['%.%-sst%.meta$'] = 'sisu',
+ ['%._sst%.meta$'] = 'sisu',
+ ['%.sst%.meta$'] = 'sisu',
+ },
+ ['file'] = {
+ ['^[mM]akefile%.am$'] = 'automake',
+ ['^Containerfile%.'] = starsetf('dockerfile'),
+ ['^Dockerfile%.'] = starsetf('dockerfile'),
+ ['^[jJ]ustfile$'] = 'just',
+ ['[mM]akefile$'] = 'make',
+ ['^[mM]akefile'] = starsetf('make'),
+ ['^[rR]akefile$'] = 'ruby',
+ ['^[rR]akefile'] = starsetf('ruby'),
+ ['^[rR]antfile$'] = 'ruby',
+ ['^%.profile'] = detect.sh,
+ },
+ ['fvwm'] = {
+ ['/%.fvwm/'] = starsetf('fvwm'),
+ ['fvwmrc'] = starsetf(detect.fvwm_v1),
+ ['fvwm95.*%.hook$'] = starsetf(detect.fvwm_v1),
+ ['fvwm2rc'] = starsetf(detect.fvwm_v2),
+ },
+ ['nginx'] = {
+ ['/nginx/.*%.conf$'] = 'nginx',
+ ['/usr/local/nginx/conf/'] = 'nginx',
+ ['nginx%.conf$'] = 'nginx',
+ ['^nginx.*%.conf$'] = 'nginx',
+ },
+ ['require'] = {
+ ['%-requirements%.txt$'] = 'requirements',
+ ['^requirements/.*%.txt$'] = 'requirements',
+ ['^requires/.*%.txt$'] = 'requirements',
+ },
+ ['s6'] = {
+ ['s6.*/down$'] = 'execline',
+ ['s6.*/finish$'] = 'execline',
+ ['s6.*/run$'] = 'execline',
+ ['s6.*/up$'] = 'execline',
+ ['^s6%-'] = 'execline',
+ },
+ ['utt'] = {
+ ['^mutt%-.*%-%w+$'] = 'mail',
+ ['^mutt' .. string.rep('[%w_-]', 6) .. '$'] = 'mail',
+ ['^muttng%-.*%-%w+$'] = 'mail',
+ ['^neomutt%-.*%-%w+$'] = 'mail',
+ ['^neomutt' .. string.rep('[%w_-]', 6) .. '$'] = 'mail',
+ -- muttngrc* and .muttngrc*
+ ['^%.?muttngrc'] = detect_muttrc,
+ -- muttrc* and .muttrc*
+ ['^%.?muttrc'] = detect_muttrc,
+ ['/%.mutt/muttrc'] = detect_muttrc,
+ ['/%.muttng/muttngrc'] = detect_muttrc,
+ ['/%.muttng/muttrc'] = detect_muttrc,
+ ['^Muttngrc$'] = 'muttrc',
+ ['^Muttngrc'] = detect_muttrc,
+ ['^Muttrc$'] = 'muttrc',
+ ['^Muttrc'] = detect_muttrc,
+ -- neomuttrc* and .neomuttrc*
+ ['^%.?neomuttrc'] = detect_neomuttrc,
+ ['/%.neomutt/neomuttrc'] = detect_neomuttrc,
+ ['^Neomuttrc'] = detect_neomuttrc,
+ },
+ ['^%.'] = {
+ ['^%.cshrc'] = detect.csh,
+ ['^%.login'] = detect.csh,
+ ['^%.gitsendemail%.msg%.......$'] = 'gitsendemail',
+ ['^%.kshrc'] = detect.ksh,
+ ['^%.article%.%d+$'] = 'mail',
+ ['^%.letter%.%d+$'] = 'mail',
+ ['^%.reminders'] = starsetf('remind'),
+ ['^%.tcshrc'] = detect.tcsh,
+ ['^%.zcompdump'] = starsetf('zsh'),
+ },
+ ['proj%.user$'] = {
+ ['%.csproj%.user$'] = 'xml',
+ ['%.fsproj%.user$'] = 'xml',
+ ['%.vbproj%.user$'] = 'xml',
+ },
+ [''] = {
+ ['/bind/db%.'] = starsetf('bindzone'),
+ ['/named/db%.'] = starsetf('bindzone'),
+ ['%.blade%.php$'] = 'blade',
+ ['^bzr_log%.'] = 'bzr',
+ ['^cabal%.project%.'] = starsetf('cabalproject'),
+ ['^sgml%.catalog'] = starsetf('catalog'),
+ ['%.[Cc][Ff][Gg]$'] = {
+ detect.cfg,
+ -- Decrease priority to avoid conflicts with more specific patterns
+ -- such as '.*/etc/a2ps/.*%.cfg', '.*enlightenment/.*%.cfg', etc.
+ { priority = -1 },
+ },
+ ['hgrc$'] = 'cfg',
+ ['^[cC]hange[lL]og'] = starsetf(detect.changelog),
+ ['%.%.ch$'] = 'chill',
+ ['%.cmake%.in$'] = 'cmake',
+ ['^crontab%.'] = starsetf('crontab'),
+ ['^cvs%d+$'] = 'cvs',
+ ['%.[Dd][Aa][Tt]$'] = detect.dat,
+ ['^php%.ini%-'] = 'dosini',
+ ['lpe$'] = 'dracula',
+ ['lvs$'] = 'dracula',
+ ['^drac%.'] = starsetf('dracula'),
+ ['/dtrace/.*%.d$'] = 'dtrace',
+ ['esmtprc$'] = 'esmtprc',
+ ['/0%.orig/'] = detect.foam,
+ ['/0/'] = detect.foam,
+ ['/constant/g$'] = detect.foam,
+ ['Transport%.'] = detect.foam,
+ ['^[a-zA-Z0-9].*Dict%.'] = detect.foam,
+ ['^[a-zA-Z0-9].*Dict$'] = detect.foam,
+ ['^[a-zA-Z].*Properties%.'] = detect.foam,
+ ['^[a-zA-Z].*Properties$'] = detect.foam,
+ ['/tmp/lltmp'] = starsetf('gedcom'),
+ ['^gkrellmrc_.$'] = 'gkrellmrc',
+ ['^${GNUPGHOME}/options$'] = 'gpg',
+ ['/boot/grub/menu%.lst$'] = 'grub',
+ -- gtkrc* and .gtkrc*
+ ['^%.?gtkrc'] = starsetf('gtkrc'),
+ ['^${VIMRUNTIME}/doc/.*%.txt$'] = 'help',
+ ['^hg%-editor%-.*%.txt$'] = 'hgcommit',
+ ['%.html%.m4$'] = 'htmlm4',
+ ['^JAM.*%.'] = starsetf('jam'),
+ ['^Prl.*%.'] = starsetf('jam'),
+ ['%.properties_..$'] = 'jproperties',
+ ['%.properties_.._..$'] = 'jproperties',
+ ['%.properties_.._.._'] = starsetf('jproperties'),
+ ['^org%.eclipse%..*%.prefs$'] = 'jproperties',
+ ['^[jt]sconfig.*%.json$'] = 'jsonc',
+ ['^Config%.in%.'] = starsetf('kconfig'),
+ ['^Kconfig%.'] = starsetf('kconfig'),
+ ['%.[Ss][Uu][Bb]$'] = 'krl',
+ ['/ldscripts/'] = 'ld',
+ ['lftp/rc$'] = 'lftp',
+ ['/LiteStep/.*/.*%.rc$'] = 'litestep',
+ ['%.[Ll][Oo][Gg]$'] = detect.log,
+ ['^/tmp/SLRN[0-9A-Z.]+$'] = 'mail',
+ ['^ae%d+%.txt$'] = 'mail',
+ ['^pico%.%d+$'] = 'mail',
+ ['^reportbug%-'] = starsetf('mail'),
+ ['^snd%.%d+$'] = 'mail',
+ ['%.[Mm][Oo][Dd]$'] = detect.mod,
+ ['^rndc.*%.key$'] = 'named',
+ ['%.NS[ACGLMNPS]$'] = 'natural',
+ ['%.[1-9]$'] = detect.nroff,
+ ['^tmac%.'] = starsetf('nroff'),
+ ['%.ml%.cppo$'] = 'ocaml',
+ ['%.mli%.cppo$'] = 'ocaml',
+ ['/octave/history$'] = 'octave',
+ ['%.opam%.locked$'] = 'opam',
+ ['%.opam%.template$'] = 'opam',
+ ['%.[Oo][Pp][Ll]$'] = 'opl',
+ ['^%.?gitolite%.rc$'] = 'perl',
+ ['^example%.gitolite%.rc$'] = 'perl',
+ ['%.php%d$'] = 'php',
+ ['%.[Pp][Rr][Gg]$'] = detect.prg,
+ ['printcap'] = starsetf(function(path, bufnr)
+ return require('vim.filetype.detect').printcap('print')
+ end),
+ ['/queries/.*%.scm$'] = 'query', -- treesitter queries (Neovim only)
+ [',v$'] = 'rcs',
+ ['%.[Ss][Rr][Cc]$'] = detect.src,
+ ['^svn%-commit.*%.tmp$'] = 'svn',
+ ['%.swift%.gyb$'] = 'swiftgyb',
+ ['%.[Ss][Yy][Ss]$'] = detect.sys,
+ ['termcap'] = starsetf(function(path, bufnr)
+ return require('vim.filetype.detect').printcap('term')
+ end),
+ ['%.t%.html$'] = 'tilde',
+ ['%.vhdl_[0-9]'] = starsetf('vhdl'),
+ ['vimrc'] = starsetf('vim'),
+ ['/Xresources/'] = starsetf('xdefaults'),
+ ['/app%-defaults/'] = starsetf('xdefaults'),
+ ['^Xresources'] = starsetf('xdefaults'),
+ -- Increase priority to run before the pattern below
+ ['^XF86Config%-4'] = starsetf(detect.xfree86_v4, { priority = -math.huge + 1 }),
+ ['^XF86Config'] = starsetf(detect.xfree86_v3),
+ ['Xmodmap$'] = 'xmodmap',
+ ['xmodmap'] = starsetf('xmodmap'),
+ -- .zlog* and zlog*
+ ['^%.?zlog'] = starsetf('zsh'),
+ -- .zsh* and zsh*
+ ['^%.?zsh'] = starsetf('zsh'),
+ -- Ignored extension
+ ['~$'] = function(path, bufnr)
+ local short = path:gsub('~+$', '', 1)
+ if path ~= short and short ~= '' then
+ return M.match({ buf = bufnr, filename = fn.fnameescape(short) })
+ end
+ end,
},
- ['%.git/modules/.*/config$'] = 'gitconfig',
- ['%.git/modules/config$'] = 'gitconfig',
- ['%.git/config$'] = 'gitconfig',
- ['/etc/gitconfig$'] = 'gitconfig',
- ['/%.config/git/config$'] = 'gitconfig',
- ['%.git/config%.worktree$'] = 'gitconfig',
- ['%.git/worktrees/.*/config%.worktree$'] = 'gitconfig',
- ['^${XDG_CONFIG_HOME}/git/config$'] = 'gitconfig',
- ['%.git/info/attributes$'] = 'gitattributes',
- ['/etc/gitattributes$'] = 'gitattributes',
- ['/%.config/git/attributes$'] = 'gitattributes',
- ['^${XDG_CONFIG_HOME}/git/attributes$'] = 'gitattributes',
- ['%.git/info/exclude$'] = 'gitignore',
- ['/%.config/git/ignore$'] = 'gitignore',
- ['^${XDG_CONFIG_HOME}/git/ignore$'] = 'gitignore',
- ['^%.gitsendemail%.msg%.......$'] = 'gitsendemail',
- ['^gkrellmrc_.$'] = 'gkrellmrc',
- ['/usr/.*/gnupg/options%.skel$'] = 'gpg',
- ['/%.gnupg/options$'] = 'gpg',
- ['/%.gnupg/gpg%.conf$'] = 'gpg',
- ['^${GNUPGHOME}/options$'] = 'gpg',
- ['^${GNUPGHOME}/gpg%.conf$'] = 'gpg',
- ['/etc/group$'] = 'group',
- ['/etc/gshadow$'] = 'group',
- ['/etc/group%.edit$'] = 'group',
- ['/var/backups/gshadow%.bak$'] = 'group',
- ['/etc/group%-$'] = 'group',
- ['/etc/gshadow%-$'] = 'group',
- ['/var/backups/group%.bak$'] = 'group',
- ['/etc/gshadow%.edit$'] = 'group',
- ['/boot/grub/grub%.conf$'] = 'grub',
- ['/boot/grub/menu%.lst$'] = 'grub',
- ['/etc/grub%.conf$'] = 'grub',
- -- gtkrc* and .gtkrc*
- ['^%.?gtkrc'] = starsetf('gtkrc'),
- ['^${VIMRUNTIME}/doc/.*%.txt$'] = 'help',
- ['^hg%-editor%-.*%.txt$'] = 'hgcommit',
- ['/etc/host%.conf$'] = 'hostconf',
- ['/etc/hosts%.deny$'] = 'hostsaccess',
- ['/etc/hosts%.allow$'] = 'hostsaccess',
- ['%.html%.m4$'] = 'htmlm4',
- ['/%.i3/config$'] = 'i3config',
- ['/i3/config$'] = 'i3config',
- ['/%.icewm/menu$'] = 'icemenu',
- ['/etc/initng/.*/.*%.i$'] = 'initng',
- ['^JAM.*%.'] = starsetf('jam'),
- ['^Prl.*%.'] = starsetf('jam'),
- ['%.properties_..$'] = 'jproperties',
- ['%.properties_.._..$'] = 'jproperties',
- ['^org%.eclipse%..*%.prefs$'] = 'jproperties',
- ['%.properties_.._.._'] = starsetf('jproperties'),
- ['^[jt]sconfig.*%.json$'] = 'jsonc',
- ['^[jJ]ustfile$'] = 'just',
- ['^Kconfig%.'] = starsetf('kconfig'),
- ['^Config%.in%.'] = starsetf('kconfig'),
- ['%.[Ss][Uu][Bb]$'] = 'krl',
- ['^lilo%.conf'] = starsetf('lilo'),
- ['/etc/logcheck/.*%.d.*/'] = starsetf('logcheck'),
- ['/ldscripts/'] = 'ld',
- ['lftp/rc$'] = 'lftp',
- ['/%.libao$'] = 'libao',
- ['/etc/libao%.conf$'] = 'libao',
- ['/etc/.*limits%.conf$'] = 'limits',
- ['/etc/limits$'] = 'limits',
- ['/etc/.*limits%.d/.*%.conf$'] = 'limits',
- ['/supertux2/config$'] = 'lisp',
- ['/LiteStep/.*/.*%.rc$'] = 'litestep',
- ['/etc/login%.access$'] = 'loginaccess',
- ['/etc/login%.defs$'] = 'logindefs',
- ['^%.letter%.%d+$'] = 'mail',
- ['^%.article%.%d+$'] = 'mail',
- ['^/tmp/SLRN[0-9A-Z.]+$'] = 'mail',
- ['^ae%d+%.txt$'] = 'mail',
- ['^pico%.%d+$'] = 'mail',
- ['^mutt%-.*%-%w+$'] = 'mail',
- ['^muttng%-.*%-%w+$'] = 'mail',
- ['^neomutt%-.*%-%w+$'] = 'mail',
- ['^mutt' .. string.rep('[%w_-]', 6) .. '$'] = 'mail',
- ['^neomutt' .. string.rep('[%w_-]', 6) .. '$'] = 'mail',
- ['^snd%.%d+$'] = 'mail',
- ['^reportbug%-'] = starsetf('mail'),
- ['/etc/mail/aliases$'] = 'mailaliases',
- ['/etc/aliases$'] = 'mailaliases',
- ['[mM]akefile$'] = 'make',
- ['^[mM]akefile'] = starsetf('make'),
- ['/etc/man%.conf$'] = 'manconf',
- ['/log/auth$'] = 'messages',
- ['/log/cron$'] = 'messages',
- ['/log/daemon$'] = 'messages',
- ['/log/debug$'] = 'messages',
- ['/log/kern$'] = 'messages',
- ['/log/lpr$'] = 'messages',
- ['/log/mail$'] = 'messages',
- ['/log/messages$'] = 'messages',
- ['/log/news/news$'] = 'messages',
- ['/log/syslog$'] = 'messages',
- ['/log/user$'] = 'messages',
- ['/log/auth%.log$'] = 'messages',
- ['/log/cron%.log$'] = 'messages',
- ['/log/daemon%.log$'] = 'messages',
- ['/log/debug%.log$'] = 'messages',
- ['/log/kern%.log$'] = 'messages',
- ['/log/lpr%.log$'] = 'messages',
- ['/log/mail%.log$'] = 'messages',
- ['/log/messages%.log$'] = 'messages',
- ['/log/news/news%.log$'] = 'messages',
- ['/log/syslog%.log$'] = 'messages',
- ['/log/user%.log$'] = 'messages',
- ['/log/auth%.err$'] = 'messages',
- ['/log/cron%.err$'] = 'messages',
- ['/log/daemon%.err$'] = 'messages',
- ['/log/debug%.err$'] = 'messages',
- ['/log/kern%.err$'] = 'messages',
- ['/log/lpr%.err$'] = 'messages',
- ['/log/mail%.err$'] = 'messages',
- ['/log/messages%.err$'] = 'messages',
- ['/log/news/news%.err$'] = 'messages',
- ['/log/syslog%.err$'] = 'messages',
- ['/log/user%.err$'] = 'messages',
- ['/log/auth%.info$'] = 'messages',
- ['/log/cron%.info$'] = 'messages',
- ['/log/daemon%.info$'] = 'messages',
- ['/log/debug%.info$'] = 'messages',
- ['/log/kern%.info$'] = 'messages',
- ['/log/lpr%.info$'] = 'messages',
- ['/log/mail%.info$'] = 'messages',
- ['/log/messages%.info$'] = 'messages',
- ['/log/news/news%.info$'] = 'messages',
- ['/log/syslog%.info$'] = 'messages',
- ['/log/user%.info$'] = 'messages',
- ['/log/auth%.warn$'] = 'messages',
- ['/log/cron%.warn$'] = 'messages',
- ['/log/daemon%.warn$'] = 'messages',
- ['/log/debug%.warn$'] = 'messages',
- ['/log/kern%.warn$'] = 'messages',
- ['/log/lpr%.warn$'] = 'messages',
- ['/log/mail%.warn$'] = 'messages',
- ['/log/messages%.warn$'] = 'messages',
- ['/log/news/news%.warn$'] = 'messages',
- ['/log/syslog%.warn$'] = 'messages',
- ['/log/user%.warn$'] = 'messages',
- ['/log/auth%.crit$'] = 'messages',
- ['/log/cron%.crit$'] = 'messages',
- ['/log/daemon%.crit$'] = 'messages',
- ['/log/debug%.crit$'] = 'messages',
- ['/log/kern%.crit$'] = 'messages',
- ['/log/lpr%.crit$'] = 'messages',
- ['/log/mail%.crit$'] = 'messages',
- ['/log/messages%.crit$'] = 'messages',
- ['/log/news/news%.crit$'] = 'messages',
- ['/log/syslog%.crit$'] = 'messages',
- ['/log/user%.crit$'] = 'messages',
- ['/log/auth%.notice$'] = 'messages',
- ['/log/cron%.notice$'] = 'messages',
- ['/log/daemon%.notice$'] = 'messages',
- ['/log/debug%.notice$'] = 'messages',
- ['/log/kern%.notice$'] = 'messages',
- ['/log/lpr%.notice$'] = 'messages',
- ['/log/mail%.notice$'] = 'messages',
- ['/log/messages%.notice$'] = 'messages',
- ['/log/news/news%.notice$'] = 'messages',
- ['/log/syslog%.notice$'] = 'messages',
- ['/log/user%.notice$'] = 'messages',
- ['%.[Mm][Oo][Dd]$'] = detect.mod,
- ['/etc/modules%.conf$'] = 'modconf',
- ['/etc/conf%.modules$'] = 'modconf',
- ['/etc/modules$'] = 'modconf',
- ['/etc/modprobe%.'] = starsetf('modconf'),
- ['/etc/modutils/'] = starsetf(function(path, bufnr)
- if fn.executable(fn.expand(path)) ~= 1 then
- return 'modconf'
- end
- end),
- ['^Muttrc$'] = 'muttrc',
- ['^Muttngrc$'] = 'muttrc',
- ['/etc/Muttrc%.d/'] = starsetf('muttrc'),
- ['/%.mplayer/config$'] = 'mplayerconf',
- ['^Muttrc'] = detect_muttrc,
- ['^Muttngrc'] = detect_muttrc,
- -- muttrc* and .muttrc*
- ['^%.?muttrc'] = detect_muttrc,
- -- muttngrc* and .muttngrc*
- ['^%.?muttngrc'] = detect_muttrc,
- ['/%.mutt/muttrc'] = detect_muttrc,
- ['/%.muttng/muttrc'] = detect_muttrc,
- ['/%.muttng/muttngrc'] = detect_muttrc,
- ['^rndc.*%.conf$'] = 'named',
- ['^rndc.*%.key$'] = 'named',
- ['^named.*%.conf$'] = 'named',
- ['/etc/nanorc$'] = 'nanorc',
- ['%.NS[ACGLMNPS]$'] = 'natural',
- ['^Neomuttrc'] = detect_neomuttrc,
- -- neomuttrc* and .neomuttrc*
- ['^%.?neomuttrc'] = detect_neomuttrc,
- ['/%.neomutt/neomuttrc'] = detect_neomuttrc,
- ['^nginx.*%.conf$'] = 'nginx',
- ['/etc/nginx/'] = 'nginx',
- ['nginx%.conf$'] = 'nginx',
- ['/nginx/.*%.conf$'] = 'nginx',
- ['/usr/local/nginx/conf/'] = 'nginx',
- ['%.[1-9]$'] = detect.nroff,
- ['%.ml%.cppo$'] = 'ocaml',
- ['%.mli%.cppo$'] = 'ocaml',
- ['/octave/history$'] = 'octave',
- ['%.opam%.locked$'] = 'opam',
- ['%.opam%.template$'] = 'opam',
- ['/openvpn/.*/.*%.conf$'] = 'openvpn',
- ['%.[Oo][Pp][Ll]$'] = 'opl',
- ['/etc/pam%.conf$'] = 'pamconf',
- ['/etc/pam%.d/'] = starsetf('pamconf'),
- ['/etc/passwd%-$'] = 'passwd',
- ['/etc/shadow$'] = 'passwd',
- ['/etc/shadow%.edit$'] = 'passwd',
- ['/var/backups/shadow%.bak$'] = 'passwd',
- ['/var/backups/passwd%.bak$'] = 'passwd',
- ['/etc/passwd$'] = 'passwd',
- ['/etc/passwd%.edit$'] = 'passwd',
- ['/etc/shadow%-$'] = 'passwd',
- ['^%.?gitolite%.rc$'] = 'perl',
- ['^example%.gitolite%.rc$'] = 'perl',
- ['%.php%d$'] = 'php',
- ['/%.pinforc$'] = 'pinfo',
- ['/etc/pinforc$'] = 'pinfo',
- ['%.[Pp][Rr][Gg]$'] = detect.prg,
- ['/etc/protocols$'] = 'protocols',
- ['printcap'] = starsetf(function(path, bufnr)
- return require('vim.filetype.detect').printcap('print')
- end),
- ['baseq[2-3]/.*%.cfg$'] = 'quake',
- ['quake[1-3]/.*%.cfg$'] = 'quake',
- ['id1/.*%.cfg$'] = 'quake',
- ['/queries/.*%.scm$'] = 'query', -- treesitter queries (Neovim only)
- [',v$'] = 'rcs',
- ['^%.reminders'] = starsetf('remind'),
- ['%-requirements%.txt$'] = 'requirements',
- ['^requirements/.*%.txt$'] = 'requirements',
- ['^requires/.*%.txt$'] = 'requirements',
- ['^[rR]akefile'] = starsetf('ruby'),
- ['^[rR]antfile$'] = 'ruby',
- ['^[rR]akefile$'] = 'ruby',
- ['/etc/sensors%.d/[^.]'] = starsetf('sensors'),
- ['/etc/sensors%.conf$'] = 'sensors',
- ['/etc/sensors3%.conf$'] = 'sensors',
- ['/etc/services$'] = 'services',
- ['/etc/serial%.conf$'] = 'setserial',
- ['/etc/udev/cdsymlinks%.conf$'] = 'sh',
- ['/neofetch/config%.conf$'] = 'sh',
- ['^%.bash[_%-]aliases$'] = detect.bash,
- ['^%.bash[_%-]history$'] = detect.bash,
- ['^%.bash[_%-]logout$'] = detect.bash,
- ['^%.bash[_%-]profile$'] = detect.bash,
- ['^%.kshrc'] = detect.ksh,
- ['^%.profile'] = detect.sh,
- ['/etc/profile$'] = detect.sh,
- ['^bash%-fc[%-%.]'] = detect.bash,
- ['^%.tcshrc'] = detect.tcsh,
- ['/etc/sudoers%.d/'] = starsetf('sudoers'),
- ['%._sst%.meta$'] = 'sisu',
- ['%.%-sst%.meta$'] = 'sisu',
- ['%.sst%.meta$'] = 'sisu',
- ['/etc/slp%.conf$'] = 'slpconf',
- ['/etc/slp%.reg$'] = 'slpreg',
- ['/etc/slp%.spi$'] = 'slpspi',
- ['/etc/ssh/ssh_config%.d/.*%.conf$'] = 'sshconfig',
- ['/%.ssh/config$'] = 'sshconfig',
- ['/%.ssh/.*%.conf$'] = 'sshconfig',
- ['/etc/ssh/sshd_config%.d/.*%.conf$'] = 'sshdconfig',
- ['%.[Ss][Rr][Cc]$'] = detect.src,
- ['/etc/sudoers$'] = 'sudoers',
- ['^svn%-commit.*%.tmp$'] = 'svn',
- ['/sway/config$'] = 'swayconfig',
- ['/%.sway/config$'] = 'swayconfig',
- ['%.swift%.gyb$'] = 'swiftgyb',
- ['%.[Ss][Yy][Ss]$'] = detect.sys,
- ['/etc/sysctl%.conf$'] = 'sysctl',
- ['/etc/sysctl%.d/.*%.conf$'] = 'sysctl',
- ['/systemd/.*%.automount$'] = 'systemd',
- ['/systemd/.*%.dnssd$'] = 'systemd',
- ['/systemd/.*%.link$'] = 'systemd',
- ['/systemd/.*%.mount$'] = 'systemd',
- ['/systemd/.*%.netdev$'] = 'systemd',
- ['/systemd/.*%.network$'] = 'systemd',
- ['/systemd/.*%.nspawn$'] = 'systemd',
- ['/systemd/.*%.path$'] = 'systemd',
- ['/systemd/.*%.service$'] = 'systemd',
- ['/systemd/.*%.slice$'] = 'systemd',
- ['/systemd/.*%.socket$'] = 'systemd',
- ['/systemd/.*%.swap$'] = 'systemd',
- ['/systemd/.*%.target$'] = 'systemd',
- ['/systemd/.*%.timer$'] = 'systemd',
- ['/etc/systemd/.*%.conf%.d/.*%.conf$'] = 'systemd',
- ['/%.config/systemd/user/.*%.d/.*%.conf$'] = 'systemd',
- ['/etc/systemd/system/.*%.d/.*%.conf$'] = 'systemd',
- ['/etc/systemd/system/.*%.d/%.#'] = 'systemd',
- ['/etc/systemd/system/%.#'] = 'systemd',
- ['/%.config/systemd/user/.*%.d/%.#'] = 'systemd',
- ['/%.config/systemd/user/%.#'] = 'systemd',
- ['termcap'] = starsetf(function(path, bufnr)
- return require('vim.filetype.detect').printcap('term')
- end),
- ['/tex/latex/.*%.cfg$'] = 'tex',
- ['%.t%.html$'] = 'tilde',
- ['^%.?tmux.*%.conf$'] = 'tmux',
- ['^%.?tmux.*%.conf'] = { 'tmux', { priority = -1 } },
- ['/%.cargo/config$'] = 'toml',
- ['/%.cargo/credentials$'] = 'toml',
- ['/etc/udev/udev%.conf$'] = 'udevconf',
- ['/etc/udev/permissions%.d/.*%.permissions$'] = 'udevperm',
- ['/etc/updatedb%.conf$'] = 'updatedb',
- ['/%.init/.*%.override$'] = 'upstart',
- ['/usr/share/upstart/.*%.conf$'] = 'upstart',
- ['/%.config/upstart/.*%.override$'] = 'upstart',
- ['/etc/init/.*%.conf$'] = 'upstart',
- ['/etc/init/.*%.override$'] = 'upstart',
- ['/%.config/upstart/.*%.conf$'] = 'upstart',
- ['/%.init/.*%.conf$'] = 'upstart',
- ['/usr/share/upstart/.*%.override$'] = 'upstart',
- ['%.[Ll][Oo][Gg]$'] = detect.log,
- ['/etc/config/'] = starsetf(detect.uci),
- ['%.vhdl_[0-9]'] = starsetf('vhdl'),
- ['/Xresources/'] = starsetf('xdefaults'),
- ['/app%-defaults/'] = starsetf('xdefaults'),
- ['/etc/xinetd%.conf$'] = 'xinetd',
- ['/usr/share/X11/xkb/compat/'] = starsetf('xkb'),
- ['/usr/share/X11/xkb/geometry/'] = starsetf('xkb'),
- ['/usr/share/X11/xkb/keycodes/'] = starsetf('xkb'),
- ['/usr/share/X11/xkb/symbols/'] = starsetf('xkb'),
- ['/usr/share/X11/xkb/types/'] = starsetf('xkb'),
- ['/etc/blkid%.tab$'] = 'xml',
- ['/etc/blkid%.tab%.old$'] = 'xml',
- ['%.vbproj%.user$'] = 'xml',
- ['%.fsproj%.user$'] = 'xml',
- ['%.csproj%.user$'] = 'xml',
- ['/etc/xdg/menus/.*%.menu$'] = 'xml',
- ['Xmodmap$'] = 'xmodmap',
- ['/etc/zprofile$'] = 'zsh',
- ['vimrc'] = starsetf('vim'),
- ['^Xresources'] = starsetf('xdefaults'),
- ['/etc/xinetd%.d/'] = starsetf('xinetd'),
- ['xmodmap'] = starsetf('xmodmap'),
- ['/xorg%.conf%.d/.*%.conf$'] = detect.xfree86_v4,
- -- Increase priority to run before the pattern below
- ['^XF86Config%-4'] = starsetf(detect.xfree86_v4, { priority = -math.huge + 1 }),
- ['^XF86Config'] = starsetf(detect.xfree86_v3),
- ['/%.bundle/config$'] = 'yaml',
- ['^%.zcompdump'] = starsetf('zsh'),
- -- .zlog* and zlog*
- ['^%.?zlog'] = starsetf('zsh'),
- -- .zsh* and zsh*
- ['^%.?zsh'] = starsetf('zsh'),
- -- Ignored extension
- ['~$'] = function(path, bufnr)
- local short = path:gsub('~+$', '', 1)
- if path ~= short and short ~= '' then
- return M.match({ buf = bufnr, filename = fn.fnameescape(short) })
- end
- end,
-- END PATTERN
}
-- luacheck: pop
@@ -2240,7 +2303,13 @@ local function compare_by_priority(a, b)
return a[next(a)][2].priority > b[next(b)][2].priority
end
---- @param t vim.filetype.mapping
+--- @param pat string
+--- @return { has_env: boolean, has_slash: boolean }
+local function parse_pattern(pat)
+ return { has_env = pat:find('%$%b{}') ~= nil, has_slash = pat:find('/') ~= nil }
+end
+
+--- @param t table<string,vim.filetype.mapping>
--- @return vim.filetype.mapping[]
--- @return vim.filetype.mapping[]
local function sort_by_priority(t)
@@ -2248,21 +2317,24 @@ local function sort_by_priority(t)
-- will be processed separately
local pos = {} --- @type vim.filetype.mapping[]
local neg = {} --- @type vim.filetype.mapping[]
- for pat, maptbl in pairs(t) do
- local ft = type(maptbl) == 'table' and maptbl[1] or maptbl
- assert(
- type(ft) == 'string' or type(ft) == 'function',
- 'Expected string or function for filetype'
- )
+ for parent, ft_map in pairs(t) do
+ pattern_lookup[parent] = pattern_lookup[parent] or parse_pattern(parent)
+ for pat, maptbl in pairs(ft_map) do
+ local ft = type(maptbl) == 'table' and maptbl[1] or maptbl
+ assert(
+ type(ft) == 'string' or type(ft) == 'function',
+ 'Expected string or function for filetype'
+ )
- -- Parse pattern for common data and cache it once
- pattern_lookup[pat] = pattern_lookup[pat]
- or { has_env = pat:find('%$%b{}') ~= nil, has_slash = pat:find('/') ~= nil }
+ -- Parse pattern for common data and cache it once
+ pattern_lookup[pat] = pattern_lookup[pat] or parse_pattern(pat)
- local opts = (type(maptbl) == 'table' and type(maptbl[2]) == 'table') and maptbl[2] or {}
- opts.priority = opts.priority or 0
+ local opts = (type(maptbl) == 'table' and type(maptbl[2]) == 'table') and maptbl[2] or {}
+ opts.parent = opts.parent or parent
+ opts.priority = opts.priority or 0
- table.insert(opts.priority >= 0 and pos or neg, { [pat] = { ft, opts } })
+ table.insert(opts.priority >= 0 and pos or neg, { [pat] = { ft, opts } })
+ end
end
table.sort(pos, compare_by_priority)
@@ -2390,8 +2462,10 @@ function M.add(filetypes)
end
for k, v in pairs(filetypes.pattern or {}) do
+ -- Add to "match all" parent pattern (might be better to optimize later or document
+ -- supplying `opts.parent` directly)
-- User patterns are assumed to be implicitly anchored (as in Vim)
- pattern['^' .. normalize_path(k, true) .. '$'] = v
+ pattern['']['^' .. normalize_path(k, true) .. '$'] = v
end
if filetypes.pattern then
@@ -2458,8 +2532,9 @@ end
--- @param path string
--- @param tail string
--- @param pat string
---- @return string|boolean?
-local function match_pattern(name, path, tail, pat)
+--- @param try_all_candidates boolean
+--- @return string?
+local function match_pattern(name, path, tail, pat, try_all_candidates)
local pat_cache = pattern_lookup[pat]
local has_slash = pat_cache.has_slash
@@ -2467,11 +2542,16 @@ local function match_pattern(name, path, tail, pat)
local some_env_missing, expanded = expand_envvar_pattern(pat)
-- If any environment variable is present in the pattern but not set, there is no match
if some_env_missing then
- return false
+ return nil
end
pat, has_slash = expanded, expanded:find('/') ~= nil
end
+ -- Try all possible candidates to make parent patterns not depend on slash presence
+ if try_all_candidates then
+ return (path:match(pat) or name:match(pat) or tail:match(pat))
+ end
+
-- If the pattern contains a / match against the full path, otherwise just the tail
if has_slash then
-- Similar to |autocmd-pattern|, if the pattern contains a '/' then check for a match against
@@ -2487,15 +2567,26 @@ end
--- @param path string
--- @param tail string
--- @param pattern_sorted vim.filetype.mapping[]
+--- @param parent_matches table<string,boolean>
--- @param bufnr integer?
-local function match_pattern_sorted(name, path, tail, pattern_sorted, bufnr)
+local function match_pattern_sorted(name, path, tail, pattern_sorted, parent_matches, bufnr)
for i = 1, #pattern_sorted do
local pat, ft_data = next(pattern_sorted[i])
- local matches = match_pattern(name, path, tail, pat)
- if matches then
- local ft, on_detect = dispatch(ft_data[1], path, bufnr, matches)
- if ft then
- return ft, on_detect
+
+ local parent = ft_data[2].parent
+ local parent_is_matched = parent_matches[parent]
+ if parent_is_matched == nil then
+ parent_matches[parent] = match_pattern(name, path, tail, parent, true) ~= nil
+ parent_is_matched = parent_matches[parent]
+ end
+
+ if parent_is_matched then
+ local matches = match_pattern(name, path, tail, pat, false)
+ if matches then
+ local ft, on_detect = dispatch(ft_data[1], path, bufnr, matches)
+ if ft then
+ return ft, on_detect
+ end
end
end
end
@@ -2594,7 +2685,10 @@ function M.match(args)
end
-- Next, check the file path against available patterns with non-negative priority
- ft, on_detect = match_pattern_sorted(name, path, tail, pattern_sorted_pos, bufnr)
+ -- Cache match results of all parent patterns to improve performance
+ local parent_matches = {}
+ ft, on_detect =
+ match_pattern_sorted(name, path, tail, pattern_sorted_pos, parent_matches, bufnr)
if ft then
return ft, on_detect
end
@@ -2609,7 +2703,8 @@ function M.match(args)
end
-- Next, check patterns with negative priority
- ft, on_detect = match_pattern_sorted(name, path, tail, pattern_sorted_neg, bufnr)
+ ft, on_detect =
+ match_pattern_sorted(name, path, tail, pattern_sorted_neg, parent_matches, bufnr)
if ft then
return ft, on_detect
end