scripts.vim 12 KB

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