diff options
-rw-r--r-- | runtime/autoload/dist/ft.vim | 71 | ||||
-rw-r--r-- | runtime/doc/filetype.txt | 2 | ||||
-rw-r--r-- | runtime/filetype.vim | 34 | ||||
-rw-r--r-- | runtime/lua/vim/filetype.lua | 7 | ||||
-rw-r--r-- | src/nvim/testdir/test_filetype.vim | 191 |
5 files changed, 276 insertions, 29 deletions
diff --git a/runtime/autoload/dist/ft.vim b/runtime/autoload/dist/ft.vim index f473d5f80b..0063e9da0b 100644 --- a/runtime/autoload/dist/ft.vim +++ b/runtime/autoload/dist/ft.vim @@ -112,6 +112,25 @@ func dist#ft#BindzoneCheck(default) endif endfunc +" Returns true if file content looks like RAPID +func IsRapid(sChkExt = "") + if a:sChkExt == "cfg" + return getline(1) =~? '\v^%(EIO|MMC|MOC|PROC|SIO|SYS):CFG' + endif + " called from FTmod, FTprg or FTsys + return getline(nextnonblank(1)) =~? '\v^\s*%(\%{3}|module\s+\k+\s*%(\(|$))' +endfunc + +func dist#ft#FTcfg() + if exists("g:filetype_cfg") + exe "setf " .. g:filetype_cfg + elseif IsRapid("cfg") + setf rapid + else + setf cfg + endif +endfunc + func dist#ft#FTlpc() if exists("g:lpc_syntax_for_c") let lnum = 1 @@ -173,7 +192,7 @@ endfunc func dist#ft#FTent() " This function checks for valid cl syntax in the first five lines. - " Look for either an opening comment, '#', or a block start, '{". + " Look for either an opening comment, '#', or a block start, '{'. " If not found, assume SGML. let lnum = 1 while lnum < 6 @@ -415,6 +434,36 @@ func dist#ft#FTmm() setf nroff endfunc +" Returns true if file content looks like LambdaProlog +func IsLProlog() + " skip apparent comments and blank lines, what looks like + " LambdaProlog comment may be RAPID header + let l = nextnonblank(1) + while l > 0 && l < line('$') && getline(l) =~ '^\s*%' " LambdaProlog comment + let l = nextnonblank(l + 1) + endwhile + " this pattern must not catch a go.mod file + return getline(l) =~ '\<module\s\+\w\+\s*\.\s*\(%\|$\)' +endfunc + +" Determine if *.mod is ABB RAPID, LambdaProlog, Modula-2, Modsim III or go.mod +func dist#ft#FTmod() + if exists("g:filetype_mod") + exe "setf " .. g:filetype_mod + elseif IsLProlog() + setf lprolog + elseif getline(nextnonblank(1)) =~ '\%(\<MODULE\s\+\w\+\s*;\|^\s*(\*\)' + setf modula2 + elseif IsRapid() + setf rapid + elseif expand("<afile>") =~ '\<go.mod$' + setf gomod + else + " Nothing recognized, assume modsim3 + setf modsim3 + endif +endfunc + func dist#ft#FTpl() if exists("g:filetype_pl") exe "setf " . g:filetype_pl @@ -531,6 +580,18 @@ func dist#ft#FTpp() endif endfunc +" Determine if *.prg is ABB RAPID. Can also be Clipper, FoxPro or eviews +func dist#ft#FTprg() + if exists("g:filetype_prg") + exe "setf " .. g:filetype_prg + elseif IsRapid() + setf rapid + else + " Nothing recognized, assume Clipper + setf clipper + endif +endfunc + func dist#ft#FTr() let max = line("$") > 50 ? 50 : line("$") @@ -739,6 +800,14 @@ func dist#ft#FTperl() return 0 endfunc +func dist#ft#FTsys() + if IsRapid() + setf rapid + else + setf bat + endif +endfunc + " Choose context, plaintex, or tex (LaTeX) based on these rules: " 1. Check the first line of the file for "%&<format>". " 2. Check the first 1000 non-comment lines for LaTeX or ConTeXt keywords. diff --git a/runtime/doc/filetype.txt b/runtime/doc/filetype.txt index 357c5d1cec..5f7c1b57f8 100644 --- a/runtime/doc/filetype.txt +++ b/runtime/doc/filetype.txt @@ -140,12 +140,14 @@ variables can be used to overrule the filetype used for certain extensions: *.asm g:asmsyntax |ft-asm-syntax| *.asp g:filetype_asp |ft-aspvbs-syntax| |ft-aspperl-syntax| *.bas g:filetype_bas |ft-basic-syntax| + *.cfg g:filetype_cfg *.dat g:filetype_dat *.frm g:filetype_frm |ft-form-syntax| *.fs g:filetype_fs |ft-forth-syntax| *.i g:filetype_i |ft-progress-syntax| *.inc g:filetype_inc *.m g:filetype_m |ft-mathematica-syntax| + *.mod g:filetype_mod *.p g:filetype_p |ft-pascal-syntax| *.pl g:filetype_pl *.pp g:filetype_pp |ft-pascal-syntax| diff --git a/runtime/filetype.vim b/runtime/filetype.vim index 255414aca6..e0d24d73c8 100644 --- a/runtime/filetype.vim +++ b/runtime/filetype.vim @@ -201,11 +201,13 @@ au BufNewFile,BufRead *.iba,*.ibi setf ibasic " FreeBasic file (similar to QBasic) au BufNewFile,BufRead *.fb setf freebasic -" Batch file for MSDOS. -au BufNewFile,BufRead *.bat,*.sys setf dosbatch +" Batch file for MSDOS. See dist#ft#FTsys for *.sys +au BufNewFile,BufRead *.bat setf dosbatch " *.cmd is close to a Batch file, but on OS/2 Rexx files also use *.cmd. au BufNewFile,BufRead *.cmd \ if getline(1) =~ '^/\*' | setf rexx | else | setf dosbatch | endif +" ABB RAPID or Batch file for MSDOS. +au BufNewFile,BufRead *.sys\c call dist#ft#FTsys() " Batch file for 4DOS au BufNewFile,BufRead *.btm call dist#ft#FTbtm() @@ -356,13 +358,8 @@ au BufNewFile,BufRead *.eni setf cl " Clever or dtd au BufNewFile,BufRead *.ent call dist#ft#FTent() -" Clipper (or FoxPro; could also be eviews) -au BufNewFile,BufRead *.prg - \ if exists("g:filetype_prg") | - \ exe "setf " . g:filetype_prg | - \ else | - \ setf clipper | - \ endif +" Clipper, FoxPro, ABB RAPID or eviews +au BufNewFile,BufRead *.prg\c call dist#ft#FTprg() " Clojure au BufNewFile,BufRead *.clj,*.cljs,*.cljx,*.cljc setf clojure @@ -440,7 +437,7 @@ au BufNewFile,BufRead *quake[1-3]/*.cfg setf quake au BufNewFile,BufRead *.qc setf c " Configure files -au BufNewFile,BufRead *.cfg setf cfg +au BufNewFile,BufRead *.cfg\c call dist#ft#FTcfg() " Cucumber au BufNewFile,BufRead *.feature setf cucumber @@ -976,7 +973,7 @@ au BufNewFile,BufRead *.latte,*.lte setf latte " Limits au BufNewFile,BufRead */etc/limits,*/etc/*limits.conf,*/etc/*limits.d/*.conf setf limits -" LambdaProlog (*.mod too, see Modsim) +" LambdaProlog (see dist#ft#FTmod for *.mod) au BufNewFile,BufRead *.sig setf lprolog " LDAP LDIF @@ -1139,18 +1136,11 @@ au BufNewFile,BufRead *.mms call dist#ft#FTmms() " Symbian meta-makefile definition (MMP) au BufNewFile,BufRead *.mmp setf mmp -" Modsim III (or LambdaProlog) -au BufNewFile,BufRead *.mod - \ if expand("<afile>") =~ '\<go.mod$' | - \ setf gomod | - \ elseif getline(1) =~ '\<module\>' | - \ setf lprolog | - \ else | - \ setf modsim3 | - \ endif +" ABB Rapid, Modula-2, Modsim III or LambdaProlog +au BufNewFile,BufRead *.mod\c call dist#ft#FTmod() -" Modula-2 (.md removed in favor of Markdown) -au BufNewFile,BufRead *.m2,*.DEF,*.MOD,*.mi setf modula2 +" Modula-2 (.md removed in favor of Markdown, see dist#ft#FTmod for *.MOD) +au BufNewFile,BufRead *.m2,*.DEF,*.mi setf modula2 " Modula-3 (.m3, .i3, .mg, .ig) au BufNewFile,BufRead *.[mi][3g] setf modula3 diff --git a/runtime/lua/vim/filetype.lua b/runtime/lua/vim/filetype.lua index 7958de97b1..9397788e9e 100644 --- a/runtime/lua/vim/filetype.lua +++ b/runtime/lua/vim/filetype.lua @@ -79,7 +79,6 @@ local extension = { cfc = "cf", cfm = "cf", cfi = "cf", - cfg = "cfg", hgrc = "cfg", chf = "ch", chai = "chaiscript", @@ -158,7 +157,6 @@ local extension = { diff = "diff", rej = "diff", Dockerfile = "dockerfile", - sys = "dosbatch", bat = "dosbatch", wrap = "dosini", ini = "dosini", @@ -395,7 +393,6 @@ local extension = { mmp = "mmp", DEF = "modula2", ["m2"] = "modula2", - MOD = "modula2", mi = "modula2", ssc = "monk", monk = "monk", @@ -1429,9 +1426,13 @@ local pattern = { return "git" end end, + [".*%.[Cc][Ff][Gg]"] = function() vim.fn["dist#ft#FTcfg"]() end, [".*%.[Dd][Aa][Tt]"] = function() vim.fn["dist#ft#FTdat"]() end, + [".*%.[Mm][Oo][Dd]"] = function() vim.fn["dist#ft#FTmod"]() end, [".*%.[Ss][Rr][Cc]"] = function() vim.fn["dist#ft#FTsrc"]() end, [".*%.[Ss][Uu][Bb]"] = "krl", + [".*%.[Pp][Rr][Gg]"] = function() vim.fn["dist#ft#FTprg"]() end, + [".*%.[Ss][Yy][Ss]"] = function() vim.fn["dist#ft#FTsys"]() end, -- Neovim only [".*/queries/.*%.scm"] = "query", -- tree-sitter queries -- END PATTERN diff --git a/src/nvim/testdir/test_filetype.vim b/src/nvim/testdir/test_filetype.vim index 9feab735e4..1f76063aed 100644 --- a/src/nvim/testdir/test_filetype.vim +++ b/src/nvim/testdir/test_filetype.vim @@ -99,7 +99,7 @@ let s:filename_checks = { \ 'cdrtoc': ['file.toc'], \ 'cf': ['file.cfm', 'file.cfi', 'file.cfc'], \ 'cfengine': ['cfengine.conf'], - \ 'cfg': ['file.cfg', 'file.hgrc', 'filehgrc', 'hgrc', 'some-hgrc'], + \ 'cfg': ['file.hgrc', 'filehgrc', 'hgrc', 'some-hgrc'], \ 'ch': ['file.chf'], \ 'chaiscript': ['file.chai'], \ 'chaskell': ['file.chs'], @@ -150,7 +150,7 @@ let s:filename_checks = { \ 'dircolors': ['.dir_colors', '.dircolors', '/etc/DIR_COLORS', 'any/etc/DIR_COLORS'], \ 'dnsmasq': ['/etc/dnsmasq.conf', '/etc/dnsmasq.d/file', 'any/etc/dnsmasq.conf', 'any/etc/dnsmasq.d/file'], \ 'dockerfile': ['Containerfile', 'Dockerfile', 'file.Dockerfile', 'Dockerfile.debian', 'Containerfile.something'], - \ 'dosbatch': ['file.bat', 'file.sys'], + \ 'dosbatch': ['file.bat'], \ 'dosini': ['.editorconfig', '/etc/pacman.conf', '/etc/yum.conf', 'file.ini', 'npmrc', '.npmrc', 'php.ini', 'php.ini-5', 'php.ini-file', '/etc/yum.repos.d/file', 'any/etc/pacman.conf', 'any/etc/yum.conf', 'any/etc/yum.repos.d/file', 'file.wrap'], \ 'dot': ['file.dot', 'file.gv'], \ 'dracula': ['file.drac', 'file.drc', 'filelvs', 'filelpe', 'drac.file', 'lpe', 'lvs', 'some-lpe', 'some-lvs'], @@ -615,7 +615,7 @@ let s:filename_checks = { \ } let s:filename_case_checks = { - \ 'modula2': ['file.DEF', 'file.MOD'], + \ 'modula2': ['file.DEF'], \ 'bzl': ['file.BUILD', 'BUILD'], \ } @@ -807,6 +807,36 @@ func Test_bas_file() filetype off endfunc +" Test dist#ft#FTcfg() +func Test_cfg_file() + filetype on + + " *.cfg defaults to cfg + call writefile(['looks like cfg'], 'cfgfile.cfg') + split cfgfile.cfg + call assert_equal('cfg', &filetype) + + let g:filetype_cfg = 'other' + edit + call assert_equal('other', &filetype) + bwipe! + unlet g:filetype_cfg + + " RAPID cfg + let ext = 'cfg' + for i in ['EIO', 'MMC', 'MOC', 'PROC', 'SIO', 'SYS'] + call writefile([i .. ':CFG'], 'cfgfile.' .. ext) + execute "split cfgfile." .. ext + call assert_equal('rapid', &filetype) + bwipe! + call delete('cfgfile.' .. ext) + " check different case of file extension + let ext = substitute(ext, '\(\l\)', '\u\1', '') + endfor + + filetype off +endfunc + func Test_d_file() filetype on @@ -1241,6 +1271,81 @@ func Test_m_file() filetype off endfunc +func Test_mod_file() + filetype on + + " *.mod defaults to Modsim III + call writefile(['locks like Modsim III'], 'modfile.mod') + split modfile.mod + call assert_equal('modsim3', &filetype) + bwipe! + + " Users preference set by g:filetype_mod + let g:filetype_mod = 'lprolog' + split modfile.mod + call assert_equal('lprolog', &filetype) + unlet g:filetype_mod + bwipe! + + " RAPID header start with a line containing only "%%%", + " but is not always present. + call writefile(['%%%'], 'modfile.mod') + split modfile.mod + call assert_equal('rapid', &filetype) + bwipe! + call delete('modfile.mod') + + " RAPID supports umlauts in module names, leading spaces, + " the .mod extension is not case sensitive. + call writefile([' module ÜmlautModule'], 'modfile.Mod') + split modfile.Mod + call assert_equal('rapid', &filetype) + bwipe! + call delete('modfile.Mod') + + " RAPID is not case sensitive, embedded spaces, sysmodule, + " file starts with empty line(s). + call writefile(['', 'MODULE rapidmödüle (SYSMODULE,NOSTEPIN)'], 'modfile.MOD') + split modfile.MOD + call assert_equal('rapid', &filetype) + bwipe! + + " Modula-2 MODULE not start of line + call writefile(['IMPLEMENTATION MODULE Module2Mod;'], 'modfile.MOD') + split modfile.MOD + call assert_equal('modula2', &filetype) + bwipe! + + " Modula-2 with comment and empty lines prior MODULE + call writefile(['', '(* with', ' comment *)', '', 'MODULE Module2Mod;'], 'modfile.MOD') + split modfile.MOD + call assert_equal('modula2', &filetype) + bwipe! + call delete('modfile.MOD') + + " LambdaProlog module + call writefile(['module lpromod.'], 'modfile.mod') + split modfile.mod + call assert_equal('lprolog', &filetype) + bwipe! + + " LambdaProlog with comment and empty lines prior module + call writefile(['', '% with', '% comment', '', 'module lpromod.'], 'modfile.mod') + split modfile.mod + call assert_equal('lprolog', &filetype) + bwipe! + call delete('modfile.mod') + + " go.mod + call writefile(['module example.com/M'], 'go.mod') + split go.mod + call assert_equal('gomod', &filetype) + bwipe! + call delete('go.mod') + + filetype off +endfunc + func Test_patch_file() filetype on @@ -1309,6 +1414,50 @@ func Test_pp_file() filetype off endfunc +" Test dist#ft#FTprg() +func Test_prg_file() + filetype on + + " *.prg defaults to clipper + call writefile(['looks like clipper'], 'prgfile.prg') + split prgfile.prg + call assert_equal('clipper', &filetype) + bwipe! + + " Users preference set by g:filetype_prg + let g:filetype_prg = 'eviews' + split prgfile.prg + call assert_equal('eviews', &filetype) + unlet g:filetype_prg + bwipe! + + " RAPID header start with a line containing only "%%%", + " but is not always present. + call writefile(['%%%'], 'prgfile.prg') + split prgfile.prg + call assert_equal('rapid', &filetype) + bwipe! + call delete('prgfile.prg') + + " RAPID supports umlauts in module names, leading spaces, + " the .prg extension is not case sensitive. + call writefile([' module ÜmlautModule'], 'prgfile.Prg') + split prgfile.Prg + call assert_equal('rapid', &filetype) + bwipe! + call delete('prgfile.Prg') + + " RAPID is not case sensitive, embedded spaces, sysmodule, + " file starts with empty line(s). + call writefile(['', 'MODULE rapidmödüle (SYSMODULE,NOSTEPIN)'], 'prgfile.PRG') + split prgfile.PRG + call assert_equal('rapid', &filetype) + bwipe! + call delete('prgfile.PRG') + + filetype off +endfunc + func Test_src_file() filetype on @@ -1333,6 +1482,42 @@ func Test_src_file() filetype off endfunc +func Test_sys_file() + filetype on + + " *.sys defaults to Batch file for MSDOS + call writefile(['looks like dos batch'], 'sysfile.sys') + split sysfile.sys + call assert_equal('bat', &filetype) + bwipe! + + " RAPID header start with a line containing only "%%%", + " but is not always present. + call writefile(['%%%'], 'sysfile.sys') + split sysfile.sys + call assert_equal('rapid', &filetype) + bwipe! + call delete('sysfile.sys') + + " RAPID supports umlauts in module names, leading spaces, + " the .sys extension is not case sensitive. + call writefile([' module ÜmlautModule'], 'sysfile.Sys') + split sysfile.Sys + call assert_equal('rapid', &filetype) + bwipe! + call delete('sysfile.Sys') + + " RAPID is not case sensitive, embedded spaces, sysmodule, + " file starts with empty line(s). + call writefile(['', 'MODULE rapidmödüle (SYSMODULE,NOSTEPIN)'], 'sysfile.SYS') + split sysfile.SYS + call assert_equal('rapid', &filetype) + bwipe! + call delete('sysfile.SYS') + + filetype off +endfunc + func Test_tex_file() filetype on |