local api = vim.api local fn = vim.fn local M = {} --- @alias vim.filetype.mapfn fun(path:string,bufnr:integer, ...):string?, fun(b:integer)? --- @alias vim.filetype.maptbl {[1]:string|vim.filetype.mapfn, [2]:{priority:integer}} --- @alias vim.filetype.mapping.value string|vim.filetype.mapfn|vim.filetype.maptbl --- @alias vim.filetype.mapping table --- @param ft string|vim.filetype.mapfn --- @param opts? {priority:integer} --- @return vim.filetype.maptbl local function starsetf(ft, opts) return { function(path, bufnr) -- Note: when `ft` is a function its return value may be nil. local f = type(ft) ~= 'function' and ft or ft(path, bufnr) if not vim.g.ft_ignore_pat then return f end local re = vim.regex(vim.g.ft_ignore_pat) if not re:match_str(path) then return f end end, { -- Starset matches should have lowest priority by default priority = (opts and opts.priority) or -math.huge, }, } end ---@private --- Get a line range from the buffer. ---@param bufnr integer The buffer to get the lines from ---@param start_lnum integer|nil The line number of the first line (inclusive, 1-based) ---@param end_lnum integer|nil The line number of the last line (inclusive, 1-based) ---@return string[] # Array of lines function M._getlines(bufnr, start_lnum, end_lnum) if start_lnum then return api.nvim_buf_get_lines(bufnr, start_lnum - 1, end_lnum or start_lnum, false) end -- Return all lines return api.nvim_buf_get_lines(bufnr, 0, -1, false) end ---@private --- Get a single line from the buffer. ---@param bufnr integer The buffer to get the lines from ---@param start_lnum integer The line number of the first line (inclusive, 1-based) ---@return string function M._getline(bufnr, start_lnum) -- Return a single line return api.nvim_buf_get_lines(bufnr, start_lnum - 1, start_lnum, false)[1] or '' end ---@private --- Check whether a string matches any of the given Lua patterns. --- ---@param s string? The string to check ---@param patterns string[] A list of Lua patterns ---@return boolean `true` if s matched a pattern, else `false` function M._findany(s, patterns) if not s then return false end for _, v in ipairs(patterns) do if s:find(v) then return true end end return false end ---@private --- Get the next non-whitespace line in the buffer. --- ---@param bufnr integer The buffer to get the line from ---@param start_lnum integer The line number of the first line to start from (inclusive, 1-based) ---@return string|nil The first non-blank line if found or `nil` otherwise function M._nextnonblank(bufnr, start_lnum) for _, line in ipairs(M._getlines(bufnr, start_lnum, -1)) do if not line:find('^%s*$') then return line end end return nil end do --- @type table local regex_cache = {} ---@private --- Check whether the given string matches the Vim regex pattern. --- @param s string? --- @param pattern string --- @return boolean function M._matchregex(s, pattern) if not s then return false end if not regex_cache[pattern] then regex_cache[pattern] = vim.regex(pattern) end return regex_cache[pattern]:match_str(s) ~= nil end end --- @module 'vim.filetype.detect' local detect = setmetatable({}, { --- @param k string --- @param t table --- @return function __index = function(t, k) t[k] = function(...) return require('vim.filetype.detect')[k](...) end return t[k] end, }) --- @param ... string|vim.filetype.mapfn --- @return vim.filetype.mapfn local function detect_seq(...) local candidates = { ... } return function(...) for _, c in ipairs(candidates) do if type(c) == 'string' then return c end if type(c) == 'function' then local r = c(...) if r then return r end end end end end local function detect_noext(path, bufnr) local root = fn.fnamemodify(path, ':r') if root == path then return end return M.match({ buf = bufnr, filename = root }) end --- @param pat string --- @param a string? --- @param b string? --- @return vim.filetype.mapfn local function detect_line1(pat, a, b) return function(_path, bufnr) if M._getline(bufnr, 1):find(pat) then return a end return b end end --- @type vim.filetype.mapfn local detect_rc = function(path, _bufnr) if not path:find('/etc/Muttrc%.d/') then return 'rc' end end -- luacheck: push no unused args -- luacheck: push ignore 122 -- Filetypes based on file extension ---@diagnostic disable: unused-local --- @type vim.filetype.mapping local extension = { -- BEGIN EXTENSION ['8th'] = '8th', a65 = 'a65', aap = 'aap', abap = 'abap', abc = 'abc', abl = 'abel', wrm = 'acedb', ads = 'ada', ada = 'ada', gpr = 'ada', adb = 'ada', tdf = 'ahdl', aidl = 'aidl', aml = 'aml', run = 'ampl', scpt = 'applescript', ino = 'arduino', pde = 'arduino', art = 'art', asciidoc = 'asciidoc', adoc = 'asciidoc', asa = function(path, bufnr) if vim.g.filetype_asa then return vim.g.filetype_asa end return 'aspvbs' end, asm = detect.asm, lst = detect.asm, mac = detect.asm, asn1 = 'asn', asn = 'asn', asp = detect.asp, astro = 'astro', atl = 'atlas', as = 'atlas', zed = 'authzed', ahk = 'autohotkey', au3 = 'autoit', ave = 'ave', gawk = 'awk', awk = 'awk', ref = 'b', imp = 'b', mch = 'b', bas = detect.bas, bass = 'bass', bi = detect.bas, bm = detect.bas, bc = 'bc', bdf = 'bdf', beancount = 'beancount', bib = 'bib', com = detect_seq(detect.bindzone, 'dcl'), db = detect.bindzone, bicep = 'bicep', bicepparam = 'bicep', bb = 'bitbake', bbappend = 'bitbake', bbclass = 'bitbake', bl = 'blank', blp = 'blueprint', bp = 'bp', bsd = 'bsdl', bsdl = 'bsdl', bst = 'bst', btm = function(path, bufnr) return (vim.g.dosbatch_syntax_for_btm and vim.g.dosbatch_syntax_for_btm ~= 0) and 'dosbatch' or 'btm' end, bzl = 'bzl', bazel = 'bzl', BUILD = 'bzl', mdh = 'c', epro = 'c', qc = 'c', cabal = 'cabal', cairo = 'cairo', capnp = 'capnp', cdc = 'cdc', cdl = 'cdl', toc = detect_line1('\\contentsline', 'tex', 'cdrtoc'), cfc = 'cf', cfm = 'cf', cfi = 'cf', hgrc = 'cfg', chf = 'ch', chai = 'chaiscript', ch = detect.change, chs = 'chaskell', chatito = 'chatito', chopro = 'chordpro', crd = 'chordpro', crdpro = 'chordpro', cho = 'chordpro', chordpro = 'chordpro', ck = 'chuck', eni = 'cl', icl = 'clean', cljx = 'clojure', clj = 'clojure', cljc = 'clojure', cljs = 'clojure', cook = 'cook', cmake = 'cmake', cmod = 'cmod', lib = 'cobol', cob = 'cobol', cbl = 'cobol', atg = 'coco', recipe = 'conaryrecipe', ctags = 'conf', hook = function(path, bufnr) return M._getline(bufnr, 1) == '[Trigger]' and 'confini' or nil end, nmconnection = 'confini', mklx = 'context', mkiv = 'context', mkii = 'context', mkxl = 'context', mkvi = 'context', control = detect.control, copyright = detect.copyright, corn = 'corn', csh = detect.csh, cpon = 'cpon', moc = 'cpp', hh = 'cpp', tlh = 'cpp', inl = 'cpp', ipp = 'cpp', ['c++'] = 'cpp', C = 'cpp', cxx = 'cpp', H = 'cpp', tcc = 'cpp', hxx = 'cpp', hpp = 'cpp', ccm = 'cpp', cppm = 'cpp', cxxm = 'cpp', ['c++m'] = 'cpp', cpp = detect.cpp, cc = detect.cpp, cql = 'cqlang', crm = 'crm', cr = 'crystal', csx = 'cs', cs = 'cs', csc = 'csc', csdl = 'csdl', cshtml = 'html', fdr = 'csp', csp = 'csp', css = 'css', csv = 'csv', con = 'cterm', feature = 'cucumber', cuh = 'cuda', cu = 'cuda', cue = 'cue', pld = 'cupl', si = 'cuplsim', cyn = 'cynpp', cypher = 'cypher', dfy = 'dafny', dart = 'dart', drt = 'dart', ds = 'datascript', dcd = 'dcd', decl = detect.decl, dec = detect.decl, dcl = detect_seq(detect.decl, 'clean'), def = detect.def, desc = 'desc', directory = 'desktop', desktop = 'desktop', dhall = 'dhall', diff = 'diff', rej = 'diff', Dockerfile = 'dockerfile', dockerfile = 'dockerfile', bat = 'dosbatch', wrap = 'dosini', ini = 'dosini', INI = 'dosini', vbp = 'dosini', dot = 'dot', gv = 'dot', drac = 'dracula', drc = 'dracula', dtd = 'dtd', d = detect.dtrace, dts = 'dts', dtsi = 'dts', dtso = 'dts', its = 'dts', keymap = 'dts', dylan = 'dylan', intr = 'dylanintr', lid = 'dylanlid', e = detect.e, E = detect.e, ecd = 'ecd', edf = 'edif', edif = 'edif', edo = 'edif', edn = detect.edn, eex = 'eelixir', leex = 'eelixir', am = 'elf', exs = 'elixir', elm = 'elm', lc = 'elsa', elv = 'elvish', ent = detect.ent, epp = 'epuppet', erl = 'erlang', hrl = 'erlang', yaws = 'erlang', erb = 'eruby', rhtml = 'eruby', esdl = 'esdl', ec = 'esqlc', EC = 'esqlc', strl = 'esterel', eu = detect.euphoria, EU = detect.euphoria, ew = detect.euphoria, EW = detect.euphoria, EX = detect.euphoria, exu = detect.euphoria, EXU = detect.euphoria, exw = detect.euphoria, EXW = detect.euphoria, ex = detect.ex, exp = 'expect', f = detect.f, factor = 'factor', fal = 'falcon', fan = 'fan', fwt = 'fan', fnl = 'fennel', m4gl = 'fgl', ['4gl'] = 'fgl', ['4gh'] = 'fgl', fir = 'firrtl', fish = 'fish', focexec = 'focexec', fex = 'focexec', ft = 'forth', fth = 'forth', ['4th'] = 'forth', FOR = 'fortran', f77 = 'fortran', f03 = 'fortran', fortran = 'fortran', F95 = 'fortran', f90 = 'fortran', F03 = 'fortran', fpp = 'fortran', FTN = 'fortran', ftn = 'fortran', ['for'] = 'fortran', F90 = 'fortran', F77 = 'fortran', f95 = 'fortran', FPP = 'fortran', F = 'fortran', F08 = 'fortran', f08 = 'fortran', fpc = 'fpcmake', fsl = 'framescript', frm = detect.frm, fb = 'freebasic', fs = detect.fs, fsh = 'fsh', fsi = 'fsharp', fsx = 'fsharp', fc = 'func', fusion = 'fusion', gdb = 'gdb', gdmo = 'gdmo', mo = 'gdmo', tscn = 'gdresource', tres = 'gdresource', gd = 'gdscript', gdshader = 'gdshader', shader = 'gdshader', ged = 'gedcom', gmi = 'gemtext', gemini = 'gemtext', gift = 'gift', gleam = 'gleam', glsl = 'glsl', gn = 'gn', gni = 'gn', gnuplot = 'gnuplot', gpi = 'gnuplot', go = 'go', gp = 'gp', gs = 'grads', gql = 'graphql', graphql = 'graphql', graphqls = 'graphql', gretl = 'gretl', gradle = 'groovy', groovy = 'groovy', gsp = 'gsp', gjs = 'javascript.glimmer', gts = 'typescript.glimmer', gyp = 'gyp', gypi = 'gyp', hack = 'hack', hackpartial = 'hack', haml = 'haml', hsm = 'hamster', hbs = 'handlebars', ha = 'hare', ['hs-boot'] = 'haskell', hsig = 'haskell', hsc = 'haskell', hs = 'haskell', persistentmodels = 'haskellpersistent', ht = 'haste', htpp = 'hastepreproc', hcl = 'hcl', hb = 'hb', h = detect.header, sum = 'hercules', errsum = 'hercules', ev = 'hercules', vc = 'hercules', heex = 'heex', hex = 'hex', ['a43'] = 'hex', ['a90'] = 'hex', ['h32'] = 'hex', ['h80'] = 'hex', ['h86'] = 'hex', ihex = 'hex', ihe = 'hex', ihx = 'hex', int = 'hex', mcs = 'hex', hjson = 'hjson', m3u = 'hlsplaylist', m3u8 = 'hlsplaylist', hog = 'hog', hws = 'hollywood', hoon = 'hoon', cpt = detect.html, dtml = detect.html, htm = detect.html, html = detect.html, pt = detect.html, shtml = detect.html, stm = detect.html, htt = 'httest', htb = 'httest', hurl = 'hurl', hw = detect.hw, module = detect.hw, pkg = detect.hw, iba = 'ibasic', ibi = 'ibasic', icn = 'icon', idl = detect.idl, inc = detect.inc, inf = 'inform', INF = 'inform', ii = 'initng', inko = 'inko', inp = detect.inp, ms = detect_seq(detect.nroff, 'xmath'), iss = 'iss', mst = 'ist', ist = 'ist', ijs = 'j', JAL = 'jal', jal = 'jal', jpr = 'jam', jpl = 'jam', janet = 'janet', jav = 'java', java = 'java', jj = 'javacc', jjt = 'javacc', es = 'javascript', mjs = 'javascript', javascript = 'javascript', js = 'javascript', jsm = 'javascript', cjs = 'javascript', jsx = 'javascriptreact', clp = 'jess', jgr = 'jgraph', jjdescription = 'jj', j73 = 'jovial', jov = 'jovial', jovial = 'jovial', properties = 'jproperties', jq = 'jq', slnf = 'json', json = 'json', jsonp = 'json', geojson = 'json', webmanifest = 'json', ipynb = 'json', ['jupyterlab-settings'] = 'json', ['sublime-project'] = 'json', ['sublime-settings'] = 'json', ['sublime-workspace'] = 'json', ['json-patch'] = 'json', bd = 'json', bda = 'json', xci = 'json', json5 = 'json5', jsonc = 'jsonc', jsonl = 'jsonl', jsonnet = 'jsonnet', libsonnet = 'jsonnet', jsp = 'jsp', jl = 'julia', just = 'just', kdl = 'kdl', kv = 'kivy', kix = 'kix', kts = 'kotlin', kt = 'kotlin', ktm = 'kotlin', ks = 'kscript', k = 'kwt', ACE = 'lace', ace = 'lace', latte = 'latte', lte = 'latte', ld = 'ld', ldif = 'ldif', lean = 'lean', journal = 'ledger', ldg = 'ledger', ledger = 'ledger', less = 'less', lex = 'lex', lxx = 'lex', ['l++'] = 'lex', l = 'lex', lhs = 'lhaskell', ll = 'lifelines', ly = 'lilypond', ily = 'lilypond', liquid = 'liquid', liq = 'liquidsoap', cl = 'lisp', L = 'lisp', lisp = 'lisp', el = 'lisp', lsp = 'lisp', asd = 'lisp', stsg = 'lisp', lt = 'lite', lite = 'lite', livemd = 'livebook', lgt = 'logtalk', lotos = 'lotos', lot = detect_line1('\\contentsline', 'tex', 'lotos'), lout = 'lout', lou = 'lout', ulpc = 'lpc', lpc = 'lpc', c = detect.lpc, lsl = detect.lsl, lss = 'lss', nse = 'lua', rockspec = 'lua', lua = 'lua', tlu = 'lua', luau = 'luau', lrc = 'lyrics', m = detect.m, at = 'm4', mc = detect.mc, quake = 'm3quake', m4 = function(path, bufnr) path = path:lower() return not (path:find('html%.m4$') or path:find('fvwm2rc')) and 'm4' or nil end, eml = 'mail', mk = 'make', mak = 'make', dsp = 'make', page = 'mallard', map = 'map', mws = 'maple', mpl = 'maple', mv = 'maple', mkdn = detect.markdown, md = detect.markdown, mdwn = detect.markdown, mkd = detect.markdown, markdown = detect.markdown, mdown = detect.markdown, mhtml = 'mason', comp = 'mason', mason = 'mason', master = 'master', mas = 'master', demo = 'maxima', dm1 = 'maxima', dm2 = 'maxima', dm3 = 'maxima', dmt = 'maxima', wxm = 'maxima', mel = 'mel', mmd = 'mermaid', mmdc = 'mermaid', mermaid = 'mermaid', mf = 'mf', mgl = 'mgl', mgp = 'mgp', my = 'mib', mib = 'mib', mix = 'mix', mixal = 'mix', mm = detect.mm, nb = 'mma', mmp = 'mmp', mms = detect.mms, DEF = 'modula2', lm3 = 'modula3', mojo = 'mojo', ['🔥'] = 'mojo', -- 🙄 ssc = 'monk', monk = 'monk', tsc = 'monk', isc = 'monk', moo = 'moo', moon = 'moonscript', move = 'move', mp = 'mp', mpiv = detect.mp, mpvi = detect.mp, mpxl = detect.mp, mof = 'msidl', odl = 'msidl', msql = 'msql', mu = 'mupad', mush = 'mush', mustache = 'mustache', mysql = 'mysql', n1ql = 'n1ql', nql = 'n1ql', nanorc = 'nanorc', ncf = 'ncf', nginx = 'nginx', nim = 'nim', nims = 'nim', nimble = 'nim', ninja = 'ninja', nix = 'nix', norg = 'norg', nqc = 'nqc', roff = 'nroff', tmac = 'nroff', man = 'nroff', mom = 'nroff', nr = 'nroff', tr = 'nroff', nsi = 'nsis', nsh = 'nsis', nu = 'nu', obj = 'obj', objdump = 'objdump', cppobjdump = 'objdump', obl = 'obse', obse = 'obse', oblivion = 'obse', obscript = 'obse', mlt = 'ocaml', mly = 'ocaml', mll = 'ocaml', mlp = 'ocaml', mlip = 'ocaml', mli = 'ocaml', ml = 'ocaml', occ = 'occam', odin = 'odin', xom = 'omnimark', xin = 'omnimark', opam = 'opam', ['or'] = 'openroad', scad = 'openscad', ovpn = 'openvpn', ora = 'ora', org = 'org', org_archive = 'org', pandoc = 'pandoc', pdk = 'pandoc', pd = 'pandoc', pdc = 'pandoc', pxsl = 'papp', papp = 'papp', pxml = 'papp', pas = 'pascal', lpr = detect_line1('<%?xml', 'xml', 'pascal'), dpr = 'pascal', txtpb = 'pbtxt', textproto = 'pbtxt', textpb = 'pbtxt', pbtxt = 'pbtxt', g = 'pccts', pcmk = 'pcmk', pdf = 'pdf', pem = 'pem', cer = 'pem', crt = 'pem', csr = 'pem', plx = 'perl', prisma = 'prisma', psgi = 'perl', al = 'perl', ctp = 'php', php = 'php', phpt = 'php', phtml = 'php', theme = 'php', pike = 'pike', pmod = 'pike', rcp = 'pilrc', PL = detect.pl, pli = 'pli', pl1 = 'pli', p36 = 'plm', plm = 'plm', pac = 'plm', plp = 'plp', pls = 'plsql', plsql = 'plsql', po = 'po', pot = 'po', pod = 'pod', filter = 'poefilter', pk = 'poke', pony = 'pony', ps = 'postscr', epsi = 'postscr', afm = 'postscr', epsf = 'postscr', eps = 'postscr', pfa = 'postscr', ai = 'postscr', pov = 'pov', ppd = 'ppd', it = 'ppwiz', ih = 'ppwiz', action = 'privoxy', pc = 'proc', pdb = 'prolog', pml = 'promela', proto = 'proto', prql = 'prql', psd1 = 'ps1', psm1 = 'ps1', ps1 = 'ps1', pssc = 'ps1', ps1xml = 'ps1xml', psf = 'psf', psl = 'psl', pug = 'pug', arr = 'pyret', pxd = 'pyrex', pyx = 'pyrex', pyw = 'python', py = 'python', pyi = 'python', ptl = 'python', ql = 'ql', qll = 'ql', qml = 'qml', qbs = 'qml', qmd = 'quarto', R = detect.r, rkt = 'racket', rktd = 'racket', rktl = 'racket', rad = 'radiance', mat = 'radiance', pod6 = 'raku', rakudoc = 'raku', rakutest = 'raku', rakumod = 'raku', pm6 = 'raku', raku = 'raku', t6 = 'raku', p6 = 'raku', raml = 'raml', rbs = 'rbs', rego = 'rego', rem = 'remind', remind = 'remind', pip = 'requirements', res = 'rescript', resi = 'rescript', frt = 'reva', testUnit = 'rexx', rex = 'rexx', orx = 'rexx', rexx = 'rexx', jrexx = 'rexx', rxj = 'rexx', rexxj = 'rexx', testGroup = 'rexx', rxo = 'rexx', Rd = 'rhelp', rd = 'rhelp', rib = 'rib', Rmd = 'rmd', rmd = 'rmd', smd = 'rmd', Smd = 'rmd', rnc = 'rnc', rng = 'rng', rnw = 'rnoweb', snw = 'rnoweb', Rnw = 'rnoweb', Snw = 'rnoweb', robot = 'robot', resource = 'robot', roc = 'roc', ron = 'ron', rsc = 'routeros', x = 'rpcgen', rpgle = 'rpgle', rpgleinc = 'rpgle', rpl = 'rpl', Srst = 'rrst', srst = 'rrst', Rrst = 'rrst', rrst = 'rrst', rst = 'rst', rtf = 'rtf', rjs = 'ruby', rxml = 'ruby', rb = 'ruby', rant = 'ruby', ru = 'ruby', rbw = 'ruby', gemspec = 'ruby', builder = 'ruby', rake = 'ruby', rs = 'rust', sage = 'sage', sas = 'sas', sass = 'sass', sa = 'sather', sbt = 'sbt', scala = 'scala', ss = 'scheme', scm = 'scheme', sld = 'scheme', sce = 'scilab', sci = 'scilab', scss = 'scss', sd = 'sd', sdc = 'sdc', pr = 'sdl', sdl = 'sdl', sed = 'sed', sexp = 'sexplib', bash = detect.bash, bats = detect.bash, ebuild = detect.bash, eclass = detect.bash, env = detect.sh, ksh = detect.ksh, sh = detect.sh, mdd = 'sh', sieve = 'sieve', siv = 'sieve', sig = detect.sig, sil = detect.sil, sim = 'simula', s85 = 'sinda', sin = 'sinda', ssm = 'sisu', sst = 'sisu', ssi = 'sisu', ['_sst'] = 'sisu', ['-sst'] = 'sisu', il = 'skill', ils = 'skill', cdf = 'skill', sl = 'slang', ice = 'slice', score = 'slrnsc', sol = 'solidity', smali = 'smali', tpl = 'smarty', ihlp = 'smcl', smcl = 'smcl', hlp = 'smcl', smith = 'smith', smt = 'smith', smithy = 'smithy', sml = 'sml', spt = 'snobol4', sno = 'snobol4', sln = 'solution', sparql = 'sparql', rq = 'sparql', spec = 'spec', spice = 'spice', sp = 'spice', spd = 'spup', spdata = 'spup', speedup = 'spup', spi = 'spyce', spy = 'spyce', tyc = 'sql', typ = detect.typ, pkb = 'sql', tyb = 'sql', pks = 'sql', sqlj = 'sqlj', sqi = 'sqr', sqr = 'sqr', nut = 'squirrel', s28 = 'srec', s37 = 'srec', srec = 'srec', mot = 'srec', s19 = 'srec', srt = 'srt', ssa = 'ssa', ass = 'ssa', st = 'st', ipd = 'starlark', star = 'starlark', starlark = 'starlark', imata = 'stata', ['do'] = 'stata', mata = 'stata', ado = 'stata', stp = 'stp', styl = 'stylus', stylus = 'stylus', quark = 'supercollider', sface = 'surface', svelte = 'svelte', svg = 'svg', swift = 'swift', swig = 'swig', swg = 'swig', svh = 'systemverilog', sv = 'systemverilog', cmm = 'trace32', t32 = 'trace32', td = 'tablegen', tak = 'tak', tal = 'tal', task = 'taskedit', tm = 'tcl', tcl = 'tcl', itk = 'tcl', itcl = 'tcl', tk = 'tcl', jacl = 'tcl', tl = 'teal', templ = 'templ', tmpl = 'template', ti = 'terminfo', dtx = 'tex', ltx = 'tex', bbl = 'tex', latex = 'tex', sty = 'tex', pgf = 'tex', nlo = 'tex', nls = 'tex', thm = 'tex', eps_tex = 'tex', pygtex = 'tex', pygstyle = 'tex', clo = 'tex', aux = 'tex', brf = 'tex', ind = 'tex', lof = 'tex', loe = 'tex', nav = 'tex', vrb = 'tex', ins = 'tex', tikz = 'tex', bbx = 'tex', cbx = 'tex', beamer = 'tex', cls = detect.cls, texi = 'texinfo', txi = 'texinfo', texinfo = 'texinfo', text = 'text', tfvars = 'terraform-vars', thrift = 'thrift', tla = 'tla', tli = 'tli', toml = 'toml', tpp = 'tpp', treetop = 'treetop', slt = 'tsalt', tsscl = 'tsscl', tssgm = 'tssgm', tssop = 'tssop', tsv = 'tsv', tutor = 'tutor', twig = 'twig', ts = detect_line1('<%?xml', 'xml', 'typescript'), mts = 'typescript', cts = 'typescript', tsx = 'typescriptreact', tsp = 'typespec', uc = 'uc', uit = 'uil', uil = 'uil', ungram = 'ungrammar', u = 'unison', uu = 'unison', url = 'urlshortcut', usd = 'usd', usda = 'usd', v = detect.v, vsh = 'v', vv = 'v', ctl = 'vb', dob = 'vb', dsm = 'vb', dsr = 'vb', pag = 'vb', sba = 'vb', vb = 'vb', vbs = 'vb', vba = detect.vba, vdf = 'vdf', vdmpp = 'vdmpp', vpp = 'vdmpp', vdmrt = 'vdmrt', vdmsl = 'vdmsl', vdm = 'vdmsl', vto = 'vento', vr = 'vera', vri = 'vera', vrh = 'vera', va = 'verilogams', vams = 'verilogams', vhdl = 'vhdl', vst = 'vhdl', vhd = 'vhdl', hdl = 'vhdl', vho = 'vhdl', vbe = 'vhdl', tape = 'vhs', vim = 'vim', mar = 'vmasm', cm = 'voscm', wrl = 'vrml', vroom = 'vroom', vue = 'vue', wast = 'wat', wat = 'wat', wdl = 'wdl', wm = 'webmacro', wgsl = 'wgsl', wbt = 'winbatch', wit = 'wit', wml = 'wml', wsml = 'wsml', ad = 'xdefaults', xhtml = 'xhtml', xht = 'xhtml', msc = 'xmath', msf = 'xmath', psc1 = 'xml', tpm = 'xml', xliff = 'xml', atom = 'xml', xul = 'xml', cdxml = 'xml', mpd = 'xml', rss = 'xml', fsproj = 'xml', ui = 'xml', vbproj = 'xml', xlf = 'xml', wsdl = 'xml', csproj = 'xml', wpl = 'xml', xmi = 'xml', xpr = 'xml', xpfm = 'xml', spfm = 'xml', bxml = 'xml', xcu = 'xml', xlb = 'xml', xlc = 'xml', xba = 'xml', xpm = detect_line1('XPM2', 'xpm2', 'xpm'), xpm2 = 'xpm2', xqy = 'xquery', xqm = 'xquery', xquery = 'xquery', xq = 'xquery', xql = 'xquery', xs = 'xs', xsd = 'xsd', xsl = 'xslt', xslt = 'xslt', yy = 'yacc', ['y++'] = 'yacc', yxx = 'yacc', yml = 'yaml', yaml = 'yaml', eyaml = 'yaml', mplstyle = 'yaml', yang = 'yang', yuck = 'yuck', z8a = 'z8a', zig = 'zig', zon = 'zig', zu = 'zimbu', zut = 'zimbutempl', zs = 'zserio', zsh = 'zsh', zunit = 'zsh', ['zsh-theme'] = 'zsh', vala = 'vala', web = detect.web, pl = detect.pl, pp = detect.pp, i = detect.i, w = detect.progress_cweb, p = detect.progress_pascal, pro = detect_seq(detect.proto, 'idlang'), patch = detect.patch, r = detect.r, rdf = detect.redif, rules = detect.rules, sc = detect.sc, scd = detect.scd, tcsh = function(path, bufnr) return require('vim.filetype.detect').shell(path, M._getlines(bufnr), 'tcsh') end, sql = detect.sql, zsql = detect.sql, tex = detect.tex, tf = detect.tf, txt = detect.txt, xml = detect.xml, y = detect.y, cmd = detect_line1('^/%*', 'rexx', 'dosbatch'), rul = detect.rul, cpy = detect_line1('^##', 'python', 'cobol'), dsl = detect_line1('^%s*', 'xml', 'smil'), smi = detect.smi, install = detect.install, pm = detect.pm, me = detect.me, reg = detect.reg, ttl = detect.ttl, rc = detect_rc, rch = detect_rc, class = detect.class, sgml = detect.sgml, sgm = detect.sgml, t = detect_seq(detect.nroff, detect.perl, 'tads'), -- Ignored extensions bak = detect_noext, ['dpkg-bak'] = detect_noext, ['dpkg-dist'] = detect_noext, ['dpkg-old'] = detect_noext, ['dpkg-new'] = detect_noext, ['in'] = function(path, bufnr) if vim.fs.basename(path) ~= 'configure.in' then return detect_noext(path, bufnr) end end, new = detect_noext, old = detect_noext, orig = detect_noext, pacsave = detect_noext, pacnew = detect_noext, rpmsave = detect_noext, rmpnew = detect_noext, -- END EXTENSION } --- @type vim.filetype.mapping local filename = { -- BEGIN FILENAME ['a2psrc'] = 'a2ps', ['/etc/a2ps.cfg'] = 'a2ps', ['.a2psrc'] = 'a2ps', ['.asoundrc'] = 'alsaconf', ['/usr/share/alsa/alsa.conf'] = 'alsaconf', ['/etc/asound.conf'] = 'alsaconf', ['build.xml'] = 'ant', ['.htaccess'] = 'apache', ['apt.conf'] = 'aptconf', ['/.aptitude/config'] = 'aptconf', ['=tagging-method'] = 'arch', ['.arch-inventory'] = 'arch', ['GNUmakefile.am'] = 'automake', ['named.root'] = 'bindzone', WORKSPACE = 'bzl', ['WORKSPACE.bzlmod'] = 'bzl', BUCK = 'bzl', BUILD = 'bzl', ['cabal.project'] = 'cabalproject', ['cabal.config'] = 'cabalconfig', calendar = 'calendar', catalog = 'catalog', ['/etc/cdrdao.conf'] = 'cdrdaoconf', ['.cdrdao'] = 'cdrdaoconf', ['/etc/default/cdrdao'] = 'cdrdaoconf', ['/etc/defaults/cdrdao'] = 'cdrdaoconf', ['cfengine.conf'] = 'cfengine', cgdbrc = 'cgdbrc', ['init.trans'] = 'clojure', ['.trans'] = 'clojure', ['CMakeLists.txt'] = 'cmake', ['CMakeCache.txt'] = 'cmakecache', ['.cling_history'] = 'cpp', ['.alias'] = detect.csh, ['.cshrc'] = detect.csh, ['.login'] = detect.csh, ['csh.cshrc'] = detect.csh, ['csh.login'] = detect.csh, ['csh.logout'] = detect.csh, ['auto.master'] = 'conf', ['texdoc.cnf'] = 'conf', ['.x11vncrc'] = 'conf', ['.chktexrc'] = 'conf', ['.ripgreprc'] = 'conf', ripgreprc = 'conf', ['.mbsyncrc'] = 'conf', ['configure.in'] = 'config', ['configure.ac'] = 'config', crontab = 'crontab', ['.cvsrc'] = 'cvsrc', ['/debian/changelog'] = 'debchangelog', ['changelog.dch'] = 'debchangelog', ['changelog.Debian'] = 'debchangelog', ['NEWS.dch'] = 'debchangelog', ['NEWS.Debian'] = 'debchangelog', ['/debian/control'] = 'debcontrol', ['/debian/copyright'] = 'debcopyright', ['/etc/apt/sources.list'] = 'debsources', ['denyhosts.conf'] = 'denyhosts', ['dict.conf'] = 'dictconf', ['.dictrc'] = 'dictconf', ['/etc/DIR_COLORS'] = 'dircolors', ['.dir_colors'] = 'dircolors', ['.dircolors'] = 'dircolors', ['/etc/dnsmasq.conf'] = 'dnsmasq', Containerfile = 'dockerfile', dockerfile = 'dockerfile', Dockerfile = 'dockerfile', npmrc = 'dosini', ['/etc/yum.conf'] = 'dosini', ['.npmrc'] = 'dosini', ['pip.conf'] = 'dosini', ['setup.cfg'] = 'dosini', ['pudb.cfg'] = 'dosini', ['.coveragerc'] = 'dosini', ['.pypirc'] = 'dosini', ['.pylintrc'] = 'dosini', ['pylintrc'] = 'dosini', ['.replyrc'] = 'dosini', ['.gitlint'] = 'dosini', ['.oelint.cfg'] = 'dosini', ['psprint.conf'] = 'dosini', sofficerc = 'dosini', ['mimeapps.list'] = 'dosini', ['.wakatime.cfg'] = 'dosini', ['nfs.conf'] = 'dosini', ['nfsmount.conf'] = 'dosini', ['.notmuch-config'] = 'dosini', ['pacman.conf'] = 'confini', ['paru.conf'] = 'confini', ['mpv.conf'] = 'confini', dune = 'dune', jbuild = 'dune', ['dune-workspace'] = 'dune', ['dune-project'] = 'dune', Earthfile = 'earthfile', ['.editorconfig'] = 'editorconfig', ['elinks.conf'] = 'elinks', ['mix.lock'] = 'elixir', ['filter-rules'] = 'elmfilt', ['exim.conf'] = 'exim', exports = 'exports', ['.fetchmailrc'] = 'fetchmail', fvSchemes = detect.foam, fvSolution = detect.foam, fvConstraints = detect.foam, fvModels = detect.foam, fstab = 'fstab', mtab = 'fstab', ['.gdbinit'] = 'gdb', gdbinit = 'gdb', ['.gdbearlyinit'] = 'gdb', gdbearlyinit = 'gdb', ['lltxxxxx.txt'] = 'gedcom', TAG_EDITMSG = 'gitcommit', MERGE_MSG = 'gitcommit', COMMIT_EDITMSG = 'gitcommit', NOTES_EDITMSG = 'gitcommit', EDIT_DESCRIPTION = 'gitcommit', ['.gitconfig'] = 'gitconfig', ['.gitmodules'] = 'gitconfig', ['.gitattributes'] = 'gitattributes', ['.gitignore'] = 'gitignore', ['gitolite.conf'] = 'gitolite', ['git-rebase-todo'] = 'gitrebase', gkrellmrc = 'gkrellmrc', ['.gnashrc'] = 'gnash', ['.gnashpluginrc'] = 'gnash', gnashpluginrc = 'gnash', gnashrc = 'gnash', ['.gnuplot_history'] = 'gnuplot', ['go.sum'] = 'gosum', ['go.work.sum'] = 'gosum', ['go.work'] = 'gowork', ['.gprc'] = 'gp', ['/.gnupg/gpg.conf'] = 'gpg', ['/.gnupg/options'] = 'gpg', Jenkinsfile = 'groovy', ['/var/backups/gshadow.bak'] = 'group', ['/etc/gshadow'] = 'group', ['/etc/group-'] = 'group', ['/etc/gshadow.edit'] = 'group', ['/etc/gshadow-'] = 'group', ['/etc/group'] = 'group', ['/var/backups/group.bak'] = 'group', ['/etc/group.edit'] = 'group', ['/boot/grub/menu.lst'] = 'grub', ['/etc/grub.conf'] = 'grub', ['/boot/grub/grub.conf'] = 'grub', ['.gtkrc'] = 'gtkrc', gtkrc = 'gtkrc', ['snort.conf'] = 'hog', ['vision.conf'] = 'hog', ['/etc/host.conf'] = 'hostconf', ['/etc/hosts.allow'] = 'hostsaccess', ['/etc/hosts.deny'] = 'hostsaccess', ['/.icewm/menu'] = 'icemenu', ['.indent.pro'] = 'indent', indentrc = 'indent', inittab = 'inittab', ['ipf.conf'] = 'ipfilter', ['ipf6.conf'] = 'ipfilter', ['ipf.rules'] = 'ipfilter', ['.node_repl_history'] = 'javascript', ['Pipfile.lock'] = 'json', ['.firebaserc'] = 'json', ['.prettierrc'] = 'json', ['.stylelintrc'] = 'json', ['flake.lock'] = 'json', ['.babelrc'] = 'jsonc', ['.eslintrc'] = 'jsonc', ['.hintrc'] = 'jsonc', ['.jscsrc'] = 'jsonc', ['.jsfmtrc'] = 'jsonc', ['.jshintrc'] = 'jsonc', ['.luaurc'] = 'jsonc', ['.swrc'] = 'jsonc', ['.vsconfig'] = 'jsonc', ['.justfile'] = 'just', Kconfig = 'kconfig', ['Kconfig.debug'] = 'kconfig', ['Config.in'] = 'kconfig', ['lftp.conf'] = 'lftp', ['.lftprc'] = 'lftp', ['/.libao'] = 'libao', ['/etc/libao.conf'] = 'libao', ['lilo.conf'] = 'lilo', ['/etc/limits'] = 'limits', ['.emacs'] = 'lisp', sbclrc = 'lisp', ['.sbclrc'] = 'lisp', ['.sawfishrc'] = 'lisp', ['/etc/login.access'] = 'loginaccess', ['/etc/login.defs'] = 'logindefs', ['.lsl'] = detect.lsl, ['.busted'] = 'lua', ['.luacheckrc'] = 'lua', ['.lua_history'] = 'lua', ['config.ld'] = 'lua', ['rock_manifest'] = 'lua', ['lynx.cfg'] = 'lynx', ['m3overrides'] = 'm3build', ['m3makefile'] = 'm3build', ['cm3.cfg'] = 'm3quake', ['.m4_history'] = 'm4', ['.followup'] = 'mail', ['.article'] = 'mail', ['.letter'] = 'mail', ['/etc/aliases'] = 'mailaliases', ['/etc/mail/aliases'] = 'mailaliases', mailcap = 'mailcap', ['.mailcap'] = 'mailcap', Kbuild = 'make', ['/etc/man.conf'] = 'manconf', ['man.config'] = 'manconf', ['maxima-init.mac'] = 'maxima', ['meson.build'] = 'meson', ['meson.options'] = 'meson', ['meson_options.txt'] = 'meson', ['/etc/conf.modules'] = 'modconf', ['/etc/modules'] = 'modconf', ['/etc/modules.conf'] = 'modconf', ['/.mplayer/config'] = 'mplayerconf', ['mplayer.conf'] = 'mplayerconf', mrxvtrc = 'mrxvtrc', ['.mrxvtrc'] = 'mrxvtrc', ['.msmtprc'] = 'msmtp', ['.mysql_history'] = 'mysql', ['/etc/nanorc'] = 'nanorc', Neomuttrc = 'neomuttrc', ['.netrc'] = 'netrc', NEWS = detect.news, ['.ocamlinit'] = 'ocaml', ['.octaverc'] = 'octave', octaverc = 'octave', ['octave.conf'] = 'octave', ['.ondirrc'] = 'ondir', opam = 'opam', ['pacman.log'] = 'pacmanlog', ['/etc/pam.conf'] = 'pamconf', ['pam_env.conf'] = 'pamenv', ['.pam_environment'] = 'pamenv', ['/var/backups/passwd.bak'] = 'passwd', ['/var/backups/shadow.bak'] = 'passwd', ['/etc/passwd'] = 'passwd', ['/etc/passwd-'] = 'passwd', ['/etc/shadow.edit'] = 'passwd', ['/etc/shadow-'] = 'passwd', ['/etc/shadow'] = 'passwd', ['/etc/passwd.edit'] = 'passwd', ['latexmkrc'] = 'perl', ['.latexmkrc'] = 'perl', ['pf.conf'] = 'pf', ['main.cf'] = 'pfmain', ['main.cf.proto'] = 'pfmain', pinerc = 'pine', ['.pinercex'] = 'pine', ['.pinerc'] = 'pine', pinercex = 'pine', ['/etc/pinforc'] = 'pinfo', ['/.pinforc'] = 'pinfo', ['.povrayrc'] = 'povini', printcap = function(path, bufnr) return 'ptcap', function(b) vim.b[b].ptcap_type = 'print' end end, termcap = function(path, bufnr) return 'ptcap', function(b) vim.b[b].ptcap_type = 'term' end end, ['.procmailrc'] = 'procmail', ['.procmail'] = 'procmail', ['indent.pro'] = detect_seq(detect.proto, 'indent'), ['/etc/protocols'] = 'protocols', INDEX = detect.psf, INFO = detect.psf, ['MANIFEST.in'] = 'pymanifest', ['.pythonstartup'] = 'python', ['.pythonrc'] = 'python', ['.python_history'] = 'python', ['.jline-jython.history'] = 'python', SConstruct = 'python', qmldir = 'qmldir', ['.Rhistory'] = 'r', ['.Rprofile'] = 'r', Rprofile = 'r', ['Rprofile.site'] = 'r', ratpoisonrc = 'ratpoison', ['.ratpoisonrc'] = 'ratpoison', inputrc = 'readline', ['.inputrc'] = 'readline', ['.reminders'] = 'remind', ['requirements.txt'] = 'requirements', ['constraints.txt'] = 'requirements', ['requirements.in'] = 'requirements', ['resolv.conf'] = 'resolv', ['robots.txt'] = 'robots', Gemfile = 'ruby', Puppetfile = 'ruby', ['.irbrc'] = 'ruby', irbrc = 'ruby', ['.irb_history'] = 'ruby', irb_history = 'ruby', Vagrantfile = 'ruby', ['smb.conf'] = 'samba', screenrc = 'screen', ['.screenrc'] = 'screen', ['/etc/sensors3.conf'] = 'sensors', ['/etc/sensors.conf'] = 'sensors', ['/etc/services'] = 'services', ['/etc/serial.conf'] = 'setserial', ['/etc/udev/cdsymlinks.conf'] = 'sh', ['.ash_history'] = 'sh', ['makepkg.conf'] = 'sh', ['.makepkg.conf'] = 'sh', ['user-dirs.dirs'] = 'sh', ['user-dirs.defaults'] = 'sh', ['.xprofile'] = 'sh', ['bash.bashrc'] = detect.bash, bashrc = detect.bash, ['.bashrc'] = detect.bash, ['.kshrc'] = detect.ksh, ['.profile'] = detect.sh, ['/etc/profile'] = detect.sh, APKBUILD = detect.bash, PKGBUILD = detect.bash, ['.tcshrc'] = detect.tcsh, ['tcsh.login'] = detect.tcsh, ['tcsh.tcshrc'] = detect.tcsh, ['/etc/slp.conf'] = 'slpconf', ['/etc/slp.reg'] = 'slpreg', ['/etc/slp.spi'] = 'slpspi', ['.slrnrc'] = 'slrnrc', ['sendmail.cf'] = 'sm', ['.sqlite_history'] = 'sql', ['squid.conf'] = 'squid', ['ssh_config'] = 'sshconfig', ['sshd_config'] = 'sshdconfig', ['/etc/sudoers'] = 'sudoers', ['sudoers.tmp'] = 'sudoers', ['/etc/sysctl.conf'] = 'sysctl', tags = 'tags', ['pending.data'] = 'taskdata', ['completed.data'] = 'taskdata', ['undo.data'] = 'taskdata', ['.tclshrc'] = 'tcl', ['.wishrc'] = 'tcl', ['.tclsh-history'] = 'tcl', ['tclsh.rc'] = 'tcl', ['.xsctcmdhistory'] = 'tcl', ['.xsdbcmdhistory'] = 'tcl', ['texmf.cnf'] = 'texmf', COPYING = 'text', README = 'text', LICENSE = 'text', AUTHORS = 'text', tfrc = 'tf', ['.tfrc'] = 'tf', ['tidy.conf'] = 'tidy', tidyrc = 'tidy', ['.tidyrc'] = 'tidy', ['.tmux.conf'] = 'tmux', ['/.cargo/config'] = 'toml', Pipfile = 'toml', ['Gopkg.lock'] = 'toml', ['/.cargo/credentials'] = 'toml', ['Cargo.lock'] = 'toml', ['.black'] = 'toml', black = detect_line1('tool%.black', 'toml', nil), ['trustees.conf'] = 'trustees', ['.ts_node_repl_history'] = 'typescript', ['/etc/udev/udev.conf'] = 'udevconf', ['/etc/updatedb.conf'] = 'updatedb', ['fdrupstream.log'] = 'upstreamlog', vgrindefs = 'vgrindefs', ['.exrc'] = 'vim', ['_exrc'] = 'vim', ['.netrwhist'] = 'vim', ['_viminfo'] = 'viminfo', ['.viminfo'] = 'viminfo', ['.wgetrc'] = 'wget', ['.wget2rc'] = 'wget2', wgetrc = 'wget', wget2rc = 'wget2', ['.wvdialrc'] = 'wvdial', ['wvdial.conf'] = 'wvdial', ['.XCompose'] = 'xcompose', ['Compose'] = 'xcompose', ['.Xresources'] = 'xdefaults', ['.Xpdefaults'] = 'xdefaults', ['xdm-config'] = 'xdefaults', ['.Xdefaults'] = 'xdefaults', ['xorg.conf'] = detect.xfree86_v4, ['xorg.conf-4'] = detect.xfree86_v4, ['XF86Config'] = detect.xfree86_v3, ['/etc/xinetd.conf'] = 'xinetd', fglrxrc = 'xml', ['/etc/blkid.tab'] = 'xml', ['/etc/blkid.tab.old'] = 'xml', ['fonts.conf'] = 'xml', ['.clangd'] = 'yaml', ['.clang-format'] = 'yaml', ['.clang-tidy'] = 'yaml', ['yarn.lock'] = 'yaml', matplotlibrc = 'yaml', zathurarc = 'zathurarc', ['/etc/zprofile'] = 'zsh', ['.zlogin'] = 'zsh', ['.zlogout'] = 'zsh', ['.zshrc'] = 'zsh', ['.zprofile'] = 'zsh', ['.zcompdump'] = 'zsh', ['.zsh_history'] = 'zsh', ['.zshenv'] = 'zsh', ['.zfbfmarks'] = 'zsh', -- END FILENAME } -- Re-use closures as much as possible local detect_apache = starsetf('apache') local detect_muttrc = starsetf('muttrc') local detect_neomuttrc = starsetf('neomuttrc') --- @type 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', ['.*%.[aA]'] = detect.asm, ['.*%.[sS]'] = detect.asm, ['[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 }, }, ['[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', ['.*%.directory'] = 'desktop', ['.*%.desktop'] = 'desktop', ['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 }, }, ['.*%.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), ['.*%.[mi][3g]'] = 'modula3', ['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%.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'), ['.*%.ws[fc]'] = 'wsh', ['.*/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 -- luacheck: pop --- @param t vim.filetype.mapping --- @return vim.filetype.mapping[] local function sort_by_priority(t) local sorted = {} --- @type vim.filetype.mapping[] for k, v in pairs(t) do local ft = type(v) == 'table' and v[1] or v assert( type(ft) == 'string' or type(ft) == 'function', 'Expected string or function for filetype' ) local opts = (type(v) == 'table' and type(v[2]) == 'table') and v[2] or {} if not opts.priority then opts.priority = 0 end table.insert(sorted, { [k] = { ft, opts } }) end table.sort(sorted, function(a, b) return a[next(a)][2].priority > b[next(b)][2].priority end) return sorted end local pattern_sorted = sort_by_priority(pattern) --- @param path string --- @param as_pattern? true --- @return string local function normalize_path(path, as_pattern) local normal = path:gsub('\\', '/') if normal:find('^~') then if as_pattern then -- Escape Lua's metacharacters when $HOME is used in a pattern. -- The rest of path should already be properly escaped. normal = vim.pesc(vim.env.HOME) .. normal:sub(2) else normal = vim.env.HOME .. normal:sub(2) --- @type string end end return normal end --- @class vim.filetype.add.filetypes --- @inlinedoc --- @field pattern? vim.filetype.mapping --- @field extension? vim.filetype.mapping --- @field filename? vim.filetype.mapping --- Add new filetype mappings. --- --- Filetype mappings can be added either by extension or by filename (either --- the "tail" or the full file path). The full file path is checked first, --- followed by the file name. If a match is not found using the filename, then --- the filename is matched against the list of |lua-patterns| (sorted by priority) --- until a match is found. Lastly, if pattern matching does not find a --- filetype, then the file extension is used. --- --- The filetype can be either a string (in which case it is used as the --- filetype directly) or a function. If a function, it takes the full path and --- buffer number of the file as arguments (along with captures from the matched --- pattern, if any) and should return a string that will be used as the --- buffer's filetype. Optionally, the function can return a second function --- value which, when called, modifies the state of the buffer. This can be used --- to, for example, set filetype-specific buffer variables. This function will --- be called by Nvim before setting the buffer's filetype. --- --- Filename patterns can specify an optional priority to resolve cases when a --- file path matches multiple patterns. Higher priorities are matched first. --- When omitted, the priority defaults to 0. --- A pattern can contain environment variables of the form "${SOME_VAR}" that will --- be automatically expanded. If the environment variable is not set, the pattern --- won't be matched. --- --- See $VIMRUNTIME/lua/vim/filetype.lua for more examples. --- --- Example: --- --- ```lua --- vim.filetype.add({ --- extension = { --- foo = 'fooscript', --- bar = function(path, bufnr) --- if some_condition() then --- return 'barscript', function(bufnr) --- -- Set a buffer variable --- vim.b[bufnr].barscript_version = 2 --- end --- end --- return 'bar' --- end, --- }, --- filename = { --- ['.foorc'] = 'toml', --- ['/etc/foo/config'] = 'toml', --- }, --- pattern = { --- ['.*/etc/foo/.*'] = 'fooscript', --- -- Using an optional priority --- ['.*/etc/foo/.*%.conf'] = { 'dosini', { priority = 10 } }, --- -- A pattern containing an environment variable --- ['${XDG_CONFIG_HOME}/foo/git'] = 'git', --- ['README.(%a+)$'] = function(path, bufnr, ext) --- if ext == 'md' then --- return 'markdown' --- elseif ext == 'rst' then --- return 'rst' --- end --- end, --- }, --- }) --- ``` --- --- To add a fallback match on contents, use --- --- ```lua --- vim.filetype.add { --- pattern = { --- ['.*'] = { --- function(path, bufnr) --- local content = vim.api.nvim_buf_get_lines(bufnr, 0, 1, false)[1] or '' --- if vim.regex([[^#!.*\\]]):match_str(content) ~= nil then --- return 'mine' --- elseif vim.regex([[\\]]):match_str(content) ~= nil then --- return 'drawing' --- end --- end, --- { priority = -math.huge }, --- }, --- }, --- } --- ``` --- ---@param filetypes vim.filetype.add.filetypes A table containing new filetype maps (see example). function M.add(filetypes) for k, v in pairs(filetypes.extension or {}) do extension[k] = v end for k, v in pairs(filetypes.filename or {}) do filename[normalize_path(k)] = v end for k, v in pairs(filetypes.pattern or {}) do pattern[normalize_path(k, true)] = v end if filetypes.pattern then pattern_sorted = sort_by_priority(pattern) end end --- @param ft vim.filetype.mapping.value --- @param path? string --- @param bufnr? integer --- @param ... any --- @return string? --- @return fun(b: integer)? local function dispatch(ft, path, bufnr, ...) if type(ft) == 'string' then return ft end if type(ft) ~= 'function' then return end assert(path) ---@type string|false?, fun(b: integer)? local ft0, on_detect if bufnr then ft0, on_detect = ft(path, bufnr, ...) else -- If bufnr is nil (meaning we are matching only against the filename), set it to an invalid -- value (-1) and catch any errors from the filetype detection function. If the function tries -- to use the buffer then it will fail, but this enables functions which do not need a buffer -- to still work. local ok ok, ft0, on_detect = pcall(ft, path, -1, ...) if not ok then return end end if not ft0 then return end return ft0, on_detect end --- Lookup table/cache for patterns that contain an environment variable pattern, e.g. ${SOME_VAR}. --- @type table local expand_env_lookup = {} --- @param name string --- @param path string --- @param tail string --- @param pat string --- @return string|false? local function match_pattern(name, path, tail, pat) if expand_env_lookup[pat] == nil then expand_env_lookup[pat] = pat:find('%${') ~= nil end if expand_env_lookup[pat] then local return_early --- @type true? --- @type string pat = pat:gsub('%${(%S-)}', function(env) -- If an environment variable is present in the pattern but not set, there is no match if not vim.env[env] then return_early = true return nil end return vim.pesc(vim.env[env]) end) if return_early then return false end end -- If the pattern contains a / match against the full path, otherwise just the tail local fullpat = '^' .. pat .. '$' if pat:find('/') then -- Similar to |autocmd-pattern|, if the pattern contains a '/' then check for a match against -- both the short file name (as typed) and the full file name (after expanding to full path -- and resolving symlinks) return (name:match(fullpat) or path:match(fullpat)) end return (tail:match(fullpat)) end --- @class vim.filetype.match.args --- @inlinedoc --- --- Buffer number to use for matching. Mutually exclusive with {contents} --- @field buf? integer --- --- Filename to use for matching. When {buf} is given, --- defaults to the filename of the given buffer number. The --- file need not actually exist in the filesystem. When used --- without {buf} only the name of the file is used for --- filetype matching. This may result in failure to detect --- the filetype in cases where the filename alone is not --- enough to disambiguate the filetype. --- @field filename? string --- --- An array of lines representing file contents to use for --- matching. Can be used with {filename}. Mutually exclusive --- with {buf}. --- @field contents? string[] --- Perform filetype detection. --- --- The filetype can be detected using one of three methods: --- 1. Using an existing buffer --- 2. Using only a file name --- 3. Using only file contents --- --- Of these, option 1 provides the most accurate result as it uses both the buffer's filename and --- (optionally) the buffer contents. Options 2 and 3 can be used without an existing buffer, but --- may not always provide a match in cases where the filename (or contents) cannot unambiguously --- determine the filetype. --- --- Each of the three options is specified using a key to the single argument of this function. --- Example: --- --- ```lua --- -- Using a buffer number --- vim.filetype.match({ buf = 42 }) --- --- -- Override the filename of the given buffer --- vim.filetype.match({ buf = 42, filename = 'foo.c' }) --- --- -- Using a filename without a buffer --- vim.filetype.match({ filename = 'main.lua' }) --- --- -- Using file contents --- vim.filetype.match({ contents = {'#!/usr/bin/env bash'} }) --- ``` --- ---@param args vim.filetype.match.args Table specifying which matching strategy to use. --- Accepted keys are: ---@return string|nil # If a match was found, the matched filetype. ---@return function|nil # A function that modifies buffer state when called (for example, to set some --- filetype specific buffer variables). The function accepts a buffer number as --- its only argument. function M.match(args) vim.validate({ arg = { args, 't' }, }) if not (args.buf or args.filename or args.contents) then error('At least one of "buf", "filename", or "contents" must be given') end local bufnr = args.buf local name = args.filename local contents = args.contents if bufnr and not name then name = api.nvim_buf_get_name(bufnr) end --- @type string?, fun(b: integer)? local ft, on_detect if name then name = normalize_path(name) -- First check for the simple case where the full path exists as a key local path = fn.fnamemodify(name, ':p') ft, on_detect = dispatch(filename[path], path, bufnr) if ft then return ft, on_detect end -- Next check against just the file name local tail = fn.fnamemodify(name, ':t') ft, on_detect = dispatch(filename[tail], path, bufnr) if ft then return ft, on_detect end -- Next, check the file path against available patterns with non-negative priority local j = 1 for i, v in ipairs(pattern_sorted) do local k = next(v) local opts = v[k][2] if opts.priority < 0 then j = i break end local filetype = v[k][1] local matches = match_pattern(name, path, tail, k) if matches then ft, on_detect = dispatch(filetype, path, bufnr, matches) if ft then return ft, on_detect end end end -- Next, check file extension -- Don't use fnamemodify() with :e modifier here, -- as that's empty when there is only an extension. local ext = name:match('%.([^.]-)$') or '' ft, on_detect = dispatch(extension[ext], path, bufnr) if ft then return ft, on_detect end -- Next, check patterns with negative priority for i = j, #pattern_sorted do local v = pattern_sorted[i] local k = next(v) local filetype = v[k][1] local matches = match_pattern(name, path, tail, k) if matches then ft, on_detect = dispatch(filetype, path, bufnr, matches) if ft then return ft, on_detect end end end end -- Finally, check file contents if contents or bufnr then if contents == nil then assert(bufnr) if api.nvim_buf_line_count(bufnr) > 101 then -- only need first 100 and last line for current checks contents = M._getlines(bufnr, 1, 100) contents[#contents + 1] = M._getline(bufnr, -1) else contents = M._getlines(bufnr) end end -- If name is nil, catch any errors from the contents filetype detection function. -- If the function tries to use the filename that is nil then it will fail, -- but this enables checks which do not need a filename to still work. local ok ok, ft, on_detect = pcall( require('vim.filetype.detect').match_contents, contents, name, function(ext) return dispatch(extension[ext], name, bufnr) end ) if ok then return ft, on_detect end end end --- Get the default option value for a {filetype}. --- --- The returned value is what would be set in a new buffer after 'filetype' --- is set, meaning it should respect all FileType autocmds and ftplugin files. --- --- Example: --- --- ```lua --- vim.filetype.get_option('vim', 'commentstring') --- ``` --- --- Note: this uses |nvim_get_option_value()| but caches the result. --- This means |ftplugin| and |FileType| autocommands are only --- triggered once and may not reflect later changes. --- @param filetype string Filetype --- @param option string Option name --- @return string|boolean|integer: Option value function M.get_option(filetype, option) return require('vim.filetype.options').get_option(filetype, option) end return M