diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-10 20:09:20 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-10 20:09:20 +0000 |
commit | 029f72b1a93430b24b88eb3a72c6114d9f149737 (patch) | |
tree | 765d5c2041967f9c6fef195fe343d9234a030e90 /runtime/autoload/dist/ft.vim | |
parent | Initial commit. (diff) | |
download | vim-029f72b1a93430b24b88eb3a72c6114d9f149737.tar.xz vim-029f72b1a93430b24b88eb3a72c6114d9f149737.zip |
Adding upstream version 2:9.1.0016.upstream/2%9.1.0016
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'runtime/autoload/dist/ft.vim')
-rw-r--r-- | runtime/autoload/dist/ft.vim | 1296 |
1 files changed, 1296 insertions, 0 deletions
diff --git a/runtime/autoload/dist/ft.vim b/runtime/autoload/dist/ft.vim new file mode 100644 index 0000000..9d0f2ee --- /dev/null +++ b/runtime/autoload/dist/ft.vim @@ -0,0 +1,1296 @@ +vim9script + +# Vim functions for file type detection +# +# Maintainer: The Vim Project <https://github.com/vim/vim> +# Last Change: 2024 Jan 05 +# Former Maintainer: Bram Moolenaar <Bram@vim.org> + +# These functions are moved here from runtime/filetype.vim to make startup +# faster. + +export def Check_inp() + if getline(1) =~ '^\*' + setf abaqus + else + var n = 1 + var nmax = line("$") > 500 ? 500 : line("$") + while n <= nmax + if getline(n) =~? "^header surface data" + setf trasys + break + endif + n += 1 + endwhile + endif +enddef + +# This function checks for the kind of assembly that is wanted by the user, or +# can be detected from the first five lines of the file. +export def FTasm() + # make sure b:asmsyntax exists + if !exists("b:asmsyntax") + b:asmsyntax = "" + endif + + if b:asmsyntax == "" + FTasmsyntax() + endif + + # if b:asmsyntax still isn't set, default to asmsyntax or GNU + if b:asmsyntax == "" + if exists("g:asmsyntax") + b:asmsyntax = g:asmsyntax + else + b:asmsyntax = "asm" + endif + endif + + exe "setf " .. fnameescape(b:asmsyntax) +enddef + +export def FTasmsyntax() + # see if the file contains any asmsyntax=foo overrides. If so, change + # b:asmsyntax appropriately + var head = " " .. getline(1) .. " " .. getline(2) .. " " + .. getline(3) .. " " .. getline(4) .. " " .. getline(5) .. " " + var match = matchstr(head, '\sasmsyntax=\zs[a-zA-Z0-9]\+\ze\s') + if match != '' + b:asmsyntax = match + elseif ((head =~? '\.title') || (head =~? '\.ident') || (head =~? '\.macro') || (head =~? '\.subtitle') || (head =~? '\.library')) + b:asmsyntax = "vmasm" + endif +enddef + +var ft_visual_basic_content = '\c^\s*\%(Attribute\s\+VB_Name\|Begin\s\+\%(VB\.\|{\%(\x\+-\)\+\x\+}\)\)' + +# See FTfrm() for Visual Basic form file detection +export def FTbas() + if exists("g:filetype_bas") + exe "setf " .. g:filetype_bas + return + endif + + # most frequent FreeBASIC-specific keywords in distro files + var fb_keywords = '\c^\s*\%(extern\|var\|enum\|private\|scope\|union\|byref\|operator\|constructor\|delete\|namespace\|public\|property\|with\|destructor\|using\)\>\%(\s*[:=(]\)\@!' + var fb_preproc = '\c^\s*\%(' .. + # preprocessor + '#\s*\a\+\|' .. + # compiler option + 'option\s\+\%(byval\|dynamic\|escape\|\%(no\)\=gosub\|nokeyword\|private\|static\)\>\|' .. + # metacommand + '\%(''\|rem\)\s*\$lang\>\|' .. + # default datatype + 'def\%(byte\|longint\|short\|ubyte\|uint\|ulongint\|ushort\)\>' .. + '\)' + var fb_comment = "^\\s*/'" + + # OPTION EXPLICIT, without the leading underscore, is common to many dialects + var qb64_preproc = '\c^\s*\%($\a\+\|option\s\+\%(_explicit\|_\=explicitarray\)\>\)' + + for lnum in range(1, min([line("$"), 100])) + var line = getline(lnum) + if line =~ ft_visual_basic_content + setf vb + return + elseif line =~ fb_preproc || line =~ fb_comment || line =~ fb_keywords + setf freebasic + return + elseif line =~ qb64_preproc + setf qb64 + return + endif + endfor + setf basic +enddef + +export def FTbtm() + if exists("g:dosbatch_syntax_for_btm") && g:dosbatch_syntax_for_btm + setf dosbatch + else + setf btm + endif +enddef + +export def BindzoneCheck(default = '') + if getline(1) .. getline(2) .. getline(3) .. getline(4) + =~ '^; <<>> DiG [0-9.]\+.* <<>>\|$ORIGIN\|$TTL\|IN\s\+SOA' + setf bindzone + elseif default != '' + exe 'setf ' .. default + endif +enddef + +# Returns true if file content looks like RAPID +def IsRapid(sChkExt: string = ""): bool + if 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*%(\(|$))' +enddef + +export def FTcfg() + if exists("g:filetype_cfg") + exe "setf " .. g:filetype_cfg + elseif IsRapid("cfg") + setf rapid + else + setf cfg + endif +enddef + +export def FTcls() + if exists("g:filetype_cls") + exe "setf " .. g:filetype_cls + return + endif + + var line1 = getline(1) + if line1 =~ '^#!.*\<\%(rexx\|regina\)\>' + setf rexx + return + elseif line1 == 'VERSION 1.0 CLASS' + setf vb + return + endif + + var nonblank1 = getline(nextnonblank(1)) + if nonblank1 =~ '^\v%(\%|\\)' + setf tex + elseif nonblank1 =~ '^\s*\%(/\*\|::\w\)' + setf rexx + else + setf st + endif +enddef + +export def FTlpc() + if exists("g:lpc_syntax_for_c") + var lnum = 1 + while lnum <= 12 + if getline(lnum) =~# '^\(//\|inherit\|private\|protected\|nosave\|string\|object\|mapping\|mixed\)' + setf lpc + return + endif + lnum += 1 + endwhile + endif + setf c +enddef + +export def FTheader() + if match(getline(1, min([line("$"), 200])), '^@\(interface\|end\|class\)') > -1 + if exists("g:c_syntax_for_h") + setf objc + else + setf objcpp + endif + elseif exists("g:c_syntax_for_h") + setf c + elseif exists("g:ch_syntax_for_h") + setf ch + else + setf cpp + endif +enddef + +# This function checks if one of the first ten lines start with a '@'. In +# that case it is probably a change file. +# If the first line starts with # or ! it's probably a ch file. +# If a line has "main", "include", "//" or "/*" it's probably ch. +# Otherwise CHILL is assumed. +export def FTchange() + var lnum = 1 + while lnum <= 10 + if getline(lnum)[0] == '@' + setf change + return + endif + if lnum == 1 && (getline(1)[0] == '#' || getline(1)[0] == '!') + setf ch + return + endif + if getline(lnum) =~ "MODULE" + setf chill + return + endif + if getline(lnum) =~ 'main\s*(\|#\s*include\|//' + setf ch + return + endif + lnum += 1 + endwhile + setf chill +enddef + +export def FTent() + # This function checks for valid cl syntax in the first five lines. + # Look for either an opening comment, '#', or a block start, '{'. + # If not found, assume SGML. + var lnum = 1 + while lnum < 6 + var line = getline(lnum) + if line =~ '^\s*[#{]' + setf cl + return + elseif line !~ '^\s*$' + # Not a blank line, not a comment, and not a block start, + # so doesn't look like valid cl code. + break + endif + lnum += 1 + endwhile + setf dtd +enddef + +export def ExCheck() + var lines = getline(1, min([line("$"), 100])) + if exists('g:filetype_euphoria') + exe 'setf ' .. g:filetype_euphoria + elseif match(lines, '^--\|^ifdef\>\|^include\>') > -1 + setf euphoria3 + else + setf elixir + endif +enddef + +export def EuphoriaCheck() + if exists('g:filetype_euphoria') + exe 'setf ' .. g:filetype_euphoria + else + setf euphoria3 + endif +enddef + +export def DtraceCheck() + if did_filetype() + # Filetype was already detected + return + endif + var lines = getline(1, min([line("$"), 100])) + if match(lines, '^module\>\|^import\>') > -1 + # D files often start with a module and/or import statement. + setf d + elseif match(lines, '^#!\S\+dtrace\|#pragma\s\+D\s\+option\|:\S\{-}:\S\{-}:') > -1 + setf dtrace + else + setf d + endif +enddef + +export def FTdef() + if get(g:, "filetype_def", "") == "modula2" || IsModula2() + SetFiletypeModula2() + return + endif + + if exists("g:filetype_def") + exe "setf " .. g:filetype_def + else + setf def + endif +enddef + +export def FTe() + if exists('g:filetype_euphoria') + exe 'setf ' .. g:filetype_euphoria + else + var n = 1 + while n < 100 && n <= line("$") + if getline(n) =~ "^\\s*\\(<'\\|'>\\)\\s*$" + setf specman + return + endif + n += 1 + endwhile + setf eiffel + endif +enddef + +def IsForth(): bool + var first_line = nextnonblank(1) + + # SwiftForth block comment (line is usually filled with '-' or '=') or + # OPTIONAL (sometimes precedes the header comment) + if getline(first_line) =~? '^\%({\%(\s\|$\)\|OPTIONAL\s\)' + return true + endif + + var n = first_line + while n < 100 && n <= line("$") + # Forth comments and colon definitions + if getline(n) =~ '^[:(\\] ' + return true + endif + n += 1 + endwhile + return false +enddef + +# Distinguish between Forth and Fortran +export def FTf() + if exists("g:filetype_f") + exe "setf " .. g:filetype_f + elseif IsForth() + setf forth + else + setf fortran + endif +enddef + +export def FTfrm() + if exists("g:filetype_frm") + exe "setf " .. g:filetype_frm + return + endif + + if getline(1) == "VERSION 5.00" + setf vb + return + endif + + var lines = getline(1, min([line("$"), 5])) + + if match(lines, ft_visual_basic_content) > -1 + setf vb + else + setf form + endif +enddef + +# Distinguish between Forth and F# +export def FTfs() + if exists("g:filetype_fs") + exe "setf " .. g:filetype_fs + elseif IsForth() + setf forth + else + setf fsharp + endif +enddef + +# Distinguish between HTML, XHTML and Django +export def FThtml() + var n = 1 + while n < 10 && n <= line("$") + if getline(n) =~ '\<DTD\s\+XHTML\s' + setf xhtml + return + endif + if getline(n) =~ '{%\s*\(extends\|block\|load\)\>\|{#\s\+' + setf htmldjango + return + endif + n += 1 + endwhile + setf FALLBACK html +enddef + +# Distinguish between standard IDL and MS-IDL +export def FTidl() + var n = 1 + while n < 50 && n <= line("$") + if getline(n) =~ '^\s*import\s\+"\(unknwn\|objidl\)\.idl"' + setf msidl + return + endif + n += 1 + endwhile + setf idl +enddef + +# Distinguish between "default", Prolog and Cproto prototype file. +export def ProtoCheck(default: string) + # Cproto files have a comment in the first line and a function prototype in + # the second line, it always ends in ";". Indent files may also have + # comments, thus we can't match comments to see the difference. + # IDL files can have a single ';' in the second line, require at least one + # chacter before the ';'. + if getline(2) =~ '.;$' + setf cpp + else + # recognize Prolog by specific text in the first non-empty line + # require a blank after the '%' because Perl uses "%list" and "%translate" + var lnum = getline(nextnonblank(1)) + if lnum =~ '\<prolog\>' || lnum =~ '^\s*\(%\+\(\s\|$\)\|/\*\)' || lnum =~ ':-' + setf prolog + else + exe 'setf ' .. default + endif + endif +enddef + +export def FTm() + if exists("g:filetype_m") + exe "setf " .. g:filetype_m + return + endif + + # excluding end(for|function|if|switch|while) common to Murphi + var octave_block_terminators = '\<end\%(_try_catch\|classdef\|enumeration\|events\|methods\|parfor\|properties\)\>' + + var objc_preprocessor = '^\s*#\s*\%(import\|include\|define\|if\|ifn\=def\|undef\|line\|error\|pragma\)\>' + + var n = 1 + var saw_comment = 0 # Whether we've seen a multiline comment leader. + while n < 100 + var line = getline(n) + if line =~ '^\s*/\*' + # /* ... */ is a comment in Objective C and Murphi, so we can't conclude + # it's either of them yet, but track this as a hint in case we don't see + # anything more definitive. + saw_comment = 1 + endif + if line =~ '^\s*//' || line =~ '^\s*@import\>' || line =~ objc_preprocessor + setf objc + return + endif + if line =~ '^\s*\%(#\|%!\)' || line =~ '^\s*unwind_protect\>' || + \ line =~ '\%(^\|;\)\s*' .. octave_block_terminators + setf octave + return + endif + # TODO: could be Matlab or Octave + if line =~ '^\s*%' + setf matlab + return + endif + if line =~ '^\s*(\*' + setf mma + return + endif + if line =~ '^\c\s*\(\(type\|var\)\>\|--\)' + setf murphi + return + endif + n += 1 + endwhile + + if saw_comment + # We didn't see anything definitive, but this looks like either Objective C + # or Murphi based on the comment leader. Assume the former as it is more + # common. + setf objc + else + # Default is Matlab + setf matlab + endif +enddef + +export def FTmms() + var n = 1 + while n < 20 + var line = getline(n) + if line =~ '^\s*\(%\|//\)' || line =~ '^\*' + setf mmix + return + endif + if line =~ '^\s*#' + setf make + return + endif + n += 1 + endwhile + setf mmix +enddef + +# This function checks if one of the first five lines start with a dot. In +# that case it is probably an nroff file: 'filetype' is set and 1 is returned. +export def FTnroff(): number + if getline(1)[0] .. getline(2)[0] .. getline(3)[0] + .. getline(4)[0] .. getline(5)[0] =~ '\.' + setf nroff + return 1 + endif + return 0 +enddef + +export def FTmm() + var n = 1 + while n < 20 + if getline(n) =~ '^\s*\(#\s*\(include\|import\)\>\|@import\>\|/\*\)' + setf objcpp + return + endif + n += 1 + endwhile + setf nroff +enddef + +# Returns true if file content looks like LambdaProlog module +def IsLProlog(): bool + # skip apparent comments and blank lines, what looks like + # LambdaProlog comment may be RAPID header + var lnum: number = nextnonblank(1) + while lnum > 0 && lnum < line('$') && getline(lnum) =~ '^\s*%' # LambdaProlog comment + lnum = nextnonblank(lnum + 1) + endwhile + # this pattern must not catch a go.mod file + return getline(lnum) =~ '\<module\s\+\w\+\s*\.\s*\(%\|$\)' +enddef + +def IsModula2(): bool + return getline(nextnonblank(1)) =~ '\<MODULE\s\+\w\+\s*;\|^\s*(\*' +enddef + +def SetFiletypeModula2() + const KNOWN_DIALECTS = ["iso", "pim", "r10"] + const KNOWN_EXTENSIONS = ["gm2"] + const LINE_COUNT = 200 + const TAG = '(\*!m2\(\w\+\)\%(+\(\w\+\)\)\=\*)' + + var dialect = get(g:, "modula2_default_dialect", "pim") + var extension = get(g:, "modula2_default_extension", "") + + var matches = [] + + # ignore unknown dialects or badly formatted tags + for lnum in range(1, min([line("$"), LINE_COUNT])) + matches = matchlist(getline(lnum), TAG) + if !empty(matches) + if index(KNOWN_DIALECTS, matches[1]) >= 0 + dialect = matches[1] + endif + if index(KNOWN_EXTENSIONS, matches[2]) >= 0 + extension = matches[2] + endif + break + endif + endfor + + modula2#SetDialect(dialect, extension) + + setf modula2 +enddef + +# Determine if *.mod is ABB RAPID, LambdaProlog, Modula-2, Modsim III or go.mod +export def FTmod() + if get(g:, "filetype_mod", "") == "modula2" || IsModula2() + SetFiletypeModula2() + return + endif + + if exists("g:filetype_mod") + exe "setf " .. g:filetype_mod + elseif expand("<afile>") =~ '\<go.mod$' + setf gomod + elseif IsLProlog() + setf lprolog + elseif IsRapid() + setf rapid + else + # Nothing recognized, assume modsim3 + setf modsim3 + endif +enddef + +export def FTpl() + if exists("g:filetype_pl") + exe "setf " .. g:filetype_pl + else + # recognize Prolog by specific text in the first non-empty line + # require a blank after the '%' because Perl uses "%list" and "%translate" + var line = getline(nextnonblank(1)) + if line =~ '\<prolog\>' || line =~ '^\s*\(%\+\(\s\|$\)\|/\*\)' || line =~ ':-' + setf prolog + else + setf perl + endif + endif +enddef + +export def FTinc() + if exists("g:filetype_inc") + exe "setf " .. g:filetype_inc + else + var lines = getline(1) .. getline(2) .. getline(3) + if lines =~? "perlscript" + setf aspperl + elseif lines =~ "<%" + setf aspvbs + elseif lines =~ "<?" + setf php + # Pascal supports // comments but they're vary rarely used for file + # headers so assume POV-Ray + elseif lines =~ '^\s*\%({\|(\*\)' || lines =~? ft_pascal_keywords + setf pascal + elseif lines =~# '\<\%(require\|inherit\)\>' || lines =~# '[A-Z][A-Za-z0-9_:${}]*\s\+\%(??\|[?:+]\)\?= ' + setf bitbake + else + FTasmsyntax() + if exists("b:asmsyntax") + exe "setf " .. fnameescape(b:asmsyntax) + else + setf pov + endif + endif + endif +enddef + +export def FTprogress_cweb() + if exists("g:filetype_w") + exe "setf " .. g:filetype_w + return + endif + if getline(1) =~ '&ANALYZE' || getline(3) =~ '&GLOBAL-DEFINE' + setf progress + else + setf cweb + endif +enddef + +# These include the leading '%' sign +var ft_swig_keywords = '^\s*%\%(addmethods\|apply\|beginfile\|clear\|constant\|define\|echo\|enddef\|endoffile\|extend\|feature\|fragment\|ignore\|import\|importfile\|include\|includefile\|inline\|insert\|keyword\|module\|name\|namewarn\|native\|newobject\|parms\|pragma\|rename\|template\|typedef\|typemap\|types\|varargs\|warn\)' +# This is the start/end of a block that is copied literally to the processor file (C/C++) +var ft_swig_verbatim_block_start = '^\s*%{' + +export def FTi() + if exists("g:filetype_i") + exe "setf " .. g:filetype_i + return + endif + # This function checks for an assembly comment or a SWIG keyword or verbatim block in the first 50 lines. + # If not found, assume Progress. + var lnum = 1 + while lnum <= 50 && lnum < line('$') + var line = getline(lnum) + if line =~ '^\s*;' || line =~ '^\*' + FTasm() + return + elseif line =~ ft_swig_keywords || line =~ ft_swig_verbatim_block_start + setf swig + return + endif + lnum += 1 + endwhile + setf progress +enddef + +var ft_pascal_comments = '^\s*\%({\|(\*\|//\)' +var ft_pascal_keywords = '^\s*\%(program\|unit\|library\|uses\|begin\|procedure\|function\|const\|type\|var\)\>' + +export def FTprogress_pascal() + if exists("g:filetype_p") + exe "setf " .. g:filetype_p + return + endif + # This function checks for valid Pascal syntax in the first ten lines. + # Look for either an opening comment or a program start. + # If not found, assume Progress. + var lnum = 1 + while lnum <= 10 && lnum < line('$') + var line = getline(lnum) + if line =~ ft_pascal_comments || line =~? ft_pascal_keywords + setf pascal + return + elseif line !~ '^\s*$' || line =~ '^/\*' + # Not an empty line: Doesn't look like valid Pascal code. + # Or it looks like a Progress /* comment + break + endif + lnum += 1 + endwhile + setf progress +enddef + +export def FTpp() + if exists("g:filetype_pp") + exe "setf " .. g:filetype_pp + else + var line = getline(nextnonblank(1)) + if line =~ ft_pascal_comments || line =~? ft_pascal_keywords + setf pascal + else + setf puppet + endif + endif +enddef + +# Determine if *.prg is ABB RAPID. Can also be Clipper, FoxPro or eviews +export def FTprg() + if exists("g:filetype_prg") + exe "setf " .. g:filetype_prg + elseif IsRapid() + setf rapid + else + # Nothing recognized, assume Clipper + setf clipper + endif +enddef + +export def FTr() + var max = line("$") > 50 ? 50 : line("$") + + for n in range(1, max) + # Rebol is easy to recognize, check for that first + if getline(n) =~? '\<REBOL\>' + setf rebol + return + endif + endfor + + for n in range(1, max) + # R has # comments + if getline(n) =~ '^\s*#' + setf r + return + endif + # Rexx has /* comments */ + if getline(n) =~ '^\s*/\*' + setf rexx + return + endif + endfor + + # Nothing recognized, use user default or assume Rexx + if exists("g:filetype_r") + exe "setf " .. g:filetype_r + else + # Rexx used to be the default, but R appears to be much more popular. + setf r + endif +enddef + +export def McSetf() + # Rely on the file to start with a comment. + # MS message text files use ';', Sendmail files use '#' or 'dnl' + for lnum in range(1, min([line("$"), 20])) + var line = getline(lnum) + if line =~ '^\s*\(#\|dnl\)' + setf m4 # Sendmail .mc file + return + elseif line =~ '^\s*;' + setf msmessages # MS Message text file + return + endif + endfor + setf m4 # Default: Sendmail .mc file +enddef + +# Called from filetype.vim and scripts.vim. +# When "setft" is passed and false then the 'filetype' option is not set. +export def SetFileTypeSH(name: string, setft = true): string + if setft && did_filetype() + # Filetype was already detected + return '' + endif + if setft && expand("<amatch>") =~ g:ft_ignore_pat + return '' + endif + if name =~ '\<csh\>' + # Some .sh scripts contain #!/bin/csh. + return SetFileTypeShell("csh", setft) + elseif name =~ '\<tcsh\>' + # Some .sh scripts contain #!/bin/tcsh. + return SetFileTypeShell("tcsh", setft) + elseif name =~ '\<zsh\>' + # Some .sh scripts contain #!/bin/zsh. + return SetFileTypeShell("zsh", setft) + elseif name =~ '\<ksh\>' + b:is_kornshell = 1 + if exists("b:is_bash") + unlet b:is_bash + endif + if exists("b:is_sh") + unlet b:is_sh + endif + elseif exists("g:bash_is_sh") || name =~ '\<bash\>' || name =~ '\<bash2\>' + b:is_bash = 1 + if exists("b:is_kornshell") + unlet b:is_kornshell + endif + if exists("b:is_sh") + unlet b:is_sh + endif + elseif name =~ '\<sh\>' || name =~ '\<dash\>' + # Ubuntu links "sh" to "dash", thus it is expected to work the same way + b:is_sh = 1 + if exists("b:is_kornshell") + unlet b:is_kornshell + endif + if exists("b:is_bash") + unlet b:is_bash + endif + endif + + return SetFileTypeShell("sh", setft) +enddef + +# For shell-like file types, check for an "exec" command hidden in a comment, +# as used for Tcl. +# When "setft" is passed and false then the 'filetype' option is not set. +# Also called from scripts.vim, thus can't be local to this script. +export def SetFileTypeShell(name: string, setft = true): string + if setft && did_filetype() + # Filetype was already detected + return '' + endif + if setft && expand("<amatch>") =~ g:ft_ignore_pat + return '' + endif + + var lnum = 2 + while lnum < 20 && lnum < line("$") && getline(lnum) =~ '^\s*\(#\|$\)' + # Skip empty and comment lines. + lnum += 1 + endwhile + if lnum < line("$") && getline(lnum) =~ '\s*exec\s' && getline(lnum - 1) =~ '^\s*#.*\\$' + # Found an "exec" line after a comment with continuation + var n = substitute(getline(lnum), '\s*exec\s\+\([^ ]*/\)\=', '', '') + if n =~ '\<tclsh\|\<wish' + if setft + setf tcl + endif + return 'tcl' + endif + endif + + if setft + exe "setf " .. name + endif + return name +enddef + +export def CSH() + if did_filetype() + # Filetype was already detected + return + endif + if exists("g:filetype_csh") + SetFileTypeShell(g:filetype_csh) + elseif &shell =~ "tcsh" + SetFileTypeShell("tcsh") + else + SetFileTypeShell("csh") + endif +enddef + +var ft_rules_udev_rules_pattern = '^\s*\cudev_rules\s*=\s*"\([^"]\{-1,}\)/*".*' +export def FTRules() + var path = expand('<amatch>:p') + if path =~ '/\(etc/udev/\%(rules\.d/\)\=.*\.rules\|\%(usr/\)\=lib/udev/\%(rules\.d/\)\=.*\.rules\)$' + setf udevrules + return + endif + if path =~ '^/etc/ufw/' + setf conf # Better than hog + return + endif + if path =~ '^/\(etc\|usr/share\)/polkit-1/rules\.d' + setf javascript + return + endif + var config_lines: list<string> + try + config_lines = readfile('/etc/udev/udev.conf') + catch /^Vim\%((\a\+)\)\=:E484/ + setf hog + return + endtry + var dir = expand('<amatch>:p:h') + for line in config_lines + if line =~ ft_rules_udev_rules_pattern + var udev_rules = substitute(line, ft_rules_udev_rules_pattern, '\1', "") + if dir == udev_rules + setf udevrules + endif + break + endif + endfor + setf hog +enddef + +export def SQL() + if exists("g:filetype_sql") + exe "setf " .. g:filetype_sql + else + setf sql + endif +enddef + +# This function checks the first 25 lines of file extension "sc" to resolve +# detection between scala and SuperCollider. +# NOTE: We don't check for 'Class : Method', as this can easily be confused +# with valid Scala like `val x : Int = 3`. So we instead only rely on +# checks that can't be confused. +export def FTsc() + for lnum in range(1, min([line("$"), 25])) + if getline(lnum) =~# 'var\s<\|classvar\s<\|\^this.*\||\w\+|\|+\s\w*\s{\|\*ar\s' + setf supercollider + return + endif + endfor + setf scala +enddef + +# This function checks the first line of file extension "scd" to resolve +# detection between scdoc and SuperCollider +export def FTscd() + if getline(1) =~# '\%^\S\+(\d[0-9A-Za-z]*)\%(\s\+\"[^"]*\"\%(\s\+\"[^"]*\"\)\=\)\=$' + setf scdoc + else + setf supercollider + endif +enddef + +# If the file has an extension of 't' and is in a directory 't' or 'xt' then +# it is almost certainly a Perl test file. +# If the first line starts with '#' and contains 'perl' it's probably a Perl +# file. +# (Slow test) If a file contains a 'use' statement then it is almost certainly +# a Perl file. +export def FTperl(): number + var dirname = expand("%:p:h:t") + if expand("%:e") == 't' && (dirname == 't' || dirname == 'xt') + setf perl + return 1 + endif + if getline(1)[0] == '#' && getline(1) =~ 'perl' + setf perl + return 1 + endif + var save_cursor = getpos('.') + call cursor(1, 1) + var has_use = search('^use\s\s*\k', 'c', 30) > 0 + call setpos('.', save_cursor) + if has_use + setf perl + return 1 + endif + return 0 +enddef + +# LambdaProlog and Standard ML signature files +export def FTsig() + if exists("g:filetype_sig") + exe "setf " .. g:filetype_sig + return + endif + + var lprolog_comment = '^\s*\%(/\*\|%\)' + var lprolog_keyword = '^\s*sig\s\+\a' + var sml_comment = '^\s*(\*' + var sml_keyword = '^\s*\%(signature\|structure\)\s\+\a' + + var line = getline(nextnonblank(1)) + + if line =~ lprolog_comment || line =~# lprolog_keyword + setf lprolog + elseif line =~ sml_comment || line =~# sml_keyword + setf sml + endif +enddef + +# This function checks the first 100 lines of files matching "*.sil" to +# resolve detection between Swift Intermediate Language and SILE. +export def FTsil() + for lnum in range(1, [line('$'), 100]->min()) + var line: string = getline(lnum) + if line =~ '^\s*[\\%]' + setf sile + return + elseif line =~ '^\s*\S' + setf sil + return + endif + endfor + # no clue, default to "sil" + setf sil +enddef + +export def FTsys() + if exists("g:filetype_sys") + exe "setf " .. g:filetype_sys + elseif IsRapid() + setf rapid + else + setf bat + endif +enddef + +# 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. +# 3. Default to "plain" or to g:tex_flavor, can be set in user's vimrc. +export def FTtex() + var firstline = getline(1) + var format: string + if firstline =~ '^%&\s*\a\+' + format = tolower(matchstr(firstline, '\a\+')) + format = substitute(format, 'pdf', '', '') + if format == 'tex' + format = 'latex' + elseif format == 'plaintex' + format = 'plain' + endif + elseif expand('%') =~ 'tex/context/.*/.*.tex' + format = 'context' + else + # Default value, may be changed later: + format = exists("g:tex_flavor") ? g:tex_flavor : 'plain' + # Save position, go to the top of the file, find first non-comment line. + var save_cursor = getpos('.') + call cursor(1, 1) + var firstNC = search('^\s*[^[:space:]%]', 'c', 1000) + if firstNC > 0 + # Check the next thousand lines for a LaTeX or ConTeXt keyword. + var lpat = 'documentclass\>\|usepackage\>\|begin{\|newcommand\>\|renewcommand\>' + var cpat = 'start\a\+\|setup\a\+\|usemodule\|enablemode\|enableregime\|setvariables\|useencoding\|usesymbols\|stelle\a\+\|verwende\a\+\|stel\a\+\|gebruik\a\+\|usa\a\+\|imposta\a\+\|regle\a\+\|utilisemodule\>' + var kwline = search('^\s*\\\%(' .. lpat .. '\)\|^\s*\\\(' .. cpat .. '\)', + 'cnp', firstNC + 1000) + if kwline == 1 # lpat matched + format = 'latex' + elseif kwline == 2 # cpat matched + format = 'context' + endif # If neither matched, keep default set above. + # let lline = search('^\s*\\\%(' . lpat . '\)', 'cn', firstNC + 1000) + # let cline = search('^\s*\\\%(' . cpat . '\)', 'cn', firstNC + 1000) + # if cline > 0 + # let format = 'context' + # endif + # if lline > 0 && (cline == 0 || cline > lline) + # let format = 'tex' + # endif + endif # firstNC + call setpos('.', save_cursor) + endif # firstline =~ '^%&\s*\a\+' + + # Translation from formats to file types. TODO: add AMSTeX, RevTex, others? + if format == 'plain' + setf plaintex + elseif format == 'context' + setf context + else # probably LaTeX + setf tex + endif + return +enddef + +export def FTxml() + var n = 1 + while n < 100 && n <= line("$") + var line = getline(n) + # DocBook 4 or DocBook 5. + var is_docbook4 = line =~ '<!DOCTYPE.*DocBook' + var is_docbook5 = line =~ ' xmlns="http://docbook.org/ns/docbook"' + if is_docbook4 || is_docbook5 + b:docbk_type = "xml" + if is_docbook5 + b:docbk_ver = 5 + else + b:docbk_ver = 4 + endif + setf docbk + return + endif + if line =~ 'xmlns:xbl="http://www.mozilla.org/xbl"' + setf xbl + return + endif + n += 1 + endwhile + setf xml +enddef + +export def FTy() + var n = 1 + while n < 100 && n <= line("$") + var line = getline(n) + if line =~ '^\s*%' + setf yacc + return + endif + if getline(n) =~ '^\s*\(#\|class\>\)' && getline(n) !~ '^\s*#\s*include' + setf racc + return + endif + n += 1 + endwhile + setf yacc +enddef + +export def Redif() + var lnum = 1 + while lnum <= 5 && lnum < line('$') + if getline(lnum) =~ "^\ctemplate-type:" + setf redif + return + endif + lnum += 1 + endwhile +enddef + +# This function is called for all files under */debian/patches/*, make sure not +# to non-dep3patch files, such as README and other text files. +export def Dep3patch() + if expand('%:t') ==# 'series' + return + endif + + for ln in getline(1, 100) + if ln =~# '^\%(Description\|Subject\|Origin\|Bug\|Forwarded\|Author\|From\|Reviewed-by\|Acked-by\|Last-Updated\|Applied-Upstream\):' + setf dep3patch + return + elseif ln =~# '^---' + # end of headers found. stop processing + return + endif + endfor +enddef + +# This function checks the first 15 lines for appearance of 'FoamFile' +# and then 'object' in a following line. +# In that case, it's probably an OpenFOAM file +export def FTfoam() + var ffile = 0 + var lnum = 1 + while lnum <= 15 + if getline(lnum) =~# '^FoamFile' + ffile = 1 + elseif ffile == 1 && getline(lnum) =~# '^\s*object' + setf foam + return + endif + lnum += 1 + endwhile +enddef + +# Determine if a *.tf file is TF mud client or terraform +export def FTtf() + var numberOfLines = line('$') + for i in range(1, numberOfLines) + var currentLine = trim(getline(i)) + var firstCharacter = currentLine[0] + if firstCharacter !=? ";" && firstCharacter !=? "/" && firstCharacter !=? "" + setf terraform + return + endif + endfor + setf tf +enddef + +var ft_krl_header = '\&\w+' +# Determine if a *.src file is Kuka Robot Language +export def FTsrc() + var ft_krl_def_or_deffct = '%(global\s+)?def%(fct)?>' + if exists("g:filetype_src") + exe "setf " .. g:filetype_src + elseif getline(nextnonblank(1)) =~? '\v^\s*%(' .. ft_krl_header .. '|' .. ft_krl_def_or_deffct .. ')' + setf krl + endif +enddef + +# Determine if a *.dat file is Kuka Robot Language +export def FTdat() + var ft_krl_defdat = 'defdat>' + if exists("g:filetype_dat") + exe "setf " .. g:filetype_dat + elseif getline(nextnonblank(1)) =~? '\v^\s*%(' .. ft_krl_header .. '|' .. ft_krl_defdat .. ')' + setf krl + endif +enddef + +export def FTlsl() + if exists("g:filetype_lsl") + exe "setf " .. g:filetype_lsl + endif + + var line = getline(nextnonblank(1)) + if line =~ '^\s*%' || line =~# ':\s*trait\s*$' + setf larch + else + setf lsl + endif +enddef + +export def FTtyp() + if exists("g:filetype_typ") + exe "setf " .. g:filetype_typ + return + endif + + # Look for SQL type definition syntax + for line in getline(1, 200) + # SQL type files may define the casing + if line =~ '^CASE\s\==\s\=\(SAME\|LOWER\|UPPER\|OPPOSITE\)$' + setf sql + return + endif + + # SQL type files may define some types as follows + if line =~ '^TYPE\s.*$' + setf sql + return + endif + endfor + + # Otherwise, affect the typst filetype + setf typst +enddef + +# Set the filetype of a *.v file to Verilog, V or Cog based on the first 200 +# lines. +export def FTv() + if did_filetype() + # ":setf" will do nothing, bail out early + return + endif + if exists("g:filetype_v") + exe "setf " .. g:filetype_v + return + endif + + var in_comment = 0 + for lnum in range(1, min([line("$"), 200])) + var line = getline(lnum) + # Skip Verilog and V comments (lines and blocks). + if line =~ '^\s*/\*' + # start comment block + in_comment = 1 + endif + if in_comment == 1 + if line =~ '\*/' + # end comment block + in_comment = 0 + endif + # skip comment-block line + continue + endif + if line =~ '^\s*//' + # skip comment line + continue + endif + + # Coq: line ends with a '.' followed by an optional variable number of + # spaces or contains the start of a comment, but not inside a Verilog or V + # comment. + # Example: "Definition x := 10. (*". + if (line =~ '\.\s*$' && line !~ '/[/*]') || (line =~ '(\*' && line !~ '/[/*].*(\*') + setf coq + return + endif + + # Verilog: line ends with ';' followed by an optional variable number of + # spaces and an optional start of a comment. + # Example: " b <= a + 1; // Add 1". + if line =~ ';\s*\(/[/*].*\)\?$' + setf verilog + return + endif + endfor + + # No line matched, fall back to "v". + setf v +enddef + +export def FTvba() + if getline(1) =~ '^["#] Vimball Archiver' + setf vim + else + setf vb + endif +enddef + +# Uncomment this line to check for compilation errors early +defcompile |