neovim

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

filetype_spec.lua (7086B)


      1 local t = require('test.testutil')
      2 local n = require('test.functional.testnvim')()
      3 
      4 local exec_lua = n.exec_lua
      5 local eq = t.eq
      6 local api = n.api
      7 local clear = n.clear
      8 local pathroot = n.pathroot
      9 local command = n.command
     10 local mkdir = t.mkdir
     11 local rmdir = n.rmdir
     12 local write_file = t.write_file
     13 local uv = vim.uv
     14 
     15 local root = pathroot()
     16 
     17 describe('vim.filetype', function()
     18  before_each(function()
     19    clear()
     20 
     21    exec_lua(function()
     22      local bufnr = vim.api.nvim_create_buf(true, false)
     23      vim.api.nvim_set_current_buf(bufnr)
     24    end)
     25  end)
     26 
     27  it('works with extensions', function()
     28    eq(
     29      'radicalscript',
     30      exec_lua(function()
     31        vim.filetype.add({
     32          extension = {
     33            rs = 'radicalscript',
     34          },
     35        })
     36        return vim.filetype.match({ filename = 'main.rs' })
     37      end)
     38    )
     39  end)
     40 
     41  it('prioritizes filenames over extensions', function()
     42    eq(
     43      'somethingelse',
     44      exec_lua(function()
     45        vim.filetype.add({
     46          extension = {
     47            rs = 'radicalscript',
     48          },
     49          filename = {
     50            ['main.rs'] = 'somethingelse',
     51          },
     52        })
     53        return vim.filetype.match({ filename = 'main.rs' })
     54      end)
     55    )
     56  end)
     57 
     58  it('works with filenames that call _getlines() internally #36272', function()
     59    eq(
     60      'sh',
     61      exec_lua(function()
     62        vim.g.ft_ignore_pat = '\\.\\(Z\\|gz\\|bz2\\|zip\\|tgz\\)$'
     63        return vim.filetype.match({ filename = 'main.sh' })
     64      end)
     65    )
     66  end)
     67 
     68  it('works with filenames that call _getline() internally #36272', function()
     69    eq(
     70      'text',
     71      exec_lua(function()
     72        vim.g.ft_ignore_pat = '\\.\\(Z\\|gz\\|bz2\\|zip\\|tgz\\)$'
     73        return vim.filetype.match({ filename = 'main.txt' })
     74      end)
     75    )
     76  end)
     77 
     78  it('works with filenames', function()
     79    eq(
     80      'nim',
     81      exec_lua(function()
     82        vim.filetype.add({
     83          filename = {
     84            ['s_O_m_e_F_i_l_e'] = 'nim',
     85          },
     86        })
     87        return vim.filetype.match({ filename = 's_O_m_e_F_i_l_e' })
     88      end)
     89    )
     90 
     91    eq(
     92      'dosini',
     93      exec_lua(function()
     94        vim.filetype.add({
     95          filename = {
     96            ['config'] = 'toml',
     97            [root .. '/.config/fun/config'] = 'dosini',
     98          },
     99        })
    100        return vim.filetype.match({ filename = root .. '/.config/fun/config' })
    101      end)
    102    )
    103  end)
    104 
    105  it('works with patterns', function()
    106    eq(
    107      'markdown',
    108      exec_lua(function()
    109        vim.env.HOME = '/a-funky+home%dir'
    110        vim.filetype.add({
    111          pattern = {
    112            ['~/blog/.*%.txt'] = 'markdown',
    113          },
    114        })
    115        return vim.filetype.match({ filename = '~/blog/why_neovim_is_awesome.txt' })
    116      end)
    117    )
    118  end)
    119 
    120  it('works with functions', function()
    121    command('new')
    122    command('file relevant_to_me')
    123    eq(
    124      'foss',
    125      exec_lua(function()
    126        vim.filetype.add({
    127          pattern = {
    128            ['relevant_to_(%a+)'] = function(_, _, capture)
    129              if capture == 'me' then
    130                return 'foss'
    131              end
    132            end,
    133          },
    134        })
    135        return vim.filetype.match({ buf = 0 })
    136      end)
    137    )
    138  end)
    139 
    140  it('works with contents #22180', function()
    141    eq(
    142      'sh',
    143      exec_lua(function()
    144        -- Needs to be set so detect#sh doesn't fail
    145        vim.g.ft_ignore_pat = '\\.\\(Z\\|gz\\|bz2\\|zip\\|tgz\\)$'
    146        return (vim.filetype.match({ contents = { '#!/usr/bin/env bash' } }))
    147      end)
    148    )
    149  end)
    150 
    151  it('considers extension mappings when matching from hashbang', function()
    152    eq(
    153      'fooscript',
    154      exec_lua(function()
    155        vim.filetype.add({
    156          extension = {
    157            foo = 'fooscript',
    158          },
    159        })
    160        return vim.filetype.match({ contents = { '#!/usr/bin/env foo' } })
    161      end)
    162    )
    163  end)
    164 
    165  it('can get default option values for filetypes via vim.filetype.get_option()', function()
    166    command('filetype plugin on')
    167 
    168    for ft, opts in pairs {
    169      lua = { commentstring = '-- %s' },
    170      vim = { commentstring = '"%s' },
    171      man = { tagfunc = "v:lua.require'man'.goto_tag" },
    172      xml = { formatexpr = 'xmlformat#Format()' },
    173    } do
    174      for option, value in pairs(opts) do
    175        eq(
    176          value,
    177          exec_lua(function()
    178            return vim.filetype.get_option(ft, option)
    179          end)
    180        )
    181      end
    182    end
    183  end)
    184 
    185  it('.get_option() cleans up buffer on error', function()
    186    api.nvim_create_autocmd('FileType', { pattern = 'foo', command = 'lua error()' })
    187 
    188    local buf = api.nvim_get_current_buf()
    189 
    190    exec_lua(function()
    191      pcall(vim.filetype.get_option, 'foo', 'lisp')
    192    end)
    193 
    194    eq(buf, api.nvim_get_current_buf())
    195  end)
    196 
    197  it('matches full paths', function()
    198    mkdir('Xfiletype')
    199    command('lcd Xfiletype')
    200    eq(
    201      'Xfiletype',
    202      exec_lua(function()
    203        vim.filetype.add({
    204          pattern = {
    205            ['.*/Xfiletype/Xfilename'] = 'Xfiletype',
    206          },
    207        })
    208        return vim.filetype.match({ filename = 'Xfilename' })
    209      end)
    210    )
    211    rmdir('Xfiletype')
    212  end)
    213 
    214  it('fallback to conf if any of the first five lines start with a #', function()
    215    eq(
    216      { 'conf', true },
    217      exec_lua(function()
    218        local bufnr = vim.api.nvim_create_buf(true, false)
    219        local lines = {
    220          '# foo',
    221        }
    222        vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, lines)
    223 
    224        -- Needs to be set so detect.conf() doesn't fail
    225        vim.g.ft_ignore_pat = '\\.\\(Z\\|gz\\|bz2\\|zip\\|tgz\\)$'
    226 
    227        local ft, _, fallback = vim.filetype.match({ buf = bufnr })
    228        return { ft, fallback }
    229      end)
    230    )
    231  end)
    232 end)
    233 
    234 describe('filetype.lua', function()
    235  before_each(function()
    236    mkdir('Xfiletype')
    237  end)
    238 
    239  after_each(function()
    240    rmdir('Xfiletype')
    241  end)
    242 
    243  it('does not override user autocommands that set filetype #20333', function()
    244    clear({
    245      args = { '--clean', '--cmd', 'autocmd BufRead *.md set filetype=notmarkdown', 'README.md' },
    246    })
    247    eq('notmarkdown', api.nvim_get_option_value('filetype', {}))
    248  end)
    249 
    250  it('uses unexpanded path for matching when editing a symlink #27914', function()
    251    mkdir('Xfiletype/.config')
    252    mkdir('Xfiletype/actual')
    253    write_file('Xfiletype/actual/config', '')
    254    uv.fs_symlink(assert(uv.fs_realpath('Xfiletype/actual')), 'Xfiletype/.config/git')
    255    finally(function()
    256      uv.fs_unlink('Xfiletype/.config/git')
    257    end)
    258    local args = { '--clean', 'Xfiletype/.config/git/config' }
    259    clear({ args = args })
    260    eq('gitconfig', api.nvim_get_option_value('filetype', {}))
    261    table.insert(args, 2, '--cmd')
    262    table.insert(args, 3, "autocmd BufRead * call expand('<afile>')")
    263    clear({ args = args })
    264    eq('gitconfig', api.nvim_get_option_value('filetype', {}))
    265  end)
    266 
    267  it('works with :doautocmd BufRead #31306', function()
    268    clear({ args = { '--clean' } })
    269    eq('', api.nvim_get_option_value('filetype', {}))
    270    command('doautocmd BufRead README.md')
    271    eq('markdown', api.nvim_get_option_value('filetype', {}))
    272  end)
    273 end)