diff options
Diffstat (limited to '')
| -rw-r--r-- | Makefile | 2 | ||||
| -rw-r--r-- | autoload/polyglot/detect.vim | 25 | ||||
| -rw-r--r-- | autoload/polyglot/ft.vim | 757 | ||||
| -rw-r--r-- | autoload/polyglot/shebang.vim | 406 | ||||
| -rw-r--r-- | autoload/polyglot/sleuth.vim | 2 | ||||
| -rw-r--r-- | ftdetect/polyglot.vim | 107 | ||||
| -rwxr-xr-x | scripts/build | 33 | 
7 files changed, 1251 insertions, 81 deletions
| @@ -7,4 +7,4 @@ test:  	@ scripts/test  dev: -	@ find scripts . -type f -depth 1 | DEV=1 entr bash -c 'make && make test' +	@ find scripts autoload/polyglot ftdetect tests . -type f -depth 1 | DEV=1 entr bash -c 'make && make test' 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*', diff --git a/ftdetect/polyglot.vim b/ftdetect/polyglot.vim index 498450d8..b3d04eff 100644 --- a/ftdetect/polyglot.vim +++ b/ftdetect/polyglot.vim @@ -1006,6 +1006,7 @@ if !has_key(s:disabled_packages, '8th')    au BufNewFile,BufRead *.8th setf 8th  endif +  " DO NOT EDIT CODE ABOVE, IT IS GENERATED WITH MAKEFILE  au! BufNewFile,BufRead,StdinReadPost * if expand("<afile>:e") == "" | @@ -1245,7 +1246,7 @@ endif  au BufNewFile,BufRead $VIMRUNTIME/doc/*.txt	setf help  " Abaqus or Trasys -au BufNewFile,BufRead *.inp			call dist#ft#Check_inp() +au BufNewFile,BufRead *.inp			call polyglot#ft#Check_inp()  " 8th (Firth-derivative)  au BufNewFile,BufRead *.8th			setf 8th @@ -1351,7 +1352,7 @@ au BufNewFile,BufRead */boot/grub/menu.lst,*/boot/grub/grub.conf,*/etc/grub.conf  " Assembly (all kinds)  " *.lst is not pure assembly, it has two extra columns (address, byte codes) -au BufNewFile,BufRead *.asm,*.[sS],*.[aA],*.mac,*.lst	call dist#ft#FTasm() +au BufNewFile,BufRead *.asm,*.[sS],*.[aA],*.mac,*.lst	call polyglot#ft#FTasm()  " Macro (VAX)  au BufNewFile,BufRead *.mar			setf vmasm @@ -1381,7 +1382,7 @@ au BufNewFile,BufRead *.awk,*.gawk		setf awk  au BufNewFile,BufRead *.mch,*.ref,*.imp		setf b  " BASIC or Visual Basic -au BufNewFile,BufRead *.bas			call dist#ft#FTVB("basic") +au BufNewFile,BufRead *.bas			call polyglot#ft#FTVB("basic")  " Visual Basic Script (close to Visual Basic) or Visual Basic .NET  au BufNewFile,BufRead *.vb,*.vbs,*.dsm,*.ctl	setf vb @@ -1399,7 +1400,7 @@ au BufNewFile,BufRead *.cmd  	\ if getline(1) =~ '^/\*' | setf rexx | else | setf dosbatch | endif  " Batch file for 4DOS -au BufNewFile,BufRead *.btm			call dist#ft#FTbtm() +au BufNewFile,BufRead *.btm			call polyglot#ft#FTbtm()  " BC calculator  au BufNewFile,BufRead *.bc			setf bc @@ -1419,7 +1420,7 @@ au BufNewFile,BufRead named*.conf,rndc*.conf,rndc*.key	setf named  " BIND zone  au BufNewFile,BufRead named.root		setf bindzone -au BufNewFile,BufRead *.db			call dist#ft#BindzoneCheck('') +au BufNewFile,BufRead *.db			call polyglot#ft#BindzoneCheck('')  " Blank  au BufNewFile,BufRead *.bl			setf blank @@ -1438,7 +1439,7 @@ if has("fname_case")  endif  " C or lpc -au BufNewFile,BufRead *.c			call dist#ft#FTlpc() +au BufNewFile,BufRead *.c			call polyglot#ft#FTlpc()  au BufNewFile,BufRead *.lpc,*.ulpc		setf lpc  " Calendar @@ -1493,7 +1494,7 @@ endif  " .h files can be C, Ch C++, ObjC or ObjC++.  " Set c_syntax_for_h if you want C, ch_syntax_for_h if you want Ch. ObjC is  " detected automatically. -au BufNewFile,BufRead *.h			call dist#ft#FTheader() +au BufNewFile,BufRead *.h			call polyglot#ft#FTheader()  " Ch (CHscript)  au BufNewFile,BufRead *.chf			setf ch @@ -1527,7 +1528,7 @@ au BufNewFile,BufRead NEWS  au BufNewFile,BufRead *..ch			setf chill  " Changes for WEB and CWEB or CHILL -au BufNewFile,BufRead *.ch			call dist#ft#FTchange() +au BufNewFile,BufRead *.ch			call polyglot#ft#FTchange()  " ChordPro  au BufNewFile,BufRead *.chopro,*.crd,*.cho,*.crdpro,*.chordpro	setf chordpro @@ -1539,7 +1540,7 @@ au BufNewFile,BufRead *.dcl,*.icl		setf clean  au BufNewFile,BufRead *.eni			setf cl  " Clever or dtd -au BufNewFile,BufRead *.ent			call dist#ft#FTent() +au BufNewFile,BufRead *.ent			call polyglot#ft#FTent()  " Clipper (or FoxPro; could also be eviews)  au BufNewFile,BufRead *.prg @@ -1594,9 +1595,9 @@ au BufNewFile,BufRead *enlightenment/*.cfg	setf c  au BufNewFile,BufRead *Eterm/*.cfg		setf eterm  " Euphoria 3 or 4 -au BufNewFile,BufRead *.eu,*.ew,*.ex,*.exu,*.exw  call dist#ft#EuphoriaCheck() +au BufNewFile,BufRead *.eu,*.ew,*.ex,*.exu,*.exw  call polyglot#ft#EuphoriaCheck()  if has("fname_case") -   au BufNewFile,BufRead *.EU,*.EW,*.EX,*.EXU,*.EXW  call dist#ft#EuphoriaCheck() +   au BufNewFile,BufRead *.EU,*.EW,*.EX,*.EXU,*.EXW  call polyglot#ft#EuphoriaCheck()  endif  " Lynx config files @@ -1653,7 +1654,7 @@ au BufNewFile,BufRead */etc/dnsmasq.conf	setf dnsmasq  au BufNewFile,BufRead *.desc			setf desc  " the D language or dtrace -au BufNewFile,BufRead *.d			call dist#ft#DtraceCheck() +au BufNewFile,BufRead *.d			call polyglot#ft#DtraceCheck()  " Desktop files  au BufNewFile,BufRead *.desktop,*.directory	setf desktop @@ -1685,7 +1686,7 @@ au BufNewFile,BufRead *.rul  	\ endif  " DCL (Digital Command Language - vms) or DNS zone file -au BufNewFile,BufRead *.com			call dist#ft#BindzoneCheck('dcl') +au BufNewFile,BufRead *.com			call polyglot#ft#BindzoneCheck('dcl')  " DOT  au BufNewFile,BufRead *.dot,*.gv		setf dot @@ -1733,7 +1734,7 @@ au BufNewFile,BufRead .editorconfig		setf dosini  au BufNewFile,BufRead *.ecd			setf ecd  " Eiffel or Specman or Euphoria -au BufNewFile,BufRead *.e,*.E			call dist#ft#FTe() +au BufNewFile,BufRead *.e,*.E			call polyglot#ft#FTe()  " Elinks configuration  au BufNewFile,BufRead elinks.conf		setf elinks @@ -1911,7 +1912,7 @@ au BufRead,BufNewFile *.hws			setf hollywood  au BufNewFile,BufRead *.t.html			setf tilde  " HTML (.shtml and .stm for server side) -au BufNewFile,BufRead *.html,*.htm,*.shtml,*.stm  call dist#ft#FThtml() +au BufNewFile,BufRead *.html,*.htm,*.shtml,*.stm  call polyglot#ft#FThtml()  " HTML with Ruby - eRuby  au BufNewFile,BufRead *.erb,*.rhtml		setf eruby @@ -1938,7 +1939,7 @@ au BufNewFile,BufRead *.htt,*.htb		setf httest  au BufNewFile,BufRead *.icn			setf icon  " IDL (Interface Description Language) -au BufNewFile,BufRead *.idl			call dist#ft#FTidl() +au BufNewFile,BufRead *.idl			call polyglot#ft#FTidl()  " Microsoft IDL (Interface Description Language)  Also *.idl  " MOF = WMI (Windows Management Instrumentation) Managed Object Format @@ -1949,10 +1950,10 @@ au BufNewFile,BufRead */.icewm/menu		setf icemenu  " Indent profile (must come before IDL *.pro!)  au BufNewFile,BufRead .indent.pro		setf indent -au BufNewFile,BufRead indent.pro		call dist#ft#ProtoCheck('indent') +au BufNewFile,BufRead indent.pro		call polyglot#ft#ProtoCheck('indent')  " IDL (Interactive Data Language) -au BufNewFile,BufRead *.pro			call dist#ft#ProtoCheck('idlang') +au BufNewFile,BufRead *.pro			call polyglot#ft#ProtoCheck('idlang')  " Indent RC  au BufNewFile,BufRead indentrc			setf indent @@ -2172,7 +2173,7 @@ au BufNewFile,BufRead *.markdown,*.mdown,*.mkd,*.mkdn,*.mdwn,*.md  setf markdown  au BufNewFile,BufRead *.mason,*.mhtml,*.comp	setf mason  " Mathematica, Matlab, Murphi or Objective C -au BufNewFile,BufRead *.m			call dist#ft#FTm() +au BufNewFile,BufRead *.m			call polyglot#ft#FTm()  " Mathematica notebook  au BufNewFile,BufRead *.nb			setf mma @@ -2205,7 +2206,7 @@ au BufNewFile,BufRead *.mgl			setf mgl  au BufNewFile,BufRead *.mix,*.mixal		setf mix  " MMIX or VMS makefile -au BufNewFile,BufRead *.mms			call dist#ft#FTmms() +au BufNewFile,BufRead *.mms			call polyglot#ft#FTmms()  " Symbian meta-makefile definition (MMP)  au BufNewFile,BufRead *.mmp			setf mmp @@ -2296,10 +2297,10 @@ au BufNewFile,BufRead *.me  	\   setf nroff |  	\ endif  au BufNewFile,BufRead *.tr,*.nr,*.roff,*.tmac,*.mom	setf nroff -au BufNewFile,BufRead *.[1-9]			call dist#ft#FTnroff() +au BufNewFile,BufRead *.[1-9]			call polyglot#ft#FTnroff()  " Nroff or Objective C++ -au BufNewFile,BufRead *.mm			call dist#ft#FTmm() +au BufNewFile,BufRead *.mm			call polyglot#ft#FTmm()  " Not Quite C  au BufNewFile,BufRead *.nqc			setf nqc @@ -2366,9 +2367,9 @@ au BufNewFile,BufRead *.pcmk			setf pcmk  " Perl  if has("fname_case") -  au BufNewFile,BufRead *.pl,*.PL		call dist#ft#FTpl() +  au BufNewFile,BufRead *.pl,*.PL		call polyglot#ft#FTpl()  else -  au BufNewFile,BufRead *.pl			call dist#ft#FTpl() +  au BufNewFile,BufRead *.pl			call polyglot#ft#FTpl()  endif  au BufNewFile,BufRead *.plx,*.al,*.psgi		setf perl  au BufNewFile,BufRead *.p6,*.pm6,*.pl6		setf perl6 @@ -2444,7 +2445,7 @@ au BufNewFile,BufRead *.pov			setf pov  au BufNewFile,BufRead .povrayrc			setf povini  " Povray, PHP or assembly -au BufNewFile,BufRead *.inc			call dist#ft#FTinc() +au BufNewFile,BufRead *.inc			call polyglot#ft#FTinc()  " Printcap and Termcap  au BufNewFile,BufRead *printcap @@ -2473,13 +2474,13 @@ au BufNewFile,BufRead *.action			setf privoxy  au BufNewFile,BufRead .procmail,.procmailrc	setf procmail  " Progress or CWEB -au BufNewFile,BufRead *.w			call dist#ft#FTprogress_cweb() +au BufNewFile,BufRead *.w			call polyglot#ft#FTprogress_cweb()  " Progress or assembly -au BufNewFile,BufRead *.i			call dist#ft#FTprogress_asm() +au BufNewFile,BufRead *.i			call polyglot#ft#FTprogress_asm()  " Progress or Pascal -au BufNewFile,BufRead *.p			call dist#ft#FTprogress_pascal() +au BufNewFile,BufRead *.p			call polyglot#ft#FTprogress_pascal()  " Software Distributor Product Specification File (POSIX 1387.2-1995)  au BufNewFile,BufRead *.psf			setf psf @@ -2569,7 +2570,7 @@ else  endif  " Rexx, Rebol or R -au BufNewFile,BufRead *.r,*.R				call dist#ft#FTr() +au BufNewFile,BufRead *.r,*.R				call polyglot#ft#FTr()  " Remind  au BufNewFile,BufRead .reminders,*.remind,*.rem		setf remind @@ -2665,7 +2666,7 @@ au BufNewFile,BufRead *.siv,*.sieve		setf sieve  au BufNewFile,BufRead sendmail.cf		setf sm  " Sendmail .mc files are actually m4.  Could also be MS Message text file. -au BufNewFile,BufRead *.mc			call dist#ft#McSetf() +au BufNewFile,BufRead *.mc			call polyglot#ft#McSetf()  " Services  au BufNewFile,BufRead */etc/services		setf services @@ -2706,9 +2707,9 @@ au BufNewFile,BufRead catalog			setf catalog  " Shell scripts (sh, ksh, bash, bash2, csh); Allow .profile_foo etc.  " Gentoo ebuilds and Arch Linux PKGBUILDs are actually bash scripts  " NOTE: Patterns ending in a star are further down, these have lower priority. -au BufNewFile,BufRead .bashrc,bashrc,bash.bashrc,.bash[_-]profile,.bash[_-]logout,.bash[_-]aliases,bash-fc[-.],*.bash,*/{,.}bash[_-]completion{,.d,.sh}{,/*},*.ebuild,*.eclass,PKGBUILD call dist#ft#SetFileTypeSH("bash") -au BufNewFile,BufRead .kshrc,*.ksh call dist#ft#SetFileTypeSH("ksh") -au BufNewFile,BufRead */etc/profile,.profile,*.sh,*.env call dist#ft#SetFileTypeSH(getline(1)) +au BufNewFile,BufRead .bashrc,bashrc,bash.bashrc,.bash[_-]profile,.bash[_-]logout,.bash[_-]aliases,bash-fc[-.],*.bash,*/{,.}bash[_-]completion{,.d,.sh}{,/*},*.ebuild,*.eclass,PKGBUILD call polyglot#ft#SetFileTypeSH("bash") +au BufNewFile,BufRead .kshrc,*.ksh call polyglot#ft#SetFileTypeSH("ksh") +au BufNewFile,BufRead */etc/profile,.profile,*.sh,*.env call polyglot#ft#SetFileTypeSH(getline(1))  " Shell script (Arch Linux) or PHP file (Drupal) @@ -2716,15 +2717,15 @@ au BufNewFile,BufRead *.install  	\ if getline(1) =~ '<?php' |  	\   setf php |  	\ else | -	\   call dist#ft#SetFileTypeSH("bash") | +	\   call polyglot#ft#SetFileTypeSH("bash") |  	\ endif  " tcsh scripts (patterns ending in a star further below) -au BufNewFile,BufRead .tcshrc,*.tcsh,tcsh.tcshrc,tcsh.login	call dist#ft#SetFileTypeShell("tcsh") +au BufNewFile,BufRead .tcshrc,*.tcsh,tcsh.tcshrc,tcsh.login	call polyglot#ft#SetFileTypeShell("tcsh")  " csh scripts, but might also be tcsh scripts (on some systems csh is tcsh)  " (patterns ending in a start further below) -au BufNewFile,BufRead .login,.cshrc,csh.cshrc,csh.login,csh.logout,*.csh,.alias  call dist#ft#CSH() +au BufNewFile,BufRead .login,.cshrc,csh.cshrc,csh.login,csh.logout,*.csh,.alias  call polyglot#ft#CSH()  " Z-Shell script (patterns ending in a star further below)  au BufNewFile,BufRead .zprofile,*/etc/zprofile,.zfbfmarks  setf zsh @@ -2795,7 +2796,7 @@ au BufNewFile,BufRead *.mib,*.my		setf mib  " Snort Configuration  au BufNewFile,BufRead *.hog,snort.conf,vision.conf	setf hog -au BufNewFile,BufRead *.rules			call dist#ft#FTRules() +au BufNewFile,BufRead *.rules			call polyglot#ft#FTRules()  " Spec (Linux RPM)  au BufNewFile,BufRead *.spec			setf spec @@ -2819,7 +2820,7 @@ au BufNewFile,BufRead squid.conf		setf squid  au BufNewFile,BufRead *.tyb,*.typ,*.tyc,*.pkb,*.pks	setf sql  " SQL -au BufNewFile,BufRead *.sql			call dist#ft#SQL() +au BufNewFile,BufRead *.sql			call polyglot#ft#SQL()  " SQLJ  au BufNewFile,BufRead *.sqlj			setf sqlj @@ -2885,8 +2886,8 @@ au BufNewFile,BufRead */etc/sudoers,sudoers.tmp	setf sudoers  au BufNewFile,BufRead *.svg			setf svg  " Tads (or Nroff or Perl test file) -au BufNewFile,BufRead *.t -	\ if !dist#ft#FTnroff() && !dist#ft#FTperl() | setf tads | endif +"au BufNewFile,BufRead *.t +"	\ if !polyglot#ft#FTnroff() && !polyglot#ft#FTperl() | setf tads | endif  " Tags  au BufNewFile,BufRead tags			setf tags @@ -2915,7 +2916,7 @@ au BufNewFile,BufRead *.ti			setf terminfo  " TeX  au BufNewFile,BufRead *.latex,*.sty,*.dtx,*.ltx,*.bbl	setf tex -au BufNewFile,BufRead *.tex			call dist#ft#FTtex() +au BufNewFile,BufRead *.tex			call polyglot#ft#FTtex()  " ConTeXt  au BufNewFile,BufRead *.mkii,*.mkiv,*.mkvi   setf context @@ -3018,7 +3019,7 @@ au BufRead,BufNewFile *.hw,*.module,*.pkg  	\ endif  " Visual Basic (also uses *.bas) or FORM -au BufNewFile,BufRead *.frm			call dist#ft#FTVB("form") +au BufNewFile,BufRead *.frm			call polyglot#ft#FTVB("form")  " SaxBasic is close to Visual Basic  au BufNewFile,BufRead *.sba			setf vb @@ -3114,10 +3115,10 @@ au BufNewFile,BufRead .Xdefaults,.Xpdefaults,.Xresources,xdm-config,*.ad setf xd  " Xmath  au BufNewFile,BufRead *.msc,*.msf		setf xmath  au BufNewFile,BufRead *.ms -	\ if !dist#ft#FTnroff() | setf xmath | endif +	\ if !polyglot#ft#FTnroff() | setf xmath | endif  " XML  specific variants: docbk and xbl -au BufNewFile,BufRead *.xml			call dist#ft#FTxml() +au BufNewFile,BufRead *.xml			call polyglot#ft#FTxml()  " XMI (holding UML models) is also XML  au BufNewFile,BufRead *.xmi			setf xml @@ -3164,7 +3165,7 @@ au BufNewFile,BufRead *.xsl,*.xslt		setf xslt  au BufNewFile,BufRead *.yy,*.yxx,*.y++		setf yacc  " Yacc or racc -au BufNewFile,BufRead *.y			call dist#ft#FTy() +au BufNewFile,BufRead *.y			call polyglot#ft#FTy()  " Yaml  au BufNewFile,BufRead *.yaml,*.yml		setf yaml @@ -3183,9 +3184,9 @@ au BufNewFile,BufRead *.zut			setf zimbutempl  " Zope  "   dtml (zope dynamic template markup language), pt (zope page template),  "   cpt (zope form controller page template) -au BufNewFile,BufRead *.dtml,*.pt,*.cpt		call dist#ft#FThtml() +au BufNewFile,BufRead *.dtml,*.pt,*.cpt		call polyglot#ft#FThtml()  "   zsql (zope sql method) -au BufNewFile,BufRead *.zsql			call dist#ft#SQL() +au BufNewFile,BufRead *.zsql			call polyglot#ft#SQL()  " Z80 assembler asz80  au BufNewFile,BufRead *.z8a			setf z8a @@ -3352,7 +3353,7 @@ au BufNewFile,BufRead *termcap*  " ReDIF  " Only used when the .rdf file was not detected to be XML. -au BufRead,BufNewFile *.rdf			call dist#ft#Redif() +au BufRead,BufNewFile *.rdf			call polyglot#ft#Redif()  " Remind  au BufNewFile,BufRead .reminders*		call s:StarSetf('remind') @@ -3361,15 +3362,15 @@ au BufNewFile,BufRead .reminders*		call s:StarSetf('remind')  au BufNewFile,BufRead sgml.catalog*		call s:StarSetf('catalog')  " Shell scripts ending in a star -au BufNewFile,BufRead .bashrc*,.bash[_-]profile*,.bash[_-]logout*,.bash[_-]aliases*,bash-fc[-.]*,,PKGBUILD* call dist#ft#SetFileTypeSH("bash") -au BufNewFile,BufRead .kshrc* call dist#ft#SetFileTypeSH("ksh") -au BufNewFile,BufRead .profile* call dist#ft#SetFileTypeSH(getline(1)) +au BufNewFile,BufRead .bashrc*,.bash[_-]profile*,.bash[_-]logout*,.bash[_-]aliases*,bash-fc[-.]*,,PKGBUILD* call polyglot#ft#SetFileTypeSH("bash") +au BufNewFile,BufRead .kshrc* call polyglot#ft#SetFileTypeSH("ksh") +au BufNewFile,BufRead .profile* call polyglot#ft#SetFileTypeSH(getline(1))  " tcsh scripts ending in a star -au BufNewFile,BufRead .tcshrc*	call dist#ft#SetFileTypeShell("tcsh") +au BufNewFile,BufRead .tcshrc*	call polyglot#ft#SetFileTypeShell("tcsh")  " csh scripts ending in a star -au BufNewFile,BufRead .login*,.cshrc*  call dist#ft#CSH() +au BufNewFile,BufRead .login*,.cshrc*  call polyglot#ft#CSH()  " VHDL  au BufNewFile,BufRead *.vhdl_[0-9]*		call s:StarSetf('vhdl') diff --git a/scripts/build b/scripts/build index 8b40e571..48ed10a1 100755 --- a/scripts/build +++ b/scripts/build @@ -392,7 +392,8 @@ def rule_to_code(rule)    if rule.has_key?("filetype")      if rule.has_key?("fallback")        return <<~EOS -        set ft=#{rule["filetype"]} | au BufWritePost <buffer> ++once call polyglot#detect##{camelize(rule["extensions"].first)}() +        setf #{rule["filetype"]} +        call s:WritePostOnce('call polyglot#detect##{camelize(rule["extensions"].first)}()')          return        EOS      end @@ -496,7 +497,7 @@ end  def generate_ftdetect(packages, heuristics)    FileUtils.mkdir_p('autoload/polyglot') -  output = "\n" +  output = ""    all_filetypes = packages.flat_map { |f| f["filetypes"] || [] }    filetype_names = Set.new(all_filetypes.map { |f| f["name"] }) @@ -581,17 +582,9 @@ def generate_ftdetect(packages, heuristics)    show_warnings(all_filetypes, expected_filetypes) -  ftdetect = File.read('ftdetect/polyglot.vim') - -  starting = '" DO NOT EDIT CODE BELOW, IT IS GENERATED WITH MAKEFILE' -  ending = '" DO NOT EDIT CODE ABOVE, IT IS GENERATED WITH MAKEFILE' - -  File.write( -    'ftdetect/polyglot.vim', -    ftdetect.gsub(/(?<=#{starting}\n)(.*)(?=#{ending})/m) { output } -  ) +  inject_code('ftdetect/polyglot.vim', output) -  output = ["\" DO NOT EDIT CODE BELOW, IT IS GENERATED WITH MAKEFILE\n"] +  output = []    for heuristic in heuristics      output << <<~EOS @@ -601,7 +594,7 @@ def generate_ftdetect(packages, heuristics)      EOS    end -  File.write('autoload/polyglot/detect.vim', output.join("\n")) +  inject_code('autoload/polyglot/detect.vim', output.join("\n"))    output = <<~EOS      let s:interpreters = { @@ -619,9 +612,15 @@ def generate_ftdetect(packages, heuristics)  end  def inject_code(path, code) -  header = "\" DO NOT EDIT CODE BELOW, IT IS GENERATED WITH MAKEFILE\n" -  normal, generated = File.read(path).split(header) -  File.write(path, [normal, generated].join(header)) +  source = File.read(path) + +  starting = '" DO NOT EDIT CODE BELOW, IT IS GENERATED WITH MAKEFILE' +  ending = '" DO NOT EDIT CODE ABOVE, IT IS GENERATED WITH MAKEFILE' + +  File.write( +    path, +    source.gsub(/(?<=#{starting}\n)(.*)(?=#{ending})/m) { "\n" + code + "\n" } +  )  end  def generate_tests(packages) @@ -739,8 +738,6 @@ end  def generate_plugins(packages)    output = <<~EOS -    " DO NOT EDIT CODE BELOW, IT IS GENERATED WITH MAKEFILE -      let s:globs = {    EOS | 
