summaryrefslogtreecommitdiffstats
path: root/autoload/polyglot
diff options
context:
space:
mode:
authorAdam Stankiewicz <sheerun@sher.pl>2020-10-02 03:42:03 +0200
committerAdam Stankiewicz <sheerun@sher.pl>2020-10-02 03:42:03 +0200
commit94ec9c38e744241e48fb8d75ae6e8811bc73fc59 (patch)
tree03940b00ce5d9a494253af5d2976d095a11a5d2f /autoload/polyglot
parentbff55a54fa8a70e664ebe8a614681dd0d92d66b6 (diff)
downloadvim-polyglot-94ec9c38e744241e48fb8d75ae6e8811bc73fc59.tar.gz
vim-polyglot-94ec9c38e744241e48fb8d75ae6e8811bc73fc59.zip
Do not use ++once to support older vims, fixes #7056
Diffstat (limited to 'autoload/polyglot')
-rw-r--r--autoload/polyglot/detect.vim25
-rw-r--r--autoload/polyglot/ft.vim757
-rw-r--r--autoload/polyglot/shebang.vim406
-rw-r--r--autoload/polyglot/sleuth.vim2
4 files changed, 1181 insertions, 9 deletions
diff --git a/autoload/polyglot/detect.vim b/autoload/polyglot/detect.vim
index af143865..86783cb3 100644
--- a/autoload/polyglot/detect.vim
+++ b/autoload/polyglot/detect.vim
@@ -1,3 +1,11 @@
+" Line continuation is used here, remove 'C' from 'cpoptions'
+let s:cpo_save = &cpo
+set cpo&vim
+
+func! s:WritePostOnce(fn)
+ exe 'au! filetypedetect BufWritePost <buffer> ++once ' . a:fn
+endfunc
+
" DO NOT EDIT CODE BELOW, IT IS GENERATED WITH MAKEFILE
func! polyglot#detect#Inp()
@@ -185,7 +193,8 @@ func! polyglot#detect#Pm()
let &ft = g:filetype_pm | return
endif
if polyglot#shebang#Detect() | return | endif
- set ft=perl | au BufWritePost <buffer> ++once call polyglot#detect#Pm()
+ setf perl
+ call s:WritePostOnce('call polyglot#detect#Pm()')
return
endfunc
@@ -207,7 +216,8 @@ func! polyglot#detect#Pl()
let &ft = g:filetype_pl | return
endif
if polyglot#shebang#Detect() | return | endif
- set ft=perl | au BufWritePost <buffer> ++once call polyglot#detect#Pl()
+ setf perl
+ call s:WritePostOnce('call polyglot#detect#Pl()')
return
endfunc
@@ -231,7 +241,8 @@ func! polyglot#detect#T()
let &ft = g:filetype_t | return
endif
if polyglot#shebang#Detect() | return | endif
- set ft=perl | au BufWritePost <buffer> ++once call polyglot#detect#T()
+ setf perl
+ call s:WritePostOnce('call polyglot#detect#T()')
return
endfunc
@@ -259,6 +270,12 @@ func! polyglot#detect#Html()
set ft=xhtml | return
endif
endfor
- set ft=html | au BufWritePost <buffer> ++once call polyglot#detect#Html()
+ setf html
+ call s:WritePostOnce('call polyglot#detect#Html()')
return
endfunc
+
+" DO NOT EDIT CODE ABOVE, IT IS GENERATED WITH MAKEFILE
+
+let &cpo = s:cpo_save
+unlet s:cpo_save
diff --git a/autoload/polyglot/ft.vim b/autoload/polyglot/ft.vim
new file mode 100644
index 00000000..35812c37
--- /dev/null
+++ b/autoload/polyglot/ft.vim
@@ -0,0 +1,757 @@
+" Vim functions for file type detection
+"
+" Maintainer: Bram Moolenaar <Bram@vim.org>
+" Last Change: 2020 Aug 17
+
+" These functions are moved here from runtime/filetype.vim to make startup
+" faster.
+
+" Line continuation is used here, remove 'C' from 'cpoptions'
+let s:cpo_save = &cpo
+set cpo&vim
+
+func polyglot#ft#Check_inp()
+ if getline(1) =~ '^\*'
+ setf abaqus
+ else
+ let n = 1
+ if line("$") > 500
+ let nmax = 500
+ else
+ let nmax = line("$")
+ endif
+ while n <= nmax
+ if getline(n) =~? "^header surface data"
+ setf trasys
+ break
+ endif
+ let n = n + 1
+ endwhile
+ endif
+endfunc
+
+" 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.
+func polyglot#ft#FTasm()
+ " make sure b:asmsyntax exists
+ if !exists("b:asmsyntax")
+ let b:asmsyntax = ""
+ endif
+
+ if b:asmsyntax == ""
+ call polyglot#ft#FTasmsyntax()
+ endif
+
+ " if b:asmsyntax still isn't set, default to asmsyntax or GNU
+ if b:asmsyntax == ""
+ if exists("g:asmsyntax")
+ let b:asmsyntax = g:asmsyntax
+ else
+ let b:asmsyntax = "asm"
+ endif
+ endif
+
+ exe "setf " . fnameescape(b:asmsyntax)
+endfunc
+
+func polyglot#ft#FTasmsyntax()
+ " see if file contains any asmsyntax=foo overrides. If so, change
+ " b:asmsyntax appropriately
+ let head = " ".getline(1)." ".getline(2)." ".getline(3)." ".getline(4).
+ \" ".getline(5)." "
+ let match = matchstr(head, '\sasmsyntax=\zs[a-zA-Z0-9]\+\ze\s')
+ if match != ''
+ let b:asmsyntax = match
+ elseif ((head =~? '\.title') || (head =~? '\.ident') || (head =~? '\.macro') || (head =~? '\.subtitle') || (head =~? '\.library'))
+ let b:asmsyntax = "vmasm"
+ endif
+endfunc
+
+" Check if one of the first five lines contains "VB_Name". In that case it is
+" probably a Visual Basic file. Otherwise it's assumed to be "alt" filetype.
+func polyglot#ft#FTVB(alt)
+ if getline(1).getline(2).getline(3).getline(4).getline(5) =~? 'VB_Name\|Begin VB\.\(Form\|MDIForm\|UserControl\)'
+ setf vb
+ else
+ exe "setf " . a:alt
+ endif
+endfunc
+
+func polyglot#ft#FTbtm()
+ if exists("g:dosbatch_syntax_for_btm") && g:dosbatch_syntax_for_btm
+ setf dosbatch
+ else
+ setf btm
+ endif
+endfunc
+
+func polyglot#ft#BindzoneCheck(default)
+ if getline(1).getline(2).getline(3).getline(4) =~ '^; <<>> DiG [0-9.]\+.* <<>>\|$ORIGIN\|$TTL\|IN\s\+SOA'
+ setf bindzone
+ elseif a:default != ''
+ exe 'setf ' . a:default
+ endif
+endfunc
+
+func polyglot#ft#FTlpc()
+ if exists("g:lpc_syntax_for_c")
+ let lnum = 1
+ while lnum <= 12
+ if getline(lnum) =~# '^\(//\|inherit\|private\|protected\|nosave\|string\|object\|mapping\|mixed\)'
+ setf lpc
+ return
+ endif
+ let lnum = lnum + 1
+ endwhile
+ endif
+ setf c
+endfunc
+
+func polyglot#ft#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
+endfunc
+
+" 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.
+func polyglot#ft#FTchange()
+ let 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
+ let lnum = lnum + 1
+ endwhile
+ setf chill
+endfunc
+
+func polyglot#ft#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.
+ let lnum = 1
+ while lnum < 6
+ let 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
+ let lnum = lnum + 1
+ endw
+ setf dtd
+endfunc
+
+func polyglot#ft#EuphoriaCheck()
+ if exists('g:filetype_euphoria')
+ exe 'setf ' . g:filetype_euphoria
+ else
+ setf euphoria3
+ endif
+endfunc
+
+func polyglot#ft#DtraceCheck()
+ let 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
+endfunc
+
+func polyglot#ft#FTe()
+ if exists('g:filetype_euphoria')
+ exe 'setf ' . g:filetype_euphoria
+ else
+ let n = 1
+ while n < 100 && n <= line("$")
+ if getline(n) =~ "^\\s*\\(<'\\|'>\\)\\s*$"
+ setf specman
+ return
+ endif
+ let n = n + 1
+ endwhile
+ setf eiffel
+ endif
+endfunc
+
+" Distinguish between HTML, XHTML and Django
+func polyglot#ft#FThtml()
+ let 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
+ let n = n + 1
+ endwhile
+ setf FALLBACK html
+endfunc
+
+" Distinguish between standard IDL and MS-IDL
+func polyglot#ft#FTidl()
+ let n = 1
+ while n < 50 && n <= line("$")
+ if getline(n) =~ '^\s*import\s\+"\(unknwn\|objidl\)\.idl"'
+ setf msidl
+ return
+ endif
+ let n = n + 1
+ endwhile
+ setf idl
+endfunc
+
+" Distinguish between "default" and Cproto prototype file. */
+func polyglot#ft#ProtoCheck(default)
+ " 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
+ exe 'setf ' . a:default
+ endif
+endfunc
+
+func polyglot#ft#FTm()
+ let n = 1
+ let saw_comment = 0 " Whether we've seen a multiline comment leader.
+ while n < 100
+ let 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.
+ let saw_comment = 1
+ endif
+ if line =~ '^\s*\(#\s*\(include\|import\)\>\|@import\>\|//\)'
+ setf objc
+ return
+ endif
+ if line =~ '^\s*%'
+ setf matlab
+ return
+ endif
+ if line =~ '^\s*(\*'
+ setf mma
+ return
+ endif
+ if line =~ '^\c\s*\(\(type\|var\)\>\|--\)'
+ setf murphi
+ return
+ endif
+ let n = 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
+ elseif exists("g:filetype_m")
+ " Use user specified default filetype for .m
+ exe "setf " . g:filetype_m
+ else
+ " Default is matlab
+ setf matlab
+ endif
+endfunc
+
+func polyglot#ft#FTmms()
+ let n = 1
+ while n < 20
+ let line = getline(n)
+ if line =~ '^\s*\(%\|//\)' || line =~ '^\*'
+ setf mmix
+ return
+ endif
+ if line =~ '^\s*#'
+ setf make
+ return
+ endif
+ let n = n + 1
+ endwhile
+ setf mmix
+endfunc
+
+" 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.
+func polyglot#ft#FTnroff()
+ if getline(1)[0] . getline(2)[0] . getline(3)[0] . getline(4)[0] . getline(5)[0] =~ '\.'
+ setf nroff
+ return 1
+ endif
+ return 0
+endfunc
+
+func polyglot#ft#FTmm()
+ let n = 1
+ while n < 20
+ let line = getline(n)
+ if line =~ '^\s*\(#\s*\(include\|import\)\>\|@import\>\|/\*\)'
+ setf objcpp
+ return
+ endif
+ let n = n + 1
+ endwhile
+ setf nroff
+endfunc
+
+func polyglot#ft#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"
+ let l = getline(nextnonblank(1))
+ if l =~ '\<prolog\>' || l =~ '^\s*\(%\+\(\s\|$\)\|/\*\)' || l =~ ':-'
+ setf prolog
+ else
+ setf perl
+ endif
+ endif
+endfunc
+
+func polyglot#ft#FTinc()
+ if exists("g:filetype_inc")
+ exe "setf " . g:filetype_inc
+ else
+ let lines = getline(1).getline(2).getline(3)
+ if lines =~? "perlscript"
+ setf aspperl
+ elseif lines =~ "<%"
+ setf aspvbs
+ elseif lines =~ "<?"
+ setf php
+ else
+ call polyglot#ft#FTasmsyntax()
+ if exists("b:asmsyntax")
+ exe "setf " . fnameescape(b:asmsyntax)
+ else
+ setf pov
+ endif
+ endif
+ endif
+endfunc
+
+func polyglot#ft#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
+endfunc
+
+func polyglot#ft#FTprogress_asm()
+ if exists("g:filetype_i")
+ exe "setf " . g:filetype_i
+ return
+ endif
+ " This function checks for an assembly comment the first ten lines.
+ " If not found, assume Progress.
+ let lnum = 1
+ while lnum <= 10 && lnum < line('$')
+ let line = getline(lnum)
+ if line =~ '^\s*;' || line =~ '^\*'
+ call polyglot#ft#FTasm()
+ return
+ elseif line !~ '^\s*$' || line =~ '^/\*'
+ " Not an empty line: Doesn't look like valid assembly code.
+ " Or it looks like a Progress /* comment
+ break
+ endif
+ let lnum = lnum + 1
+ endw
+ setf progress
+endfunc
+
+func polyglot#ft#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.
+ let lnum = 1
+ while lnum <= 10 && lnum < line('$')
+ let line = getline(lnum)
+ if line =~ '^\s*\(program\|unit\|procedure\|function\|const\|type\|var\)\>'
+ \ || line =~ '^\s*{' || line =~ '^\s*(\*'
+ 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
+ let lnum = lnum + 1
+ endw
+ setf progress
+endfunc
+
+func polyglot#ft#FTr()
+ let 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
+endfunc
+
+func polyglot#ft#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]))
+ let 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
+endfunc
+
+" Called from filetype.vim and scripts.vim.
+func polyglot#ft#SetFileTypeSH(name)
+ if did_filetype()
+ " Filetype was already detected
+ return
+ endif
+ if expand("<amatch>") =~ g:ft_ignore_pat
+ return
+ endif
+ if a:name =~ '\<csh\>'
+ " Some .sh scripts contain #!/bin/csh.
+ call polyglot#ft#SetFileTypeShell("csh")
+ return
+ elseif a:name =~ '\<tcsh\>'
+ " Some .sh scripts contain #!/bin/tcsh.
+ call polyglot#ft#SetFileTypeShell("tcsh")
+ return
+ elseif a:name =~ '\<zsh\>'
+ " Some .sh scripts contain #!/bin/zsh.
+ call polyglot#ft#SetFileTypeShell("zsh")
+ return
+ elseif a:name =~ '\<ksh\>'
+ let 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") || a:name =~ '\<bash\>' || a:name =~ '\<bash2\>'
+ let 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 a:name =~ '\<sh\>'
+ let 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
+ call polyglot#ft#SetFileTypeShell("sh")
+endfunc
+
+" For shell-like file types, check for an "exec" command hidden in a comment,
+" as used for Tcl.
+" Also called from scripts.vim, thus can't be local to this script.
+func polyglot#ft#SetFileTypeShell(name)
+ if did_filetype()
+ " Filetype was already detected
+ return
+ endif
+ if expand("<amatch>") =~ g:ft_ignore_pat
+ return
+ endif
+ let l = 2
+ while l < 20 && l < line("$") && getline(l) =~ '^\s*\(#\|$\)'
+ " Skip empty and comment lines.
+ let l = l + 1
+ endwhile
+ if l < line("$") && getline(l) =~ '\s*exec\s' && getline(l - 1) =~ '^\s*#.*\\$'
+ " Found an "exec" line after a comment with continuation
+ let n = substitute(getline(l),'\s*exec\s\+\([^ ]*/\)\=', '', '')
+ if n =~ '\<tclsh\|\<wish'
+ setf tcl
+ return
+ endif
+ endif
+ exe "setf " . a:name
+endfunc
+
+func polyglot#ft#CSH()
+ if did_filetype()
+ " Filetype was already detected
+ return
+ endif
+ if exists("g:filetype_csh")
+ call polyglot#ft#SetFileTypeShell(g:filetype_csh)
+ elseif &shell =~ "tcsh"
+ call polyglot#ft#SetFileTypeShell("tcsh")
+ else
+ call polyglot#ft#SetFileTypeShell("csh")
+ endif
+endfunc
+
+let s:ft_rules_udev_rules_pattern = '^\s*\cudev_rules\s*=\s*"\([^"]\{-1,}\)/*".*'
+func polyglot#ft#FTRules()
+ let 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
+ try
+ let config_lines = readfile('/etc/udev/udev.conf')
+ catch /^Vim\%((\a\+)\)\=:E484/
+ setf hog
+ return
+ endtry
+ let dir = expand('<amatch>:p:h')
+ for line in config_lines
+ if line =~ s:ft_rules_udev_rules_pattern
+ let udev_rules = substitute(line, s:ft_rules_udev_rules_pattern, '\1', "")
+ if dir == udev_rules
+ setf udevrules
+ endif
+ break
+ endif
+ endfor
+ setf hog
+endfunc
+
+func polyglot#ft#SQL()
+ if exists("g:filetype_sql")
+ exe "setf " . g:filetype_sql
+ else
+ setf sql
+ endif
+endfunc
+
+" 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.
+func polyglot#ft#FTperl()
+ let 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
+ let save_cursor = getpos('.')
+ call cursor(1,1)
+ let has_use = search('^use\s\s*\k', 'c', 30)
+ call setpos('.', save_cursor)
+ if has_use
+ setf perl
+ return 1
+ endif
+ return 0
+endfunc
+
+" Choose context, plaintex, or tex (LaTeX) based on these rules:
+" 1. Check the first line of the file for "%&<format>".
+" 2. Check the first 1000 non-comment lines for LaTeX or ConTeXt keywords.
+" 3. Default to "plain" or to g:tex_flavor, can be set in user's vimrc.
+func polyglot#ft#FTtex()
+ let firstline = getline(1)
+ if firstline =~ '^%&\s*\a\+'
+ let format = tolower(matchstr(firstline, '\a\+'))
+ let format = substitute(format, 'pdf', '', '')
+ if format == 'tex'
+ let format = 'latex'
+ elseif format == 'plaintex'
+ let format = 'plain'
+ endif
+ elseif expand('%') =~ 'tex/context/.*/.*.tex'
+ let format = 'context'
+ else
+ " Default value, may be changed later:
+ let format = exists("g:tex_flavor") ? g:tex_flavor : 'plain'
+ " Save position, go to the top of the file, find first non-comment line.
+ let save_cursor = getpos('.')
+ call cursor(1,1)
+ let firstNC = search('^\s*[^[:space:]%]', 'c', 1000)
+ if firstNC " Check the next thousand lines for a LaTeX or ConTeXt keyword.
+ let lpat = 'documentclass\>\|usepackage\>\|begin{\|newcommand\>\|renewcommand\>'
+ let 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\>'
+ let kwline = search('^\s*\\\%(' . lpat . '\)\|^\s*\\\(' . cpat . '\)',
+ \ 'cnp', firstNC + 1000)
+ if kwline == 1 " lpat matched
+ let format = 'latex'
+ elseif kwline == 2 " cpat matched
+ let 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
+endfunc
+
+func polyglot#ft#FTxml()
+ let n = 1
+ while n < 100 && n <= line("$")
+ let line = getline(n)
+ " DocBook 4 or DocBook 5.
+ let is_docbook4 = line =~ '<!DOCTYPE.*DocBook'
+ let is_docbook5 = line =~ ' xmlns="http://docbook.org/ns/docbook"'
+ if is_docbook4 || is_docbook5
+ let b:docbk_type = "xml"
+ if is_docbook5
+ let b:docbk_ver = 5
+ else
+ let b:docbk_ver = 4
+ endif
+ setf docbk
+ return
+ endif
+ if line =~ 'xmlns:xbl="http://www.mozilla.org/xbl"'
+ setf xbl
+ return
+ endif
+ let n += 1
+ endwhile
+ setf xml
+endfunc
+
+func polyglot#ft#FTy()
+ let n = 1
+ while n < 100 && n <= line("$")
+ let line = getline(n)
+ if line =~ '^\s*%'
+ setf yacc
+ return
+ endif
+ if getline(n) =~ '^\s*\(#\|class\>\)' && getline(n) !~ '^\s*#\s*include'
+ setf racc
+ return
+ endif
+ let n = n + 1
+ endwhile
+ setf yacc
+endfunc
+
+func polyglot#ft#Redif()
+ let lnum = 1
+ while lnum <= 5 && lnum < line('$')
+ if getline(lnum) =~ "^\ctemplate-type:"
+ setf redif
+ return
+ endif
+ let lnum = lnum + 1
+ endwhile
+endfunc
+
+
+" Restore 'cpoptions'
+let &cpo = s:cpo_save
+unlet s:cpo_save
diff --git a/autoload/polyglot/shebang.vim b/autoload/polyglot/shebang.vim
index 66ccacd6..62eb11a2 100644
--- a/autoload/polyglot/shebang.vim
+++ b/autoload/polyglot/shebang.vim
@@ -1,14 +1,20 @@
+" Line continuation is used here, remove 'C' from 'cpoptions'
+let s:cpo_save = &cpo
+set cpo&vim
+
func! polyglot#shebang#Detect()
let ft = s:Filetype()
if ft != ""
let &ft = ft
+ return 1
endif
- if &ft == ""
- runtime! scripts.vim
+ let err = polyglot#shebang#VimDetect()
+ if err == ""
+ return 1
endif
- return &ft != ""
+ return 0
endfunc
let s:r_hashbang = '^#!\s*\(\S\+\)\s*\(.*\)\s*'
@@ -58,6 +64,394 @@ func! s:Filetype()
endfor
endfunc
+func! polyglot#shebang#VimDetect()
+ let line1 = getline(1)
+
+ if line1 =~# "^#!"
+ " A script that starts with "#!".
+
+ " Check for a line like "#!/usr/bin/env {options} bash". Turn it into
+ " "#!/usr/bin/bash" to make matching easier.
+ " Recognize only a few {options} that are commonly used.
+ if line1 =~# '^#!\s*\S*\<env\s'
+ let line1 = substitute(line1, '\S\+=\S\+', '', 'g')
+ let line1 = substitute(line1, '\(-[iS]\|--ignore-environment\|--split-string\)', '', '')
+ let line1 = substitute(line1, '\<env\s\+', '', '')
+ endif
+
+ " Get the program name.
+ " Only accept spaces in PC style path "#!c:/program files/perl [args]".
+ " If the word env is used, use the first word after the space:
+ " "#!/usr/bin/env perl [path/args]"
+ " If there is no path use the first word: "#!perl [path/args]".
+ " Otherwise get the last word after a slash: "#!/usr/bin/perl [path/args]".
+ if line1 =~# '^#!\s*\a:[/\\]'
+ let name = substitute(line1, '^#!.*[/\\]\(\i\+\).*', '\1', '')
+ elseif line1 =~# '^#!.*\<env\>'
+ let name = substitute(line1, '^#!.*\<env\>\s\+\(\i\+\).*', '\1', '')
+ elseif line1 =~# '^#!\s*[^/\\ ]*\>\([^/\\]\|$\)'
+ let name = substitute(line1, '^#!\s*\([^/\\ ]*\>\).*', '\1', '')
+ else
+ let name = substitute(line1, '^#!\s*\S*[/\\]\(\i\+\).*', '\1', '')
+ endif
+
+ " tcl scripts may have #!/bin/sh in the first line and "exec wish" in the
+ " third line. Suggested by Steven Atkinson.
+ if getline(3) =~# '^exec wish'
+ let name = 'wish'
+ endif
+
+ " Bourne-like shell script bash bash2 ksh ksh93 sh
+ if name =~# '^\(bash\d*\|\|ksh\d*\|sh\)\>'
+ call dist#ft#SetFileTypeSH(line1) " defined in filetype.vim
+ return
+
+ " csh scripts
+ elseif name =~# '^csh\>'
+ if exists("g:filetype_csh")
+ call dist#ft#SetFileTypeShell(g:filetype_csh)
+ return
+ else
+ call dist#ft#SetFileTypeShell("csh")
+ return
+ endif
+
+ " tcsh scripts
+ elseif name =~# '^tcsh\>'
+ call dist#ft#SetFileTypeShell("tcsh")
+ return
+
+ " Z shell scripts
+ elseif name =~# '^zsh\>'
+ set ft=zsh | return
+
+ " TCL scripts
+ elseif name =~# '^\(tclsh\|wish\|expectk\|itclsh\|itkwish\)\>'
+ set ft=tcl | return
+
+ " Expect scripts
+ elseif name =~# '^expect\>'
+ set ft=expect | return
+
+ " Gnuplot scripts
+ elseif name =~# '^gnuplot\>'
+ set ft=gnuplot | return
+
+ " Makefiles
+ elseif name =~# 'make\>'
+ set ft=make | return
+
+ " Pike
+ elseif name =~# '^pike\%(\>\|[0-9]\)'
+ set ft=pike | return
+
+ " Lua
+ elseif name =~# 'lua'
+ set ft=lua | return
+
+ " Perl 6
+ elseif name =~# 'perl6'
+ set ft=perl6 | return
+
+ " Perl
+ elseif name =~# 'perl'
+ set ft=perl | return
+
+ " PHP
+ elseif name =~# 'php'
+ set ft=php | return
+
+ " Python
+ elseif name =~# 'python'
+ set ft=python | return
+
+ " Groovy
+ elseif name =~# '^groovy\>'
+ set ft=groovy | return
+
+ " Ruby
+ elseif name =~# 'ruby'
+ set ft=ruby | return
+
+ " JavaScript
+ elseif name =~# 'node\(js\)\=\>\|js\>' || name =~# 'rhino\>'
+ set ft=javascript | return
+
+ " BC calculator
+ elseif name =~# '^bc\>'
+ set ft=bc | return
+
+ " sed
+ elseif name =~# 'sed\>'
+ set ft=sed | return
+
+ " OCaml-scripts
+ elseif name =~# 'ocaml'
+ set ft=ocaml | return
+
+ " Awk scripts; also finds "gawk"
+ elseif name =~# 'awk\>'
+ set ft=awk | return
+
+ " Website MetaLanguage
+ elseif name =~# 'wml'
+ set ft=wml | return
+
+ " Scheme scripts
+ elseif name =~# 'scheme'
+ set ft=scheme | return
+
+ " CFEngine scripts
+ elseif name =~# 'cfengine'
+ set ft=cfengine | return
+
+ " Erlang scripts
+ elseif name =~# 'escript'
+ set ft=erlang | return
+
+ " Haskell
+ elseif name =~# 'haskell'
+ set ft=haskell | return
+
+ " Scala
+ elseif name =~# 'scala\>'
+ set ft=scala | return
+
+ " Clojure
+ elseif name =~# 'clojure'
+ set ft=clojure | return
+
+ endif
+ unlet name
+
+ else
+ " File does not start with "#!".
+
+ let line2 = getline(2)
+ let line3 = getline(3)
+ let line4 = getline(4)
+ let line5 = getline(5)
+
+ " Bourne-like shell script sh ksh bash bash2
+ if line1 =~# '^:$'
+ call dist#ft#SetFileTypeSH(line1) " defined in filetype.vim
+ return
+
+ " Z shell scripts
+ elseif line1 =~# '^#compdef\>' || line1 =~# '^#autoload\>' ||
+ \ "\n".line1."\n".line2."\n".line3."\n".line4."\n".line5 =~# '\n\s*emulate\s\+\%(-[LR]\s\+\)\=[ckz]\=sh\>'
+ set ft=zsh | return
+
+ " ELM Mail files
+ elseif line1 =~# '^From \([a-zA-Z][a-zA-Z_0-9\.=-]*\(@[^ ]*\)\=\|-\) .* \(19\|20\)\d\d$'
+ set ft=mail | return
+
+ " Mason
+ elseif line1 =~# '^<[%&].*>'
+ set ft=mason | return
+
+ " Vim scripts (must have '" vim' as the first line to trigger this)
+ elseif line1 =~# '^" *[vV]im$'
+ set ft=vim | return
+
+ " libcxx and libstdc++ standard library headers like "iostream" do not have
+ " an extension, recognize the Emacs file mode.
+ elseif line1 =~? '-\*-.*C++.*-\*-'
+ set ft=cpp | return
+
+ " MOO
+ elseif line1 =~# '^\*\* LambdaMOO Database, Format Version \%([1-3]\>\)\@!\d\+ \*\*$'
+ set ft=moo | return
+
+ " Diff file:
+ " - "diff" in first line (context diff)
+ " - "Only in " in first line
+ " - "--- " in first line and "+++ " in second line (unified diff).
+ " - "*** " in first line and "--- " in second line (context diff).
+ " - "# It was generated by makepatch " in the second line (makepatch diff).
+ " - "Index: <filename>" in the first line (CVS file)
+ " - "=== ", line of "=", "---", "+++ " (SVK diff)
+ " - "=== ", "--- ", "+++ " (bzr diff, common case)
+ " - "=== (removed|added|renamed|modified)" (bzr diff, alternative)
+ " - "# HG changeset patch" in first line (Mercurial export format)
+ elseif line1 =~# '^\(diff\>\|Only in \|\d\+\(,\d\+\)\=[cda]\d\+\>\|# It was generated by makepatch \|Index:\s\+\f\+\r\=$\|===== \f\+ \d\+\.\d\+ vs edited\|==== //\f\+#\d\+\|# HG changeset patch\)'
+ \ || (line1 =~# '^--- ' && line2 =~# '^+++ ')
+ \ || (line1 =~# '^\* looking for ' && line2 =~# '^\* comparing to ')
+ \ || (line1 =~# '^\*\*\* ' && line2 =~# '^--- ')
+ \ || (line1 =~# '^=== ' && ((line2 =~# '^=\{66\}' && line3 =~# '^--- ' && line4 =~# '^+++') || (line2 =~# '^--- ' && line3 =~# '^+++ ')))
+ \ || (line1 =~# '^=== \(removed\|added\|renamed\|modified\)')
+ set ft=diff | return
+
+ " PostScript Files (must have %!PS as the first line, like a2ps output)
+ elseif line1 =~# '^%![ \t]*PS'
+ set ft=postscr | return
+
+ " M4 script Guess there is a line that starts with "dnl".
+ elseif line1 =~# '^\s*dnl\>'
+ \ || line2 =~# '^\s*dnl\>'
+ \ || line3 =~# '^\s*dnl\>'
+ \ || line4 =~# '^\s*dnl\>'
+ \ || line5 =~# '^\s*dnl\>'
+ set ft=m4 | return
+
+ " AmigaDos scripts
+ elseif $TERM == "amiga"
+ \ && (line1 =~# "^;" || line1 =~? '^\.bra')
+ set ft=amiga | return
+
+ " SiCAD scripts (must have procn or procd as the first line to trigger this)
+ elseif line1 =~? '^ *proc[nd] *$'
+ set ft=sicad | return
+
+ " Purify log files start with "**** Purify"
+ elseif line1 =~# '^\*\*\*\* Purify'
+ set ft=purifylog | return
+
+ " XML
+ elseif line1 =~# '<?\s*xml.*?>'
+ set ft=xml | return
+
+ " XHTML (e.g.: PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN")
+ elseif line1 =~# '\<DTD\s\+XHTML\s'
+ set ft=xhtml | return
+
+ " HTML (e.g.: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN")
+ " Avoid "doctype html", used by slim.
+ elseif line1 =~? '<!DOCTYPE\s\+html\>'
+ set ft=html | return
+
+ " PDF
+ elseif line1 =~# '^%PDF-'
+ set ft=pdf | return
+
+ " XXD output
+ elseif line1 =~# '^\x\{7}: \x\{2} \=\x\{2} \=\x\{2} \=\x\{2} '
+ set ft=xxd | return
+
+ " RCS/CVS log output
+ elseif line1 =~# '^RCS file:' || line2 =~# '^RCS file:'
+ set ft=rcslog | return
+
+ " CVS commit
+ elseif line2 =~# '^CV' || getline("$") =~# '^CV '
+ set ft=cvs | return
+
+ " Prescribe
+ elseif line1 =~# '^!R!'
+ set ft=prescribe | return
+
+ " Send-pr
+ elseif line1 =~# '^SEND-PR:'
+ set ft=sendpr | return
+
+ " SNNS files
+ elseif line1 =~# '^SNNS network definition file'
+ set ft=snnsnet | return
+ elseif line1 =~# '^SNNS pattern definition file'
+ set ft=snnspat | return
+ elseif line1 =~# '^SNNS result file'
+ set ft=snnsres | return
+
+ " Virata
+ elseif line1 =~# '^%.\{-}[Vv]irata'
+ \ || line2 =~# '^%.\{-}[Vv]irata'
+ \ || line3 =~# '^%.\{-}[Vv]irata'
+ \ || line4 =~# '^%.\{-}[Vv]irata'
+ \ || line5 =~# '^%.\{-}[Vv]irata'
+ set ft=virata | return
+
+ " Strace
+ elseif line1 =~# '[0-9:.]* *execve(' || line1 =~# '^__libc_start_main'
+ set ft=strace | return
+
+ " VSE JCL
+ elseif line1 =~# '^\* $$ JOB\>' || line1 =~# '^// *JOB\>'
+ set ft=vsejcl | return
+
+ " TAK and SINDA
+ elseif line4 =~# 'K & K Associates' || line2 =~# 'TAK 2000'
+ set ft=takout | return
+ elseif line3 =~# 'S Y S T E M S I M P R O V E D '
+ set ft=sindaout | return
+ elseif getline(6) =~# 'Run Date: '
+ set ft=takcmp | return
+ elseif getline(9) =~# 'Node File 1'
+ set ft=sindacmp | return
+
+ " DNS zone files
+ elseif line1.line2.line3.line4 =~# '^; <<>> DiG [0-9.]\+.* <<>>\|$ORIGIN\|$TTL\|IN\s\+SOA'
+ set ft=bindzone | return
+
+ " BAAN
+ elseif line1 =~# '|\*\{1,80}' && line2 =~# 'VRC '
+ \ || line2 =~# '|\*\{1,80}' && line3 =~# 'VRC '
+ set ft=baan | return
+
+ " Valgrind
+ elseif line1 =~# '^==\d\+== valgrind' || line3 =~# '^==\d\+== Using valgrind'
+ set ft=valgrind | return
+
+ " Go docs
+ elseif line1 =~# '^PACKAGE DOCUMENTATION$'
+ set ft=godoc | return
+
+ " Renderman Interface Bytestream
+ elseif line1 =~# '^##RenderMan'
+ set ft=rib | return
+
+ " Scheme scripts
+ elseif line1 =~# 'exec\s\+\S*scheme' || line2 =~# 'exec\s\+\S*scheme'
+ set ft=scheme | return
+
+ " Git output
+ elseif line1 =~# '^\(commit\|tree\|object\) \x\{40\}\>\|^tag \S\+$'
+ set ft=git | return
+
+ " Gprof (gnu profiler)
+ elseif line1 == 'Flat profile:'
+ \ && line2 == ''
+ \ && line3 =~# '^Each sample counts as .* seconds.$'
+ set ft=gprof | return
+
+ " Erlang terms
+ " (See also: http://www.gnu.org/software/emacs/manual/html_node/emacs/Choosing-Modes.html#Choosing-Modes)
+ elseif line1 =~? '-\*-.*erlang.*-\*-'
+ set ft=erlang | return
+
+ " YAML
+ elseif line1 =~# '^%YAML'
+ set ft=yaml | return
+
+ " CVS diff
+ else
+ let lnum = 1
+ while getline(lnum) =~# "^? " && lnum < line("$")
+ let lnum += 1
+ endwhile
+ if getline(lnum) =~# '^Index:\s\+\f\+$'
+ set ft=diff | return
+
+ " locale input file Formal Definitions of Cultural Conventions
+ " filename must be like en_US, fr_FR@euro or en_US.UTF-8
+ elseif expand("%") =~# '\a\a_\a\a\($\|[.@]\)\|i18n$\|POSIX$\|translit_'
+ let lnum = 1
+ while lnum < 100 && lnum < line("$")
+ if getline(lnum) =~# '^LC_\(IDENTIFICATION\|CTYPE\|COLLATE\|MONETARY\|NUMERIC\|TIME\|MESSAGES\|PAPER\|TELEPHONE\|MEASUREMENT\|NAME\|ADDRESS\)$'
+ setf fdcc | return
+ break
+ endif
+ let lnum += 1
+ endwhile
+ endif
+ unlet lnum
+
+ endif
+
+ endif
+
+ return 1
+endfunc
+
" DO NOT EDIT CODE BELOW, IT IS GENERATED WITH MAKEFILE
let s:interpreters = {
@@ -71,7 +465,9 @@ let s:interpreters = {
\ 'fish': 'fish',
\ 'gnuplot': 'gnuplot',
\ 'groovy': 'groovy',
+ \ 'runghc': 'haskell',
\ 'runhaskell': 'haskell',
+ \ 'runhugs': 'haskell',
\ 'chakra': 'javascript',
\ 'd8': 'javascript',
\ 'gjs': 'javascript',
@@ -131,3 +527,7 @@ let s:interpreters = {
\ 'deno': 'typescript',
\ 'ts-node': 'typescript',
\ }
+" DO NOT EDIT CODE ABOVE, IT IS GENERATED WITH MAKEFILE
+
+let &cpo = s:cpo_save
+unlet s:cpo_save
diff --git a/autoload/polyglot/sleuth.vim b/autoload/polyglot/sleuth.vim
index 0c3c34e8..d74de687 100644
--- a/autoload/polyglot/sleuth.vim
+++ b/autoload/polyglot/sleuth.vim
@@ -1,5 +1,3 @@
-" DO NOT EDIT CODE BELOW, IT IS GENERATED WITH MAKEFILE
-
let s:globs = {
\ '8th': '*.8th',
\ 'Dockerfile': '*.dockerfile,*.dock,*.Dockerfile,Dockerfile,dockerfile,Dockerfile*',