diff options
author | Evgeni Chasnovski <evgeni.chasnovski@gmail.com> | 2024-07-18 18:26:27 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-07-18 10:26:27 -0500 |
commit | f61efe3fe77c9a517dccb9fd5ff7f16c0660ced4 (patch) | |
tree | 72dcf702742df872d28a50bad82434e590e30e73 /runtime/lua/vim | |
parent | c69ea53c9d73a29f504043cc38d4e9fac076f93b (diff) | |
download | rneovim-f61efe3fe77c9a517dccb9fd5ff7f16c0660ced4.tar.gz rneovim-f61efe3fe77c9a517dccb9fd5ff7f16c0660ced4.tar.bz2 rneovim-f61efe3fe77c9a517dccb9fd5ff7f16c0660ced4.zip |
perf(filetype): implement parent pattern pre-matching (#29660)
Problem: calling `vim.filetype.match()` has performance bottleneck in
that it has to match a lot of Lua patterns against several versions of
input file name. This might be the problem if users need to call it
synchronously a lot of times.
Solution: add "parent pattern pre-matching" which can be used to quickly
reject several potential pattern matches at (usually rare) cost of
adding time for one extra Lua pattern match.
"Parent pattern" is a manually added/tracked grouping of filetype
patterns which should have two properties:
- Match at least the same set of strings as its filetype patterns.
But not too much more.
- Be fast to match.
For them to be effective, group should consist from at least three
filetype patterns.
Example: for a filetpye pattern ".*/etc/a2ps/.*%.cfg", both "/etc/"
and "%.cfg" are good parent patterns (prefer the one which can group
more filetype patterns).
After this commit, `vim.filetype.match()` on most inputs runs ~3.4
times faster (while some inputs may see less impact if they match
many parent patterns).
Diffstat (limited to 'runtime/lua/vim')
-rw-r--r-- | runtime/lua/vim/filetype.lua | 1115 |
1 files changed, 605 insertions, 510 deletions
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 |