" 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 let err = polyglot#shebang#VimDetect() if err == "" return 1 endif return 0 endfunc let s:r_hashbang = '^#!\s*\(\S\+\)\s*\(.*\)\s*' let s:r_envflag = '%(\S\+=\S\+\|-[iS]\|--ignore-environment\|--split-string\)' let s:r_env = '^\%(\' . s:r_envflag . '\s\+\)*\(\S\+\)' func! s:Filetype() let l:line1 = getline(1) if l:line1 !~# "^#!" return endif let l:pathrest = matchlist(l:line1, s:r_hashbang) if len(l:pathrest) == 0 return endif let [_, l:path, l:rest; __] = l:pathrest let l:pathparts = split(l:path, "/") if len(l:pathparts) == 0 return endif let l:script = l:pathparts[-1] if l:script == "env" let l:argspath = matchlist(l:rest, s:r_env) if len(l:argspath) == 0 return endif let l:script = l:argspath[1] endif if has_key(s:interpreters, l:script) return s:interpreters[l:script] endif for interpreter in keys(s:interpreters) if l:script =~# '^' . interpreter return s:interpreters[interpreter] endif 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*\' let name = substitute(line1, '^#!.*\\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: " 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 =~# '' set ft=xml | return " XHTML (e.g.: PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN") elseif line1 =~# '\' 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 if line1 =~ '^# ' || getline(2) =~ '^# ' || getline(3) =~ '^# ' || getline(4) =~ '^# ' || getline(5) =~ '^# ' setf FALLBACK conf return 1 endif return 1 endfunc " DO NOT EDIT CODE BELOW, IT IS GENERATED WITH MAKEFILE let s:interpreters = { \ 'osascript': 'applescript', \ 'tcc': 'c', \ 'bb': 'clojure', \ 'coffee': 'coffee', \ 'crystal': 'crystal', \ 'dart': 'dart', \ 'elixir': 'elixir', \ 'escript': 'erlang', \ 'fish': 'fish', \ 'gnuplot': 'gnuplot', \ 'groovy': 'groovy', \ 'runghc': 'haskell', \ 'runhaskell': 'haskell', \ 'runhugs': 'haskell', \ 'chakra': 'javascript', \ 'd8': 'javascript', \ 'gjs': 'javascript', \ 'js': 'javascript', \ 'node': 'javascript', \ 'nodejs': 'javascript', \ 'qjs': 'javascript', \ 'rhino': 'javascript', \ 'v8': 'javascript', \ 'v8-shell': 'javascript', \ 'julia': 'julia', \ 'lua': 'lua', \ 'moon': 'moon', \ 'ocaml': 'ocaml', \ 'ocamlrun': 'ocaml', \ 'ocamlscript': 'ocaml', \ 'cperl': 'perl', \ 'perl': 'perl', \ 'php': 'php', \ 'swipl': 'prolog', \ 'yap': 'prolog', \ 'pwsh': 'ps1', \ 'python': 'python', \ 'python2': 'python', \ 'python3': 'python', \ 'qmake': 'qmake', \ 'Rscript': 'r', \ 'racket': 'racket', \ 'perl6': 'raku', \ 'raku': 'raku', \ 'rakudo': 'raku', \ 'ruby': 'ruby', \ 'macruby': 'ruby', \ 'rake': 'ruby', \ 'jruby': 'ruby', \ 'rbx': 'ruby', \ 'scala': 'scala', \ 'ash': 'sh', \ 'bash': 'sh', \ 'dash': 'sh', \ 'ksh': 'sh', \ 'mksh': 'sh', \ 'pdksh': 'sh', \ 'rc': 'sh', \ 'sh': 'sh', \ 'boolector': 'smt2', \ 'cvc4': 'smt2', \ 'mathsat5': 'smt2', \ 'opensmt': 'smt2', \ 'smtinterpol': 'smt2', \ 'smt-rat': 'smt2', \ 'stp': 'smt2', \ 'verit': 'smt2', \ 'yices2': 'smt2', \ 'z3': 'smt2', \ 'deno': 'typescript', \ 'ts-node': 'typescript', \ 'zsh': 'zsh', \ } " DO NOT EDIT CODE ABOVE, IT IS GENERATED WITH MAKEFILE let &cpo = s:cpo_save unlet s:cpo_save