3 vis
.ftdetect
.ignoresuffixes
= {
4 "~$", "%.orig$", "%.bak$", "%.old$", "%.new$"
7 vis
.ftdetect
.filetypes
= {
9 ext
= { "%.as$", "%.asc$" },
12 ext
= { "%.adb$", "%.ads$" },
15 ext
= { "%.c$", "%.C$", "%.h$" },
16 mime
= { "text/x-c" },
19 ext
= { "%.g$", "%.g4$" },
22 ext
= { "%.ans$", "%.inp$", "%.mac$" },
28 ext
= { "%.applescript$" },
31 ext
= { "%.asm$", "%.ASM$", "%.s$", "%.S$" },
34 ext
= { "%.asa$", "%.asp$", "%.hta$" },
37 ext
= { "%.au3$", "%.a3x$" },
43 ext
= { "%.bash$", "%.csh$", "%.sh$", "%.zsh$" ,"^APKBUILD$", "%.ebuild$"},
44 mime
= { "text/x-shellscript", "application/x-shellscript" },
47 ext
= { "%.bat$", "%.cmd$" },
56 ext
= { "%.caml$", "%.ml$", "%.mli$", "%.mll$", "%.mly$" },
62 ext
= { "%.clj$", "%.cljc$", "%.cljs$", "%.edn$" }
65 ext
= { "%.cmake$", "%.cmake.in$", "%.ctest$", "%.ctest.in$" },
68 ext
= { "%.coffee$" },
69 mime
= { "text/x-coffee" },
72 ext
= { "%.cpp$", "%.cxx$", "%.c++$", "%.cc$", "%.hh$", "%.hpp$", "%.hxx$", "%.h++$" },
73 mime
= { "text/x-c++" },
76 ext
= { "^crontab.*$" },
77 cmd
= { "set savemethod inplace" },
87 mime
= { "text/x-css" },
90 ext
= { "%.cu$", "%.cuh$" },
96 ext
= { "%.desktop$" },
99 ext
= { "%.diff$", "%.patch$", "%.rej$" },
102 ext
= { "%.d$", "%.di$" },
105 ext
= { "^Dockerfile$", "%.Dockerfile$" },
111 ext
= { "^group$", "^gshadow$", "^passwd$", "^shadow$" },
114 ext
= { "%.e$", "%.eif$" },
117 ext
= { "%.ex$", "%.exs$" },
123 ext
= { "%.erl$", "%.hrl$" },
138 ext
= { "%.forth$", "%.frt$", "%.fs$", "%.fth$" },
141 ext
= { "%.f$", "%.for$", "%.ftn$", "%.fpp$", "%.f77$", "%.f90$", "%.f95$", "%.f03$", "%.f08$" },
150 ext
= { "%.g$", "%.gd$", "%.gi$", "%.gap$" },
154 mime
= { "text/gemini" },
157 ext
= { "%.po$", "%.pot$" },
160 ext
= { "%.feature$" },
163 ext
= { "^COMMIT_EDITMSG$" },
164 cmd
= { "set colorcolumn 72" },
167 ext
= { "git%-rebase%-todo" },
170 ext
= { "%.glslf$", "%.glslv$" },
173 ext
= { "%.dem$", "%.plt$" },
179 ext
= { "%.groovy$", "%.gvy$", "^Jenkinsfile$" },
182 ext
= { "%.gtkrc$" },
186 mime
= { "text/x-haskell" },
189 ext
= { "%.htm$", "%.html$", "%.shtm$", "%.shtml$", "%.xhtml$" },
190 mime
= { "text/x-html" },
196 ext
= { "%.idl$", "%.odl$" },
199 ext
= { "%.inf$", "%.ni$" },
202 ext
= { "%.cfg$", "%.cnf$", "%.conf$", "%.inf$", "%.ini$", "%.reg$" },
208 ext
= { "%.bsh$", "%.java$" },
211 ext
= { "%.cjs$", "%.js$", "%.jsfl$", "%.mjs$", "%.ts$" },
215 mime
= { "text/x-json" },
224 ext
= { "%.bbl$", "%.cls$", "%.dtx$", "%.ins$", "%.ltx$", "%.tex$", "%.sty$" },
225 mime
= { "text/x-tex" },
228 ext
= { "%.ledger$", "%.journal$" },
234 ext
= { "%.ily$", "%.ly$" },
237 ext
= { "%.cl$", "%.el$", "%.lisp$", "%.lsp$" },
238 mime
= { "text/x-lisp" },
241 ext
= { "%.litcoffee$" },
248 mime
= { "text/x-lua" },
251 ext
= { "%.iface$", "%.mak$", "%.mk$", "GNUmakefile", "makefile", "Makefile" },
252 mime
= { "text/x-makefile" },
253 detect
= function(_
, data
)
254 return data
:match("^#!/usr/bin/make")
259 "%.1$", "%.2$", "%.3$", "%.4$", "%.5$", "%.6$", "%.7$",
260 "%.8$", "%.9$", "%.1x$", "%.2x$", "%.3x$", "%.4x$",
261 "%.5x$", "%.6x$", "%.7x$", "%.8x$", "%.9x$"
265 ext
= { "%.md$", "%.markdown$" },
266 mime
= { "text/x-markdown" },
269 ext
= { "^meson%.build$" },
273 mime
= { "text/x-moon" },
282 ext
= { "%.link$", "%.network$", "%.netdev$" },
288 ext
= { "%.nsh$", "%.nsi$", "%.nsis$" },
291 ext
= { "%.m$", "%.mm$", "%.objc$" },
292 mime
= { "text/x-objc" },
295 ext
= { "%.dpk$", "%.dpr$", "%.p$", "%.pas$" },
298 ext
= { "%.al$", "%.perl$", "%.pl$", "%.pm$", "%.pod$" },
299 mime
= { "text/x-perl" },
302 ext
= { "%.inc$", "%.php$", "%.php3$", "%.php4$", "%.phtml$" },
308 ext
= { "%.pike$", "%.pmod$" },
311 ext
= { "^PKGBUILD$" },
320 ext
= { "%.pl$", "%.pro$", "%.prolog$" },
323 ext
= { "%.props$", "%.properties$" },
326 ext
= { "%.proto$" },
329 ext
= { "%.eps$", "%.ps$" },
335 ext
= { "%.sc$", "%.py$", "%.pyw$" },
336 mime
= { "text/x-python" },
342 ext
= { "%.rc$", "%.es$" },
345 ext
= { "%.r$", "%.reb$" },
351 ext
= { "%.orx$", "%.rex$" },
354 ext
= { "%.erb$", "%.rhtml$" },
358 detect
= function(_
, data
)
359 return data
:match("^#.* by RouterOS")
363 ext
= { "%.R$", "%.Rout$", "%.Rhistory$", "%.Rt$", "Rout.save", "Rout.fail" },
366 ext
= { "%.Rakefile$", "%.rake$", "%.rb$", "%.rbw$", "^Vagrantfile$" },
367 mime
= { "text/x-ruby" },
371 mime
= { "text/x-rust" },
374 ext
= { "%.sass$", "%.scss$" },
375 mime
= { "text/x-sass", "text/x-scss" },
378 ext
= { "%.scala$" },
379 mime
= { "text/x-scala" },
382 ext
= { "%.rkt$", "%.sch$", "%.scm$", "%.sld$", "%.sls$", "%.ss$" },
385 ext
= { "%.changes$", "%.st$", "%.sources$" },
388 ext
= { "%.sml$", "%.fun$", "%.sig$" },
391 ext
= { "%.sno$", "%.SNO$" },
397 ext
= { "%.ddl$", "%.sql$" },
400 detect
= function(_
, data
)
401 return data
:match("^execve%(")
406 "%.automount$", "%.device$", "%.mount$", "%.path$",
407 "%.scope$", "%.service$", "%.slice$", "%.socket$",
408 "%.swap$", "%.target$", "%.timer$"
412 ext
= { "%.taskpaper$" },
415 ext
= { "%.tcl$", "%.tk$" },
422 -- Do *not* list mime "text/plain" here, it is covered below,
423 -- see 'try text lexer as a last resort'
433 "%.asa$", "%.bas$", "%.ctl$", "%.dob$",
434 "%.dsm$", "%.dsr$", "%.frm$", "%.pag$", "%.vb$",
439 ext
= { "%.vcf$", "%.vcard$" },
442 ext
= { "%.v$", "%.ver$", "%.sv$" },
445 ext
= { "%.vh$", "%.vhd$", "%.vhdl$" },
451 ext
= { "%.xs$", "^%.xsin$", "^%.xsrc$" },
454 ext
= { "%.dtd$", "%.plist$", "%.svg$", "%.xml$", "%.xsd$", "%.xsl$", "%.xslt$", "%.xul$" },
460 ext
= { "%.yaml$", "%.yml$" },
461 mime
= { "text/x-yaml" },
468 vis
.events
.subscribe(vis
.events
.WIN_OPEN
, function(win
)
470 local set_filetype
= function(syntax
, filetype
)
471 for _
, cmd
in pairs(filetype
.cmd
or {}) do
474 win
:set_syntax(syntax
)
477 local name
= win
.file
.name
478 -- remove ignored suffixes from filename
479 local sanitizedfn
= name
480 if sanitizedfn
~= nil then
481 sanitizedfn
= sanitizedfn
:gsub('^.*/', '')
483 local changed
= false
484 for _
, pattern
in pairs(vis
.ftdetect
.ignoresuffixes
) do
485 local start
= sanitizedfn
:find(pattern
)
487 sanitizedfn
= sanitizedfn
:sub(1, start
-1)
494 -- detect filetype by filename ending with a configured extension
495 if sanitizedfn
~= nil then
496 for lang
, ft
in pairs(vis
.ftdetect
.filetypes
) do
497 for _
, pattern
in pairs(ft
.ext
or {}) do
498 if sanitizedfn
:match(pattern
) then
499 set_filetype(lang
, ft
)
506 -- run file(1) to determine mime type
509 local file
= io
.popen(string.format("file -bL --mime-type -- '%s'", name
:gsub("'", "'\\''")))
511 mime
= file
:read('*all')
514 mime
= mime
:gsub('%s*$', '')
516 if mime
and #mime
> 0 then
517 for lang
, ft
in pairs(vis
.ftdetect
.filetypes
) do
518 for _
, ft_mime
in pairs(ft
.mime
or {}) do
519 if mime
== ft_mime
then
520 set_filetype(lang
, ft
)
529 -- pass first few bytes of file to custom file type detector functions
530 local file
= win
.file
531 local data
= file
:content(0, 256)
532 if data
and #data
> 0 then
533 for lang
, ft
in pairs(vis
.ftdetect
.filetypes
) do
534 if type(ft
.detect
) == 'function' and ft
.detect(file
, data
) then
535 set_filetype(lang
, ft
)
541 -- try text lexer as a last resort
542 if (mime
or 'text/plain'):match('^text/.+$') then
543 set_filetype('text', vis
.ftdetect
.filetypes
.text
)