scripts.vim 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412
  1. " Vim support file to detect file types in scripts
  2. "
  3. " Maintainer: Bram Moolenaar <Bram@vim.org>
  4. " Last change: 2019 Jun 25
  5. " This file is called by an autocommand for every file that has just been
  6. " loaded into a buffer. It checks if the type of file can be recognized by
  7. " the file contents. The autocommand is in $VIMRUNTIME/filetype.vim.
  8. "
  9. " Note that the pattern matches are done with =~# to avoid the value of the
  10. " 'ignorecase' option making a difference. Where case is to be ignored use
  11. " =~? instead. Do not use =~ anywhere.
  12. " Only do the rest when the FileType autocommand has not been triggered yet.
  13. if did_filetype()
  14. finish
  15. endif
  16. " Load the user defined scripts file first
  17. " Only do this when the FileType autocommand has not been triggered yet
  18. if exists("myscriptsfile") && filereadable(expand(myscriptsfile))
  19. execute "source " . myscriptsfile
  20. if did_filetype()
  21. finish
  22. endif
  23. endif
  24. " Line continuation is used here, remove 'C' from 'cpoptions'
  25. let s:cpo_save = &cpo
  26. set cpo&vim
  27. let s:line1 = getline(1)
  28. if s:line1 =~# "^#!"
  29. " A script that starts with "#!".
  30. " Check for a line like "#!/usr/bin/env VAR=val bash". Turn it into
  31. " "#!/usr/bin/bash" to make matching easier.
  32. if s:line1 =~# '^#!\s*\S*\<env\s'
  33. let s:line1 = substitute(s:line1, '\S\+=\S\+', '', 'g')
  34. let s:line1 = substitute(s:line1, '\<env\s\+', '', '')
  35. endif
  36. " Get the program name.
  37. " Only accept spaces in PC style paths: "#!c:/program files/perl [args]".
  38. " If the word env is used, use the first word after the space:
  39. " "#!/usr/bin/env perl [path/args]"
  40. " If there is no path use the first word: "#!perl [path/args]".
  41. " Otherwise get the last word after a slash: "#!/usr/bin/perl [path/args]".
  42. if s:line1 =~# '^#!\s*\a:[/\\]'
  43. let s:name = substitute(s:line1, '^#!.*[/\\]\(\i\+\).*', '\1', '')
  44. elseif s:line1 =~# '^#!.*\<env\>'
  45. let s:name = substitute(s:line1, '^#!.*\<env\>\s\+\(\i\+\).*', '\1', '')
  46. elseif s:line1 =~# '^#!\s*[^/\\ ]*\>\([^/\\]\|$\)'
  47. let s:name = substitute(s:line1, '^#!\s*\([^/\\ ]*\>\).*', '\1', '')
  48. else
  49. let s:name = substitute(s:line1, '^#!\s*\S*[/\\]\(\i\+\).*', '\1', '')
  50. endif
  51. " tcl scripts may have #!/bin/sh in the first line and "exec wish" in the
  52. " third line. Suggested by Steven Atkinson.
  53. if getline(3) =~# '^exec wish'
  54. let s:name = 'wish'
  55. endif
  56. " Bourne-like shell scripts: bash bash2 ksh ksh93 sh
  57. if s:name =~# '^\(bash\d*\|\|ksh\d*\|sh\)\>'
  58. call dist#ft#SetFileTypeSH(s:line1) " defined in filetype.vim
  59. " csh scripts
  60. elseif s:name =~# '^csh\>'
  61. if exists("g:filetype_csh")
  62. call dist#ft#SetFileTypeShell(g:filetype_csh)
  63. else
  64. call dist#ft#SetFileTypeShell("csh")
  65. endif
  66. " tcsh scripts
  67. elseif s:name =~# '^tcsh\>'
  68. call dist#ft#SetFileTypeShell("tcsh")
  69. " Z shell scripts
  70. elseif s:name =~# '^zsh\>'
  71. set ft=zsh
  72. " TCL scripts
  73. elseif s:name =~# '^\(tclsh\|wish\|expectk\|itclsh\|itkwish\)\>'
  74. set ft=tcl
  75. " Expect scripts
  76. elseif s:name =~# '^expect\>'
  77. set ft=expect
  78. " Gnuplot scripts
  79. elseif s:name =~# '^gnuplot\>'
  80. set ft=gnuplot
  81. " Makefiles
  82. elseif s:name =~# 'make\>'
  83. set ft=make
  84. " Pike
  85. elseif s:name =~# '^pike\%(\>\|[0-9]\)'
  86. set ft=pike
  87. " Lua
  88. elseif s:name =~# 'lua'
  89. set ft=lua
  90. " Perl 6
  91. elseif s:name =~# 'perl6'
  92. set ft=perl6
  93. " Perl
  94. elseif s:name =~# 'perl'
  95. set ft=perl
  96. " PHP
  97. elseif s:name =~# 'php'
  98. set ft=php
  99. " Python
  100. elseif s:name =~# 'python'
  101. set ft=python
  102. " Groovy
  103. elseif s:name =~# '^groovy\>'
  104. set ft=groovy
  105. " Ruby
  106. elseif s:name =~# 'ruby'
  107. set ft=ruby
  108. " JavaScript
  109. elseif s:name =~# 'node\(js\)\=\>\|js\>' || s:name =~# 'rhino\>'
  110. set ft=javascript
  111. " BC calculator
  112. elseif s:name =~# '^bc\>'
  113. set ft=bc
  114. " sed
  115. elseif s:name =~# 'sed\>'
  116. set ft=sed
  117. " OCaml-scripts
  118. elseif s:name =~# 'ocaml'
  119. set ft=ocaml
  120. " Awk scripts
  121. elseif s:name =~# 'awk\>'
  122. set ft=awk
  123. " Website MetaLanguage
  124. elseif s:name =~# 'wml'
  125. set ft=wml
  126. " Scheme scripts
  127. elseif s:name =~# 'scheme'
  128. set ft=scheme
  129. " CFEngine scripts
  130. elseif s:name =~# 'cfengine'
  131. set ft=cfengine
  132. " Erlang scripts
  133. elseif s:name =~# 'escript'
  134. set ft=erlang
  135. " Haskell
  136. elseif s:name =~# 'haskell'
  137. set ft=haskell
  138. " Scala
  139. elseif s:name =~# 'scala\>'
  140. set ft=scala
  141. " Clojure
  142. elseif s:name =~# 'clojure'
  143. set ft=clojure
  144. endif
  145. unlet s:name
  146. else
  147. " File does not start with "#!".
  148. let s:line2 = getline(2)
  149. let s:line3 = getline(3)
  150. let s:line4 = getline(4)
  151. let s:line5 = getline(5)
  152. " Bourne-like shell scripts: sh ksh bash bash2
  153. if s:line1 =~# '^:$'
  154. call dist#ft#SetFileTypeSH(s:line1) " defined in filetype.vim
  155. " Z shell scripts
  156. elseif s:line1 =~# '^#compdef\>' || s:line1 =~# '^#autoload\>' ||
  157. \ "\n".s:line1."\n".s:line2."\n".s:line3."\n".s:line4."\n".s:line5 =~# '\n\s*emulate\s\+\%(-[LR]\s\+\)\=[ckz]\=sh\>'
  158. set ft=zsh
  159. " ELM Mail files
  160. elseif s:line1 =~# '^From \([a-zA-Z][a-zA-Z_0-9\.=-]*\(@[^ ]*\)\=\|-\) .* \(19\|20\)\d\d$'
  161. set ft=mail
  162. " Mason
  163. elseif s:line1 =~# '^<[%&].*>'
  164. set ft=mason
  165. " Vim scripts (must have '" vim' as the first line to trigger this)
  166. elseif s:line1 =~# '^" *[vV]im$'
  167. set ft=vim
  168. " libcxx and libstdc++ standard library headers like "iostream" do not have
  169. " an extension, recognize the Emacs file mode.
  170. elseif s:line1 =~? '-\*-.*C++.*-\*-'
  171. set ft=cpp
  172. " MOO
  173. elseif s:line1 =~# '^\*\* LambdaMOO Database, Format Version \%([1-3]\>\)\@!\d\+ \*\*$'
  174. set ft=moo
  175. " Diff file:
  176. " - "diff" in first line (context diff)
  177. " - "Only in " in first line
  178. " - "--- " in first line and "+++ " in second line (unified diff).
  179. " - "*** " in first line and "--- " in second line (context diff).
  180. " - "# It was generated by makepatch " in the second line (makepatch diff).
  181. " - "Index: <filename>" in the first line (CVS file)
  182. " - "=== ", line of "=", "---", "+++ " (SVK diff)
  183. " - "=== ", "--- ", "+++ " (bzr diff, common case)
  184. " - "=== (removed|added|renamed|modified)" (bzr diff, alternative)
  185. " - "# HG changeset patch" in first line (Mercurial export format)
  186. elseif s: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\)'
  187. \ || (s:line1 =~# '^--- ' && s:line2 =~# '^+++ ')
  188. \ || (s:line1 =~# '^\* looking for ' && s:line2 =~# '^\* comparing to ')
  189. \ || (s:line1 =~# '^\*\*\* ' && s:line2 =~# '^--- ')
  190. \ || (s:line1 =~# '^=== ' && ((s:line2 =~# '^=\{66\}' && s:line3 =~# '^--- ' && s:line4 =~# '^+++') || (s:line2 =~# '^--- ' && s:line3 =~# '^+++ ')))
  191. \ || (s:line1 =~# '^=== \(removed\|added\|renamed\|modified\)')
  192. set ft=diff
  193. " PostScript Files (must have %!PS as the first line, like a2ps output)
  194. elseif s:line1 =~# '^%![ \t]*PS'
  195. set ft=postscr
  196. " M4 scripts: Guess there is a line that starts with "dnl".
  197. elseif s:line1 =~# '^\s*dnl\>'
  198. \ || s:line2 =~# '^\s*dnl\>'
  199. \ || s:line3 =~# '^\s*dnl\>'
  200. \ || s:line4 =~# '^\s*dnl\>'
  201. \ || s:line5 =~# '^\s*dnl\>'
  202. set ft=m4
  203. " AmigaDos scripts
  204. elseif $TERM == "amiga"
  205. \ && (s:line1 =~# "^;" || s:line1 =~? '^\.bra')
  206. set ft=amiga
  207. " SiCAD scripts (must have procn or procd as the first line to trigger this)
  208. elseif s:line1 =~? '^ *proc[nd] *$'
  209. set ft=sicad
  210. " Purify log files start with "**** Purify"
  211. elseif s:line1 =~# '^\*\*\*\* Purify'
  212. set ft=purifylog
  213. " XML
  214. elseif s:line1 =~# '<?\s*xml.*?>'
  215. set ft=xml
  216. " XHTML (e.g.: PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN")
  217. elseif s:line1 =~# '\<DTD\s\+XHTML\s'
  218. set ft=xhtml
  219. " HTML (e.g.: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN")
  220. " Avoid "doctype html", used by slim.
  221. elseif s:line1 =~? '<!DOCTYPE\s\+html\>'
  222. set ft=html
  223. " PDF
  224. elseif s:line1 =~# '^%PDF-'
  225. set ft=pdf
  226. " XXD output
  227. elseif s:line1 =~# '^\x\{7}: \x\{2} \=\x\{2} \=\x\{2} \=\x\{2} '
  228. set ft=xxd
  229. " RCS/CVS log output
  230. elseif s:line1 =~# '^RCS file:' || s:line2 =~# '^RCS file:'
  231. set ft=rcslog
  232. " CVS commit
  233. elseif s:line2 =~# '^CVS:' || getline("$") =~# '^CVS: '
  234. set ft=cvs
  235. " Prescribe
  236. elseif s:line1 =~# '^!R!'
  237. set ft=prescribe
  238. " Send-pr
  239. elseif s:line1 =~# '^SEND-PR:'
  240. set ft=sendpr
  241. " SNNS files
  242. elseif s:line1 =~# '^SNNS network definition file'
  243. set ft=snnsnet
  244. elseif s:line1 =~# '^SNNS pattern definition file'
  245. set ft=snnspat
  246. elseif s:line1 =~# '^SNNS result file'
  247. set ft=snnsres
  248. " Virata
  249. elseif s:line1 =~# '^%.\{-}[Vv]irata'
  250. \ || s:line2 =~# '^%.\{-}[Vv]irata'
  251. \ || s:line3 =~# '^%.\{-}[Vv]irata'
  252. \ || s:line4 =~# '^%.\{-}[Vv]irata'
  253. \ || s:line5 =~# '^%.\{-}[Vv]irata'
  254. set ft=virata
  255. " Strace
  256. elseif s:line1 =~# '[0-9:.]* *execve(' || s:line1 =~# '^__libc_start_main'
  257. set ft=strace
  258. " VSE JCL
  259. elseif s:line1 =~# '^\* $$ JOB\>' || s:line1 =~# '^// *JOB\>'
  260. set ft=vsejcl
  261. " TAK and SINDA
  262. elseif s:line4 =~# 'K & K Associates' || s:line2 =~# 'TAK 2000'
  263. set ft=takout
  264. elseif s:line3 =~# 'S Y S T E M S I M P R O V E D '
  265. set ft=sindaout
  266. elseif getline(6) =~# 'Run Date: '
  267. set ft=takcmp
  268. elseif getline(9) =~# 'Node File 1'
  269. set ft=sindacmp
  270. " DNS zone files
  271. elseif s:line1.s:line2.s:line3.s:line4 =~# '^; <<>> DiG [0-9.]\+.* <<>>\|$ORIGIN\|$TTL\|IN\s\+SOA'
  272. set ft=bindzone
  273. " BAAN
  274. elseif s:line1 =~# '|\*\{1,80}' && s:line2 =~# 'VRC '
  275. \ || s:line2 =~# '|\*\{1,80}' && s:line3 =~# 'VRC '
  276. set ft=baan
  277. " Valgrind
  278. elseif s:line1 =~# '^==\d\+== valgrind' || s:line3 =~# '^==\d\+== Using valgrind'
  279. set ft=valgrind
  280. " Go docs
  281. elseif s:line1 =~# '^PACKAGE DOCUMENTATION$'
  282. set ft=godoc
  283. " Renderman Interface Bytestream
  284. elseif s:line1 =~# '^##RenderMan'
  285. set ft=rib
  286. " Scheme scripts
  287. elseif s:line1 =~# 'exec\s\+\S*scheme' || s:line2 =~# 'exec\s\+\S*scheme'
  288. set ft=scheme
  289. " Git output
  290. elseif s:line1 =~# '^\(commit\|tree\|object\) \x\{40\}\>\|^tag \S\+$'
  291. set ft=git
  292. " Gprof (gnu profiler)
  293. elseif s:line1 == 'Flat profile:'
  294. \ && s:line2 == ''
  295. \ && s:line3 =~# '^Each sample counts as .* seconds.$'
  296. set ft=gprof
  297. " Erlang terms
  298. " (See also: http://www.gnu.org/software/emacs/manual/html_node/emacs/Choosing-Modes.html#Choosing-Modes)
  299. elseif s:line1 =~? '-\*-.*erlang.*-\*-'
  300. set ft=erlang
  301. " CVS diff
  302. else
  303. let s:lnum = 1
  304. while getline(s:lnum) =~# "^? " && s:lnum < line("$")
  305. let s:lnum += 1
  306. endwhile
  307. if getline(s:lnum) =~# '^Index:\s\+\f\+$'
  308. set ft=diff
  309. " locale input files: Formal Definitions of Cultural Conventions
  310. " filename must be like en_US, fr_FR@euro or en_US.UTF-8
  311. elseif expand("%") =~# '\a\a_\a\a\($\|[.@]\)\|i18n$\|POSIX$\|translit_'
  312. let s:lnum = 1
  313. while s:lnum < 100 && s:lnum < line("$")
  314. if getline(s:lnum) =~# '^LC_\(IDENTIFICATION\|CTYPE\|COLLATE\|MONETARY\|NUMERIC\|TIME\|MESSAGES\|PAPER\|TELEPHONE\|MEASUREMENT\|NAME\|ADDRESS\)$'
  315. setf fdcc
  316. break
  317. endif
  318. let s:lnum += 1
  319. endwhile
  320. endif
  321. unlet s:lnum
  322. endif
  323. unlet s:line2 s:line3 s:line4 s:line5
  324. endif
  325. " Restore 'cpoptions'
  326. let &cpo = s:cpo_save
  327. unlet s:cpo_save s:line1