neovim

Neovim text editor
git clone https://git.dasho.dev/neovim.git
Log | Files | Refs | README

filetype.lua (94106B)


      1 local api = vim.api
      2 local fn = vim.fn
      3 
      4 local M = {}
      5 
      6 --- @alias vim.filetype.mapfn fun(path:string,bufnr:integer, ...):string?, fun(b:integer)?
      7 --- @alias vim.filetype.mapopts { priority: number }
      8 --- @alias vim.filetype.maptbl [string|vim.filetype.mapfn, vim.filetype.mapopts]
      9 --- @alias vim.filetype.mapping.value string|vim.filetype.mapfn|vim.filetype.maptbl
     10 --- @alias vim.filetype.mapping table<string,vim.filetype.mapping.value>
     11 
     12 --- @class vim.filetype.mapping.sorted
     13 --- @nodoc
     14 --- @field [1] string parent pattern
     15 --- @field [2] string pattern
     16 --- @field [3] string|vim.filetype.mapfn
     17 --- @field [4] integer priority
     18 
     19 --- @param ft string|vim.filetype.mapfn
     20 --- @param priority? integer
     21 --- @return vim.filetype.maptbl
     22 local function starsetf(ft, priority)
     23  return {
     24    function(path, bufnr)
     25      -- Note: when `ft` is a function its return value may be nil.
     26      local f = type(ft) ~= 'function' and ft or ft(path, bufnr)
     27      if not vim.g.ft_ignore_pat then
     28        return f
     29      end
     30 
     31      local re = vim.regex(vim.g.ft_ignore_pat)
     32      if not re:match_str(path) then
     33        return f
     34      end
     35    end,
     36    {
     37      -- Starset matches should have lowest priority by default
     38      priority = priority or -math.huge,
     39    },
     40  }
     41 end
     42 
     43 --- Get a line range from the buffer.
     44 ---@param bufnr integer The buffer to get the lines from
     45 ---@param start_lnum integer|nil The line number of the first line (inclusive, 1-based)
     46 ---@param end_lnum integer|nil The line number of the last line (inclusive, 1-based)
     47 ---@return string[] # Array of lines
     48 function M._getlines(bufnr, start_lnum, end_lnum)
     49  if not bufnr or bufnr < 0 then
     50    return {}
     51  end
     52 
     53  if start_lnum then
     54    return api.nvim_buf_get_lines(bufnr, start_lnum - 1, end_lnum or start_lnum, false)
     55  end
     56 
     57  -- Return all lines
     58  return api.nvim_buf_get_lines(bufnr, 0, -1, false)
     59 end
     60 
     61 --- Get a single line from the buffer.
     62 ---@param bufnr integer The buffer to get the lines from
     63 ---@param start_lnum integer The line number of the first line (inclusive, 1-based)
     64 ---@return string
     65 function M._getline(bufnr, start_lnum)
     66  if not bufnr or bufnr < 0 then
     67    return ''
     68  end
     69 
     70  -- Return a single line
     71  return api.nvim_buf_get_lines(bufnr, start_lnum - 1, start_lnum, false)[1] or ''
     72 end
     73 
     74 --- Check whether a string matches any of the given Lua patterns.
     75 ---
     76 ---@param s string? The string to check
     77 ---@param patterns string[] A list of Lua patterns
     78 ---@return boolean `true` if s matched a pattern, else `false`
     79 function M._findany(s, patterns)
     80  if not s then
     81    return false
     82  end
     83  for _, v in ipairs(patterns) do
     84    if s:find(v) then
     85      return true
     86    end
     87  end
     88  return false
     89 end
     90 
     91 --- Get the next non-whitespace line in the buffer.
     92 ---
     93 ---@param bufnr integer The buffer to get the line from
     94 ---@param start_lnum integer The line number of the first line to start from (inclusive, 1-based)
     95 ---@return string|nil The first non-blank line if found or `nil` otherwise
     96 function M._nextnonblank(bufnr, start_lnum)
     97  for _, line in ipairs(M._getlines(bufnr, start_lnum, -1)) do
     98    if not line:find('^%s*$') then
     99      return line
    100    end
    101  end
    102  return nil
    103 end
    104 
    105 do
    106  --- @type table<string,vim.regex>
    107  local regex_cache = {}
    108 
    109  --- Check whether the given string matches the Vim regex pattern.
    110  --- @param s string?
    111  --- @param pattern string
    112  --- @return boolean
    113  function M._matchregex(s, pattern)
    114    if not s then
    115      return false
    116    end
    117    if not regex_cache[pattern] then
    118      regex_cache[pattern] = vim.regex(pattern)
    119    end
    120    return regex_cache[pattern]:match_str(s) ~= nil
    121  end
    122 end
    123 
    124 --- @module 'vim.filetype.detect'
    125 local detect = setmetatable({}, {
    126  --- @param k string
    127  --- @param t table<string,function>
    128  --- @return function
    129  __index = function(t, k)
    130    t[k] = function(...)
    131      return require('vim.filetype.detect')[k](...)
    132    end
    133    return t[k]
    134  end,
    135 })
    136 
    137 --- @param ... string|vim.filetype.mapfn
    138 --- @return vim.filetype.mapfn
    139 local function detect_seq(...)
    140  local candidates = { ... }
    141  return function(...)
    142    for _, c in ipairs(candidates) do
    143      if type(c) == 'string' then
    144        return c
    145      end
    146      if type(c) == 'function' then
    147        local r = c(...)
    148        if r then
    149          return r
    150        end
    151      end
    152    end
    153  end
    154 end
    155 
    156 local function detect_noext(path, bufnr)
    157  local root = fn.fnamemodify(path, ':r')
    158  if root == path then
    159    return
    160  end
    161  return M.match({ buf = bufnr, filename = root })
    162 end
    163 
    164 --- @param pat string
    165 --- @param a string?
    166 --- @param b string?
    167 --- @return vim.filetype.mapfn
    168 local function detect_line1(pat, a, b)
    169  return function(_path, bufnr)
    170    if M._getline(bufnr, 1):find(pat) then
    171      return a
    172    end
    173    return b
    174  end
    175 end
    176 
    177 --- @type vim.filetype.mapfn
    178 local detect_rc = function(path, _bufnr)
    179  if not path:find('/etc/Muttrc%.d/') then
    180    return 'rc'
    181  end
    182 end
    183 
    184 -- luacheck: push no unused args
    185 -- luacheck: push ignore 122
    186 
    187 -- Filetype detection logic is encoded in three tables:
    188 -- 1. `extension` for literal extension lookup
    189 -- 2. `filename` for literal full path or basename lookup;
    190 -- 3. `pattern` for matching filenames or paths against Lua patterns,
    191 --     optimized for fast lookup.
    192 -- See `:h dev-vimpatch-filetype` for guidance when porting Vim filetype patches.
    193 
    194 ---@diagnostic disable: unused-local
    195 ---@type vim.filetype.mapping
    196 local extension = {
    197  -- BEGIN EXTENSION
    198  ['8th'] = '8th',
    199  a65 = 'a65',
    200  aap = 'aap',
    201  abap = 'abap',
    202  abc = 'abc',
    203  abl = 'abel',
    204  abnf = 'abnf',
    205  wrm = 'acedb',
    206  ads = 'ada',
    207  ada = 'ada',
    208  gpr = 'ada',
    209  adb = 'ada',
    210  tdf = 'ahdl',
    211  aidl = 'aidl',
    212  aml = 'aml',
    213  run = 'ampl',
    214  g4 = 'antlr4',
    215  app = detect.app,
    216  applescript = 'applescript',
    217  scpt = 'applescript',
    218  ino = 'arduino',
    219  pde = 'arduino',
    220  art = 'art',
    221  asciidoc = 'asciidoc',
    222  adoc = 'asciidoc',
    223  asa = function(_path, _bufnr)
    224    if vim.g.filetype_asa then
    225      return vim.g.filetype_asa
    226    end
    227    return 'aspvbs'
    228  end,
    229  asm = detect.asm,
    230  s = detect.asm,
    231  S = detect.asm,
    232  a = detect.asm,
    233  A = detect.asm,
    234  lst = detect.asm,
    235  mac = detect.asm,
    236  asn1 = 'asn',
    237  asn = 'asn',
    238  asp = detect.asp,
    239  astro = 'astro',
    240  asy = 'asy',
    241  atl = 'atlas',
    242  as = 'atlas',
    243  zed = 'authzed',
    244  ahk = 'autohotkey',
    245  au3 = 'autoit',
    246  ave = 'ave',
    247  gawk = 'awk',
    248  awk = 'awk',
    249  ref = 'b',
    250  imp = 'b',
    251  mch = 'b',
    252  bas = detect.bas,
    253  bass = 'bass',
    254  bi = detect.bas,
    255  bm = detect.bas,
    256  bc = 'bc',
    257  bdf = 'bdf',
    258  beancount = 'beancount',
    259  bib = 'bib',
    260  com = detect_seq(detect.bindzone, 'dcl'),
    261  db = detect.bindzone,
    262  bicep = 'bicep',
    263  bicepparam = 'bicep-params',
    264  zone = 'bindzone',
    265  bb = 'bitbake',
    266  bbappend = 'bitbake',
    267  bbclass = 'bitbake',
    268  bl = 'blank',
    269  blp = 'blueprint',
    270  bp = 'bp',
    271  bt = 'bpftrace',
    272  bs = 'brighterscript',
    273  brs = 'brightscript',
    274  bsd = 'bsdl',
    275  bsdl = 'bsdl',
    276  bst = 'bst',
    277  btm = function(_path, _bufnr)
    278    return (vim.g.dosbatch_syntax_for_btm and vim.g.dosbatch_syntax_for_btm ~= 0) and 'dosbatch'
    279      or 'btm'
    280  end,
    281  bzl = 'bzl',
    282  bxl = 'bzl',
    283  bazel = 'bzl',
    284  BUILD = 'bzl',
    285  mdh = 'c',
    286  epro = 'c',
    287  qc = 'c',
    288  c3 = 'c3',
    289  c3i = 'c3',
    290  c3t = 'c3',
    291  cabal = 'cabal',
    292  cairo = 'cairo',
    293  cj = 'cangjie',
    294  capnp = 'capnp',
    295  cdc = 'cdc',
    296  cdl = 'cdl',
    297  toc = detect_line1('\\contentsline', 'tex', 'cdrtoc'),
    298  cedar = 'cedar',
    299  cel = 'cel',
    300  cfc = 'cf',
    301  cfm = 'cf',
    302  cfi = 'cf',
    303  hgrc = 'cfg',
    304  cfg = detect.cfg,
    305  Cfg = detect.cfg,
    306  CFG = detect.cfg,
    307  chf = 'ch',
    308  chai = 'chaiscript',
    309  ch = detect.change,
    310  chs = 'chaskell',
    311  chatito = 'chatito',
    312  chopro = 'chordpro',
    313  crd = 'chordpro',
    314  crdpro = 'chordpro',
    315  cho = 'chordpro',
    316  chordpro = 'chordpro',
    317  ck = 'chuck',
    318  cl = detect.cl,
    319  eni = 'cl',
    320  icl = 'clean',
    321  cljx = 'clojure',
    322  clj = 'clojure',
    323  cljc = 'clojure',
    324  cljs = 'clojure',
    325  cook = 'cook',
    326  cmake = 'cmake',
    327  cmod = 'cmod',
    328  cob = 'cobol',
    329  cbl = 'cobol',
    330  atg = 'coco',
    331  recipe = 'conaryrecipe',
    332  ctags = 'conf',
    333  hook = function(_path, bufnr)
    334    return M._getline(bufnr, 1) == '[Trigger]' and 'confini' or nil
    335  end,
    336  nmconnection = 'confini',
    337  mklx = 'context',
    338  mkiv = 'context',
    339  mkii = 'context',
    340  mkxl = 'context',
    341  mkvi = 'context',
    342  control = detect.control,
    343  copyright = detect.copyright,
    344  corn = 'corn',
    345  csh = detect.csh,
    346  cpon = 'cpon',
    347  moc = 'cpp',
    348  hh = 'cpp',
    349  tlh = 'cpp',
    350  inl = 'cpp',
    351  ipp = 'cpp',
    352  ['c++'] = 'cpp',
    353  C = 'cpp',
    354  cxx = 'cpp',
    355  H = 'cpp',
    356  tcc = 'cpp',
    357  hxx = 'cpp',
    358  hpp = 'cpp',
    359  ixx = 'cpp',
    360  mpp = 'cpp',
    361  ccm = 'cpp',
    362  cppm = 'cpp',
    363  cxxm = 'cpp',
    364  ['c++m'] = 'cpp',
    365  cpp = detect.cpp,
    366  cc = detect.cpp,
    367  cql = 'cqlang',
    368  crm = 'crm',
    369  cr = 'crystal',
    370  cake = 'cs',
    371  csx = 'cs',
    372  cs = 'cs',
    373  csc = 'csc',
    374  csdl = 'csdl',
    375  fdr = 'csp',
    376  csp = 'csp',
    377  css = 'css',
    378  csv = 'csv',
    379  con = 'cterm',
    380  feature = 'cucumber',
    381  cuh = 'cuda',
    382  cu = 'cuda',
    383  cue = 'cue',
    384  pld = 'cupl',
    385  si = 'cuplsim',
    386  cyn = 'cynpp',
    387  cypher = 'cypher',
    388  dfy = 'dafny',
    389  dart = 'dart',
    390  drt = 'dart',
    391  ds = 'datascript',
    392  dat = detect.dat,
    393  Dat = detect.dat,
    394  DAT = detect.dat,
    395  dax = 'dax',
    396  dcd = 'dcd',
    397  decl = detect.decl,
    398  dec = detect.decl,
    399  dcl = detect_seq(detect.decl, 'clean'),
    400  def = detect.def,
    401  desc = 'desc',
    402  directory = 'desktop',
    403  desktop = 'desktop',
    404  dhall = 'dhall',
    405  diff = 'diff',
    406  rej = 'diff',
    407  dj = 'djot',
    408  djot = 'djot',
    409  Dockerfile = 'dockerfile',
    410  dockerfile = 'dockerfile',
    411  bat = 'dosbatch',
    412  wrap = 'dosini',
    413  ini = 'dosini',
    414  INI = 'dosini',
    415  vbp = 'dosini',
    416  dot = 'dot',
    417  gv = 'dot',
    418  drac = 'dracula',
    419  drc = 'dracula',
    420  lvs = 'dracula',
    421  lpe = 'dracula',
    422  dsp = detect.dsp,
    423  dtd = 'dtd',
    424  d = detect.dtrace,
    425  dts = 'dts',
    426  dtsi = 'dts',
    427  dtso = 'dts',
    428  its = 'dts',
    429  keymap = 'dts',
    430  overlay = 'dts',
    431  dylan = 'dylan',
    432  intr = 'dylanintr',
    433  lid = 'dylanlid',
    434  e = detect.e,
    435  E = detect.e,
    436  ecd = 'ecd',
    437  edf = 'edif',
    438  edif = 'edif',
    439  edo = 'edif',
    440  edn = detect.edn,
    441  eex = 'eelixir',
    442  leex = 'eelixir',
    443  am = 'elf',
    444  exs = 'elixir',
    445  elm = 'elm',
    446  lc = 'elsa',
    447  elv = 'elvish',
    448  ent = detect.ent,
    449  env = 'env',
    450  epp = 'epuppet',
    451  erl = 'erlang',
    452  hrl = 'erlang',
    453  yaws = 'erlang',
    454  erb = 'eruby',
    455  rhtml = 'eruby',
    456  esdl = 'esdl',
    457  ec = 'esqlc',
    458  EC = 'esqlc',
    459  strl = 'esterel',
    460  eu = detect.euphoria,
    461  EU = detect.euphoria,
    462  ew = detect.euphoria,
    463  EW = detect.euphoria,
    464  EX = detect.euphoria,
    465  exu = detect.euphoria,
    466  EXU = detect.euphoria,
    467  exw = detect.euphoria,
    468  EXW = detect.euphoria,
    469  ex = detect.ex,
    470  exp = 'expect',
    471  f = detect.f,
    472  factor = 'factor',
    473  fal = 'falcon',
    474  fan = 'fan',
    475  fwt = 'fan',
    476  lib = 'faust',
    477  fnl = 'fennel',
    478  fnlm = 'fennel',
    479  fga = 'fga',
    480  m4gl = 'fgl',
    481  ['4gl'] = 'fgl',
    482  ['4gh'] = 'fgl',
    483  fir = 'firrtl',
    484  fish = 'fish',
    485  flix = 'flix',
    486  ftl = 'fluent',
    487  focexec = 'focexec',
    488  fex = 'focexec',
    489  ft = 'forth',
    490  fth = 'forth',
    491  ['4th'] = 'forth',
    492  FOR = 'fortran',
    493  f77 = 'fortran',
    494  f03 = 'fortran',
    495  fortran = 'fortran',
    496  F95 = 'fortran',
    497  f90 = 'fortran',
    498  F03 = 'fortran',
    499  fpp = 'fortran',
    500  FTN = 'fortran',
    501  ftn = 'fortran',
    502  ['for'] = 'fortran',
    503  F90 = 'fortran',
    504  F77 = 'fortran',
    505  f95 = 'fortran',
    506  FPP = 'fortran',
    507  F = 'fortran',
    508  F08 = 'fortran',
    509  f08 = 'fortran',
    510  fpc = 'fpcmake',
    511  fsl = 'framescript',
    512  frm = detect.frm,
    513  fb = 'freebasic',
    514  fs = detect.fs,
    515  fsh = 'fsh',
    516  fsi = 'fsharp',
    517  fsx = 'fsharp',
    518  fc = 'func',
    519  fusion = 'fusion',
    520  gdb = 'gdb',
    521  gdmo = 'gdmo',
    522  mo = 'gdmo',
    523  tscn = 'gdresource',
    524  tres = 'gdresource',
    525  gd = 'gdscript',
    526  gdshader = 'gdshader',
    527  shader = 'gdshader',
    528  ged = 'gedcom',
    529  gel = 'gel',
    530  gmi = 'gemtext',
    531  gemini = 'gemtext',
    532  gift = 'gift',
    533  prettierignore = 'gitignore',
    534  gleam = 'gleam',
    535  vert = 'glsl',
    536  tesc = 'glsl',
    537  tese = 'glsl',
    538  glsl = 'glsl',
    539  geom = 'glsl',
    540  frag = 'glsl',
    541  comp = 'glsl',
    542  rgen = 'glsl',
    543  rmiss = 'glsl',
    544  rchit = 'glsl',
    545  rahit = 'glsl',
    546  rint = 'glsl',
    547  rcall = 'glsl',
    548  gn = 'gn',
    549  gni = 'gn',
    550  gnuplot = 'gnuplot',
    551  gpi = 'gnuplot',
    552  go = 'go',
    553  gp = 'gp',
    554  gs = 'grads',
    555  gql = 'graphql',
    556  graphql = 'graphql',
    557  graphqls = 'graphql',
    558  gretl = 'gretl',
    559  groff = 'groff',
    560  mom = 'groff',
    561  gradle = 'groovy',
    562  groovy = 'groovy',
    563  gsp = 'gsp',
    564  gjs = 'javascript.glimmer',
    565  gts = 'typescript.glimmer',
    566  gyp = 'gyp',
    567  gypi = 'gyp',
    568  hack = 'hack',
    569  hackpartial = 'hack',
    570  haml = 'haml',
    571  hsm = 'hamster',
    572  hbs = 'handlebars',
    573  ha = 'hare',
    574  ['hs-boot'] = 'haskell',
    575  hsig = 'haskell',
    576  hsc = 'haskell',
    577  hs = 'haskell',
    578  persistentmodels = 'haskellpersistent',
    579  ht = 'haste',
    580  htpp = 'hastepreproc',
    581  hx = 'haxe',
    582  hcl = 'hcl',
    583  hb = 'hb',
    584  h = detect.header,
    585  sum = 'hercules',
    586  errsum = 'hercules',
    587  ev = 'hercules',
    588  vc = 'hercules',
    589  heex = 'heex',
    590  hex = 'hex',
    591  ['a43'] = 'hex',
    592  ['a90'] = 'hex',
    593  ['h32'] = 'hex',
    594  ['h80'] = 'hex',
    595  ['h86'] = 'hex',
    596  ihex = 'hex',
    597  ihe = 'hex',
    598  ihx = 'hex',
    599  int = 'hex',
    600  mcs = 'hex',
    601  hjson = 'hjson',
    602  m3u = 'hlsplaylist',
    603  m3u8 = 'hlsplaylist',
    604  hog = 'hog',
    605  hws = 'hollywood',
    606  hoon = 'hoon',
    607  cpt = detect.html,
    608  dtml = detect.html,
    609  htm = detect.html,
    610  html = detect.html,
    611  pt = detect.html,
    612  shtml = detect.html,
    613  stm = detect.html,
    614  htt = 'httest',
    615  htb = 'httest',
    616  http = 'http',
    617  hurl = 'hurl',
    618  hw = detect.hw,
    619  module = detect.hw,
    620  pkg = detect.hw,
    621  hy = 'hy',
    622  hylo = 'hylo',
    623  iba = 'ibasic',
    624  ibi = 'ibasic',
    625  icn = 'icon',
    626  idl = detect.idl,
    627  idr = 'idris2',
    628  inc = detect.inc,
    629  inf = 'inform',
    630  INF = 'inform',
    631  ii = 'initng',
    632  inko = 'inko',
    633  inp = detect.inp,
    634  ms = detect_seq(detect.nroff, 'xmath'),
    635  ipkg = 'ipkg',
    636  iss = 'iss',
    637  mst = 'ist',
    638  ist = 'ist',
    639  ijs = 'j',
    640  JAL = 'jal',
    641  jal = 'jal',
    642  jpr = 'jam',
    643  jpl = 'jam',
    644  janet = 'janet',
    645  jav = 'java',
    646  java = 'java',
    647  jsh = 'java',
    648  jj = 'javacc',
    649  jjt = 'javacc',
    650  es = 'javascript',
    651  mjs = 'javascript',
    652  javascript = 'javascript',
    653  js = 'javascript',
    654  jsm = 'javascript',
    655  cjs = 'javascript',
    656  jsx = 'javascriptreact',
    657  clp = 'jess',
    658  jgr = 'jgraph',
    659  jinja = 'jinja',
    660  jjdescription = 'jjdescription',
    661  j73 = 'jovial',
    662  jov = 'jovial',
    663  jovial = 'jovial',
    664  properties = 'jproperties',
    665  jq = 'jq',
    666  slnf = 'json',
    667  json = 'json',
    668  jsonp = 'json',
    669  geojson = 'json',
    670  mcmeta = 'json',
    671  webmanifest = 'json',
    672  ipynb = 'json',
    673  ['jupyterlab-settings'] = 'json',
    674  ['sublime-project'] = 'json',
    675  ['sublime-settings'] = 'json',
    676  ['sublime-workspace'] = 'json',
    677  ['json-patch'] = 'json',
    678  bd = 'json',
    679  bda = 'json',
    680  xci = 'json',
    681  json5 = 'json5',
    682  jsonc = 'jsonc',
    683  jsonl = 'jsonl',
    684  jsonnet = 'jsonnet',
    685  libsonnet = 'jsonnet',
    686  jsp = 'jsp',
    687  jl = 'julia',
    688  just = 'just',
    689  Just = 'just',
    690  JUST = 'just',
    691  kl = 'karel',
    692  KL = 'karel',
    693  kdl = 'kdl',
    694  kerml = 'kerml',
    695  kv = 'kivy',
    696  kix = 'kix',
    697  kk = 'koka',
    698  kos = 'kos',
    699  kts = 'kotlin',
    700  kt = 'kotlin',
    701  ktm = 'kotlin',
    702  sub = 'krl',
    703  Sub = 'krl',
    704  SUB = 'krl',
    705  ks = 'kscript',
    706  k = 'kwt',
    707  ACE = 'lace',
    708  ace = 'lace',
    709  lalrpop = 'lalrpop',
    710  latte = 'latte',
    711  lte = 'latte',
    712  ld = 'ld',
    713  ldif = 'ldif',
    714  lean = 'lean',
    715  journal = 'ledger',
    716  ldg = 'ledger',
    717  ledger = 'ledger',
    718  xrl = 'leex',
    719  leo = 'leo',
    720  less = 'less',
    721  lex = 'lex',
    722  lxx = 'lex',
    723  ['l++'] = 'lex',
    724  l = 'lex',
    725  lhs = 'lhaskell',
    726  lidr = 'lidris2',
    727  ly = 'lilypond',
    728  ily = 'lilypond',
    729  liquid = 'liquid',
    730  liq = 'liquidsoap',
    731  L = 'lisp',
    732  lisp = 'lisp',
    733  el = 'lisp',
    734  lsp = 'lisp',
    735  asd = 'lisp',
    736  lt = 'lite',
    737  lite = 'lite',
    738  livemd = 'livebook',
    739  ll = detect.ll,
    740  log = detect.log,
    741  Log = detect.log,
    742  LOG = detect.log,
    743  lgt = 'logtalk',
    744  lotos = 'lotos',
    745  lot = detect_line1('\\contentsline', 'tex', 'lotos'),
    746  lout = 'lout',
    747  lou = 'lout',
    748  ulpc = 'lpc',
    749  lpc = 'lpc',
    750  c = detect.lpc,
    751  lsl = detect.lsl,
    752  lss = 'lss',
    753  nse = 'lua',
    754  rockspec = 'lua',
    755  lua = 'lua',
    756  tlu = 'lua',
    757  luau = 'luau',
    758  lrc = 'lyrics',
    759  m = detect.m,
    760  at = 'config',
    761  mc = detect.mc,
    762  quake = 'm3quake',
    763  m4 = detect.m4,
    764  eml = 'mail',
    765  mk = detect.make,
    766  mak = detect.make,
    767  page = 'mallard',
    768  map = detect_line1('^%*+$', 'lnkmap', 'map'),
    769  mws = 'maple',
    770  mpl = 'maple',
    771  mv = 'maple',
    772  mkdn = detect.markdown,
    773  md = detect.markdown,
    774  mdwn = detect.markdown,
    775  mkd = detect.markdown,
    776  markdown = detect.markdown,
    777  mdown = detect.markdown,
    778  masm = 'masm',
    779  mhtml = 'mason',
    780  mason = 'mason',
    781  master = 'master',
    782  mas = 'master',
    783  demo = 'maxima',
    784  dm1 = 'maxima',
    785  dm2 = 'maxima',
    786  dm3 = 'maxima',
    787  dmt = 'maxima',
    788  wxm = 'maxima',
    789  mbsyncrc = 'mbsync',
    790  mw = 'mediawiki',
    791  wiki = 'mediawiki',
    792  mel = 'mel',
    793  mmd = 'mermaid',
    794  mmdc = 'mermaid',
    795  mermaid = 'mermaid',
    796  mf = 'mf',
    797  mgl = 'mgl',
    798  mgp = 'mgp',
    799  my = 'mib',
    800  mib = 'mib',
    801  mix = 'mix',
    802  mixal = 'mix',
    803  mlir = 'mlir',
    804  mm = detect.mm,
    805  nb = 'mma',
    806  wl = 'mma',
    807  mmp = 'mmp',
    808  mms = detect.mms,
    809  mod = detect.mod,
    810  Mod = detect.mod,
    811  MOD = detect.mod,
    812  DEF = 'modula2',
    813  m3 = 'modula3',
    814  i3 = 'modula3',
    815  mg = 'modula3',
    816  ig = 'modula3',
    817  lm3 = 'modula3',
    818  mojo = 'mojo',
    819  ['🔥'] = 'mojo', -- 🙄
    820  ssc = 'monk',
    821  monk = 'monk',
    822  tsc = 'monk',
    823  isc = 'monk',
    824  moo = 'moo',
    825  moon = 'moonscript',
    826  move = 'move',
    827  mp = 'mp',
    828  mpiv = detect.mp,
    829  mpvi = detect.mp,
    830  mpxl = detect.mp,
    831  mof = 'msidl',
    832  odl = 'msidl',
    833  msql = 'msql',
    834  mss = 'mss',
    835  mu = 'mupad',
    836  mush = 'mush',
    837  mustache = 'mustache',
    838  mysql = 'mysql',
    839  n1ql = 'n1ql',
    840  nql = 'n1ql',
    841  nanorc = 'nanorc',
    842  nasm = 'nasm',
    843  NSA = 'natural',
    844  NSC = 'natural',
    845  NSG = 'natural',
    846  NSL = 'natural',
    847  NSM = 'natural',
    848  NSN = 'natural',
    849  NSP = 'natural',
    850  NSS = 'natural',
    851  ncf = 'ncf',
    852  neon = 'neon',
    853  axs = 'netlinx',
    854  axi = 'netlinx',
    855  nginx = 'nginx',
    856  ncl = 'nickel',
    857  nim = 'nim',
    858  nims = 'nim',
    859  nimble = 'nim',
    860  ninja = 'ninja',
    861  nix = 'nix',
    862  norg = 'norg',
    863  nq = 'nq',
    864  nqc = 'nqc',
    865  ['0'] = detect.nroff,
    866  ['1'] = detect.nroff,
    867  ['2'] = detect.nroff,
    868  ['3'] = detect.nroff,
    869  ['4'] = detect.nroff,
    870  ['5'] = detect.nroff,
    871  ['6'] = detect.nroff,
    872  ['7'] = detect.nroff,
    873  ['8'] = detect.nroff,
    874  ['9'] = detect.nroff,
    875  ['0p'] = detect.nroff,
    876  ['1p'] = detect.nroff,
    877  ['3p'] = detect.nroff,
    878  ['1x'] = detect.nroff,
    879  ['2x'] = detect.nroff,
    880  ['3x'] = detect.nroff,
    881  ['4x'] = detect.nroff,
    882  ['5x'] = detect.nroff,
    883  ['6x'] = detect.nroff,
    884  ['7x'] = detect.nroff,
    885  ['8x'] = detect.nroff,
    886  ['3am'] = detect.nroff,
    887  ['3perl'] = detect.nroff,
    888  ['3pm'] = detect.nroff,
    889  ['3posix'] = detect.nroff,
    890  ['3type'] = detect.nroff,
    891  n = detect.nroff,
    892  roff = 'nroff',
    893  tmac = 'nroff',
    894  man = 'nroff',
    895  nr = 'nroff',
    896  tr = 'nroff',
    897  nsi = 'nsis',
    898  nsh = 'nsis',
    899  nt = 'ntriples',
    900  nu = 'nu',
    901  nbt = 'numbat',
    902  obj = 'obj',
    903  objdump = 'objdump',
    904  cppobjdump = 'objdump',
    905  obl = 'obse',
    906  obse = 'obse',
    907  oblivion = 'obse',
    908  obscript = 'obse',
    909  mlt = 'ocaml',
    910  mly = 'ocaml',
    911  mll = 'ocaml',
    912  mlp = 'ocaml',
    913  mlip = 'ocaml',
    914  mli = 'ocaml',
    915  ml = 'ocaml',
    916  occ = 'occam',
    917  odin = 'odin',
    918  xom = 'omnimark',
    919  xin = 'omnimark',
    920  opam = 'opam',
    921  ['or'] = 'openroad',
    922  scad = 'openscad',
    923  ovpn = 'openvpn',
    924  opl = 'opl',
    925  opL = 'opl',
    926  oPl = 'opl',
    927  oPL = 'opl',
    928  Opl = 'opl',
    929  OpL = 'opl',
    930  OPl = 'opl',
    931  OPL = 'opl',
    932  ora = 'ora',
    933  org = 'org',
    934  org_archive = 'org',
    935  pandoc = 'pandoc',
    936  pdk = 'pandoc',
    937  pd = 'pandoc',
    938  pdc = 'pandoc',
    939  pxsl = 'papp',
    940  papp = 'papp',
    941  pxml = 'papp',
    942  pas = 'pascal',
    943  lpr = detect_line1('<%?xml', 'xml', 'pascal'),
    944  dpr = 'pascal',
    945  txtpb = 'pbtxt',
    946  textproto = 'pbtxt',
    947  textpb = 'pbtxt',
    948  pbtxt = 'pbtxt',
    949  aconfig = 'pbtxt',
    950  g = 'pccts',
    951  pcmk = 'pcmk',
    952  pdf = 'pdf',
    953  pem = 'pem',
    954  cer = 'pem',
    955  crt = 'pem',
    956  csr = 'pem',
    957  plx = 'perl',
    958  prisma = 'prisma',
    959  psgi = 'perl',
    960  al = 'perl',
    961  ctp = 'php',
    962  php = 'php',
    963  phpt = 'php',
    964  php0 = 'php',
    965  php1 = 'php',
    966  php2 = 'php',
    967  php3 = 'php',
    968  php4 = 'php',
    969  php5 = 'php',
    970  php6 = 'php',
    971  php7 = 'php',
    972  php8 = 'php',
    973  php9 = 'php',
    974  phtml = 'php',
    975  theme = 'php',
    976  pike = 'pike',
    977  pmod = 'pike',
    978  rcp = 'pilrc',
    979  pkl = 'pkl',
    980  pcf = 'pkl',
    981  PL = detect.pl,
    982  pli = 'pli',
    983  pl1 = 'pli',
    984  p36 = 'plm',
    985  plm = 'plm',
    986  pac = 'plm',
    987  plp = 'plp',
    988  pls = 'plsql',
    989  plsql = 'plsql',
    990  po = 'po',
    991  pot = 'po',
    992  pod = 'pod',
    993  filter = 'poefilter',
    994  pk = 'poke',
    995  pony = 'pony',
    996  ps = 'postscr',
    997  epsi = 'postscr',
    998  afm = 'postscr',
    999  epsf = 'postscr',
   1000  eps = 'postscr',
   1001  pfa = 'postscr',
   1002  ai = 'postscr',
   1003  pov = 'pov',
   1004  ppd = 'ppd',
   1005  it = 'ppwiz',
   1006  ih = 'ppwiz',
   1007  pq = 'pq',
   1008  action = 'privoxy',
   1009  prg = detect.prg,
   1010  Prg = detect.prg,
   1011  PRG = detect.prg,
   1012  pc = 'proc',
   1013  pdb = 'prolog',
   1014  pml = 'promela',
   1015  proto = 'proto',
   1016  prql = 'prql',
   1017  psd1 = 'ps1',
   1018  psm1 = 'ps1',
   1019  ps1 = 'ps1',
   1020  pssc = 'ps1',
   1021  ps1xml = 'ps1xml',
   1022  psf = 'psf',
   1023  psl = 'psl',
   1024  ptx = 'ptx',
   1025  pug = 'pug',
   1026  purs = 'purescript',
   1027  arr = 'pyret',
   1028  pxd = 'pyrex',
   1029  pxi = 'pyrex',
   1030  pyx = 'pyrex',
   1031  ['pyx+'] = 'pyrex',
   1032  pyw = 'python',
   1033  py = 'python',
   1034  pyi = 'python',
   1035  ptl = 'python',
   1036  ipy = 'python',
   1037  ql = 'ql',
   1038  qll = 'ql',
   1039  qml = 'qml',
   1040  qbs = 'qml',
   1041  qmd = 'quarto',
   1042  bms = 'quickbms',
   1043  R = detect.r,
   1044  rkt = 'racket',
   1045  rktd = 'racket',
   1046  rktl = 'racket',
   1047  rad = 'radiance',
   1048  mat = 'radiance',
   1049  pod6 = 'raku',
   1050  rakudoc = 'raku',
   1051  rakutest = 'raku',
   1052  rakumod = 'raku',
   1053  pm6 = 'raku',
   1054  raku = 'raku',
   1055  t6 = 'raku',
   1056  p6 = 'raku',
   1057  raml = 'raml',
   1058  sysx = 'rapid',
   1059  sysX = 'rapid',
   1060  Sysx = 'rapid',
   1061  SysX = 'rapid',
   1062  SYSX = 'rapid',
   1063  SYSx = 'rapid',
   1064  modx = 'rapid',
   1065  modX = 'rapid',
   1066  Modx = 'rapid',
   1067  ModX = 'rapid',
   1068  MODX = 'rapid',
   1069  MODx = 'rapid',
   1070  rasi = 'rasi',
   1071  rasinc = 'rasi',
   1072  cshtml = 'razor',
   1073  razor = 'razor',
   1074  rbs = 'rbs',
   1075  rego = 'rego',
   1076  rem = 'remind',
   1077  remind = 'remind',
   1078  pip = 'requirements',
   1079  res = 'rescript',
   1080  resi = 'rescript',
   1081  frt = 'reva',
   1082  testUnit = 'rexx',
   1083  rex = 'rexx',
   1084  orx = 'rexx',
   1085  rexx = 'rexx',
   1086  jrexx = 'rexx',
   1087  rxj = 'rexx',
   1088  rexxj = 'rexx',
   1089  testGroup = 'rexx',
   1090  rxo = 'rexx',
   1091  Rd = 'rhelp',
   1092  rd = 'rhelp',
   1093  rib = 'rib',
   1094  Rmd = 'rmd',
   1095  rmd = 'rmd',
   1096  smd = 'rmd',
   1097  Smd = 'rmd',
   1098  rnc = 'rnc',
   1099  rng = 'rng',
   1100  rnw = 'rnoweb',
   1101  snw = 'rnoweb',
   1102  Rnw = 'rnoweb',
   1103  Snw = 'rnoweb',
   1104  robot = 'robot',
   1105  resource = 'robot',
   1106  roc = 'roc',
   1107  ron = 'ron',
   1108  rsc = 'routeros',
   1109  x = 'rpcgen',
   1110  rpgle = 'rpgle',
   1111  rpgleinc = 'rpgle',
   1112  rpl = 'rpl',
   1113  Srst = 'rrst',
   1114  srst = 'rrst',
   1115  Rrst = 'rrst',
   1116  rrst = 'rrst',
   1117  rst = 'rst',
   1118  rtf = 'rtf',
   1119  rjs = 'ruby',
   1120  rxml = 'ruby',
   1121  rb = 'ruby',
   1122  rbi = 'ruby',
   1123  rant = 'ruby',
   1124  ru = 'ruby',
   1125  rbw = 'ruby',
   1126  gemspec = 'ruby',
   1127  builder = 'ruby',
   1128  rake = 'ruby',
   1129  rs = 'rust',
   1130  sa = detect.sa,
   1131  sage = 'sage',
   1132  sls = 'salt',
   1133  sas = 'sas',
   1134  sass = 'sass',
   1135  sbt = 'sbt',
   1136  scala = 'scala',
   1137  mill = 'scala',
   1138  ss = 'scheme',
   1139  scm = 'scheme',
   1140  sld = 'scheme',
   1141  stsg = 'scheme',
   1142  sce = 'scilab',
   1143  sci = 'scilab',
   1144  scss = 'scss',
   1145  sd = 'sd',
   1146  sdc = 'sdc',
   1147  pr = 'sdl',
   1148  sdl = 'sdl',
   1149  sed = 'sed',
   1150  sexp = 'sexplib',
   1151  bash = detect.bash,
   1152  bats = detect.bash,
   1153  cygport = detect.bash,
   1154  ebuild = detect.bash,
   1155  eclass = detect.bash,
   1156  envrc = detect.sh,
   1157  ksh = detect.ksh,
   1158  sh = detect.sh,
   1159  lo = 'sh',
   1160  la = 'sh',
   1161  lai = 'sh',
   1162  mdd = 'sh',
   1163  slang = 'shaderslang',
   1164  sieve = 'sieve',
   1165  siv = 'sieve',
   1166  sig = detect.sig,
   1167  sil = detect.sil,
   1168  sim = 'simula',
   1169  s85 = 'sinda',
   1170  sin = 'sinda',
   1171  ssm = 'sisu',
   1172  sst = 'sisu',
   1173  ssi = 'sisu',
   1174  ['_sst'] = 'sisu',
   1175  ['-sst'] = 'sisu',
   1176  il = 'skill',
   1177  ils = 'skill',
   1178  cdf = 'skill',
   1179  sl = 'slang',
   1180  ice = 'slice',
   1181  slint = 'slint',
   1182  score = 'slrnsc',
   1183  sol = 'solidity',
   1184  smali = 'smali',
   1185  tpl = 'smarty',
   1186  ihlp = 'smcl',
   1187  smcl = 'smcl',
   1188  hlp = 'smcl',
   1189  smith = 'smith',
   1190  smt = 'smith',
   1191  smithy = 'smithy',
   1192  sml = 'sml',
   1193  smk = 'snakemake',
   1194  spt = 'snobol4',
   1195  sno = 'snobol4',
   1196  sln = 'solution',
   1197  soy = 'soy',
   1198  sparql = 'sparql',
   1199  rq = 'sparql',
   1200  spec = 'spec',
   1201  spice = 'spice',
   1202  sp = 'spice',
   1203  spd = 'spup',
   1204  spdata = 'spup',
   1205  speedup = 'spup',
   1206  spi = 'spyce',
   1207  spy = 'spyce',
   1208  tyc = 'sql',
   1209  typ = detect.typ,
   1210  pkb = 'sql',
   1211  tyb = 'sql',
   1212  pks = 'sql',
   1213  sqlj = 'sqlj',
   1214  sqi = 'sqr',
   1215  sqr = 'sqr',
   1216  nut = 'squirrel',
   1217  src = detect.src,
   1218  Src = detect.src,
   1219  SRC = detect.src,
   1220  s28 = 'srec',
   1221  s37 = 'srec',
   1222  srec = 'srec',
   1223  mot = 'srec',
   1224  s19 = 'srec',
   1225  srt = 'srt',
   1226  ssa = 'ssa',
   1227  ass = 'ssa',
   1228  st = 'st',
   1229  ipd = 'starlark',
   1230  sky = 'starlark',
   1231  star = 'starlark',
   1232  starlark = 'starlark',
   1233  imata = 'stata',
   1234  ['do'] = 'stata',
   1235  mata = 'stata',
   1236  ado = 'stata',
   1237  stp = 'stp',
   1238  styl = 'stylus',
   1239  stylus = 'stylus',
   1240  quark = 'supercollider',
   1241  sface = 'surface',
   1242  svelte = 'svelte',
   1243  svg = 'svg',
   1244  sw = 'sway',
   1245  swift = 'swift',
   1246  swiftinterface = 'swift',
   1247  swig = 'swig',
   1248  swg = 'swig',
   1249  sys = detect.sys,
   1250  Sys = detect.sys,
   1251  SYS = detect.sys,
   1252  sysml = 'sysml',
   1253  svh = 'systemverilog',
   1254  sv = 'systemverilog',
   1255  cmm = 'trace32',
   1256  cmmt = 'trace32',
   1257  t32 = 'trace32',
   1258  td = 'tablegen',
   1259  tak = 'tak',
   1260  tal = 'tal',
   1261  task = 'taskedit',
   1262  tm = 'tcl',
   1263  tcl = 'tcl',
   1264  itk = 'tcl',
   1265  itcl = 'tcl',
   1266  tk = 'tcl',
   1267  jacl = 'tcl',
   1268  tl = 'teal',
   1269  templ = 'templ',
   1270  tmpl = 'template',
   1271  tera = 'tera',
   1272  ti = 'terminfo',
   1273  dtx = 'tex',
   1274  ltx = 'tex',
   1275  bbl = 'tex',
   1276  latex = 'tex',
   1277  sty = 'tex',
   1278  pgf = 'tex',
   1279  nlo = 'tex',
   1280  nls = 'tex',
   1281  thm = 'tex',
   1282  eps_tex = 'tex',
   1283  pdf_tex = 'tex',
   1284  pygtex = 'tex',
   1285  pygstyle = 'tex',
   1286  clo = 'tex',
   1287  aux = 'tex',
   1288  brf = 'tex',
   1289  ind = 'tex',
   1290  lof = 'tex',
   1291  loe = 'tex',
   1292  nav = 'tex',
   1293  vrb = 'tex',
   1294  ins = 'tex',
   1295  tikz = 'tex',
   1296  bbx = 'tex',
   1297  cbx = 'tex',
   1298  beamer = 'tex',
   1299  cls = detect.cls,
   1300  texi = 'texinfo',
   1301  txi = 'texinfo',
   1302  texinfo = 'texinfo',
   1303  text = 'text',
   1304  tfvars = 'terraform-vars',
   1305  thrift = 'thrift',
   1306  tig = 'tiger',
   1307  Tiltfile = 'tiltfile',
   1308  tiltfile = 'tiltfile',
   1309  tla = 'tla',
   1310  tli = 'tli',
   1311  toml = 'toml',
   1312  tpp = 'tpp',
   1313  treetop = 'treetop',
   1314  trig = 'trig',
   1315  slt = 'tsalt',
   1316  tsscl = 'tsscl',
   1317  tssgm = 'tssgm',
   1318  tssop = 'tssop',
   1319  tsv = 'tsv',
   1320  tutor = 'tutor',
   1321  twig = 'twig',
   1322  ts = detect_line1('<%?xml', 'xml', 'typescript'),
   1323  mts = 'typescript',
   1324  cts = 'typescript',
   1325  tsx = 'typescriptreact',
   1326  tsp = 'typespec',
   1327  uc = 'uc',
   1328  uit = 'uil',
   1329  uil = 'uil',
   1330  ungram = 'ungrammar',
   1331  u = 'unison',
   1332  uu = 'unison',
   1333  url = 'urlshortcut',
   1334  usd = 'usd',
   1335  usda = 'usd',
   1336  v = detect.v,
   1337  vsh = 'v',
   1338  vv = 'v',
   1339  ctl = 'vb',
   1340  dob = 'vb',
   1341  dsm = 'vb',
   1342  dsr = 'vb',
   1343  pag = 'vb',
   1344  sba = 'vb',
   1345  vb = 'vb',
   1346  vbs = 'vb',
   1347  vba = detect.vba,
   1348  vdf = 'vdf',
   1349  vdmpp = 'vdmpp',
   1350  vpp = 'vdmpp',
   1351  vdmrt = 'vdmrt',
   1352  vdmsl = 'vdmsl',
   1353  vdm = 'vdmsl',
   1354  vto = 'vento',
   1355  vr = 'vera',
   1356  vri = 'vera',
   1357  vrh = 'vera',
   1358  va = 'verilogams',
   1359  vams = 'verilogams',
   1360  vhdl = 'vhdl',
   1361  vst = 'vhdl',
   1362  vhd = 'vhdl',
   1363  hdl = 'vhdl',
   1364  vho = 'vhdl',
   1365  vbe = 'vhdl',
   1366  tape = 'vhs',
   1367  vim = 'vim',
   1368  mar = 'vmasm',
   1369  cm = 'voscm',
   1370  wrl = 'vrml',
   1371  vroom = 'vroom',
   1372  vue = 'vue',
   1373  wast = 'wat',
   1374  wat = 'wat',
   1375  wdl = 'wdl',
   1376  wm = 'webmacro',
   1377  wgsl = 'wgsl',
   1378  wbt = 'winbatch',
   1379  wit = 'wit',
   1380  wml = 'wml',
   1381  wsf = 'wsh',
   1382  wsc = 'wsh',
   1383  wsml = 'wsml',
   1384  ad = 'xdefaults',
   1385  xhtml = 'xhtml',
   1386  xht = 'xhtml',
   1387  msc = 'xmath',
   1388  msf = 'xmath',
   1389  psc1 = 'xml',
   1390  tpm = 'xml',
   1391  xliff = 'xml',
   1392  atom = 'xml',
   1393  xul = 'xml',
   1394  cdxml = 'xml',
   1395  mpd = 'xml',
   1396  rss = 'xml',
   1397  fsproj = 'xml',
   1398  ui = 'xml',
   1399  vbproj = 'xml',
   1400  xlf = 'xml',
   1401  wsdl = 'xml',
   1402  csproj = 'xml',
   1403  wpl = 'xml',
   1404  xmi = 'xml',
   1405  xpr = 'xml',
   1406  xpfm = 'xml',
   1407  spfm = 'xml',
   1408  bxml = 'xml',
   1409  mmi = 'xml',
   1410  xcu = 'xml',
   1411  xlb = 'xml',
   1412  xlc = 'xml',
   1413  xba = 'xml',
   1414  slnx = 'xml',
   1415  xpm = detect_line1('XPM2', 'xpm2', 'xpm'),
   1416  xpm2 = 'xpm2',
   1417  xqy = 'xquery',
   1418  xqm = 'xquery',
   1419  xquery = 'xquery',
   1420  xq = 'xquery',
   1421  xql = 'xquery',
   1422  xs = 'xs',
   1423  xsd = 'xsd',
   1424  xsl = 'xslt',
   1425  xslt = 'xslt',
   1426  yy = 'yacc',
   1427  ['y++'] = 'yacc',
   1428  yxx = 'yacc',
   1429  yml = 'yaml',
   1430  yaml = 'yaml',
   1431  eyaml = 'yaml',
   1432  mplstyle = 'yaml',
   1433  kyaml = 'yaml',
   1434  kyml = 'yaml',
   1435  grc = detect_line1('<%?xml', 'xml', 'yaml'),
   1436  yang = 'yang',
   1437  yara = 'yara',
   1438  yar = 'yara',
   1439  yuck = 'yuck',
   1440  z8a = 'z8a',
   1441  zig = 'zig',
   1442  zon = 'zig',
   1443  ziggy = 'ziggy',
   1444  ['ziggy-schema'] = 'ziggy_schema',
   1445  zu = 'zimbu',
   1446  zut = 'zimbutempl',
   1447  zs = 'zserio',
   1448  zsh = 'zsh',
   1449  zunit = 'zsh',
   1450  ['zsh-theme'] = 'zsh',
   1451  vala = 'vala',
   1452  web = detect.web,
   1453  pl = detect.pl,
   1454  pp = detect.pp,
   1455  i = detect.i,
   1456  w = detect.progress_cweb,
   1457  p = detect.progress_pascal,
   1458  pro = detect_seq(detect.proto, 'idlang'),
   1459  patch = detect.patch,
   1460  r = detect.r,
   1461  rdf = detect.redif,
   1462  rules = detect.rules,
   1463  sc = detect.sc,
   1464  scd = detect.scd,
   1465  tcsh = function(path, bufnr)
   1466    return require('vim.filetype.detect').shell(path, M._getlines(bufnr), 'tcsh')
   1467  end,
   1468  sql = detect.sql,
   1469  zsql = detect.sql,
   1470  tex = detect.tex,
   1471  tf = detect.tf,
   1472  txt = detect.txt,
   1473  xml = detect.xml,
   1474  y = detect.y,
   1475  cmd = detect.cmd,
   1476  rul = detect.rul,
   1477  cpy = detect_line1('^##', 'python', 'cobol'),
   1478  dsl = detect_line1('^%s*<!', 'dsl', 'structurizr'),
   1479  smil = detect_line1('<%?%s*xml.*%?>', 'xml', 'smil'),
   1480  smi = detect.smi,
   1481  install = detect.install,
   1482  pm = detect.pm,
   1483  me = detect.me,
   1484  reg = detect.reg,
   1485  ttl = detect.ttl,
   1486  rc = detect_rc,
   1487  rch = detect_rc,
   1488  class = detect.class,
   1489  sgml = detect.sgml,
   1490  sgm = detect.sgml,
   1491  t = detect_seq(detect.nroff, detect.perl, 'tads'),
   1492  -- Ignored extensions
   1493  bak = detect_noext,
   1494  ['dpkg-bak'] = detect_noext,
   1495  ['dpkg-dist'] = detect_noext,
   1496  ['dpkg-old'] = detect_noext,
   1497  ['dpkg-new'] = detect_noext,
   1498  ['in'] = function(path, bufnr)
   1499    if vim.fs.basename(path) ~= 'configure.in' then
   1500      return detect_noext(path, bufnr)
   1501    end
   1502  end,
   1503  new = detect_noext,
   1504  old = detect_noext,
   1505  orig = detect_noext,
   1506  pacsave = detect_noext,
   1507  pacnew = detect_noext,
   1508  rpmsave = detect_noext,
   1509  rmpnew = detect_noext,
   1510  -- END EXTENSION
   1511 }
   1512 
   1513 ---@type vim.filetype.mapping
   1514 local filename = {
   1515  -- BEGIN FILENAME
   1516  ['a2psrc'] = 'a2ps',
   1517  ['/etc/a2ps.cfg'] = 'a2ps',
   1518  ['.a2psrc'] = 'a2ps',
   1519  ['.asoundrc'] = 'alsaconf',
   1520  ['/usr/share/alsa/alsa.conf'] = 'alsaconf',
   1521  ['/etc/asound.conf'] = 'alsaconf',
   1522  ['build.xml'] = 'ant',
   1523  ['.htaccess'] = 'apache',
   1524  APKBUILD = 'apkbuild',
   1525  ['apt.conf'] = 'aptconf',
   1526  ['/.aptitude/config'] = 'aptconf',
   1527  ['=tagging-method'] = 'arch',
   1528  ['.arch-inventory'] = 'arch',
   1529  ['makefile.am'] = 'automake',
   1530  ['Makefile.am'] = 'automake',
   1531  ['GNUmakefile.am'] = 'automake',
   1532  ['.bash_aliases'] = detect.bash,
   1533  ['.bash-aliases'] = detect.bash,
   1534  ['.bash_history'] = detect.bash,
   1535  ['.bash-history'] = detect.bash,
   1536  ['.bash_logout'] = detect.bash,
   1537  ['.bash-logout'] = detect.bash,
   1538  ['.bash_profile'] = detect.bash,
   1539  ['.bash-profile'] = detect.bash,
   1540  ['named.root'] = 'bindzone',
   1541  WORKSPACE = 'bzl',
   1542  ['WORKSPACE.bzlmod'] = 'bzl',
   1543  BUCK = 'bzl',
   1544  BUILD = 'bzl',
   1545  ['cabal.project'] = 'cabalproject',
   1546  ['cabal.config'] = 'cabalconfig',
   1547  calendar = 'calendar',
   1548  catalog = 'catalog',
   1549  ['/etc/cdrdao.conf'] = 'cdrdaoconf',
   1550  ['.cdrdao'] = 'cdrdaoconf',
   1551  ['/etc/default/cdrdao'] = 'cdrdaoconf',
   1552  ['/etc/defaults/cdrdao'] = 'cdrdaoconf',
   1553  ['cfengine.conf'] = 'cfengine',
   1554  cgdbrc = 'cgdbrc',
   1555  ['init.trans'] = 'clojure',
   1556  ['.trans'] = 'clojure',
   1557  ['CMakeLists.txt'] = 'cmake',
   1558  ['CMakeCache.txt'] = 'cmakecache',
   1559  ['CODEOWNERS'] = 'codeowners',
   1560  ['.cling_history'] = 'cpp',
   1561  ['.alias'] = detect.csh,
   1562  ['.cshrc'] = detect.csh,
   1563  ['.login'] = detect.csh,
   1564  ['csh.cshrc'] = detect.csh,
   1565  ['csh.login'] = detect.csh,
   1566  ['csh.logout'] = detect.csh,
   1567  ['auto.master'] = 'conf',
   1568  ['texdoc.cnf'] = 'conf',
   1569  ['.x11vncrc'] = 'conf',
   1570  ['.chktexrc'] = 'conf',
   1571  ['.ripgreprc'] = 'conf',
   1572  ripgreprc = 'conf',
   1573  ['configure.in'] = 'config',
   1574  ['configure.ac'] = 'config',
   1575  crontab = 'crontab',
   1576  ['.cvsrc'] = 'cvsrc',
   1577  ['/debian/changelog'] = 'debchangelog',
   1578  ['changelog.dch'] = 'debchangelog',
   1579  ['changelog.Debian'] = 'debchangelog',
   1580  ['NEWS.dch'] = 'debchangelog',
   1581  ['NEWS.Debian'] = 'debchangelog',
   1582  ['/debian/control'] = 'debcontrol',
   1583  ['/DEBIAN/control'] = 'debcontrol',
   1584  ['/debian/copyright'] = 'debcopyright',
   1585  ['/etc/apt/sources.list'] = 'debsources',
   1586  ['denyhosts.conf'] = 'denyhosts',
   1587  ['dict.conf'] = 'dictconf',
   1588  ['.dictrc'] = 'dictconf',
   1589  ['/etc/DIR_COLORS'] = 'dircolors',
   1590  ['.dir_colors'] = 'dircolors',
   1591  ['.dircolors'] = 'dircolors',
   1592  ['/etc/dnsmasq.conf'] = 'dnsmasq',
   1593  Containerfile = 'dockerfile',
   1594  dockerfile = 'dockerfile',
   1595  Dockerfile = 'dockerfile',
   1596  npmrc = 'dosini',
   1597  ['/etc/yum.conf'] = 'dosini',
   1598  ['.npmrc'] = 'dosini',
   1599  ['pip.conf'] = 'dosini',
   1600  ['setup.cfg'] = 'dosini',
   1601  ['pudb.cfg'] = 'dosini',
   1602  ['.coveragerc'] = 'dosini',
   1603  ['.pypirc'] = 'dosini',
   1604  ['.pylintrc'] = 'dosini',
   1605  ['pylintrc'] = 'dosini',
   1606  ['.replyrc'] = 'dosini',
   1607  ['.gitlint'] = 'dosini',
   1608  ['.oelint.cfg'] = 'dosini',
   1609  ['psprint.conf'] = 'dosini',
   1610  sofficerc = 'dosini',
   1611  ['mimeapps.list'] = 'dosini',
   1612  ['.wakatime.cfg'] = 'dosini',
   1613  ['nfs.conf'] = 'dosini',
   1614  ['nfsmount.conf'] = 'dosini',
   1615  ['.notmuch-config'] = 'dosini',
   1616  ['.alsoftrc'] = 'dosini',
   1617  ['alsoft.conf'] = 'dosini',
   1618  ['alsoft.ini'] = 'dosini',
   1619  ['alsoftrc.sample'] = 'dosini',
   1620  ['pacman.conf'] = 'confini',
   1621  ['paru.conf'] = 'confini',
   1622  ['mpv.conf'] = 'confini',
   1623  dune = 'dune',
   1624  jbuild = 'dune',
   1625  ['dune-workspace'] = 'dune',
   1626  ['dune-project'] = 'dune',
   1627  ['dune-file'] = 'dune',
   1628  Earthfile = 'earthfile',
   1629  ['.editorconfig'] = 'editorconfig',
   1630  ['elinks.conf'] = 'elinks',
   1631  ['.env'] = 'env',
   1632  ['rebar.config'] = 'erlang',
   1633  ['mix.lock'] = 'elixir',
   1634  ['filter-rules'] = 'elmfilt',
   1635  ['exim.conf'] = 'exim',
   1636  exports = 'exports',
   1637  fennelrc = 'fennel',
   1638  ['.fennelrc'] = 'fennel',
   1639  ['.fetchmailrc'] = 'fetchmail',
   1640  fvSchemes = detect.foam,
   1641  fvSolution = detect.foam,
   1642  fvConstraints = detect.foam,
   1643  fvModels = detect.foam,
   1644  fstab = 'fstab',
   1645  mtab = 'fstab',
   1646  ['.gdbinit'] = 'gdb',
   1647  gdbinit = 'gdb',
   1648  ['.cuda-gdbinit'] = 'gdb',
   1649  ['cuda-gdbinit'] = 'gdb',
   1650  ['.gdbearlyinit'] = 'gdb',
   1651  gdbearlyinit = 'gdb',
   1652  ['lltxxxxx.txt'] = 'gedcom',
   1653  TAG_EDITMSG = 'gitcommit',
   1654  MERGE_MSG = 'gitcommit',
   1655  COMMIT_EDITMSG = 'gitcommit',
   1656  NOTES_EDITMSG = 'gitcommit',
   1657  EDIT_DESCRIPTION = 'gitcommit',
   1658  ['.gitconfig'] = 'gitconfig',
   1659  ['.gitmodules'] = 'gitconfig',
   1660  ['.gitattributes'] = 'gitattributes',
   1661  ['.gitignore'] = 'gitignore',
   1662  ['.ignore'] = 'gitignore',
   1663  ['.containerignore'] = 'gitignore',
   1664  ['.dockerignore'] = 'gitignore',
   1665  ['.fdignore'] = 'gitignore',
   1666  ['.npmignore'] = 'gitignore',
   1667  ['.rgignore'] = 'gitignore',
   1668  ['.vscodeignore'] = 'gitignore',
   1669  ['gitolite.conf'] = 'gitolite',
   1670  ['git-rebase-todo'] = 'gitrebase',
   1671  gkrellmrc = 'gkrellmrc',
   1672  ['.gnashrc'] = 'gnash',
   1673  ['.gnashpluginrc'] = 'gnash',
   1674  gnashpluginrc = 'gnash',
   1675  gnashrc = 'gnash',
   1676  ['.gnuplot_history'] = 'gnuplot',
   1677  ['goaccess.conf'] = 'goaccess',
   1678  ['go.sum'] = 'gosum',
   1679  ['go.work.sum'] = 'gosum',
   1680  ['go.work'] = 'gowork',
   1681  ['.gprc'] = 'gp',
   1682  ['/.gnupg/gpg.conf'] = 'gpg',
   1683  ['/.gnupg/options'] = 'gpg',
   1684  Jenkinsfile = 'groovy',
   1685  ['/var/backups/gshadow.bak'] = 'group',
   1686  ['/etc/gshadow'] = 'group',
   1687  ['/etc/group-'] = 'group',
   1688  ['/etc/gshadow.edit'] = 'group',
   1689  ['/etc/gshadow-'] = 'group',
   1690  ['/etc/group'] = 'group',
   1691  ['/var/backups/group.bak'] = 'group',
   1692  ['/etc/group.edit'] = 'group',
   1693  ['/boot/grub/menu.lst'] = 'grub',
   1694  ['/etc/grub.conf'] = 'grub',
   1695  ['/boot/grub/grub.conf'] = 'grub',
   1696  ['.gtkrc'] = 'gtkrc',
   1697  gtkrc = 'gtkrc',
   1698  ['snort.conf'] = 'hog',
   1699  ['vision.conf'] = 'hog',
   1700  ['/etc/host.conf'] = 'hostconf',
   1701  ['/etc/hosts.allow'] = 'hostsaccess',
   1702  ['/etc/hosts.deny'] = 'hostsaccess',
   1703  ['.hy-history'] = 'hy',
   1704  ['hyprland.conf'] = 'hyprlang',
   1705  ['hyprpaper.conf'] = 'hyprlang',
   1706  ['hypridle.conf'] = 'hyprlang',
   1707  ['hyprlock.conf'] = 'hyprlang',
   1708  ['/.icewm/menu'] = 'icemenu',
   1709  ['.indent.pro'] = 'indent',
   1710  indentrc = 'indent',
   1711  inittab = 'inittab',
   1712  ['ipf.conf'] = 'ipfilter',
   1713  ['ipf6.conf'] = 'ipfilter',
   1714  ['ipf.rules'] = 'ipfilter',
   1715  ['.bun_repl_history'] = 'javascript',
   1716  ['.node_repl_history'] = 'javascript',
   1717  ['deno_history.txt'] = 'javascript',
   1718  ['Pipfile.lock'] = 'json',
   1719  ['.firebaserc'] = 'json',
   1720  ['.prettierrc'] = 'json',
   1721  ['.stylelintrc'] = 'json',
   1722  ['.lintstagedrc'] = 'json',
   1723  ['deno.lock'] = 'json',
   1724  ['flake.lock'] = 'json',
   1725  ['.swcrc'] = 'json',
   1726  ['composer.lock'] = 'json',
   1727  ['symfony.lock'] = 'json',
   1728  ['.babelrc'] = 'jsonc',
   1729  ['.eslintrc'] = 'jsonc',
   1730  ['.hintrc'] = 'jsonc',
   1731  ['.jscsrc'] = 'jsonc',
   1732  ['.jsfmtrc'] = 'jsonc',
   1733  ['.jshintrc'] = 'jsonc',
   1734  ['.luaurc'] = 'jsonc',
   1735  ['.swrc'] = 'jsonc',
   1736  ['.vsconfig'] = 'jsonc',
   1737  ['bun.lock'] = 'jsonc',
   1738  ['.justfile'] = 'just',
   1739  ['.Justfile'] = 'just',
   1740  ['.JUSTFILE'] = 'just',
   1741  ['justfile'] = 'just',
   1742  ['Justfile'] = 'just',
   1743  ['JUSTFILE'] = 'just',
   1744  Kconfig = 'kconfig',
   1745  ['Kconfig.debug'] = 'kconfig',
   1746  ['Config.in'] = 'kconfig',
   1747  ['kitty.conf'] = 'kitty',
   1748  ['ldaprc'] = 'ldapconf',
   1749  ['.ldaprc'] = 'ldapconf',
   1750  ['ldap.conf'] = 'ldapconf',
   1751  ['lfrc'] = 'lf',
   1752  ['lftp.conf'] = 'lftp',
   1753  ['.lftprc'] = 'lftp',
   1754  ['/.libao'] = 'libao',
   1755  ['/etc/libao.conf'] = 'libao',
   1756  ['lilo.conf'] = 'lilo',
   1757  ['/etc/limits'] = 'limits',
   1758  ['.emacs'] = 'lisp',
   1759  sbclrc = 'lisp',
   1760  ['.sbclrc'] = 'lisp',
   1761  ['.sawfishrc'] = 'lisp',
   1762  ['/etc/login.access'] = 'loginaccess',
   1763  ['/etc/login.defs'] = 'logindefs',
   1764  ['.lsl'] = detect.lsl,
   1765  ['.busted'] = 'lua',
   1766  ['.luacheckrc'] = 'lua',
   1767  ['.lua_history'] = 'lua',
   1768  ['config.ld'] = 'lua',
   1769  ['rock_manifest'] = 'lua',
   1770  ['lynx.cfg'] = 'lynx',
   1771  ['m3overrides'] = 'm3build',
   1772  ['m3makefile'] = 'm3build',
   1773  ['cm3.cfg'] = 'm3quake',
   1774  ['.m4_history'] = 'm4',
   1775  ['.followup'] = 'mail',
   1776  ['.article'] = 'mail',
   1777  ['.letter'] = 'mail',
   1778  ['/etc/aliases'] = 'mailaliases',
   1779  ['/etc/mail/aliases'] = 'mailaliases',
   1780  mailcap = 'mailcap',
   1781  ['.mailcap'] = 'mailcap',
   1782  Kbuild = 'make',
   1783  ['/etc/man.conf'] = 'manconf',
   1784  ['man.config'] = 'manconf',
   1785  ['maxima-init.mac'] = 'maxima',
   1786  isyncrc = 'mbsync',
   1787  ['meson.build'] = 'meson',
   1788  ['meson.options'] = 'meson',
   1789  ['meson_options.txt'] = 'meson',
   1790  ['/etc/conf.modules'] = 'modconf',
   1791  ['/etc/modules'] = 'modconf',
   1792  ['/etc/modules.conf'] = 'modconf',
   1793  ['/.mplayer/config'] = 'mplayerconf',
   1794  ['mplayer.conf'] = 'mplayerconf',
   1795  mrxvtrc = 'mrxvtrc',
   1796  ['.mrxvtrc'] = 'mrxvtrc',
   1797  ['.msmtprc'] = 'msmtp',
   1798  ['Muttngrc'] = 'muttrc',
   1799  ['Muttrc'] = 'muttrc',
   1800  ['.mysql_history'] = 'mysql',
   1801  ['/etc/nanorc'] = 'nanorc',
   1802  Neomuttrc = 'neomuttrc',
   1803  ['.netrc'] = 'netrc',
   1804  NEWS = detect.news,
   1805  ['.ocamlinit'] = 'ocaml',
   1806  ['.octaverc'] = 'octave',
   1807  octaverc = 'octave',
   1808  ['octave.conf'] = 'octave',
   1809  ['.ondirrc'] = 'ondir',
   1810  opam = 'opam',
   1811  ['opam.locked'] = 'opam',
   1812  ['/etc/pam.conf'] = 'pamconf',
   1813  ['pam_env.conf'] = 'pamenv',
   1814  ['.pam_environment'] = 'pamenv',
   1815  ['/var/backups/passwd.bak'] = 'passwd',
   1816  ['/var/backups/shadow.bak'] = 'passwd',
   1817  ['/etc/passwd'] = 'passwd',
   1818  ['/etc/passwd-'] = 'passwd',
   1819  ['/etc/shadow.edit'] = 'passwd',
   1820  ['/etc/shadow-'] = 'passwd',
   1821  ['/etc/shadow'] = 'passwd',
   1822  ['/etc/passwd.edit'] = 'passwd',
   1823  ['.gitolite.rc'] = 'perl',
   1824  ['gitolite.rc'] = 'perl',
   1825  ['example.gitolite.rc'] = 'perl',
   1826  ['latexmkrc'] = 'perl',
   1827  ['.latexmkrc'] = 'perl',
   1828  ['pf.conf'] = 'pf',
   1829  ['main.cf'] = 'pfmain',
   1830  ['main.cf.proto'] = 'pfmain',
   1831  pinerc = 'pine',
   1832  ['.pinercex'] = 'pine',
   1833  ['.pinerc'] = 'pine',
   1834  pinercex = 'pine',
   1835  ['/etc/pinforc'] = 'pinfo',
   1836  ['/.pinforc'] = 'pinfo',
   1837  ['.povrayrc'] = 'povini',
   1838  printcap = function(_path, _bufnr)
   1839    return 'ptcap', function(b)
   1840      vim.b[b].ptcap_type = 'print'
   1841    end
   1842  end,
   1843  termcap = function(_path, _bufnr)
   1844    return 'ptcap', function(b)
   1845      vim.b[b].ptcap_type = 'term'
   1846    end
   1847  end,
   1848  ['.procmailrc'] = 'procmail',
   1849  ['.procmail'] = 'procmail',
   1850  ['indent.pro'] = detect_seq(detect.proto, 'indent'),
   1851  ['/etc/protocols'] = 'protocols',
   1852  INDEX = detect.psf,
   1853  INFO = detect.psf,
   1854  ['MANIFEST.in'] = 'pymanifest',
   1855  ['.pythonstartup'] = 'python',
   1856  ['.pythonrc'] = 'python',
   1857  ['.python_history'] = 'python',
   1858  ['.jline-jython.history'] = 'python',
   1859  SConstruct = 'python',
   1860  qmldir = 'qmldir',
   1861  ['.Rhistory'] = 'r',
   1862  ['.Rprofile'] = 'r',
   1863  Rprofile = 'r',
   1864  ['Rprofile.site'] = 'r',
   1865  ratpoisonrc = 'ratpoison',
   1866  ['.ratpoisonrc'] = 'ratpoison',
   1867  inputrc = 'readline',
   1868  ['.inputrc'] = 'readline',
   1869  ['.reminders'] = 'remind',
   1870  ['requirements.txt'] = 'requirements',
   1871  ['constraints.txt'] = 'requirements',
   1872  ['requirements.in'] = 'requirements',
   1873  ['resolv.conf'] = 'resolv',
   1874  ['robots.txt'] = 'robots',
   1875  Brewfile = 'ruby',
   1876  Gemfile = 'ruby',
   1877  Puppetfile = 'ruby',
   1878  ['.irbrc'] = 'ruby',
   1879  irbrc = 'ruby',
   1880  ['.irb_history'] = 'ruby',
   1881  irb_history = 'ruby',
   1882  ['rakefile'] = 'ruby',
   1883  ['Rakefile'] = 'ruby',
   1884  ['rantfile'] = 'ruby',
   1885  ['Rantfile'] = 'ruby',
   1886  Vagrantfile = 'ruby',
   1887  ['smb.conf'] = 'samba',
   1888  ['.lips_repl_history'] = 'scheme',
   1889  ['.guile'] = 'scheme',
   1890  screenrc = 'screen',
   1891  ['.screenrc'] = 'screen',
   1892  ['/etc/sensors3.conf'] = 'sensors',
   1893  ['/etc/sensors.conf'] = 'sensors',
   1894  ['/etc/services'] = 'services',
   1895  ['/etc/serial.conf'] = 'setserial',
   1896  ['/etc/udev/cdsymlinks.conf'] = 'sh',
   1897  ['.ash_history'] = 'sh',
   1898  ['.devscripts'] = 'sh',
   1899  ['devscripts.conf'] = 'sh',
   1900  ['makepkg.conf'] = 'sh',
   1901  ['.makepkg.conf'] = 'sh',
   1902  ['user-dirs.dirs'] = 'sh',
   1903  ['user-dirs.defaults'] = 'sh',
   1904  ['.xprofile'] = 'sh',
   1905  ['bash.bashrc'] = detect.bash,
   1906  bashrc = detect.bash,
   1907  ['.bashrc'] = detect.bash,
   1908  ['.kshrc'] = detect.ksh,
   1909  ['.profile'] = detect.sh,
   1910  ['/etc/profile'] = detect.sh,
   1911  PKGBUILD = detect.bash,
   1912  ['.tcshrc'] = detect.tcsh,
   1913  ['tcsh.login'] = detect.tcsh,
   1914  ['tcsh.tcshrc'] = detect.tcsh,
   1915  ['.skhdrc'] = 'skhd',
   1916  ['skhdrc'] = 'skhd',
   1917  ['/etc/slp.conf'] = 'slpconf',
   1918  ['/etc/slp.reg'] = 'slpreg',
   1919  ['/etc/slp.spi'] = 'slpspi',
   1920  ['.slrnrc'] = 'slrnrc',
   1921  ['sendmail.cf'] = 'sm',
   1922  Snakefile = 'snakemake',
   1923  ['.sqlite_history'] = 'sql',
   1924  ['squid.conf'] = 'squid',
   1925  ['ssh_config'] = 'sshconfig',
   1926  ['sshd_config'] = 'sshdconfig',
   1927  ['/etc/sudoers'] = 'sudoers',
   1928  ['sudoers.tmp'] = 'sudoers',
   1929  ['/etc/sysctl.conf'] = 'sysctl',
   1930  tags = 'tags',
   1931  ['pending.data'] = 'taskdata',
   1932  ['completed.data'] = 'taskdata',
   1933  ['undo.data'] = 'taskdata',
   1934  ['.tclshrc'] = 'tcl',
   1935  ['.wishrc'] = 'tcl',
   1936  ['.tclsh-history'] = 'tcl',
   1937  ['tclsh.rc'] = 'tcl',
   1938  ['.xsctcmdhistory'] = 'tcl',
   1939  ['.xsdbcmdhistory'] = 'tcl',
   1940  ['texmf.cnf'] = 'texmf',
   1941  COPYING = 'text',
   1942  README = detect_seq(detect.haredoc, 'text'),
   1943  LICENSE = 'text',
   1944  AUTHORS = 'text',
   1945  tfrc = 'tf',
   1946  ['.tfrc'] = 'tf',
   1947  ['tidy.conf'] = 'tidy',
   1948  tidyrc = 'tidy',
   1949  ['.tidyrc'] = 'tidy',
   1950  Tiltfile = 'tiltfile',
   1951  tiltfile = 'tiltfile',
   1952  ['.tmux.conf'] = 'tmux',
   1953  ['Cargo.lock'] = 'toml',
   1954  ['/.cargo/config'] = 'toml',
   1955  ['/.cargo/credentials'] = 'toml',
   1956  Pipfile = 'toml',
   1957  ['Gopkg.lock'] = 'toml',
   1958  ['uv.lock'] = 'toml',
   1959  ['.black'] = 'toml',
   1960  black = detect_line1('tool%.black', 'toml', nil),
   1961  ['trustees.conf'] = 'trustees',
   1962  ['.ts_node_repl_history'] = 'typescript',
   1963  ['/etc/udev/udev.conf'] = 'udevconf',
   1964  ['/etc/updatedb.conf'] = 'updatedb',
   1965  ['fdrupstream.log'] = 'upstreamlog',
   1966  vgrindefs = 'vgrindefs',
   1967  ['.exrc'] = 'vim',
   1968  ['_exrc'] = 'vim',
   1969  ['.netrwhist'] = 'vim',
   1970  ['_viminfo'] = 'viminfo',
   1971  ['.viminfo'] = 'viminfo',
   1972  ['.wgetrc'] = 'wget',
   1973  ['.wget2rc'] = 'wget2',
   1974  wgetrc = 'wget',
   1975  wget2rc = 'wget2',
   1976  ['.wvdialrc'] = 'wvdial',
   1977  ['wvdial.conf'] = 'wvdial',
   1978  ['.XCompose'] = 'xcompose',
   1979  ['Compose'] = 'xcompose',
   1980  ['.Xresources'] = 'xdefaults',
   1981  ['.Xpdefaults'] = 'xdefaults',
   1982  ['xdm-config'] = 'xdefaults',
   1983  ['.Xdefaults'] = 'xdefaults',
   1984  ['xorg.conf'] = detect.xfree86_v4,
   1985  ['xorg.conf-4'] = detect.xfree86_v4,
   1986  ['XF86Config'] = detect.xfree86_v3,
   1987  ['/etc/xinetd.conf'] = 'xinetd',
   1988  fglrxrc = 'xml',
   1989  ['/etc/blkid.tab'] = 'xml',
   1990  ['/etc/blkid.tab.old'] = 'xml',
   1991  ['fonts.conf'] = 'xml',
   1992  ['Directory.Packages.props'] = 'xml',
   1993  ['Directory.Build.props'] = 'xml',
   1994  ['Directory.Build.targets'] = 'xml',
   1995  ['.clangd'] = 'yaml',
   1996  ['.clang-format'] = 'yaml',
   1997  ['.clang-tidy'] = 'yaml',
   1998  ['pixi.lock'] = 'yaml',
   1999  ['yarn.lock'] = 'yaml',
   2000  matplotlibrc = 'yaml',
   2001  ['.condarc'] = 'yaml',
   2002  condarc = 'yaml',
   2003  ['.mambarc'] = 'yaml',
   2004  mambarc = 'yaml',
   2005  zathurarc = 'zathurarc',
   2006  ['/etc/zprofile'] = 'zsh',
   2007  ['.zlogin'] = 'zsh',
   2008  ['.zlogout'] = 'zsh',
   2009  ['.zshrc'] = 'zsh',
   2010  ['.zprofile'] = 'zsh',
   2011  ['.zcompdump'] = 'zsh',
   2012  ['.zsh_history'] = 'zsh',
   2013  ['.zshenv'] = 'zsh',
   2014  ['.zfbfmarks'] = 'zsh',
   2015  -- END FILENAME
   2016 }
   2017 
   2018 -- Re-use closures as much as possible
   2019 local detect_apache = starsetf('apache')
   2020 local detect_muttrc = starsetf('muttrc')
   2021 local detect_neomuttrc = starsetf('neomuttrc')
   2022 local detect_xkb = starsetf('xkb')
   2023 
   2024 ---@type table<string,vim.filetype.mapping>
   2025 local pattern = {
   2026  -- BEGIN PATTERN
   2027  ['/debian/'] = {
   2028    ['/debian/tests/control$'] = 'autopkgtest',
   2029    ['/debian/changelog$'] = 'debchangelog',
   2030    ['/debian/control$'] = 'debcontrol',
   2031    ['/debian/copyright$'] = 'debcopyright',
   2032    ['/debian/patches/'] = detect.dep3patch,
   2033  },
   2034  ['/etc/'] = {
   2035    ['/etc/a2ps/.*%.cfg$'] = 'a2ps',
   2036    ['/etc/a2ps%.cfg$'] = 'a2ps',
   2037    ['/etc/asound%.conf$'] = 'alsaconf',
   2038    ['/etc/apache2/sites%-.*/.*%.com$'] = 'apache',
   2039    ['/etc/httpd/.*%.conf$'] = 'apache',
   2040    ['/etc/apache2/.*%.conf'] = detect_apache,
   2041    ['/etc/apache2/conf%..*/'] = detect_apache,
   2042    ['/etc/apache2/mods%-.*/'] = detect_apache,
   2043    ['/etc/apache2/sites%-.*/'] = detect_apache,
   2044    ['/etc/httpd/conf%..*/'] = detect_apache,
   2045    ['/etc/httpd/conf%.d/.*%.conf'] = detect_apache,
   2046    ['/etc/httpd/mods%-.*/'] = detect_apache,
   2047    ['/etc/httpd/sites%-.*/'] = detect_apache,
   2048    ['/etc/proftpd/.*%.conf'] = starsetf('apachestyle'),
   2049    ['/etc/proftpd/conf%..*/'] = starsetf('apachestyle'),
   2050    ['/etc/cdrdao%.conf$'] = 'cdrdaoconf',
   2051    ['/etc/default/cdrdao$'] = 'cdrdaoconf',
   2052    ['/etc/defaults/cdrdao$'] = 'cdrdaoconf',
   2053    ['/etc/translate%-shell$'] = 'clojure',
   2054    ['/etc/hostname%.'] = starsetf('config'),
   2055    ['/etc/cron%.d/'] = starsetf('crontab'),
   2056    ['/etc/apt/sources%.list%.d/.*%.sources$'] = 'deb822sources',
   2057    ['/etc/apt/sources%.list%.d/.*%.list$'] = 'debsources',
   2058    ['/etc/apt/sources%.list$'] = 'debsources',
   2059    ['/etc/DIR_COLORS$'] = 'dircolors',
   2060    ['/etc/dnsmasq%.conf$'] = 'dnsmasq',
   2061    ['/etc/dnsmasq%.d/'] = starsetf('dnsmasq'),
   2062    ['/etc/yum%.conf$'] = 'dosini',
   2063    ['/etc/yum%.repos%.d/'] = starsetf('dosini'),
   2064    ['/etc/gitconfig%.d/'] = starsetf('gitconfig'),
   2065    ['/etc/gitconfig$'] = 'gitconfig',
   2066    ['/etc/gitattributes$'] = 'gitattributes',
   2067    ['/etc/group$'] = 'group',
   2068    ['/etc/group%-$'] = 'group',
   2069    ['/etc/group%.edit$'] = 'group',
   2070    ['/etc/gshadow%-$'] = 'group',
   2071    ['/etc/gshadow%.edit$'] = 'group',
   2072    ['/etc/gshadow$'] = 'group',
   2073    ['/etc/grub%.conf$'] = 'grub',
   2074    ['/etc/host%.conf$'] = 'hostconf',
   2075    ['/etc/hosts%.allow$'] = 'hostsaccess',
   2076    ['/etc/hosts%.deny$'] = 'hostsaccess',
   2077    ['/etc/initng/.*/.*%.i$'] = 'initng',
   2078    ['/etc/libao%.conf$'] = 'libao',
   2079    ['/etc/.*limits%.conf$'] = 'limits',
   2080    ['/etc/.*limits%.d/.*%.conf$'] = 'limits',
   2081    ['/etc/limits$'] = 'limits',
   2082    ['/etc/logcheck/.*%.d.*/'] = starsetf('logcheck'),
   2083    ['/etc/login%.access$'] = 'loginaccess',
   2084    ['/etc/login%.defs$'] = 'logindefs',
   2085    ['/etc/aliases$'] = 'mailaliases',
   2086    ['/etc/mail/aliases$'] = 'mailaliases',
   2087    ['/etc/man%.conf$'] = 'manconf',
   2088    ['/etc/conf%.modules$'] = 'modconf',
   2089    ['/etc/modprobe%.'] = starsetf('modconf'),
   2090    ['/etc/modules%.conf$'] = 'modconf',
   2091    ['/etc/modules$'] = 'modconf',
   2092    ['/etc/modutils/'] = starsetf(function(path, _bufnr)
   2093      if fn.executable(fn.expand(path)) ~= 1 then
   2094        return 'modconf'
   2095      end
   2096    end),
   2097    ['/etc/Muttrc%.d/'] = starsetf('muttrc'),
   2098    ['/etc/nanorc$'] = 'nanorc',
   2099    ['/etc/nginx/'] = starsetf('nginx'),
   2100    ['/etc/pam%.conf$'] = 'pamconf',
   2101    ['/etc/pam%.d/'] = starsetf('pamconf'),
   2102    ['/etc/passwd%-$'] = 'passwd',
   2103    ['/etc/shadow$'] = 'passwd',
   2104    ['/etc/shadow%.edit$'] = 'passwd',
   2105    ['/etc/passwd$'] = 'passwd',
   2106    ['/etc/passwd%.edit$'] = 'passwd',
   2107    ['/etc/shadow%-$'] = 'passwd',
   2108    ['/etc/pinforc$'] = 'pinfo',
   2109    ['/etc/protocols$'] = 'protocols',
   2110    ['/etc/sensors%.d/[^.]'] = starsetf('sensors'),
   2111    ['/etc/sensors%.conf$'] = 'sensors',
   2112    ['/etc/sensors3%.conf$'] = 'sensors',
   2113    ['/etc/services$'] = 'services',
   2114    ['/etc/serial%.conf$'] = 'setserial',
   2115    ['/etc/udev/cdsymlinks%.conf$'] = 'sh',
   2116    ['/etc/profile$'] = detect.sh,
   2117    ['/etc/slp%.conf$'] = 'slpconf',
   2118    ['/etc/slp%.reg$'] = 'slpreg',
   2119    ['/etc/slp%.spi$'] = 'slpspi',
   2120    ['/etc/sudoers%.d/'] = starsetf('sudoers'),
   2121    ['/etc/ssh/ssh_config%.d/.*%.conf$'] = 'sshconfig',
   2122    ['/etc/ssh/sshd_config%.d/.*%.conf$'] = 'sshdconfig',
   2123    ['/etc/sudoers$'] = 'sudoers',
   2124    ['/etc/sysctl%.conf$'] = 'sysctl',
   2125    ['/etc/sysctl%.d/.*%.conf$'] = 'sysctl',
   2126    ['/etc/systemd/.*%.conf%.d/.*%.conf$'] = 'systemd',
   2127    ['/etc/systemd/system/.*%.d/.*%.conf$'] = 'systemd',
   2128    ['/etc/systemd/system/.*%.d/%.#'] = 'systemd',
   2129    ['/etc/systemd/system/%.#'] = 'systemd',
   2130    ['/etc/containers/systemd/users/.*/.*%.artifact$'] = 'systemd',
   2131    ['/etc/containers/systemd/users/.*/.*%.build$'] = 'systemd',
   2132    ['/etc/containers/systemd/users/.*/.*%.container$'] = 'systemd',
   2133    ['/etc/containers/systemd/users/.*/.*%.image$'] = 'systemd',
   2134    ['/etc/containers/systemd/users/.*/.*%.kube$'] = 'systemd',
   2135    ['/etc/containers/systemd/users/.*/.*%.network$'] = 'systemd',
   2136    ['/etc/containers/systemd/users/.*/.*%.pod$'] = 'systemd',
   2137    ['/etc/containers/systemd/users/.*/.*%.volume$'] = 'systemd',
   2138    ['/etc/containers/systemd/users/.*%.artifact$'] = 'systemd',
   2139    ['/etc/containers/systemd/users/.*%.build$'] = 'systemd',
   2140    ['/etc/containers/systemd/users/.*%.container$'] = 'systemd',
   2141    ['/etc/containers/systemd/users/.*%.image$'] = 'systemd',
   2142    ['/etc/containers/systemd/users/.*%.kube$'] = 'systemd',
   2143    ['/etc/containers/systemd/users/.*%.network$'] = 'systemd',
   2144    ['/etc/containers/systemd/users/.*%.pod$'] = 'systemd',
   2145    ['/etc/containers/systemd/users/.*%.volume$'] = 'systemd',
   2146    ['/etc/containers/systemd/users/.*/.*%.d/.*%.conf$'] = 'systemd',
   2147    ['/etc/containers/systemd/users/.*%.d/.*%.conf$'] = 'systemd',
   2148    ['/etc/config/'] = starsetf(detect.uci),
   2149    ['/etc/udev/udev%.conf$'] = 'udevconf',
   2150    ['/etc/udev/permissions%.d/.*%.permissions$'] = 'udevperm',
   2151    ['/etc/updatedb%.conf$'] = 'updatedb',
   2152    ['/etc/init/.*%.conf$'] = 'upstart',
   2153    ['/etc/init/.*%.override$'] = 'upstart',
   2154    ['/etc/xinetd%.conf$'] = 'xinetd',
   2155    ['/etc/xinetd%.d/'] = starsetf('xinetd'),
   2156    ['/etc/blkid%.tab%.old$'] = 'xml',
   2157    ['/etc/blkid%.tab$'] = 'xml',
   2158    ['/etc/xdg/menus/.*%.menu$'] = 'xml',
   2159    ['/etc/zprofile$'] = 'zsh',
   2160  },
   2161  ['/log/'] = {
   2162    ['/log/auth%.crit$'] = 'messages',
   2163    ['/log/auth%.err$'] = 'messages',
   2164    ['/log/auth%.info$'] = 'messages',
   2165    ['/log/auth%.log$'] = 'messages',
   2166    ['/log/auth%.notice$'] = 'messages',
   2167    ['/log/auth%.warn$'] = 'messages',
   2168    ['/log/auth$'] = 'messages',
   2169    ['/log/cron%.crit$'] = 'messages',
   2170    ['/log/cron%.err$'] = 'messages',
   2171    ['/log/cron%.info$'] = 'messages',
   2172    ['/log/cron%.log$'] = 'messages',
   2173    ['/log/cron%.notice$'] = 'messages',
   2174    ['/log/cron%.warn$'] = 'messages',
   2175    ['/log/cron$'] = 'messages',
   2176    ['/log/daemon%.crit$'] = 'messages',
   2177    ['/log/daemon%.err$'] = 'messages',
   2178    ['/log/daemon%.info$'] = 'messages',
   2179    ['/log/daemon%.log$'] = 'messages',
   2180    ['/log/daemon%.notice$'] = 'messages',
   2181    ['/log/daemon%.warn$'] = 'messages',
   2182    ['/log/daemon$'] = 'messages',
   2183    ['/log/debug%.crit$'] = 'messages',
   2184    ['/log/debug%.err$'] = 'messages',
   2185    ['/log/debug%.info$'] = 'messages',
   2186    ['/log/debug%.log$'] = 'messages',
   2187    ['/log/debug%.notice$'] = 'messages',
   2188    ['/log/debug%.warn$'] = 'messages',
   2189    ['/log/debug$'] = 'messages',
   2190    ['/log/kern%.crit$'] = 'messages',
   2191    ['/log/kern%.err$'] = 'messages',
   2192    ['/log/kern%.info$'] = 'messages',
   2193    ['/log/kern%.log$'] = 'messages',
   2194    ['/log/kern%.notice$'] = 'messages',
   2195    ['/log/kern%.warn$'] = 'messages',
   2196    ['/log/kern$'] = 'messages',
   2197    ['/log/lpr%.crit$'] = 'messages',
   2198    ['/log/lpr%.err$'] = 'messages',
   2199    ['/log/lpr%.info$'] = 'messages',
   2200    ['/log/lpr%.log$'] = 'messages',
   2201    ['/log/lpr%.notice$'] = 'messages',
   2202    ['/log/lpr%.warn$'] = 'messages',
   2203    ['/log/lpr$'] = 'messages',
   2204    ['/log/mail%.crit$'] = 'messages',
   2205    ['/log/mail%.err$'] = 'messages',
   2206    ['/log/mail%.info$'] = 'messages',
   2207    ['/log/mail%.log$'] = 'messages',
   2208    ['/log/mail%.notice$'] = 'messages',
   2209    ['/log/mail%.warn$'] = 'messages',
   2210    ['/log/mail$'] = 'messages',
   2211    ['/log/messages%.crit$'] = 'messages',
   2212    ['/log/messages%.err$'] = 'messages',
   2213    ['/log/messages%.info$'] = 'messages',
   2214    ['/log/messages%.log$'] = 'messages',
   2215    ['/log/messages%.notice$'] = 'messages',
   2216    ['/log/messages%.warn$'] = 'messages',
   2217    ['/log/messages$'] = 'messages',
   2218    ['/log/news/news%.crit$'] = 'messages',
   2219    ['/log/news/news%.err$'] = 'messages',
   2220    ['/log/news/news%.info$'] = 'messages',
   2221    ['/log/news/news%.log$'] = 'messages',
   2222    ['/log/news/news%.notice$'] = 'messages',
   2223    ['/log/news/news%.warn$'] = 'messages',
   2224    ['/log/news/news$'] = 'messages',
   2225    ['/log/syslog%.crit$'] = 'messages',
   2226    ['/log/syslog%.err$'] = 'messages',
   2227    ['/log/syslog%.info$'] = 'messages',
   2228    ['/log/syslog%.log$'] = 'messages',
   2229    ['/log/syslog%.notice$'] = 'messages',
   2230    ['/log/syslog%.warn$'] = 'messages',
   2231    ['/log/syslog$'] = 'messages',
   2232    ['/log/user%.crit$'] = 'messages',
   2233    ['/log/user%.err$'] = 'messages',
   2234    ['/log/user%.info$'] = 'messages',
   2235    ['/log/user%.log$'] = 'messages',
   2236    ['/log/user%.notice$'] = 'messages',
   2237    ['/log/user%.warn$'] = 'messages',
   2238    ['/log/user$'] = 'messages',
   2239    ['/log/auth%.crit%.[0-9]*$'] = starsetf('messages'),
   2240    ['/log/auth%.err%.[0-9]*$'] = starsetf('messages'),
   2241    ['/log/auth%.info%.[0-9]*$'] = starsetf('messages'),
   2242    ['/log/auth%.log%.[0-9]*$'] = starsetf('messages'),
   2243    ['/log/auth%.notice%.[0-9]*$'] = starsetf('messages'),
   2244    ['/log/auth%.warn%.[0-9]*$'] = starsetf('messages'),
   2245    ['/log/auth%.[0-9]*$'] = starsetf('messages'),
   2246    ['/log/cron%.crit%.[0-9]*$'] = starsetf('messages'),
   2247    ['/log/cron%.err%.[0-9]*$'] = starsetf('messages'),
   2248    ['/log/cron%.info%.[0-9]*$'] = starsetf('messages'),
   2249    ['/log/cron%.log%.[0-9]*$'] = starsetf('messages'),
   2250    ['/log/cron%.notice%.[0-9]*$'] = starsetf('messages'),
   2251    ['/log/cron%.warn%.[0-9]*$'] = starsetf('messages'),
   2252    ['/log/cron%.[0-9]*$'] = starsetf('messages'),
   2253    ['/log/daemon%.crit%.[0-9]*$'] = starsetf('messages'),
   2254    ['/log/daemon%.err%.[0-9]*$'] = starsetf('messages'),
   2255    ['/log/daemon%.info%.[0-9]*$'] = starsetf('messages'),
   2256    ['/log/daemon%.log%.[0-9]*$'] = starsetf('messages'),
   2257    ['/log/daemon%.notice%.[0-9]*$'] = starsetf('messages'),
   2258    ['/log/daemon%.warn%.[0-9]*$'] = starsetf('messages'),
   2259    ['/log/daemon%.[0-9]*$'] = starsetf('messages'),
   2260    ['/log/debug%.crit%.[0-9]*$'] = starsetf('messages'),
   2261    ['/log/debug%.err%.[0-9]*$'] = starsetf('messages'),
   2262    ['/log/debug%.info%.[0-9]*$'] = starsetf('messages'),
   2263    ['/log/debug%.log%.[0-9]*$'] = starsetf('messages'),
   2264    ['/log/debug%.notice%.[0-9]*$'] = starsetf('messages'),
   2265    ['/log/debug%.warn%.[0-9]*$'] = starsetf('messages'),
   2266    ['/log/debug%.[0-9]*$'] = starsetf('messages'),
   2267    ['/log/kern%.crit%.[0-9]*$'] = starsetf('messages'),
   2268    ['/log/kern%.err%.[0-9]*$'] = starsetf('messages'),
   2269    ['/log/kern%.info%.[0-9]*$'] = starsetf('messages'),
   2270    ['/log/kern%.log%.[0-9]*$'] = starsetf('messages'),
   2271    ['/log/kern%.notice%.[0-9]*$'] = starsetf('messages'),
   2272    ['/log/kern%.warn%.[0-9]*$'] = starsetf('messages'),
   2273    ['/log/kern%.[0-9]*$'] = starsetf('messages'),
   2274    ['/log/lpr%.crit%.[0-9]*$'] = starsetf('messages'),
   2275    ['/log/lpr%.err%.[0-9]*$'] = starsetf('messages'),
   2276    ['/log/lpr%.info%.[0-9]*$'] = starsetf('messages'),
   2277    ['/log/lpr%.log%.[0-9]*$'] = starsetf('messages'),
   2278    ['/log/lpr%.notice%.[0-9]*$'] = starsetf('messages'),
   2279    ['/log/lpr%.warn%.[0-9]*$'] = starsetf('messages'),
   2280    ['/log/lpr%.[0-9]*$'] = starsetf('messages'),
   2281    ['/log/mail%.crit%.[0-9]*$'] = starsetf('messages'),
   2282    ['/log/mail%.err%.[0-9]*$'] = starsetf('messages'),
   2283    ['/log/mail%.info%.[0-9]*$'] = starsetf('messages'),
   2284    ['/log/mail%.log%.[0-9]*$'] = starsetf('messages'),
   2285    ['/log/mail%.notice%.[0-9]*$'] = starsetf('messages'),
   2286    ['/log/mail%.warn%.[0-9]*$'] = starsetf('messages'),
   2287    ['/log/mail%.[0-9]*$'] = starsetf('messages'),
   2288    ['/log/messages%.crit%.[0-9]*$'] = starsetf('messages'),
   2289    ['/log/messages%.err%.[0-9]*$'] = starsetf('messages'),
   2290    ['/log/messages%.info%.[0-9]*$'] = starsetf('messages'),
   2291    ['/log/messages%.log%.[0-9]*$'] = starsetf('messages'),
   2292    ['/log/messages%.notice%.[0-9]*$'] = starsetf('messages'),
   2293    ['/log/messages%.warn%.[0-9]*$'] = starsetf('messages'),
   2294    ['/log/messages%.[0-9]*$'] = starsetf('messages'),
   2295    ['/log/news/news%.crit%.[0-9]*$'] = starsetf('messages'),
   2296    ['/log/news/news%.err%.[0-9]*$'] = starsetf('messages'),
   2297    ['/log/news/news%.info%.[0-9]*$'] = starsetf('messages'),
   2298    ['/log/news/news%.log%.[0-9]*$'] = starsetf('messages'),
   2299    ['/log/news/news%.notice%.[0-9]*$'] = starsetf('messages'),
   2300    ['/log/news/news%.warn%.[0-9]*$'] = starsetf('messages'),
   2301    ['/log/news/news%.[0-9]*$'] = starsetf('messages'),
   2302    ['/log/syslog%.crit%.[0-9]*$'] = starsetf('messages'),
   2303    ['/log/syslog%.err%.[0-9]*$'] = starsetf('messages'),
   2304    ['/log/syslog%.info%.[0-9]*$'] = starsetf('messages'),
   2305    ['/log/syslog%.log%.[0-9]*$'] = starsetf('messages'),
   2306    ['/log/syslog%.notice%.[0-9]*$'] = starsetf('messages'),
   2307    ['/log/syslog%.warn%.[0-9]*$'] = starsetf('messages'),
   2308    ['/log/syslog%.[0-9]*$'] = starsetf('messages'),
   2309    ['/log/user%.crit%.[0-9]*$'] = starsetf('messages'),
   2310    ['/log/user%.err%.[0-9]*$'] = starsetf('messages'),
   2311    ['/log/user%.info%.[0-9]*$'] = starsetf('messages'),
   2312    ['/log/user%.log%.[0-9]*$'] = starsetf('messages'),
   2313    ['/log/user%.notice%.[0-9]*$'] = starsetf('messages'),
   2314    ['/log/user%.warn%.[0-9]*$'] = starsetf('messages'),
   2315    ['/log/user%.[0-9]*$'] = starsetf('messages'),
   2316    ['/log/auth%.crit%-[0-9]*$'] = starsetf('messages'),
   2317    ['/log/auth%.err%-[0-9]*$'] = starsetf('messages'),
   2318    ['/log/auth%.info%-[0-9]*$'] = starsetf('messages'),
   2319    ['/log/auth%.log%-[0-9]*$'] = starsetf('messages'),
   2320    ['/log/auth%.notice%-[0-9]*$'] = starsetf('messages'),
   2321    ['/log/auth%.warn%-[0-9]*$'] = starsetf('messages'),
   2322    ['/log/auth%-[0-9]*$'] = starsetf('messages'),
   2323    ['/log/cron%.crit%-[0-9]*$'] = starsetf('messages'),
   2324    ['/log/cron%.err%-[0-9]*$'] = starsetf('messages'),
   2325    ['/log/cron%.info%-[0-9]*$'] = starsetf('messages'),
   2326    ['/log/cron%.log%-[0-9]*$'] = starsetf('messages'),
   2327    ['/log/cron%.notice%-[0-9]*$'] = starsetf('messages'),
   2328    ['/log/cron%.warn%-[0-9]*$'] = starsetf('messages'),
   2329    ['/log/cron%-[0-9]*$'] = starsetf('messages'),
   2330    ['/log/daemon%.crit%-[0-9]*$'] = starsetf('messages'),
   2331    ['/log/daemon%.err%-[0-9]*$'] = starsetf('messages'),
   2332    ['/log/daemon%.info%-[0-9]*$'] = starsetf('messages'),
   2333    ['/log/daemon%.log%-[0-9]*$'] = starsetf('messages'),
   2334    ['/log/daemon%.notice%-[0-9]*$'] = starsetf('messages'),
   2335    ['/log/daemon%.warn%-[0-9]*$'] = starsetf('messages'),
   2336    ['/log/daemon%-[0-9]*$'] = starsetf('messages'),
   2337    ['/log/debug%.crit%-[0-9]*$'] = starsetf('messages'),
   2338    ['/log/debug%.err%-[0-9]*$'] = starsetf('messages'),
   2339    ['/log/debug%.info%-[0-9]*$'] = starsetf('messages'),
   2340    ['/log/debug%.log%-[0-9]*$'] = starsetf('messages'),
   2341    ['/log/debug%.notice%-[0-9]*$'] = starsetf('messages'),
   2342    ['/log/debug%.warn%-[0-9]*$'] = starsetf('messages'),
   2343    ['/log/debug%-[0-9]*$'] = starsetf('messages'),
   2344    ['/log/kern%.crit%-[0-9]*$'] = starsetf('messages'),
   2345    ['/log/kern%.err%-[0-9]*$'] = starsetf('messages'),
   2346    ['/log/kern%.info%-[0-9]*$'] = starsetf('messages'),
   2347    ['/log/kern%.log%-[0-9]*$'] = starsetf('messages'),
   2348    ['/log/kern%.notice%-[0-9]*$'] = starsetf('messages'),
   2349    ['/log/kern%.warn%-[0-9]*$'] = starsetf('messages'),
   2350    ['/log/kern%-[0-9]*$'] = starsetf('messages'),
   2351    ['/log/lpr%.crit%-[0-9]*$'] = starsetf('messages'),
   2352    ['/log/lpr%.err%-[0-9]*$'] = starsetf('messages'),
   2353    ['/log/lpr%.info%-[0-9]*$'] = starsetf('messages'),
   2354    ['/log/lpr%.log%-[0-9]*$'] = starsetf('messages'),
   2355    ['/log/lpr%.notice%-[0-9]*$'] = starsetf('messages'),
   2356    ['/log/lpr%.warn%-[0-9]*$'] = starsetf('messages'),
   2357    ['/log/lpr%-[0-9]*$'] = starsetf('messages'),
   2358    ['/log/mail%.crit%-[0-9]*$'] = starsetf('messages'),
   2359    ['/log/mail%.err%-[0-9]*$'] = starsetf('messages'),
   2360    ['/log/mail%.info%-[0-9]*$'] = starsetf('messages'),
   2361    ['/log/mail%.log%-[0-9]*$'] = starsetf('messages'),
   2362    ['/log/mail%.notice%-[0-9]*$'] = starsetf('messages'),
   2363    ['/log/mail%.warn%-[0-9]*$'] = starsetf('messages'),
   2364    ['/log/mail%-[0-9]*$'] = starsetf('messages'),
   2365    ['/log/messages%.crit%-[0-9]*$'] = starsetf('messages'),
   2366    ['/log/messages%.err%-[0-9]*$'] = starsetf('messages'),
   2367    ['/log/messages%.info%-[0-9]*$'] = starsetf('messages'),
   2368    ['/log/messages%.log%-[0-9]*$'] = starsetf('messages'),
   2369    ['/log/messages%.notice%-[0-9]*$'] = starsetf('messages'),
   2370    ['/log/messages%.warn%-[0-9]*$'] = starsetf('messages'),
   2371    ['/log/messages%-[0-9]*$'] = starsetf('messages'),
   2372    ['/log/news/news%.crit%-[0-9]*$'] = starsetf('messages'),
   2373    ['/log/news/news%.err%-[0-9]*$'] = starsetf('messages'),
   2374    ['/log/news/news%.info%-[0-9]*$'] = starsetf('messages'),
   2375    ['/log/news/news%.log%-[0-9]*$'] = starsetf('messages'),
   2376    ['/log/news/news%.notice%-[0-9]*$'] = starsetf('messages'),
   2377    ['/log/news/news%.warn%-[0-9]*$'] = starsetf('messages'),
   2378    ['/log/news/news%-[0-9]*$'] = starsetf('messages'),
   2379    ['/log/syslog%.crit%-[0-9]*$'] = starsetf('messages'),
   2380    ['/log/syslog%.err%-[0-9]*$'] = starsetf('messages'),
   2381    ['/log/syslog%.info%-[0-9]*$'] = starsetf('messages'),
   2382    ['/log/syslog%.log%-[0-9]*$'] = starsetf('messages'),
   2383    ['/log/syslog%.notice%-[0-9]*$'] = starsetf('messages'),
   2384    ['/log/syslog%.warn%-[0-9]*$'] = starsetf('messages'),
   2385    ['/log/syslog%-[0-9]*$'] = starsetf('messages'),
   2386    ['/log/user%.crit%-[0-9]*$'] = starsetf('messages'),
   2387    ['/log/user%.err%-[0-9]*$'] = starsetf('messages'),
   2388    ['/log/user%.info%-[0-9]*$'] = starsetf('messages'),
   2389    ['/log/user%.log%-[0-9]*$'] = starsetf('messages'),
   2390    ['/log/user%.notice%-[0-9]*$'] = starsetf('messages'),
   2391    ['/log/user%.warn%-[0-9]*$'] = starsetf('messages'),
   2392    ['/log/user%-[0-9]*$'] = starsetf('messages'),
   2393  },
   2394  ['/systemd/'] = {
   2395    ['/%.config/systemd/user/%.#'] = 'systemd',
   2396    ['/%.config/systemd/user/.*%.d/%.#'] = 'systemd',
   2397    ['/%.config/systemd/user/.*%.d/.*%.conf$'] = 'systemd',
   2398    ['/containers/systemd/.*%.artifact$'] = 'systemd',
   2399    ['/containers/systemd/.*%.build$'] = 'systemd',
   2400    ['/containers/systemd/.*%.container$'] = 'systemd',
   2401    ['/containers/systemd/.*%.image$'] = 'systemd',
   2402    ['/containers/systemd/.*%.kube$'] = 'systemd',
   2403    ['/containers/systemd/.*%.network$'] = 'systemd',
   2404    ['/containers/systemd/.*%.pod$'] = 'systemd',
   2405    ['/containers/systemd/.*%.volume$'] = 'systemd',
   2406    ['/systemd/.*%.automount$'] = 'systemd',
   2407    ['/systemd/.*%.dnssd$'] = 'systemd',
   2408    ['/systemd/.*%.link$'] = 'systemd',
   2409    ['/systemd/.*%.mount$'] = 'systemd',
   2410    ['/systemd/.*%.netdev$'] = 'systemd',
   2411    ['/systemd/.*%.network$'] = 'systemd',
   2412    ['/systemd/.*%.nspawn$'] = 'systemd',
   2413    ['/systemd/.*%.path$'] = 'systemd',
   2414    ['/systemd/.*%.service$'] = 'systemd',
   2415    ['/systemd/.*%.slice$'] = 'systemd',
   2416    ['/systemd/.*%.socket$'] = 'systemd',
   2417    ['/systemd/.*%.swap$'] = 'systemd',
   2418    ['/systemd/.*%.target$'] = 'systemd',
   2419    ['/systemd/.*%.timer$'] = 'systemd',
   2420  },
   2421  ['/usr/'] = {
   2422    ['/usr/share/alsa/alsa%.conf$'] = 'alsaconf',
   2423    ['/usr/.*/gnupg/options%.skel$'] = 'gpg',
   2424    ['/usr/share/upstart/.*%.conf$'] = 'upstart',
   2425    ['/usr/share/upstart/.*%.override$'] = 'upstart',
   2426  },
   2427  ['/var/'] = {
   2428    ['/var/backups/group%.bak$'] = 'group',
   2429    ['/var/backups/gshadow%.bak$'] = 'group',
   2430    ['/var/backups/passwd%.bak$'] = 'passwd',
   2431    ['/var/backups/shadow%.bak$'] = 'passwd',
   2432  },
   2433  ['/conf'] = {
   2434    ['/%.aptitude/config$'] = 'aptconf',
   2435    ['/build/conf/.*%.conf$'] = 'bitbake',
   2436    ['/meta%-.*/conf/.*%.conf$'] = 'bitbake',
   2437    ['/meta/conf/.*%.conf$'] = 'bitbake',
   2438    ['/project%-spec/configs/.*%.conf$'] = 'bitbake',
   2439    ['/%.cabal/config$'] = 'cabalconfig',
   2440    ['/cabal/config$'] = 'cabalconfig',
   2441    ['/%.aws/config$'] = 'confini',
   2442    ['/bpython/config$'] = 'dosini',
   2443    ['/flatpak/repo/config$'] = 'dosini',
   2444    ['/mypy/config$'] = 'dosini',
   2445    ['^${HOME}/%.config/notmuch/.*/config$'] = 'dosini',
   2446    ['^${XDG_CONFIG_HOME}/notmuch/.*/config$'] = 'dosini',
   2447    ['^${XDG_CONFIG_HOME}/git/config$'] = 'gitconfig',
   2448    ['%.git/config%.worktree$'] = 'gitconfig',
   2449    ['%.git/config$'] = 'gitconfig',
   2450    ['%.git/modules/.*/config$'] = 'gitconfig',
   2451    ['%.git/modules/config$'] = 'gitconfig',
   2452    ['%.git/worktrees/.*/config%.worktree$'] = 'gitconfig',
   2453    ['/%.config/git/config$'] = 'gitconfig',
   2454    ['/gitolite%-admin/conf/'] = starsetf('gitolite'),
   2455    ['/%.i3/config$'] = 'i3config',
   2456    ['/i3/config$'] = 'i3config',
   2457    ['/waybar/config$'] = 'jsonc',
   2458    ['/%.mplayer/config$'] = 'mplayerconf',
   2459    ['/supertux2/config$'] = 'scheme',
   2460    ['/neofetch/config%.conf$'] = 'sh',
   2461    ['/%.ssh/config$'] = 'sshconfig',
   2462    ['/%.sway/config$'] = 'swayconfig',
   2463    ['/sway/config$'] = 'swayconfig',
   2464    ['/sway/config%.d/'] = 'swayconfig',
   2465    ['/%.cargo/config$'] = 'toml',
   2466    ['/%.bundle/config$'] = 'yaml',
   2467    ['/%.kube/config$'] = 'yaml',
   2468  },
   2469  ['/%.'] = {
   2470    ['/%.aws/credentials$'] = 'confini',
   2471    ['/%.aws/cli/alias$'] = 'confini',
   2472    ['/%.gitconfig%.d/'] = starsetf('gitconfig'),
   2473    ['/%.gnupg/gpg%.conf$'] = 'gpg',
   2474    ['/%.gnupg/options$'] = 'gpg',
   2475    ['/%.icewm/menu$'] = 'icemenu',
   2476    ['/%.libao$'] = 'libao',
   2477    ['/%.pinforc$'] = 'pinfo',
   2478    ['/%.cargo/credentials$'] = 'toml',
   2479    ['/%.init/.*%.override$'] = 'upstart',
   2480    ['/%.kube/kuberc$'] = 'yaml',
   2481  },
   2482  ['calendar/'] = {
   2483    ['/%.calendar/'] = starsetf('calendar'),
   2484    ['/share/calendar/.*/calendar%.'] = starsetf('calendar'),
   2485    ['/share/calendar/calendar%.'] = starsetf('calendar'),
   2486  },
   2487  ['cmus/'] = {
   2488    -- */cmus/*.theme and */.cmus/*.theme
   2489    ['/%.?cmus/.*%.theme$'] = 'cmusrc',
   2490    -- */cmus/rc and */.cmus/rc
   2491    ['/%.?cmus/rc$'] = 'cmusrc',
   2492    ['/%.cmus/autosave$'] = 'cmusrc',
   2493    ['/%.cmus/command%-history$'] = 'cmusrc',
   2494  },
   2495  ['git/'] = {
   2496    ['%.git/'] = {
   2497      detect.git,
   2498      -- Decrease priority to run after simple pattern checks
   2499      { priority = -1 },
   2500    },
   2501    ['^${XDG_CONFIG_HOME}/git/attributes$'] = 'gitattributes',
   2502    ['%.git/info/attributes$'] = 'gitattributes',
   2503    ['/%.config/git/attributes$'] = 'gitattributes',
   2504    ['^${XDG_CONFIG_HOME}/git/ignore$'] = 'gitignore',
   2505    ['%.git/info/exclude$'] = 'gitignore',
   2506    ['/%.config/git/ignore$'] = 'gitignore',
   2507  },
   2508  ['%.cfg'] = {
   2509    ['enlightenment/.*%.cfg$'] = 'c',
   2510    ['Eterm/.*%.cfg$'] = 'eterm',
   2511    ['baseq[2-3]/.*%.cfg$'] = 'quake',
   2512    ['id1/.*%.cfg$'] = 'quake',
   2513    ['quake[1-3]/.*%.cfg$'] = 'quake',
   2514    ['/tex/latex/.*%.cfg$'] = 'tex',
   2515  },
   2516  ['%.conf'] = {
   2517    ['^proftpd%.conf'] = starsetf('apachestyle'),
   2518    ['^access%.conf'] = detect_apache,
   2519    ['^apache%.conf'] = detect_apache,
   2520    ['^apache2%.conf'] = detect_apache,
   2521    ['^httpd%.conf'] = detect_apache,
   2522    ['^httpd%-.*%.conf'] = detect_apache,
   2523    ['^proxy%-html%.conf'] = detect_apache,
   2524    ['^srm%.conf'] = detect_apache,
   2525    ['asterisk/.*%.conf'] = starsetf('asterisk'),
   2526    ['asterisk.*/.*voicemail%.conf'] = starsetf('asteriskvm'),
   2527    ['^dictd.*%.conf$'] = 'dictdconf',
   2528    ['/%.?gnuradio/.*%.conf$'] = 'confini',
   2529    ['/gnuradio/conf%.d/.*%.conf$'] = 'confini',
   2530    ['/lxqt/.*%.conf$'] = 'dosini',
   2531    ['/screengrab/.*%.conf$'] = 'dosini',
   2532    ['/%.config/fd/ignore$'] = 'gitignore',
   2533    ['^${GNUPGHOME}/gpg%.conf$'] = 'gpg',
   2534    ['/boot/grub/grub%.conf$'] = 'grub',
   2535    ['/hypr/.*%.conf$'] = 'hyprlang',
   2536    ['/kitty/.*%.conf$'] = 'kitty',
   2537    ['^lilo%.conf'] = starsetf('lilo'),
   2538    ['^named.*%.conf$'] = 'named',
   2539    ['^rndc.*%.conf$'] = 'named',
   2540    ['/openvpn/.*/.*%.conf$'] = 'openvpn',
   2541    ['/pipewire/.*%.conf$'] = 'spajson',
   2542    ['/wireplumber/.*%.conf$'] = 'spajson',
   2543    ['/%.ssh/.*%.conf$'] = 'sshconfig',
   2544    ['/containers/systemd/.*%.d/.*%.conf$'] = 'systemd',
   2545    ['^%.?tmux.*%.conf$'] = 'tmux',
   2546    ['^%.?tmux.*%.conf'] = starsetf('tmux'),
   2547    ['/containers/containers%.conf$'] = 'toml',
   2548    ['/containers/containers%.conf%.d/.*%.conf$'] = 'toml',
   2549    ['/containers/containers%.conf%.modules/.*%.conf$'] = 'toml',
   2550    ['/containers/registries%.conf$'] = 'toml',
   2551    ['/containers/registries%.conf%.d/.*%.conf$'] = 'toml',
   2552    ['/containers/storage%.conf$'] = 'toml',
   2553    ['/%.config/upstart/.*%.conf$'] = 'upstart',
   2554    ['/%.config/upstart/.*%.override$'] = 'upstart',
   2555    ['/%.init/.*%.conf$'] = 'upstart',
   2556    ['/xorg%.conf%.d/.*%.conf$'] = detect.xfree86_v4,
   2557  },
   2558  ['sst%.meta'] = {
   2559    ['%.%-sst%.meta$'] = 'sisu',
   2560    ['%._sst%.meta$'] = 'sisu',
   2561    ['%.sst%.meta$'] = 'sisu',
   2562  },
   2563  ['file'] = {
   2564    ['^Containerfile%.'] = starsetf('dockerfile'),
   2565    ['^Dockerfile%.'] = starsetf('dockerfile'),
   2566    ['[mM]akefile$'] = detect.make,
   2567    ['^[mM]akefile'] = starsetf(detect.make),
   2568    ['^[rR]akefile'] = starsetf('ruby'),
   2569    ['^%.profile'] = detect.sh,
   2570  },
   2571  ['fvwm'] = {
   2572    ['/%.fvwm/'] = starsetf('fvwm'),
   2573    ['fvwmrc'] = starsetf(detect.fvwm_v1),
   2574    ['fvwm95.*%.hook$'] = starsetf(detect.fvwm_v1),
   2575    ['fvwm2rc'] = starsetf(detect.fvwm_v2),
   2576  },
   2577  ['nginx'] = {
   2578    ['/nginx/.*%.conf$'] = 'nginx',
   2579    ['/usr/local/nginx/conf/'] = starsetf('nginx'),
   2580    ['nginx%.conf$'] = 'nginx',
   2581    ['^nginx.*%.conf$'] = 'nginx',
   2582  },
   2583  ['require'] = {
   2584    ['%-requirements%.txt$'] = 'requirements',
   2585    ['^requirements%-.*%.txt$'] = 'requirements',
   2586    ['^requirements/.*%.txt$'] = 'requirements',
   2587    ['^requires/.*%.txt$'] = 'requirements',
   2588  },
   2589  ['s6'] = {
   2590    ['s6.*/down$'] = 'execline',
   2591    ['s6.*/finish$'] = 'execline',
   2592    ['s6.*/run$'] = 'execline',
   2593    ['s6.*/up$'] = 'execline',
   2594    ['^s6%-'] = starsetf('execline'),
   2595  },
   2596  ['utt'] = {
   2597    ['^mutt%-.*%-%w+$'] = 'mail',
   2598    ['^mutt' .. string.rep('[%w_-]', 6) .. '$'] = 'mail',
   2599    ['^muttng%-.*%-%w+$'] = 'mail',
   2600    ['^neomutt%-.*%-%w+$'] = 'mail',
   2601    ['^neomutt' .. string.rep('[%w_-]', 6) .. '$'] = 'mail',
   2602    -- muttngrc* and .muttngrc*
   2603    ['^%.?muttngrc'] = detect_muttrc,
   2604    -- muttrc* and .muttrc*
   2605    ['^%.?muttrc'] = detect_muttrc,
   2606    ['/%.mutt/muttrc'] = detect_muttrc,
   2607    ['/%.muttng/muttngrc'] = detect_muttrc,
   2608    ['/%.muttng/muttrc'] = detect_muttrc,
   2609    ['^Muttngrc'] = detect_muttrc,
   2610    ['^Muttrc'] = detect_muttrc,
   2611    -- neomuttrc* and .neomuttrc*
   2612    ['^%.?neomuttrc'] = detect_neomuttrc,
   2613    ['/%.neomutt/neomuttrc'] = detect_neomuttrc,
   2614    ['^Neomuttrc'] = detect_neomuttrc,
   2615    ['%.neomuttdebug'] = 'neomuttlog',
   2616  },
   2617  ['xkb/'] = {
   2618    ['/%.?xkb/compat/'] = detect_xkb,
   2619    ['/%.?xkb/geometry/'] = detect_xkb,
   2620    ['/%.?xkb/keycodes/'] = detect_xkb,
   2621    ['/%.?xkb/symbols/'] = detect_xkb,
   2622    ['/%.?xkb/types/'] = detect_xkb,
   2623  },
   2624  ['m17n'] = {
   2625    ['/m17n/.*%.ali$'] = 'm17ndb',
   2626    ['/m17n/.*%.cs$'] = 'm17ndb',
   2627    ['/m17n/.*%.dir$'] = 'm17ndb',
   2628    ['/m17n/.*%.flt$'] = 'm17ndb',
   2629    ['/m17n/.*%.fst$'] = 'm17ndb',
   2630    ['/m17n/.*%.lnm$'] = 'm17ndb',
   2631    ['/m17n/.*%.mic$'] = 'm17ndb',
   2632    ['/m17n/.*%.mim$'] = 'm17ndb',
   2633    ['/m17n/.*%.tbl$'] = 'm17ndb',
   2634    ['/%.m17n%.d/.*%.ali$'] = 'm17ndb',
   2635    ['/%.m17n%.d/.*%.cs$'] = 'm17ndb',
   2636    ['/%.m17n%.d/.*%.dir$'] = 'm17ndb',
   2637    ['/%.m17n%.d/.*%.flt$'] = 'm17ndb',
   2638    ['/%.m17n%.d/.*%.fst$'] = 'm17ndb',
   2639    ['/%.m17n%.d/.*%.lnm$'] = 'm17ndb',
   2640    ['/%.m17n%.d/.*%.mic$'] = 'm17ndb',
   2641    ['/%.m17n%.d/.*%.mim$'] = 'm17ndb',
   2642    ['/%.m17n%.d/.*%.tbl$'] = 'm17ndb',
   2643    ['/m17n%-db/.*%.ali$'] = 'm17ndb',
   2644    ['/m17n%-db/.*%.cs$'] = 'm17ndb',
   2645    ['/m17n%-db/.*%.dir$'] = 'm17ndb',
   2646    ['/m17n%-db/.*%.flt$'] = 'm17ndb',
   2647    ['/m17n%-db/.*%.fst$'] = 'm17ndb',
   2648    ['/m17n%-db/.*%.lnm$'] = 'm17ndb',
   2649    ['/m17n%-db/.*%.mic$'] = 'm17ndb',
   2650    ['/m17n%-db/.*%.mim$'] = 'm17ndb',
   2651    ['/m17n%-db/.*%.tbl$'] = 'm17ndb',
   2652  },
   2653  ['^%.'] = {
   2654    ['^%.cshrc'] = detect.csh,
   2655    ['^%.login'] = detect.csh,
   2656    ['^%.notmuch%-config%.'] = 'dosini',
   2657    ['^%.env%.'] = 'env',
   2658    ['^%.gitsendemail%.msg%.......$'] = 'gitsendemail',
   2659    ['^%.kshrc'] = detect.ksh,
   2660    ['^%.article%.%d+$'] = 'mail',
   2661    ['^%.letter%.%d+$'] = 'mail',
   2662    ['^%.reminders'] = starsetf('remind'),
   2663    ['^%.envrc%.'] = detect.sh,
   2664    ['^%.tcshrc'] = detect.tcsh,
   2665    ['^%.zcompdump'] = starsetf('zsh'),
   2666  },
   2667  ['proj%.user$'] = {
   2668    ['%.csproj%.user$'] = 'xml',
   2669    ['%.fsproj%.user$'] = 'xml',
   2670    ['%.vbproj%.user$'] = 'xml',
   2671  },
   2672  [''] = {
   2673    ['^bash%-fc[%-%.]'] = detect.bash,
   2674    ['/bind/db%.'] = starsetf('bindzone'),
   2675    ['/named/db%.'] = starsetf('bindzone'),
   2676    ['%.blade%.php$'] = 'blade',
   2677    ['^bzr_log%.'] = 'bzr',
   2678    ['^cabal%.project%.'] = starsetf('cabalproject'),
   2679    ['^sgml%.catalog'] = starsetf('catalog'),
   2680    ['hgrc$'] = 'cfg',
   2681    ['^[cC]hange[lL]og'] = starsetf(detect.changelog),
   2682    ['%.%.ch$'] = 'chill',
   2683    ['%.cmake%.in$'] = 'cmake',
   2684    ['^crontab%.'] = starsetf('crontab'),
   2685    ['^cvs%d+$'] = 'cvs',
   2686    ['/DEBIAN/control$'] = 'debcontrol',
   2687    ['^php%.ini%-'] = starsetf('dosini'),
   2688    ['^php%-fpm%.conf'] = starsetf('dosini'),
   2689    ['^www%.conf'] = starsetf('dosini'),
   2690    ['^drac%.'] = starsetf('dracula'),
   2691    ['/dtrace/.*%.d$'] = 'dtrace',
   2692    ['%.app%.src$'] = 'erlang',
   2693    ['esmtprc$'] = 'esmtprc',
   2694    ['/0%.orig/'] = starsetf(detect.foam),
   2695    ['/0/'] = starsetf(detect.foam),
   2696    ['/constant/g$'] = detect.foam,
   2697    ['Transport%.'] = starsetf(detect.foam),
   2698    ['^[a-zA-Z0-9].*Dict%.'] = starsetf(detect.foam),
   2699    ['^[a-zA-Z0-9].*Dict$'] = detect.foam,
   2700    ['^[a-zA-Z].*Properties%.'] = starsetf(detect.foam),
   2701    ['^[a-zA-Z].*Properties$'] = detect.foam,
   2702    ['/tmp/lltmp'] = starsetf('gedcom'),
   2703    ['^gkrellmrc_.$'] = 'gkrellmrc',
   2704    ['^${GNUPGHOME}/options$'] = 'gpg',
   2705    ['/boot/grub/menu%.lst$'] = 'grub',
   2706    -- gtkrc* and .gtkrc*
   2707    ['^%.?gtkrc'] = starsetf('gtkrc'),
   2708    ['/doc/.*%.txt$'] = function(_, bufnr)
   2709      local line = M._getline(bufnr, -1)
   2710      if
   2711        M._findany(line, {
   2712          '^vim:ft=help[:%s]',
   2713          '^vim:ft=help$',
   2714          '^vim:filetype=help[:%s]',
   2715          '^vim:filetype=help$',
   2716          '^vim:.*[:%s]ft=help[:%s]',
   2717          '^vim:.*[:%s]ft=help$',
   2718          '^vim:.*[:%s]filetype=help[:%s]',
   2719          '^vim:.*[:%s]filetype=help$',
   2720          '%svim:ft=help[:%s]',
   2721          '%svim:ft=help$',
   2722          '%svim:filetype=help[:%s]',
   2723          '%svim:filetype=help$',
   2724          '%svim:.*[:%s]ft=help[:%s]',
   2725          '%svim:.*[:%s]ft=help$',
   2726          '%svim:.*[:%s]filetype=help[:%s]',
   2727          '%svim:.*[:%s]filetype=help$',
   2728        })
   2729      then
   2730        return 'help'
   2731      end
   2732    end,
   2733    ['^hg%-editor%-.*%.txt$'] = 'hgcommit',
   2734    ['^JAM.*%.'] = starsetf('jam'),
   2735    ['^Prl.*%.'] = starsetf('jam'),
   2736    ['^${HOME}/.*/Code/User/.*%.json$'] = 'jsonc',
   2737    ['^${HOME}/.*/VSCodium/User/.*%.json$'] = 'jsonc',
   2738    ['%.properties_..$'] = 'jproperties',
   2739    ['%.properties_.._..$'] = 'jproperties',
   2740    ['%.properties_.._.._'] = starsetf('jproperties'),
   2741    ['^org%.eclipse%..*%.prefs$'] = 'jproperties',
   2742    ['^[jt]sconfig.*%.json$'] = 'jsonc',
   2743    ['^Config%.in%.'] = starsetf('kconfig'),
   2744    ['^Kconfig%.'] = starsetf('kconfig'),
   2745    ['/ldscripts/'] = 'ld',
   2746    ['lftp/rc$'] = 'lftp',
   2747    ['/LiteStep/.*/.*%.rc$'] = 'litestep',
   2748    ['^/tmp/SLRN[0-9A-Z.]+$'] = 'mail',
   2749    ['^ae%d+%.txt$'] = 'mail',
   2750    ['^pico%.%d+$'] = 'mail',
   2751    ['^reportbug%-'] = starsetf('mail'),
   2752    ['^snd%.%d+$'] = 'mail',
   2753    ['^rndc.*%.key$'] = 'named',
   2754    ['^tmac%.'] = starsetf('nroff'),
   2755    ['%.ml%.cppo$'] = 'ocaml',
   2756    ['%.mli%.cppo$'] = 'ocaml',
   2757    ['/octave/history$'] = 'octave',
   2758    ['%.opam%.locked$'] = 'opam',
   2759    ['%.opam%.template$'] = 'opam',
   2760    ['^pacman%.log'] = starsetf(function(path, _bufnr)
   2761      return vim.uv.fs_stat(path) and 'pacmanlog' or nil
   2762    end),
   2763    ['^pkl%-lsp://'] = 'pkl',
   2764    ['printcap'] = starsetf(function(_path, _bufnr)
   2765      return require('vim.filetype.detect').printcap('print')
   2766    end),
   2767    ['/queries/.*%.scm$'] = 'query', -- treesitter queries (Neovim only)
   2768    [',v$'] = 'rcs',
   2769    ['^svn%-commit.*%.tmp$'] = 'svn',
   2770    ['%.swift%.gyb$'] = 'swiftgyb',
   2771    ['^vivado.*%.jou$'] = 'tcl',
   2772    ['^vivado.*%.log$'] = 'tcl',
   2773    ['termcap'] = starsetf(function(_path, _bufnr)
   2774      return require('vim.filetype.detect').printcap('term')
   2775    end),
   2776    ['^Tiltfile%.'] = starsetf('tiltfile'),
   2777    ['%.t%.html$'] = 'tilde',
   2778    ['%.vhdl_[0-9]'] = starsetf('vhdl'),
   2779    ['vimrc'] = starsetf('vim'),
   2780    ['/Xresources/'] = starsetf('xdefaults'),
   2781    ['/app%-defaults/'] = starsetf('xdefaults'),
   2782    ['^Xresources'] = starsetf('xdefaults'),
   2783    -- Increase priority to run before the pattern below
   2784    ['^XF86Config%-4'] = starsetf(detect.xfree86_v4, -math.huge + 1),
   2785    ['^XF86Config'] = starsetf(detect.xfree86_v3),
   2786    ['Xmodmap$'] = 'xmodmap',
   2787    ['xmodmap'] = starsetf('xmodmap'),
   2788    -- .zlog* and zlog*
   2789    ['^%.?zlog'] = starsetf('zsh'),
   2790    -- .zsh* and zsh*
   2791    ['^%.?zsh'] = starsetf('zsh'),
   2792    -- Ignored extension
   2793    ['~$'] = function(path, bufnr)
   2794      local short = path:gsub('~+$', '', 1)
   2795      if path ~= short and short ~= '' then
   2796        return M.match({ buf = bufnr, filename = fn.fnameescape(short) })
   2797      end
   2798    end,
   2799  },
   2800  -- END PATTERN
   2801 }
   2802 -- luacheck: pop
   2803 -- luacheck: pop
   2804 
   2805 --- Lookup table/cache for patterns
   2806 --- @alias vim.filetype.pattern_cache { has_env: boolean, has_slash: boolean }
   2807 --- @type table<string,vim.filetype.pattern_cache>
   2808 local pattern_lookup = {}
   2809 
   2810 --- @param a vim.filetype.mapping.sorted
   2811 --- @param b vim.filetype.mapping.sorted
   2812 local function compare_by_priority(a, b)
   2813  return a[4] > b[4]
   2814 end
   2815 
   2816 --- @param pat string
   2817 --- @return { has_env: boolean, has_slash: boolean }
   2818 local function parse_pattern(pat)
   2819  return { has_env = pat:find('%$%b{}') ~= nil, has_slash = pat:find('/') ~= nil }
   2820 end
   2821 
   2822 --- @param t table<string,vim.filetype.mapping>
   2823 --- @return vim.filetype.mapping.sorted[]
   2824 --- @return vim.filetype.mapping.sorted[]
   2825 local function sort_by_priority(t)
   2826  -- Separate patterns with non-negative and negative priority because they
   2827  -- will be processed separately
   2828  local pos = {} --- @type vim.filetype.mapping.sorted[]
   2829  local neg = {} --- @type vim.filetype.mapping.sorted[]
   2830  for parent, ft_map in pairs(t) do
   2831    pattern_lookup[parent] = pattern_lookup[parent] or parse_pattern(parent)
   2832    for pat, maptbl in pairs(ft_map) do
   2833      local ft_or_fun = type(maptbl) == 'table' and maptbl[1] or maptbl
   2834      assert(
   2835        type(ft_or_fun) == 'string' or type(ft_or_fun) == 'function',
   2836        'Expected string or function for filetype'
   2837      )
   2838 
   2839      -- Parse pattern for common data and cache it once
   2840      pattern_lookup[pat] = pattern_lookup[pat] or parse_pattern(pat)
   2841 
   2842      --- @type vim.filetype.mapopts?
   2843      local opts = (type(maptbl) == 'table' and type(maptbl[2]) == 'table') and maptbl[2] or nil
   2844      local priority = opts and opts.priority or 0
   2845 
   2846      table.insert(priority >= 0 and pos or neg, { parent, pat, ft_or_fun, priority })
   2847    end
   2848  end
   2849 
   2850  table.sort(pos, compare_by_priority)
   2851  table.sort(neg, compare_by_priority)
   2852  return pos, neg
   2853 end
   2854 
   2855 local pattern_sorted_pos, pattern_sorted_neg = sort_by_priority(pattern)
   2856 
   2857 --- @param path string
   2858 --- @param as_pattern? true
   2859 --- @return string
   2860 local function normalize_path(path, as_pattern)
   2861  local normal = path:gsub('\\', '/')
   2862  if normal:find('^~') then
   2863    if as_pattern then
   2864      -- Escape Lua's metacharacters when $HOME is used in a pattern.
   2865      -- The rest of path should already be properly escaped.
   2866      normal = vim.pesc(vim.env.HOME) .. normal:sub(2)
   2867    else
   2868      normal = vim.env.HOME .. normal:sub(2) --- @type string
   2869    end
   2870  end
   2871  return normal
   2872 end
   2873 
   2874 --- @class vim.filetype.add.filetypes
   2875 --- @inlinedoc
   2876 --- @field pattern? vim.filetype.mapping
   2877 --- @field extension? vim.filetype.mapping
   2878 --- @field filename? vim.filetype.mapping
   2879 
   2880 --- Add new filetype mappings.
   2881 ---
   2882 --- Filetype mappings can be added either by extension or by filename (either
   2883 --- the "tail" or the full file path). The full file path is checked first,
   2884 --- followed by the file name. If a match is not found using the filename, then
   2885 --- the filename is matched against the list of |lua-pattern|s (sorted by priority)
   2886 --- until a match is found. Lastly, if pattern matching does not find a
   2887 --- filetype, then the file extension is used.
   2888 ---
   2889 --- The filetype can be either a string (in which case it is used as the
   2890 --- filetype directly) or a function. If a function, it takes the full path and
   2891 --- buffer number of the file as arguments (along with captures from the matched
   2892 --- pattern, if any) and should return a string that will be used as the
   2893 --- buffer's filetype. Optionally, the function can return a second function
   2894 --- value which, when called, modifies the state of the buffer. This can be used
   2895 --- to, for example, set filetype-specific buffer variables. This function will
   2896 --- be called by Nvim before setting the buffer's filetype.
   2897 ---
   2898 --- Filename patterns can specify an optional priority to resolve cases when a
   2899 --- file path matches multiple patterns. Higher priorities are matched first.
   2900 --- When omitted, the priority defaults to 0.
   2901 --- A pattern can contain environment variables of the form "${SOME_VAR}" that will
   2902 --- be automatically expanded. If the environment variable is not set, the pattern
   2903 --- won't be matched.
   2904 ---
   2905 --- See $VIMRUNTIME/lua/vim/filetype.lua for more examples.
   2906 ---
   2907 --- Example:
   2908 ---
   2909 --- ```lua
   2910 --- vim.filetype.add({
   2911 ---   extension = {
   2912 ---     foo = 'fooscript',
   2913 ---     bar = function(path, bufnr)
   2914 ---       if some_condition() then
   2915 ---         return 'barscript', function(bufnr)
   2916 ---           -- Set a buffer variable
   2917 ---           vim.b[bufnr].barscript_version = 2
   2918 ---         end
   2919 ---       end
   2920 ---       return 'bar'
   2921 ---     end,
   2922 ---   },
   2923 ---   filename = {
   2924 ---     ['.foorc'] = 'toml',
   2925 ---     ['/etc/foo/config'] = 'toml',
   2926 ---   },
   2927 ---   pattern = {
   2928 ---     ['.*/etc/foo/.*'] = 'fooscript',
   2929 ---     -- Using an optional priority
   2930 ---     ['.*/etc/foo/.*%.conf'] = { 'dosini', { priority = 10 } },
   2931 ---     -- A pattern containing an environment variable
   2932 ---     ['${XDG_CONFIG_HOME}/foo/git'] = 'git',
   2933 ---     ['.*README.(%a+)'] = function(path, bufnr, ext)
   2934 ---       if ext == 'md' then
   2935 ---         return 'markdown'
   2936 ---       elseif ext == 'rst' then
   2937 ---         return 'rst'
   2938 ---       end
   2939 ---     end,
   2940 ---   },
   2941 --- })
   2942 --- ```
   2943 ---
   2944 --- To add a fallback match on contents, use
   2945 ---
   2946 --- ```lua
   2947 --- vim.filetype.add {
   2948 ---   pattern = {
   2949 ---     ['.*'] = {
   2950 ---       function(path, bufnr)
   2951 ---         local content = vim.api.nvim_buf_get_lines(bufnr, 0, 1, false)[1] or ''
   2952 ---         if vim.regex([[^#!.*\\<mine\\>]]):match_str(content) ~= nil then
   2953 ---           return 'mine'
   2954 ---         elseif vim.regex([[\\<drawing\\>]]):match_str(content) ~= nil then
   2955 ---           return 'drawing'
   2956 ---         end
   2957 ---       end,
   2958 ---       { priority = -math.huge },
   2959 ---     },
   2960 ---   },
   2961 --- }
   2962 --- ```
   2963 ---
   2964 ---@param filetypes vim.filetype.add.filetypes A table containing new filetype maps (see example).
   2965 function M.add(filetypes)
   2966  for k, v in pairs(filetypes.extension or {}) do
   2967    extension[k] = v
   2968  end
   2969 
   2970  for k, v in pairs(filetypes.filename or {}) do
   2971    filename[normalize_path(k)] = v
   2972  end
   2973 
   2974  for k, v in pairs(filetypes.pattern or {}) do
   2975    -- Add to "match all" parent pattern (might be better to optimize later or document
   2976    -- supplying `opts.parent` directly)
   2977    -- User patterns are assumed to be implicitly anchored (as in Vim)
   2978    pattern['']['^' .. normalize_path(k, true) .. '$'] = v
   2979  end
   2980 
   2981  if filetypes.pattern then
   2982    -- TODO: full resorting might be expensive with a lot of separate `vim.filetype.add()` calls.
   2983    -- Consider inserting new patterns precisely into already sorted lists of built-in patterns.
   2984    pattern_sorted_pos, pattern_sorted_neg = sort_by_priority(pattern)
   2985  end
   2986 end
   2987 
   2988 --- @param ft vim.filetype.mapping.value
   2989 --- @param path? string
   2990 --- @param bufnr? integer
   2991 --- @param ... any
   2992 --- @return string?
   2993 --- @return fun(b: integer)?
   2994 local function dispatch(ft, path, bufnr, ...)
   2995  if type(ft) == 'string' then
   2996    return ft
   2997  end
   2998 
   2999  if type(ft) ~= 'function' then
   3000    return
   3001  end
   3002 
   3003  assert(path)
   3004 
   3005  ---@type string|false?, fun(b: integer)?
   3006  local ft0, on_detect
   3007  if bufnr then
   3008    ft0, on_detect = ft(path, bufnr, ...)
   3009  else
   3010    -- If bufnr is nil (meaning we are matching only against the filename), set it to an invalid
   3011    -- value (-1) and catch any errors from the filetype detection function. If the function tries
   3012    -- to use the buffer then it will fail, but this enables functions which do not need a buffer
   3013    -- to still work.
   3014    local ok
   3015    ok, ft0, on_detect = pcall(ft, path, -1, ...)
   3016    if not ok then
   3017      return
   3018    end
   3019  end
   3020 
   3021  if not ft0 then
   3022    return
   3023  end
   3024 
   3025  return ft0, on_detect
   3026 end
   3027 
   3028 --- @param pat string
   3029 --- @return boolean
   3030 --- @return string
   3031 local function expand_envvar_pattern(pat)
   3032  local some_env_missing = false
   3033  local expanded = pat:gsub('%${(%S-)}', function(env)
   3034    local val = vim.env[env] --- @type string?
   3035    some_env_missing = some_env_missing or val == nil
   3036    return vim.pesc(val or '')
   3037  end)
   3038  return some_env_missing, expanded
   3039 end
   3040 
   3041 --- @param name string
   3042 --- @param path string
   3043 --- @param tail string
   3044 --- @param pat string
   3045 --- @param try_all_candidates boolean
   3046 --- @return string?
   3047 local function match_pattern(name, path, tail, pat, try_all_candidates)
   3048  local pat_cache = pattern_lookup[pat]
   3049  local has_slash = pat_cache.has_slash
   3050 
   3051  if pat_cache.has_env then
   3052    local some_env_missing, expanded = expand_envvar_pattern(pat)
   3053    -- If any environment variable is present in the pattern but not set, there is no match
   3054    if some_env_missing then
   3055      return nil
   3056    end
   3057    pat = expanded
   3058    has_slash = has_slash or expanded:find('/') ~= nil
   3059  end
   3060 
   3061  -- Try all possible candidates to make parent patterns not depend on slash presence
   3062  if try_all_candidates then
   3063    return (path:match(pat) or name:match(pat) or tail:match(pat))
   3064  end
   3065 
   3066  -- If the pattern contains a / match against the full path, otherwise just the tail
   3067  if has_slash then
   3068    -- Similar to |autocmd-pattern|, if the pattern contains a '/' then check for a match against
   3069    -- both the short file name (as typed) and the full file name (after expanding to full path
   3070    -- and resolving symlinks)
   3071    return (name:match(pat) or path:match(pat))
   3072  end
   3073 
   3074  return (tail:match(pat))
   3075 end
   3076 
   3077 --- @param name string
   3078 --- @param path string
   3079 --- @param tail string
   3080 --- @param pattern_sorted vim.filetype.mapping.sorted[]
   3081 --- @param parent_matches table<string,boolean>
   3082 --- @param bufnr integer?
   3083 local function match_pattern_sorted(name, path, tail, pattern_sorted, parent_matches, bufnr)
   3084  for _, p in ipairs(pattern_sorted) do
   3085    local parent, pat, ft_or_fn = p[1], p[2], p[3]
   3086 
   3087    local parent_is_matched = parent_matches[parent]
   3088    if parent_is_matched == nil then
   3089      parent_matches[parent] = match_pattern(name, path, tail, parent, true) ~= nil
   3090      parent_is_matched = parent_matches[parent]
   3091    end
   3092 
   3093    if parent_is_matched then
   3094      local matches = match_pattern(name, path, tail, pat, false)
   3095      if matches then
   3096        local ft, on_detect = dispatch(ft_or_fn, path, bufnr, matches)
   3097        if ft then
   3098          return ft, on_detect
   3099        end
   3100      end
   3101    end
   3102  end
   3103 end
   3104 
   3105 --- @class vim.filetype.match.args
   3106 --- @inlinedoc
   3107 ---
   3108 --- Buffer number to use for matching. Mutually exclusive with {contents}
   3109 --- @field buf? integer
   3110 ---
   3111 --- Filename to use for matching. When {buf} is given,
   3112 --- defaults to the filename of the given buffer number. The
   3113 --- file need not actually exist in the filesystem. When used
   3114 --- without {buf} only the name of the file is used for
   3115 --- filetype matching. This may result in failure to detect
   3116 --- the filetype in cases where the filename alone is not
   3117 --- enough to disambiguate the filetype.
   3118 --- @field filename? string
   3119 ---
   3120 --- An array of lines representing file contents to use for
   3121 --- matching. Can be used with {filename}. Mutually exclusive
   3122 --- with {buf}.
   3123 --- @field contents? string[]
   3124 
   3125 --- Perform filetype detection.
   3126 ---
   3127 --- The filetype can be detected using one of three methods:
   3128 --- 1. Using an existing buffer
   3129 --- 2. Using only a file name
   3130 --- 3. Using only file contents
   3131 ---
   3132 --- Of these, option 1 provides the most accurate result as it uses both the buffer's filename and
   3133 --- (optionally) the buffer contents. Options 2 and 3 can be used without an existing buffer, but
   3134 --- may not always provide a match in cases where the filename (or contents) cannot unambiguously
   3135 --- determine the filetype.
   3136 ---
   3137 --- Each of the three options is specified using a key to the single argument of this function.
   3138 --- Example:
   3139 ---
   3140 --- ```lua
   3141 --- -- Using a buffer number
   3142 --- vim.filetype.match({ buf = 42 })
   3143 ---
   3144 --- -- Override the filename of the given buffer
   3145 --- vim.filetype.match({ buf = 42, filename = 'foo.c' })
   3146 ---
   3147 --- -- Using a filename without a buffer
   3148 --- vim.filetype.match({ filename = 'main.lua' })
   3149 ---
   3150 --- -- Using file contents
   3151 --- vim.filetype.match({ contents = {'#!/usr/bin/env bash'} })
   3152 --- ```
   3153 ---
   3154 ---@param args vim.filetype.match.args Table specifying which matching strategy to use.
   3155 ---                 Accepted keys are:
   3156 ---@return string|nil   # The matched filetype, if any.
   3157 ---@return function|nil # A function `fun(buf: integer)` that modifies buffer state when called (for
   3158 ---                     example, to set some filetype specific buffer variables).
   3159 ---@return boolean|nil  # true if a match was found by falling back to a generic filetype
   3160 ---                     (i.e., ".conf"), which indicates the filetype should be set with
   3161 ---                     `:setf FALLBACK conf`. See |:setfiletype|.
   3162 function M.match(args)
   3163  vim.validate('arg', args, 'table')
   3164 
   3165  if not (args.buf or args.filename or args.contents) then
   3166    error('At least one of "buf", "filename", or "contents" must be given')
   3167  end
   3168 
   3169  local bufnr = args.buf
   3170  local name = args.filename
   3171  local contents = args.contents
   3172 
   3173  if bufnr and not name then
   3174    name = api.nvim_buf_get_name(bufnr)
   3175  end
   3176 
   3177  if name then
   3178    name = normalize_path(name)
   3179 
   3180    local path = vim.fs.abspath(name)
   3181    do -- First check for the simple case where the full path exists as a key
   3182      local ft, on_detect = dispatch(filename[path], path, bufnr)
   3183      if ft then
   3184        return ft, on_detect
   3185      end
   3186    end
   3187 
   3188    local tail = vim.fs.basename(name)
   3189 
   3190    do -- Next check against just the file name
   3191      local ft, on_detect = dispatch(filename[tail], path, bufnr)
   3192      if ft then
   3193        return ft, on_detect
   3194      end
   3195    end
   3196 
   3197    -- Next, check the file path against available patterns with non-negative priority
   3198    -- Cache match results of all parent patterns to improve performance
   3199    local parent_matches = {}
   3200    do
   3201      local ft, on_detect =
   3202        match_pattern_sorted(name, path, tail, pattern_sorted_pos, parent_matches, bufnr)
   3203      if ft then
   3204        return ft, on_detect
   3205      end
   3206    end
   3207 
   3208    -- Next, check file extension
   3209    -- Don't use fnamemodify() with :e modifier here,
   3210    -- as that's empty when there is only an extension.
   3211    do
   3212      local ext = name:match('%.([^.]-)$') or ''
   3213      local ft, on_detect = dispatch(extension[ext], path, bufnr)
   3214      if ft then
   3215        return ft, on_detect
   3216      end
   3217    end
   3218 
   3219    do -- Next, check patterns with negative priority
   3220      local ft, on_detect =
   3221        match_pattern_sorted(name, path, tail, pattern_sorted_neg, parent_matches, bufnr)
   3222      if ft then
   3223        return ft, on_detect
   3224      end
   3225    end
   3226  end
   3227 
   3228  -- Finally, check file contents
   3229  if contents or bufnr then
   3230    if contents == nil then
   3231      assert(bufnr)
   3232      if api.nvim_buf_line_count(bufnr) > 101 then
   3233        -- only need first 100 and last line for current checks
   3234        contents = M._getlines(bufnr, 1, 100)
   3235        contents[#contents + 1] = M._getline(bufnr, -1)
   3236      else
   3237        contents = M._getlines(bufnr)
   3238      end
   3239    end
   3240 
   3241    -- Match based solely on content only if there is any content (for performance)
   3242    if not (#contents == 1 and contents[1] == '') then
   3243      -- If name is nil, catch any errors from the contents filetype detection function.
   3244      -- If the function tries to use the filename that is nil then it will fail,
   3245      -- but this enables checks which do not need a filename to still work.
   3246      local ok, ft, on_detect = pcall(
   3247        require('vim.filetype.detect').match_contents,
   3248        contents,
   3249        name,
   3250        function(ext)
   3251          return dispatch(extension[ext], name, bufnr)
   3252        end
   3253      )
   3254      if ok and ft then
   3255        return ft, on_detect
   3256      end
   3257    end
   3258  end
   3259 
   3260  -- Generic configuration file used as fallback
   3261  if name and bufnr then
   3262    local ft = detect.conf(name, bufnr)
   3263    if ft then
   3264      return ft, nil, true
   3265    end
   3266  end
   3267 end
   3268 
   3269 --- Get the default option value for a {filetype}.
   3270 ---
   3271 --- The returned value is what would be set in a new buffer after 'filetype'
   3272 --- is set, meaning it should respect all FileType autocmds and ftplugin files.
   3273 ---
   3274 --- Example:
   3275 ---
   3276 --- ```lua
   3277 --- vim.filetype.get_option('vim', 'commentstring')
   3278 --- ```
   3279 ---
   3280 --- Note: this uses |nvim_get_option_value()| but caches the result.
   3281 --- This means |ftplugin| and |FileType| autocommands are only
   3282 --- triggered once and may not reflect later changes.
   3283 --- @since 11
   3284 --- @param filetype string Filetype
   3285 --- @param option string Option name
   3286 --- @return string|boolean|integer: Option value
   3287 function M.get_option(filetype, option)
   3288  return require('vim.filetype.options').get_option(filetype, option)
   3289 end
   3290 
   3291 return M