2022-02-04 16:09:54 +00:00
|
|
|
vim9script
|
2017-11-09 20:46:17 +01:00
|
|
|
|
2022-02-04 16:09:54 +00:00
|
|
|
# Vim functions for file type detection
|
|
|
|
#
|
2024-01-05 17:59:04 +01:00
|
|
|
# Maintainer: The Vim Project <https://github.com/vim/vim>
|
2024-05-24 08:05:00 +02:00
|
|
|
# Last Change: 2024 May 23
|
2023-08-13 10:33:05 +02:00
|
|
|
# Former Maintainer: Bram Moolenaar <Bram@vim.org>
|
2017-11-09 20:46:17 +01:00
|
|
|
|
2022-02-04 16:09:54 +00:00
|
|
|
# These functions are moved here from runtime/filetype.vim to make startup
|
|
|
|
# faster.
|
2017-11-09 20:46:17 +01:00
|
|
|
|
2024-07-18 21:34:36 +02:00
|
|
|
var prolog_pattern = '^\s*\(:-\|%\+\(\s\|$\)\|\/\*\)\|\.\s*$'
|
|
|
|
|
2022-02-04 16:09:54 +00:00
|
|
|
export def Check_inp()
|
2024-04-09 22:09:30 +02:00
|
|
|
if getline(1) =~ '%%'
|
|
|
|
setf tex
|
|
|
|
elseif getline(1) =~ '^\*'
|
2017-11-09 20:46:17 +01:00
|
|
|
setf abaqus
|
|
|
|
else
|
2022-02-04 16:09:54 +00:00
|
|
|
var n = 1
|
|
|
|
var nmax = line("$") > 500 ? 500 : line("$")
|
2017-11-09 20:46:17 +01:00
|
|
|
while n <= nmax
|
|
|
|
if getline(n) =~? "^header surface data"
|
|
|
|
setf trasys
|
|
|
|
break
|
|
|
|
endif
|
2022-02-04 16:09:54 +00:00
|
|
|
n += 1
|
2017-11-09 20:46:17 +01:00
|
|
|
endwhile
|
|
|
|
endif
|
2022-02-04 16:09:54 +00:00
|
|
|
enddef
|
2017-11-09 20:46:17 +01:00
|
|
|
|
2022-02-04 16:09:54 +00:00
|
|
|
# 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
|
2017-11-09 20:46:17 +01:00
|
|
|
if !exists("b:asmsyntax")
|
2022-02-04 16:09:54 +00:00
|
|
|
b:asmsyntax = ""
|
2017-11-09 20:46:17 +01:00
|
|
|
endif
|
|
|
|
|
|
|
|
if b:asmsyntax == ""
|
2022-02-04 16:09:54 +00:00
|
|
|
FTasmsyntax()
|
2017-11-09 20:46:17 +01:00
|
|
|
endif
|
|
|
|
|
2022-02-04 16:09:54 +00:00
|
|
|
# if b:asmsyntax still isn't set, default to asmsyntax or GNU
|
2017-11-09 20:46:17 +01:00
|
|
|
if b:asmsyntax == ""
|
|
|
|
if exists("g:asmsyntax")
|
2022-02-04 16:09:54 +00:00
|
|
|
b:asmsyntax = g:asmsyntax
|
2017-11-09 20:46:17 +01:00
|
|
|
else
|
2022-02-04 16:09:54 +00:00
|
|
|
b:asmsyntax = "asm"
|
2017-11-09 20:46:17 +01:00
|
|
|
endif
|
|
|
|
endif
|
|
|
|
|
2022-02-04 16:09:54 +00:00
|
|
|
exe "setf " .. fnameescape(b:asmsyntax)
|
|
|
|
enddef
|
2017-11-09 20:46:17 +01:00
|
|
|
|
2022-02-04 16:09:54 +00:00
|
|
|
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')
|
2017-11-09 20:46:17 +01:00
|
|
|
if match != ''
|
2022-02-04 16:09:54 +00:00
|
|
|
b:asmsyntax = match
|
2017-11-09 20:46:17 +01:00
|
|
|
elseif ((head =~? '\.title') || (head =~? '\.ident') || (head =~? '\.macro') || (head =~? '\.subtitle') || (head =~? '\.library'))
|
2022-02-04 16:09:54 +00:00
|
|
|
b:asmsyntax = "vmasm"
|
2017-11-09 20:46:17 +01:00
|
|
|
endif
|
2022-02-04 16:09:54 +00:00
|
|
|
enddef
|
2017-11-09 20:46:17 +01:00
|
|
|
|
2023-08-27 18:44:09 +02:00
|
|
|
var ft_visual_basic_content = '\c^\s*\%(Attribute\s\+VB_Name\|Begin\s\+\%(VB\.\|{\%(\x\+-\)\+\x\+}\)\)'
|
2022-01-31 17:09:14 +00:00
|
|
|
|
2022-02-04 16:09:54 +00:00
|
|
|
# See FTfrm() for Visual Basic form file detection
|
|
|
|
export def FTbas()
|
2022-01-21 14:55:13 +00:00
|
|
|
if exists("g:filetype_bas")
|
2022-02-04 16:09:54 +00:00
|
|
|
exe "setf " .. g:filetype_bas
|
2022-01-21 14:55:13 +00:00
|
|
|
return
|
|
|
|
endif
|
|
|
|
|
2022-02-04 16:09:54 +00:00
|
|
|
# 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*[:=(]\)\@!'
|
2022-06-29 14:39:12 +01:00
|
|
|
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\)\>' ..
|
|
|
|
'\)'
|
2022-02-04 16:09:54 +00:00
|
|
|
var fb_comment = "^\\s*/'"
|
2022-06-29 14:39:12 +01:00
|
|
|
|
2022-02-04 16:09:54 +00:00
|
|
|
# OPTION EXPLICIT, without the leading underscore, is common to many dialects
|
|
|
|
var qb64_preproc = '\c^\s*\%($\a\+\|option\s\+\%(_explicit\|_\=explicitarray\)\>\)'
|
2022-01-21 14:55:13 +00:00
|
|
|
|
2022-06-29 14:39:12 +01:00
|
|
|
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
|
2022-02-04 16:09:54 +00:00
|
|
|
enddef
|
2017-11-09 20:46:17 +01:00
|
|
|
|
2022-02-04 16:09:54 +00:00
|
|
|
export def FTbtm()
|
2017-11-09 20:46:17 +01:00
|
|
|
if exists("g:dosbatch_syntax_for_btm") && g:dosbatch_syntax_for_btm
|
|
|
|
setf dosbatch
|
|
|
|
else
|
|
|
|
setf btm
|
|
|
|
endif
|
2022-02-04 16:09:54 +00:00
|
|
|
enddef
|
2017-11-09 20:46:17 +01:00
|
|
|
|
2022-02-04 16:09:54 +00:00
|
|
|
export def BindzoneCheck(default = '')
|
|
|
|
if getline(1) .. getline(2) .. getline(3) .. getline(4)
|
|
|
|
=~ '^; <<>> DiG [0-9.]\+.* <<>>\|$ORIGIN\|$TTL\|IN\s\+SOA'
|
2017-11-09 20:46:17 +01:00
|
|
|
setf bindzone
|
2022-02-04 16:09:54 +00:00
|
|
|
elseif default != ''
|
|
|
|
exe 'setf ' .. default
|
2017-11-09 20:46:17 +01:00
|
|
|
endif
|
2022-02-04 16:09:54 +00:00
|
|
|
enddef
|
2017-11-09 20:46:17 +01:00
|
|
|
|
2022-04-09 15:16:53 +01:00
|
|
|
# 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
|
|
|
|
|
2024-11-19 20:55:25 +01:00
|
|
|
export def FTcl()
|
|
|
|
if join(getline(1, 4), '') =~ '/\*'
|
|
|
|
setf opencl
|
|
|
|
else
|
|
|
|
setf lisp
|
|
|
|
endif
|
|
|
|
enddef
|
|
|
|
|
2022-06-29 14:39:12 +01:00
|
|
|
export def FTcls()
|
|
|
|
if exists("g:filetype_cls")
|
|
|
|
exe "setf " .. g:filetype_cls
|
|
|
|
return
|
|
|
|
endif
|
|
|
|
|
2023-08-27 18:44:09 +02:00
|
|
|
var line1 = getline(1)
|
2023-08-29 22:21:35 +02:00
|
|
|
if line1 =~ '^#!.*\<\%(rexx\|regina\)\>'
|
2022-06-29 14:39:12 +01:00
|
|
|
setf rexx
|
2023-08-29 22:21:35 +02:00
|
|
|
return
|
2023-08-27 18:44:09 +02:00
|
|
|
elseif line1 == 'VERSION 1.0 CLASS'
|
2022-06-29 14:39:12 +01:00
|
|
|
setf vb
|
2023-08-29 22:21:35 +02:00
|
|
|
return
|
|
|
|
endif
|
|
|
|
|
|
|
|
var nonblank1 = getline(nextnonblank(1))
|
|
|
|
if nonblank1 =~ '^\v%(\%|\\)'
|
|
|
|
setf tex
|
|
|
|
elseif nonblank1 =~ '^\s*\%(/\*\|::\w\)'
|
|
|
|
setf rexx
|
2022-06-29 14:39:12 +01:00
|
|
|
else
|
|
|
|
setf st
|
|
|
|
endif
|
|
|
|
enddef
|
|
|
|
|
2024-11-14 22:55:36 +01:00
|
|
|
export def FTll()
|
|
|
|
if getline(1) =~ ';\|\<source_filename\>\|\<target\>'
|
|
|
|
setf llvm
|
|
|
|
else
|
|
|
|
setf lifelines
|
|
|
|
endif
|
|
|
|
enddef
|
|
|
|
|
2022-02-04 16:09:54 +00:00
|
|
|
export def FTlpc()
|
2017-11-09 20:46:17 +01:00
|
|
|
if exists("g:lpc_syntax_for_c")
|
2022-02-04 16:09:54 +00:00
|
|
|
var lnum = 1
|
2017-11-09 20:46:17 +01:00
|
|
|
while lnum <= 12
|
|
|
|
if getline(lnum) =~# '^\(//\|inherit\|private\|protected\|nosave\|string\|object\|mapping\|mixed\)'
|
|
|
|
setf lpc
|
|
|
|
return
|
|
|
|
endif
|
2022-02-04 16:09:54 +00:00
|
|
|
lnum += 1
|
2017-11-09 20:46:17 +01:00
|
|
|
endwhile
|
|
|
|
endif
|
|
|
|
setf c
|
2022-02-04 16:09:54 +00:00
|
|
|
enddef
|
2017-11-09 20:46:17 +01:00
|
|
|
|
2022-02-04 16:09:54 +00:00
|
|
|
export def FTheader()
|
2017-11-09 20:46:17 +01:00
|
|
|
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
|
2022-02-04 16:09:54 +00:00
|
|
|
enddef
|
2017-11-09 20:46:17 +01:00
|
|
|
|
2022-02-04 16:09:54 +00:00
|
|
|
# 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
|
2017-11-09 20:46:17 +01:00
|
|
|
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
|
2022-02-04 16:09:54 +00:00
|
|
|
lnum += 1
|
2017-11-09 20:46:17 +01:00
|
|
|
endwhile
|
|
|
|
setf chill
|
2022-02-04 16:09:54 +00:00
|
|
|
enddef
|
2017-11-09 20:46:17 +01:00
|
|
|
|
2022-02-04 16:09:54 +00:00
|
|
|
export def FTent()
|
|
|
|
# This function checks for valid cl syntax in the first five lines.
|
2022-04-09 15:16:53 +01:00
|
|
|
# Look for either an opening comment, '#', or a block start, '{'.
|
2022-02-04 16:09:54 +00:00
|
|
|
# If not found, assume SGML.
|
|
|
|
var lnum = 1
|
2017-11-09 20:46:17 +01:00
|
|
|
while lnum < 6
|
2022-02-04 16:09:54 +00:00
|
|
|
var line = getline(lnum)
|
2017-11-09 20:46:17 +01:00
|
|
|
if line =~ '^\s*[#{]'
|
|
|
|
setf cl
|
|
|
|
return
|
|
|
|
elseif line !~ '^\s*$'
|
2022-02-04 16:09:54 +00:00
|
|
|
# Not a blank line, not a comment, and not a block start,
|
|
|
|
# so doesn't look like valid cl code.
|
2017-11-09 20:46:17 +01:00
|
|
|
break
|
|
|
|
endif
|
2022-02-04 16:09:54 +00:00
|
|
|
lnum += 1
|
2022-03-05 13:45:56 +00:00
|
|
|
endwhile
|
2017-11-09 20:46:17 +01:00
|
|
|
setf dtd
|
2022-02-04 16:09:54 +00:00
|
|
|
enddef
|
2017-11-09 20:46:17 +01:00
|
|
|
|
2022-02-04 16:09:54 +00:00
|
|
|
export def ExCheck()
|
|
|
|
var lines = getline(1, min([line("$"), 100]))
|
2021-06-26 12:02:55 +02:00
|
|
|
if exists('g:filetype_euphoria')
|
2022-02-04 16:09:54 +00:00
|
|
|
exe 'setf ' .. g:filetype_euphoria
|
2021-06-26 12:02:55 +02:00
|
|
|
elseif match(lines, '^--\|^ifdef\>\|^include\>') > -1
|
|
|
|
setf euphoria3
|
|
|
|
else
|
|
|
|
setf elixir
|
|
|
|
endif
|
2022-02-04 16:09:54 +00:00
|
|
|
enddef
|
2021-06-26 12:02:55 +02:00
|
|
|
|
2022-02-04 16:09:54 +00:00
|
|
|
export def EuphoriaCheck()
|
2017-11-09 20:46:17 +01:00
|
|
|
if exists('g:filetype_euphoria')
|
2022-02-04 16:09:54 +00:00
|
|
|
exe 'setf ' .. g:filetype_euphoria
|
2017-11-09 20:46:17 +01:00
|
|
|
else
|
|
|
|
setf euphoria3
|
|
|
|
endif
|
2022-02-04 16:09:54 +00:00
|
|
|
enddef
|
2017-11-09 20:46:17 +01:00
|
|
|
|
2022-02-04 16:09:54 +00:00
|
|
|
export def DtraceCheck()
|
2022-02-24 17:59:09 +00:00
|
|
|
if did_filetype()
|
|
|
|
# Filetype was already detected
|
|
|
|
return
|
|
|
|
endif
|
2022-02-04 16:09:54 +00:00
|
|
|
var lines = getline(1, min([line("$"), 100]))
|
2017-11-09 20:46:17 +01:00
|
|
|
if match(lines, '^module\>\|^import\>') > -1
|
2022-02-04 16:09:54 +00:00
|
|
|
# D files often start with a module and/or import statement.
|
2017-11-09 20:46:17 +01:00
|
|
|
setf d
|
|
|
|
elseif match(lines, '^#!\S\+dtrace\|#pragma\s\+D\s\+option\|:\S\{-}:\S\{-}:') > -1
|
|
|
|
setf dtrace
|
|
|
|
else
|
|
|
|
setf d
|
|
|
|
endif
|
2022-02-04 16:09:54 +00:00
|
|
|
enddef
|
2017-11-09 20:46:17 +01:00
|
|
|
|
2024-01-05 17:59:04 +01:00
|
|
|
export def FTdef()
|
2024-04-09 22:09:30 +02:00
|
|
|
# LaTeX def files are usually generated by docstrip, which will output '%%' in first line
|
|
|
|
if getline(1) =~ '%%'
|
|
|
|
setf tex
|
|
|
|
endif
|
2024-01-05 17:59:04 +01:00
|
|
|
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
|
|
|
|
|
2022-02-04 16:09:54 +00:00
|
|
|
export def FTe()
|
2017-11-09 20:46:17 +01:00
|
|
|
if exists('g:filetype_euphoria')
|
2022-02-04 16:09:54 +00:00
|
|
|
exe 'setf ' .. g:filetype_euphoria
|
2017-11-09 20:46:17 +01:00
|
|
|
else
|
2022-02-04 16:09:54 +00:00
|
|
|
var n = 1
|
2019-03-17 17:16:12 +01:00
|
|
|
while n < 100 && n <= line("$")
|
2017-11-09 20:46:17 +01:00
|
|
|
if getline(n) =~ "^\\s*\\(<'\\|'>\\)\\s*$"
|
|
|
|
setf specman
|
|
|
|
return
|
|
|
|
endif
|
2022-02-04 16:09:54 +00:00
|
|
|
n += 1
|
2017-11-09 20:46:17 +01:00
|
|
|
endwhile
|
|
|
|
setf eiffel
|
|
|
|
endif
|
2022-02-04 16:09:54 +00:00
|
|
|
enddef
|
2017-11-09 20:46:17 +01:00
|
|
|
|
2023-08-20 20:51:12 +02:00
|
|
|
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
|
|
|
|
|
2022-02-04 16:09:54 +00:00
|
|
|
export def FTfrm()
|
2022-01-31 17:09:14 +00:00
|
|
|
if exists("g:filetype_frm")
|
2022-02-04 16:09:54 +00:00
|
|
|
exe "setf " .. g:filetype_frm
|
2022-01-31 17:09:14 +00:00
|
|
|
return
|
|
|
|
endif
|
|
|
|
|
2023-08-27 18:44:09 +02:00
|
|
|
if getline(1) == "VERSION 5.00"
|
|
|
|
setf vb
|
|
|
|
return
|
|
|
|
endif
|
|
|
|
|
2022-02-04 16:09:54 +00:00
|
|
|
var lines = getline(1, min([line("$"), 5]))
|
2022-01-31 17:09:14 +00:00
|
|
|
|
2022-02-22 21:17:40 +00:00
|
|
|
if match(lines, ft_visual_basic_content) > -1
|
2022-01-31 17:09:14 +00:00
|
|
|
setf vb
|
|
|
|
else
|
|
|
|
setf form
|
|
|
|
endif
|
2022-02-04 16:09:54 +00:00
|
|
|
enddef
|
2022-01-31 17:09:14 +00:00
|
|
|
|
2023-08-20 20:51:12 +02:00
|
|
|
# Distinguish between Forth and F#
|
2022-02-04 16:09:54 +00:00
|
|
|
export def FTfs()
|
2021-11-27 17:22:07 +00:00
|
|
|
if exists("g:filetype_fs")
|
2022-02-04 16:09:54 +00:00
|
|
|
exe "setf " .. g:filetype_fs
|
2023-08-20 20:51:12 +02:00
|
|
|
elseif IsForth()
|
|
|
|
setf forth
|
2021-11-27 17:22:07 +00:00
|
|
|
else
|
2023-04-02 20:29:38 +01:00
|
|
|
setf fsharp
|
2021-11-27 17:22:07 +00:00
|
|
|
endif
|
2022-02-04 16:09:54 +00:00
|
|
|
enddef
|
2021-11-27 17:22:07 +00:00
|
|
|
|
2024-05-24 08:05:00 +02:00
|
|
|
# Recursively search for Hare source files in a directory and any
|
|
|
|
# subdirectories, up to a given depth.
|
|
|
|
def IsHareModule(dir: string, depth: number): bool
|
|
|
|
if depth <= 0
|
|
|
|
return !empty(glob(dir .. '/*.ha'))
|
|
|
|
endif
|
|
|
|
|
|
|
|
return reduce(sort(glob(dir .. '/*', true, true),
|
|
|
|
(a, b) => isdirectory(a) - isdirectory(b)),
|
|
|
|
(acc, n) => acc
|
|
|
|
|| n =~ '\.ha$'
|
|
|
|
|| isdirectory(n)
|
|
|
|
&& IsHareModule(n, depth - 1),
|
|
|
|
false)
|
|
|
|
enddef
|
|
|
|
|
|
|
|
# Determine if a README file exists within a Hare module and should be given the
|
|
|
|
# Haredoc filetype.
|
|
|
|
export def FTharedoc()
|
|
|
|
if exists('g:filetype_haredoc')
|
|
|
|
if IsHareModule('<afile>:h', get(g:, 'haredoc_search_depth', 1))
|
|
|
|
setf haredoc
|
|
|
|
endif
|
|
|
|
endif
|
|
|
|
enddef
|
|
|
|
|
patch 9.1.0551: filetype: htmlangular files are not properly detected
Problem: filetype: htmlangular files are not properly detected
Solution: Use the new htmlangular filetype for angular files, because
since angular v17, those are no longer valid HTML files.
(Dennis van den Berg)
Since Angular 17, the new Control Flow Syntax is not valid HTML. This PR
adds a new filetype detection for the HTML templates of Angular.
It first checks the filename. The Angular convention is to use
*.component.html for the template. However, this is not mandatory.
If the filename does not match, it will check the contents of the file
if it contains:
- One of the Control-Flow blocks: @if, @for, @switch, @defer
- A structural directive: *ngIf, *ngFor, *ngSwitch, *ngTemplateOutlet
- Builtin Angular elements: ng-template or ng-content
- String interpolation: {{ something }}
This enables the Angular LSP to attach only to htmlangular filetypes, as
well as language parsers, such as tree-sitter.
closes: #15190
Signed-off-by: Dennis van den Berg <dennis.vandenberg@nedap.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
2024-07-09 19:25:33 +02:00
|
|
|
# Distinguish between HTML, XHTML, Django and Angular
|
2022-02-04 16:09:54 +00:00
|
|
|
export def FThtml()
|
|
|
|
var n = 1
|
patch 9.1.0551: filetype: htmlangular files are not properly detected
Problem: filetype: htmlangular files are not properly detected
Solution: Use the new htmlangular filetype for angular files, because
since angular v17, those are no longer valid HTML files.
(Dennis van den Berg)
Since Angular 17, the new Control Flow Syntax is not valid HTML. This PR
adds a new filetype detection for the HTML templates of Angular.
It first checks the filename. The Angular convention is to use
*.component.html for the template. However, this is not mandatory.
If the filename does not match, it will check the contents of the file
if it contains:
- One of the Control-Flow blocks: @if, @for, @switch, @defer
- A structural directive: *ngIf, *ngFor, *ngSwitch, *ngTemplateOutlet
- Builtin Angular elements: ng-template or ng-content
- String interpolation: {{ something }}
This enables the Angular LSP to attach only to htmlangular filetypes, as
well as language parsers, such as tree-sitter.
closes: #15190
Signed-off-by: Dennis van den Berg <dennis.vandenberg@nedap.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
2024-07-09 19:25:33 +02:00
|
|
|
|
|
|
|
# Test if the filename follows the Angular component template convention
|
2024-07-10 19:23:39 +02:00
|
|
|
# Disabled for the reasons mentioned here: #13594
|
|
|
|
# if expand('%:t') =~ '^.*\.component\.html$'
|
|
|
|
# setf htmlangular
|
|
|
|
# return
|
|
|
|
# endif
|
patch 9.1.0551: filetype: htmlangular files are not properly detected
Problem: filetype: htmlangular files are not properly detected
Solution: Use the new htmlangular filetype for angular files, because
since angular v17, those are no longer valid HTML files.
(Dennis van den Berg)
Since Angular 17, the new Control Flow Syntax is not valid HTML. This PR
adds a new filetype detection for the HTML templates of Angular.
It first checks the filename. The Angular convention is to use
*.component.html for the template. However, this is not mandatory.
If the filename does not match, it will check the contents of the file
if it contains:
- One of the Control-Flow blocks: @if, @for, @switch, @defer
- A structural directive: *ngIf, *ngFor, *ngSwitch, *ngTemplateOutlet
- Builtin Angular elements: ng-template or ng-content
- String interpolation: {{ something }}
This enables the Angular LSP to attach only to htmlangular filetypes, as
well as language parsers, such as tree-sitter.
closes: #15190
Signed-off-by: Dennis van den Berg <dennis.vandenberg@nedap.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
2024-07-09 19:25:33 +02:00
|
|
|
|
2024-06-18 19:59:53 +02:00
|
|
|
while n < 40 && n <= line("$")
|
patch 9.1.0551: filetype: htmlangular files are not properly detected
Problem: filetype: htmlangular files are not properly detected
Solution: Use the new htmlangular filetype for angular files, because
since angular v17, those are no longer valid HTML files.
(Dennis van den Berg)
Since Angular 17, the new Control Flow Syntax is not valid HTML. This PR
adds a new filetype detection for the HTML templates of Angular.
It first checks the filename. The Angular convention is to use
*.component.html for the template. However, this is not mandatory.
If the filename does not match, it will check the contents of the file
if it contains:
- One of the Control-Flow blocks: @if, @for, @switch, @defer
- A structural directive: *ngIf, *ngFor, *ngSwitch, *ngTemplateOutlet
- Builtin Angular elements: ng-template or ng-content
- String interpolation: {{ something }}
This enables the Angular LSP to attach only to htmlangular filetypes, as
well as language parsers, such as tree-sitter.
closes: #15190
Signed-off-by: Dennis van den Berg <dennis.vandenberg@nedap.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
2024-07-09 19:25:33 +02:00
|
|
|
# Check for Angular
|
|
|
|
if getline(n) =~ '@\(if\|for\|defer\|switch\)\|\*\(ngIf\|ngFor\|ngSwitch\|ngTemplateOutlet\)\|ng-template\|ng-content\|{{.*}}'
|
|
|
|
setf htmlangular
|
|
|
|
return
|
|
|
|
endif
|
|
|
|
# Check for XHTML
|
2017-11-09 20:46:17 +01:00
|
|
|
if getline(n) =~ '\<DTD\s\+XHTML\s'
|
|
|
|
setf xhtml
|
|
|
|
return
|
|
|
|
endif
|
patch 9.1.0551: filetype: htmlangular files are not properly detected
Problem: filetype: htmlangular files are not properly detected
Solution: Use the new htmlangular filetype for angular files, because
since angular v17, those are no longer valid HTML files.
(Dennis van den Berg)
Since Angular 17, the new Control Flow Syntax is not valid HTML. This PR
adds a new filetype detection for the HTML templates of Angular.
It first checks the filename. The Angular convention is to use
*.component.html for the template. However, this is not mandatory.
If the filename does not match, it will check the contents of the file
if it contains:
- One of the Control-Flow blocks: @if, @for, @switch, @defer
- A structural directive: *ngIf, *ngFor, *ngSwitch, *ngTemplateOutlet
- Builtin Angular elements: ng-template or ng-content
- String interpolation: {{ something }}
This enables the Angular LSP to attach only to htmlangular filetypes, as
well as language parsers, such as tree-sitter.
closes: #15190
Signed-off-by: Dennis van den Berg <dennis.vandenberg@nedap.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
2024-07-09 19:25:33 +02:00
|
|
|
# Check for Django
|
2024-06-18 19:59:53 +02:00
|
|
|
if getline(n) =~ '{%\s*\(autoescape\|block\|comment\|csrf_token\|cycle\|debug\|extends\|filter\|firstof\|for\|if\|ifchanged\|include\|load\|lorem\|now\|query_string\|regroup\|resetcycle\|spaceless\|templatetag\|url\|verbatim\|widthratio\|with\)\>\|{#\s\+'
|
2017-11-09 20:46:17 +01:00
|
|
|
setf htmldjango
|
|
|
|
return
|
|
|
|
endif
|
2024-07-28 21:28:11 +02:00
|
|
|
# Check for SuperHTML
|
|
|
|
if getline(n) =~ '<extend\|<super>'
|
|
|
|
setf superhtml
|
|
|
|
return
|
|
|
|
endif
|
2022-02-04 16:09:54 +00:00
|
|
|
n += 1
|
2017-11-09 20:46:17 +01:00
|
|
|
endwhile
|
2019-03-17 17:16:12 +01:00
|
|
|
setf FALLBACK html
|
2022-02-04 16:09:54 +00:00
|
|
|
enddef
|
2017-11-09 20:46:17 +01:00
|
|
|
|
2022-02-04 16:09:54 +00:00
|
|
|
# Distinguish between standard IDL and MS-IDL
|
|
|
|
export def FTidl()
|
|
|
|
var n = 1
|
2019-03-17 17:16:12 +01:00
|
|
|
while n < 50 && n <= line("$")
|
2017-11-09 20:46:17 +01:00
|
|
|
if getline(n) =~ '^\s*import\s\+"\(unknwn\|objidl\)\.idl"'
|
|
|
|
setf msidl
|
|
|
|
return
|
|
|
|
endif
|
2022-02-04 16:09:54 +00:00
|
|
|
n += 1
|
2017-11-09 20:46:17 +01:00
|
|
|
endwhile
|
|
|
|
setf idl
|
2022-02-04 16:09:54 +00:00
|
|
|
enddef
|
|
|
|
|
2024-05-09 20:35:13 +02:00
|
|
|
# Distinguish between "default", Prolog, zsh module's C and Cproto prototype file.
|
2022-02-04 16:09:54 +00:00
|
|
|
export def ProtoCheck(default: string)
|
2024-05-09 20:35:13 +02:00
|
|
|
# zsh modules use '#include "*.pro"'
|
|
|
|
# https://github.com/zsh-users/zsh/blob/63f086d167960a27ecdbcb762179e2c2bf8a29f5/Src/Modules/example.c#L31
|
|
|
|
if getline(1) =~ '/* Generated automatically */'
|
|
|
|
setf c
|
2022-02-04 16:09:54 +00:00
|
|
|
# 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 ';'.
|
2024-05-09 20:35:13 +02:00
|
|
|
elseif getline(2) =~ '.;$'
|
2017-11-09 20:46:17 +01:00
|
|
|
setf cpp
|
|
|
|
else
|
2022-08-08 15:42:38 +01:00
|
|
|
# recognize Prolog by specific text in the first non-empty line
|
|
|
|
# require a blank after the '%' because Perl uses "%list" and "%translate"
|
2023-06-09 21:01:47 +01:00
|
|
|
var lnum = getline(nextnonblank(1))
|
2024-07-18 21:34:36 +02:00
|
|
|
if lnum =~ '\<prolog\>' || lnum =~ prolog_pattern
|
2022-08-08 15:42:38 +01:00
|
|
|
setf prolog
|
|
|
|
else
|
|
|
|
exe 'setf ' .. default
|
|
|
|
endif
|
2017-11-09 20:46:17 +01:00
|
|
|
endif
|
2022-02-04 16:09:54 +00:00
|
|
|
enddef
|
2017-11-09 20:46:17 +01:00
|
|
|
|
2022-02-04 16:09:54 +00:00
|
|
|
export def FTm()
|
2021-09-03 19:21:36 +02:00
|
|
|
if exists("g:filetype_m")
|
2022-02-04 16:09:54 +00:00
|
|
|
exe "setf " .. g:filetype_m
|
2021-09-03 19:21:36 +02:00
|
|
|
return
|
|
|
|
endif
|
|
|
|
|
2022-02-04 16:09:54 +00:00
|
|
|
# excluding end(for|function|if|switch|while) common to Murphi
|
|
|
|
var octave_block_terminators = '\<end\%(_try_catch\|classdef\|enumeration\|events\|methods\|parfor\|properties\)\>'
|
2021-09-03 19:21:36 +02:00
|
|
|
|
2022-02-04 16:09:54 +00:00
|
|
|
var objc_preprocessor = '^\s*#\s*\%(import\|include\|define\|if\|ifn\=def\|undef\|line\|error\|pragma\)\>'
|
2021-11-26 13:01:41 +00:00
|
|
|
|
2022-02-04 16:09:54 +00:00
|
|
|
var n = 1
|
|
|
|
var saw_comment = 0 # Whether we've seen a multiline comment leader.
|
2017-11-09 20:46:17 +01:00
|
|
|
while n < 100
|
2022-02-04 16:09:54 +00:00
|
|
|
var line = getline(n)
|
2017-11-09 20:46:17 +01:00
|
|
|
if line =~ '^\s*/\*'
|
2022-02-04 16:09:54 +00:00
|
|
|
# /* ... */ 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
|
2017-11-09 20:46:17 +01:00
|
|
|
endif
|
2021-11-26 13:01:41 +00:00
|
|
|
if line =~ '^\s*//' || line =~ '^\s*@import\>' || line =~ objc_preprocessor
|
2017-11-09 20:46:17 +01:00
|
|
|
setf objc
|
|
|
|
return
|
|
|
|
endif
|
2021-09-12 17:03:08 +02:00
|
|
|
if line =~ '^\s*\%(#\|%!\)' || line =~ '^\s*unwind_protect\>' ||
|
2021-09-03 19:21:36 +02:00
|
|
|
\ line =~ '\%(^\|;\)\s*' .. octave_block_terminators
|
|
|
|
setf octave
|
|
|
|
return
|
|
|
|
endif
|
2022-02-04 16:09:54 +00:00
|
|
|
# TODO: could be Matlab or Octave
|
2017-11-09 20:46:17 +01:00
|
|
|
if line =~ '^\s*%'
|
|
|
|
setf matlab
|
|
|
|
return
|
|
|
|
endif
|
|
|
|
if line =~ '^\s*(\*'
|
|
|
|
setf mma
|
|
|
|
return
|
|
|
|
endif
|
|
|
|
if line =~ '^\c\s*\(\(type\|var\)\>\|--\)'
|
|
|
|
setf murphi
|
|
|
|
return
|
|
|
|
endif
|
2022-02-04 16:09:54 +00:00
|
|
|
n += 1
|
2017-11-09 20:46:17 +01:00
|
|
|
endwhile
|
|
|
|
|
|
|
|
if saw_comment
|
2022-02-04 16:09:54 +00:00
|
|
|
# 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.
|
2017-11-09 20:46:17 +01:00
|
|
|
setf objc
|
|
|
|
else
|
2022-02-04 16:09:54 +00:00
|
|
|
# Default is Matlab
|
2017-11-09 20:46:17 +01:00
|
|
|
setf matlab
|
|
|
|
endif
|
2022-02-04 16:09:54 +00:00
|
|
|
enddef
|
2017-11-09 20:46:17 +01:00
|
|
|
|
2024-07-25 21:07:13 +02:00
|
|
|
export def FTmake()
|
|
|
|
# Check if it is a Microsoft Makefile
|
|
|
|
unlet! b:make_microsoft
|
|
|
|
var n = 1
|
|
|
|
while n < 1000 && n <= line('$')
|
|
|
|
var line = getline(n)
|
|
|
|
if line =~? '^\s*!\s*\(ifn\=\(def\)\=\|include\|message\|error\)\>'
|
|
|
|
b:make_microsoft = 1
|
|
|
|
break
|
|
|
|
elseif line =~ '^ *ifn\=\(eq\|def\)\>' || line =~ '^ *[-s]\=include\s'
|
|
|
|
break
|
|
|
|
elseif line =~ '^ *\w\+\s*[!?:+]='
|
|
|
|
break
|
|
|
|
endif
|
|
|
|
n += 1
|
|
|
|
endwhile
|
|
|
|
setf make
|
|
|
|
enddef
|
|
|
|
|
2022-02-04 16:09:54 +00:00
|
|
|
export def FTmms()
|
|
|
|
var n = 1
|
2020-01-02 21:34:42 +01:00
|
|
|
while n < 20
|
2022-02-04 16:09:54 +00:00
|
|
|
var line = getline(n)
|
2017-11-09 20:46:17 +01:00
|
|
|
if line =~ '^\s*\(%\|//\)' || line =~ '^\*'
|
|
|
|
setf mmix
|
|
|
|
return
|
|
|
|
endif
|
|
|
|
if line =~ '^\s*#'
|
|
|
|
setf make
|
|
|
|
return
|
|
|
|
endif
|
2022-02-04 16:09:54 +00:00
|
|
|
n += 1
|
2017-11-09 20:46:17 +01:00
|
|
|
endwhile
|
|
|
|
setf mmix
|
2022-02-04 16:09:54 +00:00
|
|
|
enddef
|
2017-11-09 20:46:17 +01:00
|
|
|
|
2022-02-04 16:09:54 +00:00
|
|
|
# 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] =~ '\.'
|
2017-11-09 20:46:17 +01:00
|
|
|
setf nroff
|
|
|
|
return 1
|
|
|
|
endif
|
|
|
|
return 0
|
2022-02-04 16:09:54 +00:00
|
|
|
enddef
|
2017-11-09 20:46:17 +01:00
|
|
|
|
2022-02-04 16:09:54 +00:00
|
|
|
export def FTmm()
|
|
|
|
var n = 1
|
2020-04-10 22:10:56 +02:00
|
|
|
while n < 20
|
2022-02-04 16:09:54 +00:00
|
|
|
if getline(n) =~ '^\s*\(#\s*\(include\|import\)\>\|@import\>\|/\*\)'
|
2017-11-09 20:46:17 +01:00
|
|
|
setf objcpp
|
|
|
|
return
|
|
|
|
endif
|
2022-02-04 16:09:54 +00:00
|
|
|
n += 1
|
2017-11-09 20:46:17 +01:00
|
|
|
endwhile
|
|
|
|
setf nroff
|
2022-02-04 16:09:54 +00:00
|
|
|
enddef
|
2017-11-09 20:46:17 +01:00
|
|
|
|
2022-06-30 16:25:21 +01:00
|
|
|
# Returns true if file content looks like LambdaProlog module
|
2022-04-09 15:16:53 +01:00
|
|
|
def IsLProlog(): bool
|
2023-05-10 22:01:55 +01:00
|
|
|
# skip apparent comments and blank lines, what looks like
|
2022-04-09 15:16:53 +01:00
|
|
|
# LambdaProlog comment may be RAPID header
|
2023-06-09 21:01:47 +01:00
|
|
|
var lnum: number = nextnonblank(1)
|
|
|
|
while lnum > 0 && lnum < line('$') && getline(lnum) =~ '^\s*%' # LambdaProlog comment
|
|
|
|
lnum = nextnonblank(lnum + 1)
|
2022-04-09 15:16:53 +01:00
|
|
|
endwhile
|
|
|
|
# this pattern must not catch a go.mod file
|
2023-06-09 21:01:47 +01:00
|
|
|
return getline(lnum) =~ '\<module\s\+\w\+\s*\.\s*\(%\|$\)'
|
2022-04-09 15:16:53 +01:00
|
|
|
enddef
|
|
|
|
|
2024-01-05 17:59:04 +01:00
|
|
|
def IsModula2(): bool
|
2024-02-20 06:58:30 +11:00
|
|
|
return getline(nextnonblank(1)) =~ '\<MODULE\s\+\w\+\s*\%(\[.*]\s*\)\=;\|^\s*(\*'
|
2024-01-05 17:59:04 +01:00
|
|
|
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
|
|
|
|
|
2022-04-09 15:16:53 +01:00
|
|
|
# Determine if *.mod is ABB RAPID, LambdaProlog, Modula-2, Modsim III or go.mod
|
|
|
|
export def FTmod()
|
2024-01-05 17:59:04 +01:00
|
|
|
if get(g:, "filetype_mod", "") == "modula2" || IsModula2()
|
|
|
|
SetFiletypeModula2()
|
|
|
|
return
|
|
|
|
endif
|
|
|
|
|
2022-04-09 15:16:53 +01:00
|
|
|
if exists("g:filetype_mod")
|
|
|
|
exe "setf " .. g:filetype_mod
|
2023-05-29 19:59:45 +01:00
|
|
|
elseif expand("<afile>") =~ '\<go.mod$'
|
|
|
|
setf gomod
|
2022-04-09 15:16:53 +01:00
|
|
|
elseif IsLProlog()
|
|
|
|
setf lprolog
|
|
|
|
elseif IsRapid()
|
|
|
|
setf rapid
|
|
|
|
else
|
|
|
|
# Nothing recognized, assume modsim3
|
|
|
|
setf modsim3
|
|
|
|
endif
|
|
|
|
enddef
|
|
|
|
|
2022-02-04 16:09:54 +00:00
|
|
|
export def FTpl()
|
2017-11-09 20:46:17 +01:00
|
|
|
if exists("g:filetype_pl")
|
2022-02-04 16:09:54 +00:00
|
|
|
exe "setf " .. g:filetype_pl
|
2017-11-09 20:46:17 +01:00
|
|
|
else
|
2022-02-04 16:09:54 +00:00
|
|
|
# recognize Prolog by specific text in the first non-empty line
|
|
|
|
# require a blank after the '%' because Perl uses "%list" and "%translate"
|
2023-06-09 21:01:47 +01:00
|
|
|
var line = getline(nextnonblank(1))
|
2024-07-18 21:34:36 +02:00
|
|
|
if line =~ '\<prolog\>' || line =~ prolog_pattern
|
2017-11-09 20:46:17 +01:00
|
|
|
setf prolog
|
|
|
|
else
|
|
|
|
setf perl
|
|
|
|
endif
|
|
|
|
endif
|
2022-02-04 16:09:54 +00:00
|
|
|
enddef
|
2017-11-09 20:46:17 +01:00
|
|
|
|
2022-02-04 16:09:54 +00:00
|
|
|
export def FTinc()
|
2017-11-09 20:46:17 +01:00
|
|
|
if exists("g:filetype_inc")
|
2022-02-04 16:09:54 +00:00
|
|
|
exe "setf " .. g:filetype_inc
|
2017-11-09 20:46:17 +01:00
|
|
|
else
|
2022-02-04 16:09:54 +00:00
|
|
|
var lines = getline(1) .. getline(2) .. getline(3)
|
2017-11-09 20:46:17 +01:00
|
|
|
if lines =~? "perlscript"
|
|
|
|
setf aspperl
|
|
|
|
elseif lines =~ "<%"
|
|
|
|
setf aspvbs
|
|
|
|
elseif lines =~ "<?"
|
|
|
|
setf php
|
2022-02-04 16:09:54 +00:00
|
|
|
# Pascal supports // comments but they're vary rarely used for file
|
|
|
|
# headers so assume POV-Ray
|
2022-02-22 21:17:40 +00:00
|
|
|
elseif lines =~ '^\s*\%({\|(\*\)' || lines =~? ft_pascal_keywords
|
2021-01-12 17:42:24 +01:00
|
|
|
setf pascal
|
2022-07-26 21:42:03 +01:00
|
|
|
elseif lines =~# '\<\%(require\|inherit\)\>' || lines =~# '[A-Z][A-Za-z0-9_:${}]*\s\+\%(??\|[?:+]\)\?= '
|
2022-07-16 17:46:47 +01:00
|
|
|
setf bitbake
|
2017-11-09 20:46:17 +01:00
|
|
|
else
|
2022-02-04 16:09:54 +00:00
|
|
|
FTasmsyntax()
|
2017-11-09 20:46:17 +01:00
|
|
|
if exists("b:asmsyntax")
|
2022-07-16 17:46:47 +01:00
|
|
|
exe "setf " .. fnameescape(b:asmsyntax)
|
2017-11-09 20:46:17 +01:00
|
|
|
else
|
2022-07-16 17:46:47 +01:00
|
|
|
setf pov
|
2017-11-09 20:46:17 +01:00
|
|
|
endif
|
|
|
|
endif
|
|
|
|
endif
|
2022-02-04 16:09:54 +00:00
|
|
|
enddef
|
2017-11-09 20:46:17 +01:00
|
|
|
|
2022-02-04 16:09:54 +00:00
|
|
|
export def FTprogress_cweb()
|
2017-11-09 20:46:17 +01:00
|
|
|
if exists("g:filetype_w")
|
2022-02-04 16:09:54 +00:00
|
|
|
exe "setf " .. g:filetype_w
|
2017-11-09 20:46:17 +01:00
|
|
|
return
|
|
|
|
endif
|
|
|
|
if getline(1) =~ '&ANALYZE' || getline(3) =~ '&GLOBAL-DEFINE'
|
|
|
|
setf progress
|
|
|
|
else
|
|
|
|
setf cweb
|
|
|
|
endif
|
2022-02-04 16:09:54 +00:00
|
|
|
enddef
|
2017-11-09 20:46:17 +01:00
|
|
|
|
2023-11-25 15:30:46 +01:00
|
|
|
# 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()
|
2017-11-09 20:46:17 +01:00
|
|
|
if exists("g:filetype_i")
|
2022-02-04 16:09:54 +00:00
|
|
|
exe "setf " .. g:filetype_i
|
2017-11-09 20:46:17 +01:00
|
|
|
return
|
|
|
|
endif
|
2023-11-25 15:30:46 +01:00
|
|
|
# This function checks for an assembly comment or a SWIG keyword or verbatim block in the first 50 lines.
|
2022-02-04 16:09:54 +00:00
|
|
|
# If not found, assume Progress.
|
|
|
|
var lnum = 1
|
2023-11-25 15:30:46 +01:00
|
|
|
while lnum <= 50 && lnum < line('$')
|
2022-02-04 16:09:54 +00:00
|
|
|
var line = getline(lnum)
|
2017-11-09 20:46:17 +01:00
|
|
|
if line =~ '^\s*;' || line =~ '^\*'
|
2022-02-04 16:09:54 +00:00
|
|
|
FTasm()
|
2017-11-09 20:46:17 +01:00
|
|
|
return
|
2023-11-25 15:30:46 +01:00
|
|
|
elseif line =~ ft_swig_keywords || line =~ ft_swig_verbatim_block_start
|
|
|
|
setf swig
|
|
|
|
return
|
2017-11-09 20:46:17 +01:00
|
|
|
endif
|
2022-02-04 16:09:54 +00:00
|
|
|
lnum += 1
|
2022-03-05 13:45:56 +00:00
|
|
|
endwhile
|
2017-11-09 20:46:17 +01:00
|
|
|
setf progress
|
2022-02-04 16:09:54 +00:00
|
|
|
enddef
|
2017-11-09 20:46:17 +01:00
|
|
|
|
2022-02-04 16:09:54 +00:00
|
|
|
var ft_pascal_comments = '^\s*\%({\|(\*\|//\)'
|
|
|
|
var ft_pascal_keywords = '^\s*\%(program\|unit\|library\|uses\|begin\|procedure\|function\|const\|type\|var\)\>'
|
2021-01-12 17:42:24 +01:00
|
|
|
|
2022-02-04 16:09:54 +00:00
|
|
|
export def FTprogress_pascal()
|
2017-11-09 20:46:17 +01:00
|
|
|
if exists("g:filetype_p")
|
2022-02-04 16:09:54 +00:00
|
|
|
exe "setf " .. g:filetype_p
|
2017-11-09 20:46:17 +01:00
|
|
|
return
|
|
|
|
endif
|
2022-02-04 16:09:54 +00:00
|
|
|
# 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
|
2017-11-09 20:46:17 +01:00
|
|
|
while lnum <= 10 && lnum < line('$')
|
2022-02-04 16:09:54 +00:00
|
|
|
var line = getline(lnum)
|
2022-02-22 21:17:40 +00:00
|
|
|
if line =~ ft_pascal_comments || line =~? ft_pascal_keywords
|
2017-11-09 20:46:17 +01:00
|
|
|
setf pascal
|
|
|
|
return
|
|
|
|
elseif line !~ '^\s*$' || line =~ '^/\*'
|
2022-02-04 16:09:54 +00:00
|
|
|
# Not an empty line: Doesn't look like valid Pascal code.
|
|
|
|
# Or it looks like a Progress /* comment
|
2017-11-09 20:46:17 +01:00
|
|
|
break
|
|
|
|
endif
|
2022-02-04 16:09:54 +00:00
|
|
|
lnum += 1
|
2022-03-05 13:45:56 +00:00
|
|
|
endwhile
|
2017-11-09 20:46:17 +01:00
|
|
|
setf progress
|
2022-02-04 16:09:54 +00:00
|
|
|
enddef
|
2017-11-09 20:46:17 +01:00
|
|
|
|
2022-02-04 16:09:54 +00:00
|
|
|
export def FTpp()
|
2021-01-12 17:42:24 +01:00
|
|
|
if exists("g:filetype_pp")
|
2022-02-04 16:09:54 +00:00
|
|
|
exe "setf " .. g:filetype_pp
|
2021-01-12 17:42:24 +01:00
|
|
|
else
|
2022-02-04 16:09:54 +00:00
|
|
|
var line = getline(nextnonblank(1))
|
2022-02-22 21:17:40 +00:00
|
|
|
if line =~ ft_pascal_comments || line =~? ft_pascal_keywords
|
2021-01-12 17:42:24 +01:00
|
|
|
setf pascal
|
|
|
|
else
|
|
|
|
setf puppet
|
|
|
|
endif
|
|
|
|
endif
|
2022-02-04 16:09:54 +00:00
|
|
|
enddef
|
2021-01-12 17:42:24 +01:00
|
|
|
|
2022-04-09 15:16:53 +01:00
|
|
|
# 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
|
|
|
|
|
2022-02-04 16:09:54 +00:00
|
|
|
export def FTr()
|
|
|
|
var max = line("$") > 50 ? 50 : line("$")
|
2017-11-09 20:46:17 +01:00
|
|
|
|
|
|
|
for n in range(1, max)
|
2022-02-04 16:09:54 +00:00
|
|
|
# Rebol is easy to recognize, check for that first
|
2017-11-09 20:46:17 +01:00
|
|
|
if getline(n) =~? '\<REBOL\>'
|
|
|
|
setf rebol
|
|
|
|
return
|
|
|
|
endif
|
|
|
|
endfor
|
|
|
|
|
|
|
|
for n in range(1, max)
|
2022-02-04 16:09:54 +00:00
|
|
|
# R has # comments
|
2017-11-09 20:46:17 +01:00
|
|
|
if getline(n) =~ '^\s*#'
|
|
|
|
setf r
|
|
|
|
return
|
|
|
|
endif
|
2022-02-04 16:09:54 +00:00
|
|
|
# Rexx has /* comments */
|
2017-11-09 20:46:17 +01:00
|
|
|
if getline(n) =~ '^\s*/\*'
|
|
|
|
setf rexx
|
|
|
|
return
|
|
|
|
endif
|
|
|
|
endfor
|
|
|
|
|
2022-02-04 16:09:54 +00:00
|
|
|
# Nothing recognized, use user default or assume Rexx
|
2017-11-09 20:46:17 +01:00
|
|
|
if exists("g:filetype_r")
|
2022-02-04 16:09:54 +00:00
|
|
|
exe "setf " .. g:filetype_r
|
2017-11-09 20:46:17 +01:00
|
|
|
else
|
2022-02-04 16:09:54 +00:00
|
|
|
# Rexx used to be the default, but R appears to be much more popular.
|
2017-11-09 20:46:17 +01:00
|
|
|
setf r
|
|
|
|
endif
|
2022-02-04 16:09:54 +00:00
|
|
|
enddef
|
2017-11-09 20:46:17 +01:00
|
|
|
|
2022-02-04 16:09:54 +00:00
|
|
|
export def McSetf()
|
|
|
|
# Rely on the file to start with a comment.
|
|
|
|
# MS message text files use ';', Sendmail files use '#' or 'dnl'
|
2017-11-09 20:46:17 +01:00
|
|
|
for lnum in range(1, min([line("$"), 20]))
|
2022-02-04 16:09:54 +00:00
|
|
|
var line = getline(lnum)
|
2017-11-09 20:46:17 +01:00
|
|
|
if line =~ '^\s*\(#\|dnl\)'
|
2022-02-04 16:09:54 +00:00
|
|
|
setf m4 # Sendmail .mc file
|
2017-11-09 20:46:17 +01:00
|
|
|
return
|
|
|
|
elseif line =~ '^\s*;'
|
2022-02-04 16:09:54 +00:00
|
|
|
setf msmessages # MS Message text file
|
2017-11-09 20:46:17 +01:00
|
|
|
return
|
|
|
|
endif
|
|
|
|
endfor
|
2022-04-09 15:16:53 +01:00
|
|
|
setf m4 # Default: Sendmail .mc file
|
2022-02-04 16:09:54 +00:00
|
|
|
enddef
|
2017-11-09 20:46:17 +01:00
|
|
|
|
2022-02-04 16:09:54 +00:00
|
|
|
# Called from filetype.vim and scripts.vim.
|
2023-06-09 21:01:47 +01:00
|
|
|
# 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()
|
2022-02-04 16:09:54 +00:00
|
|
|
# Filetype was already detected
|
2023-06-09 21:01:47 +01:00
|
|
|
return ''
|
2019-01-18 21:46:47 +01:00
|
|
|
endif
|
2023-06-09 21:01:47 +01:00
|
|
|
if setft && expand("<amatch>") =~ g:ft_ignore_pat
|
|
|
|
return ''
|
2017-11-09 20:46:17 +01:00
|
|
|
endif
|
2022-02-04 16:09:54 +00:00
|
|
|
if name =~ '\<csh\>'
|
|
|
|
# Some .sh scripts contain #!/bin/csh.
|
2023-06-09 21:01:47 +01:00
|
|
|
return SetFileTypeShell("csh", setft)
|
2022-02-04 16:09:54 +00:00
|
|
|
elseif name =~ '\<tcsh\>'
|
|
|
|
# Some .sh scripts contain #!/bin/tcsh.
|
2023-06-09 21:01:47 +01:00
|
|
|
return SetFileTypeShell("tcsh", setft)
|
2022-02-04 16:09:54 +00:00
|
|
|
elseif name =~ '\<zsh\>'
|
|
|
|
# Some .sh scripts contain #!/bin/zsh.
|
2023-06-09 21:01:47 +01:00
|
|
|
return SetFileTypeShell("zsh", setft)
|
2022-02-04 16:09:54 +00:00
|
|
|
elseif name =~ '\<ksh\>'
|
|
|
|
b:is_kornshell = 1
|
2017-11-09 20:46:17 +01:00
|
|
|
if exists("b:is_bash")
|
|
|
|
unlet b:is_bash
|
|
|
|
endif
|
|
|
|
if exists("b:is_sh")
|
|
|
|
unlet b:is_sh
|
|
|
|
endif
|
2022-02-04 16:09:54 +00:00
|
|
|
elseif exists("g:bash_is_sh") || name =~ '\<bash\>' || name =~ '\<bash2\>'
|
|
|
|
b:is_bash = 1
|
2017-11-09 20:46:17 +01:00
|
|
|
if exists("b:is_kornshell")
|
|
|
|
unlet b:is_kornshell
|
|
|
|
endif
|
|
|
|
if exists("b:is_sh")
|
|
|
|
unlet b:is_sh
|
|
|
|
endif
|
2024-12-27 16:08:14 +01:00
|
|
|
return SetFileTypeShell("bash", setft)
|
2022-11-24 10:58:10 +00:00
|
|
|
elseif name =~ '\<sh\>' || name =~ '\<dash\>'
|
|
|
|
# Ubuntu links "sh" to "dash", thus it is expected to work the same way
|
2022-02-04 16:09:54 +00:00
|
|
|
b:is_sh = 1
|
2017-11-09 20:46:17 +01:00
|
|
|
if exists("b:is_kornshell")
|
|
|
|
unlet b:is_kornshell
|
|
|
|
endif
|
|
|
|
if exists("b:is_bash")
|
|
|
|
unlet b:is_bash
|
|
|
|
endif
|
|
|
|
endif
|
2023-06-09 21:01:47 +01:00
|
|
|
|
|
|
|
return SetFileTypeShell("sh", setft)
|
2022-02-04 16:09:54 +00:00
|
|
|
enddef
|
2017-11-09 20:46:17 +01:00
|
|
|
|
2022-02-04 16:09:54 +00:00
|
|
|
# For shell-like file types, check for an "exec" command hidden in a comment,
|
|
|
|
# as used for Tcl.
|
2023-06-09 21:01:47 +01:00
|
|
|
# When "setft" is passed and false then the 'filetype' option is not set.
|
2022-02-04 16:09:54 +00:00
|
|
|
# Also called from scripts.vim, thus can't be local to this script.
|
2023-06-09 21:01:47 +01:00
|
|
|
export def SetFileTypeShell(name: string, setft = true): string
|
|
|
|
if setft && did_filetype()
|
2022-02-04 16:09:54 +00:00
|
|
|
# Filetype was already detected
|
2023-06-09 21:01:47 +01:00
|
|
|
return ''
|
2019-01-18 21:46:47 +01:00
|
|
|
endif
|
2023-06-09 21:01:47 +01:00
|
|
|
if setft && expand("<amatch>") =~ g:ft_ignore_pat
|
|
|
|
return ''
|
2017-11-09 20:46:17 +01:00
|
|
|
endif
|
2023-06-09 21:01:47 +01:00
|
|
|
|
|
|
|
var lnum = 2
|
|
|
|
while lnum < 20 && lnum < line("$") && getline(lnum) =~ '^\s*\(#\|$\)'
|
2022-02-04 16:09:54 +00:00
|
|
|
# Skip empty and comment lines.
|
2023-06-09 21:01:47 +01:00
|
|
|
lnum += 1
|
2017-11-09 20:46:17 +01:00
|
|
|
endwhile
|
2023-06-09 21:01:47 +01:00
|
|
|
if lnum < line("$") && getline(lnum) =~ '\s*exec\s' && getline(lnum - 1) =~ '^\s*#.*\\$'
|
2022-02-04 16:09:54 +00:00
|
|
|
# Found an "exec" line after a comment with continuation
|
2023-06-09 21:01:47 +01:00
|
|
|
var n = substitute(getline(lnum), '\s*exec\s\+\([^ ]*/\)\=', '', '')
|
2017-11-09 20:46:17 +01:00
|
|
|
if n =~ '\<tclsh\|\<wish'
|
2023-06-09 21:01:47 +01:00
|
|
|
if setft
|
|
|
|
setf tcl
|
|
|
|
endif
|
|
|
|
return 'tcl'
|
2017-11-09 20:46:17 +01:00
|
|
|
endif
|
|
|
|
endif
|
2023-06-09 21:01:47 +01:00
|
|
|
|
|
|
|
if setft
|
|
|
|
exe "setf " .. name
|
|
|
|
endif
|
|
|
|
return name
|
2022-02-04 16:09:54 +00:00
|
|
|
enddef
|
2017-11-09 20:46:17 +01:00
|
|
|
|
2022-02-04 16:09:54 +00:00
|
|
|
export def CSH()
|
2019-01-18 21:46:47 +01:00
|
|
|
if did_filetype()
|
2022-02-04 16:09:54 +00:00
|
|
|
# Filetype was already detected
|
2019-01-18 21:46:47 +01:00
|
|
|
return
|
|
|
|
endif
|
2017-11-09 20:46:17 +01:00
|
|
|
if exists("g:filetype_csh")
|
2022-02-04 16:09:54 +00:00
|
|
|
SetFileTypeShell(g:filetype_csh)
|
2017-11-09 20:46:17 +01:00
|
|
|
elseif &shell =~ "tcsh"
|
2022-02-04 16:09:54 +00:00
|
|
|
SetFileTypeShell("tcsh")
|
2017-11-09 20:46:17 +01:00
|
|
|
else
|
2022-02-04 16:09:54 +00:00
|
|
|
SetFileTypeShell("csh")
|
2017-11-09 20:46:17 +01:00
|
|
|
endif
|
2022-02-04 16:09:54 +00:00
|
|
|
enddef
|
2017-11-09 20:46:17 +01:00
|
|
|
|
2022-02-04 16:09:54 +00:00
|
|
|
var ft_rules_udev_rules_pattern = '^\s*\cudev_rules\s*=\s*"\([^"]\{-1,}\)/*".*'
|
|
|
|
export def FTRules()
|
|
|
|
var path = expand('<amatch>:p')
|
2020-08-17 21:57:09 +02:00
|
|
|
if path =~ '/\(etc/udev/\%(rules\.d/\)\=.*\.rules\|\%(usr/\)\=lib/udev/\%(rules\.d/\)\=.*\.rules\)$'
|
2017-11-09 20:46:17 +01:00
|
|
|
setf udevrules
|
|
|
|
return
|
|
|
|
endif
|
|
|
|
if path =~ '^/etc/ufw/'
|
2022-02-04 16:09:54 +00:00
|
|
|
setf conf # Better than hog
|
2017-11-09 20:46:17 +01:00
|
|
|
return
|
|
|
|
endif
|
|
|
|
if path =~ '^/\(etc\|usr/share\)/polkit-1/rules\.d'
|
|
|
|
setf javascript
|
|
|
|
return
|
|
|
|
endif
|
2022-02-04 16:09:54 +00:00
|
|
|
var config_lines: list<string>
|
2017-11-09 20:46:17 +01:00
|
|
|
try
|
2022-02-04 16:09:54 +00:00
|
|
|
config_lines = readfile('/etc/udev/udev.conf')
|
2017-11-09 20:46:17 +01:00
|
|
|
catch /^Vim\%((\a\+)\)\=:E484/
|
|
|
|
setf hog
|
|
|
|
return
|
|
|
|
endtry
|
2022-02-04 16:09:54 +00:00
|
|
|
var dir = expand('<amatch>:p:h')
|
2017-11-09 20:46:17 +01:00
|
|
|
for line in config_lines
|
2022-02-22 21:17:40 +00:00
|
|
|
if line =~ ft_rules_udev_rules_pattern
|
|
|
|
var udev_rules = substitute(line, ft_rules_udev_rules_pattern, '\1', "")
|
2017-11-09 20:46:17 +01:00
|
|
|
if dir == udev_rules
|
|
|
|
setf udevrules
|
|
|
|
endif
|
|
|
|
break
|
|
|
|
endif
|
|
|
|
endfor
|
|
|
|
setf hog
|
2022-02-04 16:09:54 +00:00
|
|
|
enddef
|
2017-11-09 20:46:17 +01:00
|
|
|
|
2022-02-04 16:09:54 +00:00
|
|
|
export def SQL()
|
2017-11-09 20:46:17 +01:00
|
|
|
if exists("g:filetype_sql")
|
2022-02-04 16:09:54 +00:00
|
|
|
exe "setf " .. g:filetype_sql
|
2017-11-09 20:46:17 +01:00
|
|
|
else
|
|
|
|
setf sql
|
|
|
|
endif
|
2022-02-04 16:09:54 +00:00
|
|
|
enddef
|
2017-11-09 20:46:17 +01:00
|
|
|
|
2022-04-13 15:29:21 +01:00
|
|
|
# This function checks the first 25 lines of file extension "sc" to resolve
|
2022-12-14 16:42:15 +00:00
|
|
|
# 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.
|
2022-04-13 15:29:21 +01:00
|
|
|
export def FTsc()
|
|
|
|
for lnum in range(1, min([line("$"), 25]))
|
2022-12-14 16:42:15 +00:00
|
|
|
if getline(lnum) =~# 'var\s<\|classvar\s<\|\^this.*\||\w\+|\|+\s\w*\s{\|\*ar\s'
|
2022-04-13 15:29:21 +01:00
|
|
|
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
|
|
|
|
|
2022-02-04 16:09:54 +00:00
|
|
|
# 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")
|
2017-11-09 20:46:17 +01:00
|
|
|
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
|
2022-02-04 16:09:54 +00:00
|
|
|
var save_cursor = getpos('.')
|
|
|
|
call cursor(1, 1)
|
2022-02-05 19:50:34 +00:00
|
|
|
var has_use = search('^use\s\s*\k', 'c', 30) > 0
|
2017-12-17 17:17:07 +01:00
|
|
|
call setpos('.', save_cursor)
|
|
|
|
if has_use
|
2017-11-09 20:46:17 +01:00
|
|
|
setf perl
|
|
|
|
return 1
|
|
|
|
endif
|
|
|
|
return 0
|
2022-02-04 16:09:54 +00:00
|
|
|
enddef
|
|
|
|
|
2022-06-30 16:25:21 +01:00
|
|
|
# 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
|
|
|
|
|
2022-09-01 15:01:25 +01:00
|
|
|
# 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
|
|
|
|
|
2022-04-09 15:16:53 +01:00
|
|
|
export def FTsys()
|
2022-04-13 20:46:21 +01:00
|
|
|
if exists("g:filetype_sys")
|
|
|
|
exe "setf " .. g:filetype_sys
|
|
|
|
elseif IsRapid()
|
2022-04-09 15:16:53 +01:00
|
|
|
setf rapid
|
|
|
|
else
|
|
|
|
setf bat
|
|
|
|
endif
|
|
|
|
enddef
|
|
|
|
|
2022-02-04 16:09:54 +00:00
|
|
|
# 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
|
2017-11-09 20:46:17 +01:00
|
|
|
if firstline =~ '^%&\s*\a\+'
|
2022-02-04 16:09:54 +00:00
|
|
|
format = tolower(matchstr(firstline, '\a\+'))
|
|
|
|
format = substitute(format, 'pdf', '', '')
|
2017-11-09 20:46:17 +01:00
|
|
|
if format == 'tex'
|
2022-02-04 16:09:54 +00:00
|
|
|
format = 'latex'
|
2017-11-09 20:46:17 +01:00
|
|
|
elseif format == 'plaintex'
|
2022-02-04 16:09:54 +00:00
|
|
|
format = 'plain'
|
2017-11-09 20:46:17 +01:00
|
|
|
endif
|
|
|
|
elseif expand('%') =~ 'tex/context/.*/.*.tex'
|
2022-02-04 16:09:54 +00:00
|
|
|
format = 'context'
|
2017-11-09 20:46:17 +01:00
|
|
|
else
|
2022-02-04 16:09:54 +00:00
|
|
|
# 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)
|
2022-02-05 19:50:34 +00:00
|
|
|
if firstNC > 0
|
|
|
|
# Check the next thousand lines for a LaTeX or ConTeXt keyword.
|
2022-02-04 16:09:54 +00:00
|
|
|
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
|
2017-11-09 20:46:17 +01:00
|
|
|
call setpos('.', save_cursor)
|
2022-02-04 16:09:54 +00:00
|
|
|
endif # firstline =~ '^%&\s*\a\+'
|
2017-11-09 20:46:17 +01:00
|
|
|
|
2022-02-04 16:09:54 +00:00
|
|
|
# Translation from formats to file types. TODO: add AMSTeX, RevTex, others?
|
2017-11-09 20:46:17 +01:00
|
|
|
if format == 'plain'
|
|
|
|
setf plaintex
|
|
|
|
elseif format == 'context'
|
|
|
|
setf context
|
2022-02-04 16:09:54 +00:00
|
|
|
else # probably LaTeX
|
2017-11-09 20:46:17 +01:00
|
|
|
setf tex
|
|
|
|
endif
|
|
|
|
return
|
2022-02-04 16:09:54 +00:00
|
|
|
enddef
|
2017-11-09 20:46:17 +01:00
|
|
|
|
2022-02-04 16:09:54 +00:00
|
|
|
export def FTxml()
|
|
|
|
var n = 1
|
2019-03-17 17:16:12 +01:00
|
|
|
while n < 100 && n <= line("$")
|
2022-02-04 16:09:54 +00:00
|
|
|
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"'
|
2017-11-09 20:46:17 +01:00
|
|
|
if is_docbook4 || is_docbook5
|
2022-02-04 16:09:54 +00:00
|
|
|
b:docbk_type = "xml"
|
2017-11-09 20:46:17 +01:00
|
|
|
if is_docbook5
|
2022-02-04 16:09:54 +00:00
|
|
|
b:docbk_ver = 5
|
2017-11-09 20:46:17 +01:00
|
|
|
else
|
2022-02-04 16:09:54 +00:00
|
|
|
b:docbk_ver = 4
|
2017-11-09 20:46:17 +01:00
|
|
|
endif
|
|
|
|
setf docbk
|
|
|
|
return
|
|
|
|
endif
|
|
|
|
if line =~ 'xmlns:xbl="http://www.mozilla.org/xbl"'
|
|
|
|
setf xbl
|
|
|
|
return
|
|
|
|
endif
|
2022-02-04 16:09:54 +00:00
|
|
|
n += 1
|
2017-11-09 20:46:17 +01:00
|
|
|
endwhile
|
|
|
|
setf xml
|
2022-02-04 16:09:54 +00:00
|
|
|
enddef
|
2017-11-09 20:46:17 +01:00
|
|
|
|
2022-02-04 16:09:54 +00:00
|
|
|
export def FTy()
|
|
|
|
var n = 1
|
2019-03-17 17:16:12 +01:00
|
|
|
while n < 100 && n <= line("$")
|
2022-02-04 16:09:54 +00:00
|
|
|
var line = getline(n)
|
2017-11-09 20:46:17 +01:00
|
|
|
if line =~ '^\s*%'
|
|
|
|
setf yacc
|
|
|
|
return
|
|
|
|
endif
|
|
|
|
if getline(n) =~ '^\s*\(#\|class\>\)' && getline(n) !~ '^\s*#\s*include'
|
|
|
|
setf racc
|
|
|
|
return
|
|
|
|
endif
|
2022-02-04 16:09:54 +00:00
|
|
|
n += 1
|
2017-11-09 20:46:17 +01:00
|
|
|
endwhile
|
|
|
|
setf yacc
|
2022-02-04 16:09:54 +00:00
|
|
|
enddef
|
2017-11-09 20:46:17 +01:00
|
|
|
|
2022-02-04 16:09:54 +00:00
|
|
|
export def Redif()
|
|
|
|
var lnum = 1
|
2017-11-09 20:46:17 +01:00
|
|
|
while lnum <= 5 && lnum < line('$')
|
|
|
|
if getline(lnum) =~ "^\ctemplate-type:"
|
|
|
|
setf redif
|
|
|
|
return
|
|
|
|
endif
|
2022-02-04 16:09:54 +00:00
|
|
|
lnum += 1
|
2017-11-09 20:46:17 +01:00
|
|
|
endwhile
|
2022-02-04 16:09:54 +00:00
|
|
|
enddef
|
2017-11-09 20:46:17 +01:00
|
|
|
|
2022-02-04 16:09:54 +00:00
|
|
|
# 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()
|
2021-12-17 20:52:57 +00:00
|
|
|
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 =~# '^---'
|
2022-02-04 16:09:54 +00:00
|
|
|
# end of headers found. stop processing
|
2021-12-17 20:52:57 +00:00
|
|
|
return
|
|
|
|
endif
|
|
|
|
endfor
|
2022-02-04 16:09:54 +00:00
|
|
|
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
|
2022-01-11 18:14:23 +00:00
|
|
|
while lnum <= 15
|
|
|
|
if getline(lnum) =~# '^FoamFile'
|
2022-02-04 16:09:54 +00:00
|
|
|
ffile = 1
|
2022-01-11 18:14:23 +00:00
|
|
|
elseif ffile == 1 && getline(lnum) =~# '^\s*object'
|
|
|
|
setf foam
|
|
|
|
return
|
|
|
|
endif
|
2022-02-04 16:09:54 +00:00
|
|
|
lnum += 1
|
2022-01-11 18:14:23 +00:00
|
|
|
endwhile
|
2022-02-04 16:09:54 +00:00
|
|
|
enddef
|
2022-01-11 18:14:23 +00:00
|
|
|
|
2022-02-04 16:09:54 +00:00
|
|
|
# Determine if a *.tf file is TF mud client or terraform
|
|
|
|
export def FTtf()
|
|
|
|
var numberOfLines = line('$')
|
2022-01-28 14:15:09 +00:00
|
|
|
for i in range(1, numberOfLines)
|
2022-02-04 16:09:54 +00:00
|
|
|
var currentLine = trim(getline(i))
|
|
|
|
var firstCharacter = currentLine[0]
|
2022-01-28 14:15:09 +00:00
|
|
|
if firstCharacter !=? ";" && firstCharacter !=? "/" && firstCharacter !=? ""
|
|
|
|
setf terraform
|
|
|
|
return
|
|
|
|
endif
|
|
|
|
endfor
|
|
|
|
setf tf
|
2022-02-04 16:09:54 +00:00
|
|
|
enddef
|
2022-01-28 14:15:09 +00:00
|
|
|
|
2022-04-16 21:14:04 +01:00
|
|
|
var ft_krl_header = '\&\w+'
|
2022-04-06 18:57:39 +01:00
|
|
|
# Determine if a *.src file is Kuka Robot Language
|
|
|
|
export def FTsrc()
|
2022-04-16 21:14:04 +01:00
|
|
|
var ft_krl_def_or_deffct = '%(global\s+)?def%(fct)?>'
|
2022-04-06 18:57:39 +01:00
|
|
|
if exists("g:filetype_src")
|
|
|
|
exe "setf " .. g:filetype_src
|
2022-04-16 21:14:04 +01:00
|
|
|
elseif getline(nextnonblank(1)) =~? '\v^\s*%(' .. ft_krl_header .. '|' .. ft_krl_def_or_deffct .. ')'
|
2022-04-06 18:57:39 +01:00
|
|
|
setf krl
|
|
|
|
endif
|
|
|
|
enddef
|
|
|
|
|
|
|
|
# Determine if a *.dat file is Kuka Robot Language
|
|
|
|
export def FTdat()
|
2022-04-16 21:14:04 +01:00
|
|
|
var ft_krl_defdat = 'defdat>'
|
2022-04-06 18:57:39 +01:00
|
|
|
if exists("g:filetype_dat")
|
|
|
|
exe "setf " .. g:filetype_dat
|
2022-04-16 21:14:04 +01:00
|
|
|
elseif getline(nextnonblank(1)) =~? '\v^\s*%(' .. ft_krl_header .. '|' .. ft_krl_defdat .. ')'
|
2022-04-06 18:57:39 +01:00
|
|
|
setf krl
|
|
|
|
endif
|
|
|
|
enddef
|
2022-01-28 14:15:09 +00:00
|
|
|
|
2022-10-17 13:32:17 +01:00
|
|
|
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
|
|
|
|
|
2023-05-10 22:01:55 +01:00
|
|
|
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
|
|
|
|
|
2024-06-19 20:32:11 +02:00
|
|
|
# Detect Microsoft Developer Studio Project files (Makefile) or Faust DSP
|
|
|
|
# files.
|
|
|
|
export def FTdsp()
|
|
|
|
if exists("g:filetype_dsp")
|
|
|
|
exe "setf " .. g:filetype_dsp
|
|
|
|
return
|
|
|
|
endif
|
|
|
|
|
|
|
|
# Test the filename
|
|
|
|
if expand('%:t') =~ '^[mM]akefile.*$'
|
|
|
|
setf make
|
|
|
|
return
|
|
|
|
endif
|
|
|
|
|
|
|
|
# Test the file contents
|
|
|
|
for line in getline(1, 200)
|
|
|
|
# Chech for comment style
|
|
|
|
if line =~ '^#.*'
|
|
|
|
setf make
|
|
|
|
return
|
|
|
|
endif
|
|
|
|
|
|
|
|
# Check for common lines
|
|
|
|
if line =~ '^.*Microsoft Developer Studio Project File.*$'
|
|
|
|
setf make
|
|
|
|
return
|
|
|
|
endif
|
|
|
|
|
|
|
|
if line =~ '^!MESSAGE This is not a valid makefile\..+$'
|
|
|
|
setf make
|
|
|
|
return
|
|
|
|
endif
|
|
|
|
|
|
|
|
# Check for keywords
|
|
|
|
if line =~ '^!(IF,ELSEIF,ENDIF).*$'
|
|
|
|
setf make
|
|
|
|
return
|
|
|
|
endif
|
|
|
|
|
|
|
|
# Check for common assignments
|
|
|
|
if line =~ '^SOURCE=.*$'
|
|
|
|
setf make
|
|
|
|
return
|
|
|
|
endif
|
|
|
|
endfor
|
|
|
|
|
|
|
|
# Otherwise, assume we have a Faust file
|
|
|
|
setf faust
|
|
|
|
enddef
|
|
|
|
|
2023-04-22 21:38:47 +01:00
|
|
|
# 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
|
2024-01-01 19:19:20 +01:00
|
|
|
if exists("g:filetype_v")
|
|
|
|
exe "setf " .. g:filetype_v
|
|
|
|
return
|
|
|
|
endif
|
2023-04-22 21:38:47 +01:00
|
|
|
|
2024-01-01 19:19:20 +01:00
|
|
|
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*//'
|
2023-04-22 21:38:47 +01:00
|
|
|
# skip comment line
|
|
|
|
continue
|
|
|
|
endif
|
|
|
|
|
2024-01-01 19:19:20 +01:00
|
|
|
# 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
|
2023-04-22 21:38:47 +01:00
|
|
|
return
|
|
|
|
endif
|
|
|
|
|
2024-01-01 19:19:20 +01:00
|
|
|
# Verilog: line ends with ';' followed by an optional variable number of
|
2023-04-22 21:38:47 +01:00
|
|
|
# spaces and an optional start of a comment.
|
2024-01-01 19:19:20 +01:00
|
|
|
# Example: " b <= a + 1; // Add 1".
|
|
|
|
if line =~ ';\s*\(/[/*].*\)\?$'
|
|
|
|
setf verilog
|
2023-04-22 21:38:47 +01:00
|
|
|
return
|
|
|
|
endif
|
|
|
|
endfor
|
|
|
|
|
|
|
|
# No line matched, fall back to "v".
|
|
|
|
setf v
|
|
|
|
enddef
|
|
|
|
|
2023-08-27 18:44:09 +02:00
|
|
|
export def FTvba()
|
|
|
|
if getline(1) =~ '^["#] Vimball Archiver'
|
|
|
|
setf vim
|
|
|
|
else
|
|
|
|
setf vb
|
|
|
|
endif
|
|
|
|
enddef
|
|
|
|
|
2024-04-18 23:53:02 +02:00
|
|
|
export def Detect_UCI_statements(): bool
|
|
|
|
# Match a config or package statement at the start of the line.
|
|
|
|
const config_or_package_statement = '^\s*\(\(c\|config\)\|\(p\|package\)\)\s\+\S'
|
|
|
|
# Match a line that is either all blank or blank followed by a comment
|
|
|
|
const comment_or_blank = '^\s*\(#.*\)\?$'
|
|
|
|
|
|
|
|
# Return true iff the file has a config or package statement near the
|
|
|
|
# top of the file and all preceding lines were comments or blank.
|
|
|
|
return getline(1) =~# config_or_package_statement
|
|
|
|
\ || getline(1) =~# comment_or_blank
|
|
|
|
\ && ( getline(2) =~# config_or_package_statement
|
|
|
|
\ || getline(2) =~# comment_or_blank
|
|
|
|
\ && getline(3) =~# config_or_package_statement
|
|
|
|
\ )
|
|
|
|
enddef
|
|
|
|
|
2022-02-04 16:09:54 +00:00
|
|
|
# Uncomment this line to check for compilation errors early
|
2024-02-20 06:58:30 +11:00
|
|
|
# defcompile
|