diff options
Diffstat (limited to 'autoload')
| -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 | 
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*', | 
