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)