2014-07-10 21:05:51 -07:00
" Vim support file to detect file types in scripts
"
" Maintainer: Bram Moolenaar <Bram@vim.org>
2021-05-01 20:21:50 -07:00
" Last change: 2021 Jan 22
2014-07-10 21:05:51 -07:00
" This file is called by an autocommand for every file that has just been
" loaded into a buffer. It checks if the type of file can be recognized by
" the file contents. The autocommand is in $VIMRUNTIME/filetype.vim.
2017-11-09 17:41:45 -07:00
"
" Note that the pattern matches are done with =~# to avoid the value of the
" 'ignorecase' option making a difference. Where case is to be ignored use
" =~? instead. Do not use =~ anywhere.
2014-07-10 21:05:51 -07:00
" Only do the rest when the FileType autocommand has not been triggered yet.
if did_filetype ( )
finish
endif
" Load the user defined scripts file first
" Only do this when the FileType autocommand has not been triggered yet
if exists ( "myscriptsfile" ) && filereadable ( expand ( myscriptsfile ) )
execute "source " . myscriptsfile
if did_filetype ( )
finish
endif
endif
" Line continuation is used here, remove 'C' from 'cpoptions'
let s :cpo_save = &cpo
set cpo &vim
let s :line1 = getline ( 1 )
2017-11-09 17:41:45 -07:00
if s :line1 = ~ # "^#!"
2014-07-10 21:05:51 -07:00
" A script that starts with "#!".
2020-06-07 15:56:28 -07:00
" Check for a line like "#!/usr/bin/env {options} bash". Turn it into
2014-07-10 21:05:51 -07:00
" "#!/usr/bin/bash" to make matching easier.
2020-06-07 15:56:28 -07:00
" Recognize only a few {options} that are commonly used.
2017-11-09 17:41:45 -07:00
if s :line1 = ~ # '^#!\s*\S*\<env\s'
2014-07-10 21:05:51 -07:00
let s :line1 = substitute ( s :line1 , '\S\+=\S\+' , '' , 'g' )
2020-06-07 15:56:28 -07:00
let s :line1 = substitute ( s :line1 , '\(-[iS]\|--ignore-environment\|--split-string\)' , '' , '' )
2014-07-10 21:05:51 -07:00
let s :line1 = substitute ( s :line1 , '\<env\s\+' , '' , '' )
endif
" Get the program name.
" Only accept spaces in PC style paths: "#!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]".
2017-11-09 17:41:45 -07:00
if s :line1 = ~ # '^#!\s*\a:[/\\]'
2014-07-10 21:05:51 -07:00
let s :name = substitute ( s :line1 , '^#!.*[/\\]\(\i\+\).*' , '\1' , '' )
2017-11-09 17:41:45 -07:00
elseif s :line1 = ~ # '^#!.*\<env\>'
2014-07-10 21:05:51 -07:00
let s :name = substitute ( s :line1 , '^#!.*\<env\>\s\+\(\i\+\).*' , '\1' , '' )
2017-11-09 17:41:45 -07:00
elseif s :line1 = ~ # '^#!\s*[^/\\ ]*\>\([^/\\]\|$\)'
2014-07-10 21:05:51 -07:00
let s :name = substitute ( s :line1 , '^#!\s*\([^/\\ ]*\>\).*' , '\1' , '' )
else
let s :name = substitute ( s :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.
2017-11-09 17:41:45 -07:00
if getline ( 3 ) = ~ # '^exec wish'
2014-07-10 21:05:51 -07:00
let s :name = 'wish'
endif
" Bourne-like shell scripts: bash bash2 ksh ksh93 sh
2017-11-09 17:41:45 -07:00
if s :name = ~ # '^\(bash\d*\|\|ksh\d*\|sh\)\>'
2018-04-02 14:18:26 -07:00
call dist #ft #SetFileTypeSH ( s :line1 ) " defined in filetype.vim
2014-07-10 21:05:51 -07:00
" csh scripts
2017-11-09 17:41:45 -07:00
elseif s :name = ~ # '^csh\>'
2014-07-10 21:05:51 -07:00
if exists ( "g:filetype_csh" )
2018-04-02 14:18:26 -07:00
call dist #ft #SetFileTypeShell ( g :filetype_csh )
2014-07-10 21:05:51 -07:00
else
2018-04-02 14:18:26 -07:00
call dist #ft #SetFileTypeShell ( "csh" )
2014-07-10 21:05:51 -07:00
endif
" tcsh scripts
2017-11-09 17:41:45 -07:00
elseif s :name = ~ # '^tcsh\>'
2018-04-02 14:18:26 -07:00
call dist #ft #SetFileTypeShell ( "tcsh" )
2014-07-10 21:05:51 -07:00
" Z shell scripts
2017-11-09 17:41:45 -07:00
elseif s :name = ~ # '^zsh\>'
2014-07-10 21:05:51 -07:00
set ft = zsh
" TCL scripts
2017-11-09 17:41:45 -07:00
elseif s :name = ~ # '^\(tclsh\|wish\|expectk\|itclsh\|itkwish\)\>'
2014-07-10 21:05:51 -07:00
set ft = tcl
" Expect scripts
2017-11-09 17:41:45 -07:00
elseif s :name = ~ # '^expect\>'
2014-07-10 21:05:51 -07:00
set ft = expect
" Gnuplot scripts
2017-11-09 17:41:45 -07:00
elseif s :name = ~ # '^gnuplot\>'
2014-07-10 21:05:51 -07:00
set ft = gnuplot
" Makefiles
2017-11-09 17:41:45 -07:00
elseif s :name = ~ # 'make\>'
2014-07-10 21:05:51 -07:00
set ft = make
2018-09-18 18:18:55 -07:00
" Pike
elseif s :name = ~ # '^pike\%(\>\|[0-9]\)'
set ft = pike
2014-07-10 21:05:51 -07:00
" Lua
2017-11-09 17:41:45 -07:00
elseif s :name = ~ # 'lua'
2014-07-10 21:05:51 -07:00
set ft = lua
" Perl
2017-11-09 17:41:45 -07:00
elseif s :name = ~ # 'perl'
2014-07-10 21:05:51 -07:00
set ft = perl
" PHP
2017-11-09 17:41:45 -07:00
elseif s :name = ~ # 'php'
2014-07-10 21:05:51 -07:00
set ft = php
" Python
2017-11-09 17:41:45 -07:00
elseif s :name = ~ # 'python'
2014-07-10 21:05:51 -07:00
set ft = python
" Groovy
2017-11-09 17:41:45 -07:00
elseif s :name = ~ # '^groovy\>'
2014-07-10 21:05:51 -07:00
set ft = groovy
2021-04-22 05:23:41 -07:00
" Raku
elseif s :name = ~ # 'raku'
set ft = raku
2014-07-10 21:05:51 -07:00
" Ruby
2017-11-09 17:41:45 -07:00
elseif s :name = ~ # 'ruby'
2014-07-10 21:05:51 -07:00
set ft = ruby
2017-11-05 21:05:54 -07:00
" JavaScript
2018-09-18 18:20:51 -07:00
elseif s :name = ~ # 'node\(js\)\=\>\|js\>' | | s :name = ~ # 'rhino\>'
2017-11-05 21:05:54 -07:00
set ft = javascript
2014-07-10 21:05:51 -07:00
" BC calculator
2017-11-09 17:41:45 -07:00
elseif s :name = ~ # '^bc\>'
2014-07-10 21:05:51 -07:00
set ft = bc
" sed
2017-11-09 17:41:45 -07:00
elseif s :name = ~ # 'sed\>'
2014-07-10 21:05:51 -07:00
set ft = sed
" OCaml-scripts
2017-11-09 17:41:45 -07:00
elseif s :name = ~ # 'ocaml'
2014-07-10 21:05:51 -07:00
set ft = ocaml
2021-04-29 17:43:22 -07:00
" Awk scripts; also finds "gawk"
2017-11-09 17:41:45 -07:00
elseif s :name = ~ # 'awk\>'
2014-07-10 21:05:51 -07:00
set ft = awk
" Website MetaLanguage
2017-11-09 17:41:45 -07:00
elseif s :name = ~ # 'wml'
2014-07-10 21:05:51 -07:00
set ft = wml
" Scheme scripts
2017-11-09 17:41:45 -07:00
elseif s :name = ~ # 'scheme'
2014-07-10 21:05:51 -07:00
set ft = scheme
" CFEngine scripts
2017-11-09 17:41:45 -07:00
elseif s :name = ~ # 'cfengine'
2014-07-10 21:05:51 -07:00
set ft = cfengine
" Erlang scripts
2017-11-09 17:41:45 -07:00
elseif s :name = ~ # 'escript'
2014-07-10 21:05:51 -07:00
set ft = erlang
2017-11-05 21:05:54 -07:00
" Haskell
2017-11-09 17:41:45 -07:00
elseif s :name = ~ # 'haskell'
2017-11-05 21:05:54 -07:00
set ft = haskell
" Scala
2017-11-09 17:41:45 -07:00
elseif s :name = ~ # 'scala\>'
2017-11-05 21:05:54 -07:00
set ft = scala
2018-09-18 18:18:55 -07:00
" Clojure
elseif s :name = ~ # 'clojure'
set ft = clojure
2021-01-13 07:37:15 -07:00
" Free Pascal
elseif s :name = ~ # 'instantfpc\>'
set ft = pascal
2021-01-23 09:18:30 -07:00
" Fennel
elseif s :name = ~ # 'fennel\>'
set ft = fennel
2021-11-16 05:03:57 -07:00
" MikroTik RouterOS script
elseif s :name = ~ # 'rsc\>'
set ft = routeros
2021-11-16 10:26:03 -07:00
" Fish shell
elseif s :name = ~ # 'fish\>'
set ft = fish
2021-11-27 10:39:34 -07:00
" Gforth
elseif s :name = ~ # 'gforth\>'
set ft = forth
2014-07-10 21:05:51 -07:00
endif
unlet s :name
else
" File does not start with "#!".
let s :line2 = getline ( 2 )
let s :line3 = getline ( 3 )
let s :line4 = getline ( 4 )
let s :line5 = getline ( 5 )
" Bourne-like shell scripts: sh ksh bash bash2
2017-11-09 17:41:45 -07:00
if s :line1 = ~ # '^:$'
2018-04-02 14:18:26 -07:00
call dist #ft #SetFileTypeSH ( s :line1 ) " defined in filetype.vim
2014-07-10 21:05:51 -07:00
2019-06-25 18:20:19 -07:00
" Z shell scripts
2017-11-09 17:41:45 -07:00
elseif s :line1 = ~ # '^#compdef\>' | | s :line1 = ~ # '^#autoload\>' | |
\ "\n" .s :line1 ."\n" .s :line2 ."\n" .s :line3 ."\n" .s :line4 ."\n" .s :line5 = ~ # '\n\s*emulate\s\+\%(-[LR]\s\+\)\=[ckz]\=sh\>'
2014-07-10 21:05:51 -07:00
set ft = zsh
" ELM Mail files
2017-11-09 17:41:45 -07:00
elseif s :line1 = ~ # '^From \([a-zA-Z][a-zA-Z_0-9\.=-]*\(@[^ ]*\)\=\|-\) .* \(19\|20\)\d\d$'
2014-07-10 21:05:51 -07:00
set ft = mail
2019-06-25 18:20:19 -07:00
" Mason
2017-11-09 17:41:45 -07:00
elseif s :line1 = ~ # '^<[%&].*>'
2014-07-10 21:05:51 -07:00
set ft = mason
2019-06-25 18:20:19 -07:00
" Vim scripts (must have '" vim' as the first line to trigger this)
2017-11-09 17:41:45 -07:00
elseif s :line1 = ~ # '^" *[vV]im$'
2014-07-10 21:05:51 -07:00
set ft = vim
2019-06-25 18:20:19 -07:00
" libcxx and libstdc++ standard library headers like "iostream" do not have
" an extension, recognize the Emacs file mode.
elseif s :line1 = ~ ? '-\*-.*C++.*-\*-'
set ft = cpp
" MOO
2017-11-09 17:41:45 -07:00
elseif s :line1 = ~ # '^\*\* LambdaMOO Database, Format Version \%([1-3]\>\)\@!\d\+ \*\*$'
2014-07-10 21:05:51 -07:00
set ft = moo
" 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)
2017-11-09 17:41:45 -07:00
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\)'
\ | | ( s :line1 = ~ # '^--- ' && s :line2 = ~ # '^+++ ' )
\ | | ( s :line1 = ~ # '^\* looking for ' && s :line2 = ~ # '^\* comparing to ' )
\ | | ( s :line1 = ~ # '^\*\*\* ' && s :line2 = ~ # '^--- ' )
\ | | ( s :line1 = ~ # '^=== ' && ( ( s :line2 = ~ # '^=\{66\}' && s :line3 = ~ # '^--- ' && s :line4 = ~ # '^+++' ) | | ( s :line2 = ~ # '^--- ' && s :line3 = ~ # '^+++ ' ) ) )
\ | | ( s :line1 = ~ # '^=== \(removed\|added\|renamed\|modified\)' )
2014-07-10 21:05:51 -07:00
set ft = diff
" PostScript Files (must have %!PS as the first line, like a2ps output)
2017-11-09 17:41:45 -07:00
elseif s :line1 = ~ # '^%![ \t]*PS'
2014-07-10 21:05:51 -07:00
set ft = postscr
" M4 scripts: Guess there is a line that starts with "dnl".
2017-11-09 17:41:45 -07:00
elseif s :line1 = ~ # '^\s*dnl\>'
\ | | s :line2 = ~ # '^\s*dnl\>'
\ | | s :line3 = ~ # '^\s*dnl\>'
\ | | s :line4 = ~ # '^\s*dnl\>'
\ | | s :line5 = ~ # '^\s*dnl\>'
2014-07-10 21:05:51 -07:00
set ft = m4
2017-11-09 17:41:45 -07:00
" AmigaDos scripts
elseif $TERM = = "amiga"
\ && ( s :line1 = ~ # "^;" | | s :line1 = ~ ? '^\.bra' )
set ft = amiga
2014-07-10 21:05:51 -07:00
" SiCAD scripts (must have procn or procd as the first line to trigger this)
elseif s :line1 = ~ ? '^ *proc[nd] *$'
set ft = sicad
" Purify log files start with "**** Purify"
2017-11-09 17:41:45 -07:00
elseif s :line1 = ~ # '^\*\*\*\* Purify'
2014-07-10 21:05:51 -07:00
set ft = purifylog
" XML
2017-11-09 17:41:45 -07:00
elseif s :line1 = ~ # '<?\s*xml.*?>'
2014-07-10 21:05:51 -07:00
set ft = xml
" XHTML (e.g.: PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN")
2017-11-09 17:41:45 -07:00
elseif s :line1 = ~ # '\<DTD\s\+XHTML\s'
2014-07-10 21:05:51 -07:00
set ft = xhtml
" HTML (e.g.: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN")
2016-10-14 20:12:48 -07:00
" Avoid "doctype html", used by slim.
elseif s :line1 = ~ ? '<!DOCTYPE\s\+html\>'
2014-07-10 21:05:51 -07:00
set ft = html
" PDF
2017-11-09 17:41:45 -07:00
elseif s :line1 = ~ # '^%PDF-'
2014-07-10 21:05:51 -07:00
set ft = pdf
" XXD output
2017-11-09 17:41:45 -07:00
elseif s :line1 = ~ # '^\x\{7}: \x\{2} \=\x\{2} \=\x\{2} \=\x\{2} '
2014-07-10 21:05:51 -07:00
set ft = xxd
" RCS/CVS log output
2017-11-09 17:41:45 -07:00
elseif s :line1 = ~ # '^RCS file:' | | s :line2 = ~ # '^RCS file:'
2014-07-10 21:05:51 -07:00
set ft = rcslog
" CVS commit
2017-11-09 17:41:45 -07:00
elseif s :line2 = ~ # '^CVS:' | | getline ( "$" ) = ~ # '^CVS: '
2014-07-10 21:05:51 -07:00
set ft = cvs
" Prescribe
2017-11-09 17:41:45 -07:00
elseif s :line1 = ~ # '^!R!'
2014-07-10 21:05:51 -07:00
set ft = prescribe
" Send-pr
2017-11-09 17:41:45 -07:00
elseif s :line1 = ~ # '^SEND-PR:'
2014-07-10 21:05:51 -07:00
set ft = sendpr
" SNNS files
2017-11-09 17:41:45 -07:00
elseif s :line1 = ~ # '^SNNS network definition file'
2014-07-10 21:05:51 -07:00
set ft = snnsnet
2017-11-09 17:41:45 -07:00
elseif s :line1 = ~ # '^SNNS pattern definition file'
2014-07-10 21:05:51 -07:00
set ft = snnspat
2017-11-09 17:41:45 -07:00
elseif s :line1 = ~ # '^SNNS result file'
2014-07-10 21:05:51 -07:00
set ft = snnsres
" Virata
2017-11-09 17:41:45 -07:00
elseif s :line1 = ~ # '^%.\{-}[Vv]irata'
\ | | s :line2 = ~ # '^%.\{-}[Vv]irata'
\ | | s :line3 = ~ # '^%.\{-}[Vv]irata'
\ | | s :line4 = ~ # '^%.\{-}[Vv]irata'
\ | | s :line5 = ~ # '^%.\{-}[Vv]irata'
2014-07-10 21:05:51 -07:00
set ft = virata
" Strace
2017-11-06 19:16:52 -07:00
elseif s :line1 = ~ # '[0-9:.]* *execve(' | | s :line1 = ~ # '^__libc_start_main'
2014-07-10 21:05:51 -07:00
set ft = strace
" VSE JCL
2017-11-09 17:41:45 -07:00
elseif s :line1 = ~ # '^\* $$ JOB\>' | | s :line1 = ~ # '^// *JOB\>'
2014-07-10 21:05:51 -07:00
set ft = vsejcl
" TAK and SINDA
2017-11-09 17:41:45 -07:00
elseif s :line4 = ~ # 'K & K Associates' | | s :line2 = ~ # 'TAK 2000'
2014-07-10 21:05:51 -07:00
set ft = takout
2017-11-09 17:41:45 -07:00
elseif s :line3 = ~ # 'S Y S T E M S I M P R O V E D '
2014-07-10 21:05:51 -07:00
set ft = sindaout
2017-11-09 17:41:45 -07:00
elseif getline ( 6 ) = ~ # 'Run Date: '
2014-07-10 21:05:51 -07:00
set ft = takcmp
2017-11-09 17:41:45 -07:00
elseif getline ( 9 ) = ~ # 'Node File 1'
2014-07-10 21:05:51 -07:00
set ft = sindacmp
" DNS zone files
2017-11-07 12:43:11 -07:00
elseif s :line1 .s :line2 .s :line3 .s :line4 = ~ # '^; <<>> DiG [0-9.]\+.* <<>>\|$ORIGIN\|$TTL\|IN\s\+SOA'
2014-07-10 21:05:51 -07:00
set ft = bindzone
" BAAN
2017-11-09 17:41:45 -07:00
elseif s :line1 = ~ # '|\*\{1,80}' && s :line2 = ~ # 'VRC '
\ | | s :line2 = ~ # '|\*\{1,80}' && s :line3 = ~ # 'VRC '
2014-07-10 21:05:51 -07:00
set ft = baan
" Valgrind
2017-11-09 17:41:45 -07:00
elseif s :line1 = ~ # '^==\d\+== valgrind' | | s :line3 = ~ # '^==\d\+== Using valgrind'
2014-07-10 21:05:51 -07:00
set ft = valgrind
2015-01-04 11:37:32 -07:00
" Go docs
2017-11-09 17:41:45 -07:00
elseif s :line1 = ~ # '^PACKAGE DOCUMENTATION$'
2015-01-04 11:37:32 -07:00
set ft = godoc
2014-07-10 21:05:51 -07:00
" Renderman Interface Bytestream
2017-11-09 17:41:45 -07:00
elseif s :line1 = ~ # '^##RenderMan'
2014-07-10 21:05:51 -07:00
set ft = rib
" Scheme scripts
2017-11-09 17:41:45 -07:00
elseif s :line1 = ~ # 'exec\s\+\S*scheme' | | s :line2 = ~ # 'exec\s\+\S*scheme'
2014-07-10 21:05:51 -07:00
set ft = scheme
" Git output
2022-01-07 02:27:34 -07:00
elseif s :line1 = ~ # '^\(commit\|tree\|object\) \x\{40,\}\>\|^tag \S\+$'
2014-07-10 21:05:51 -07:00
set ft = git
" Gprof (gnu profiler)
elseif s :line1 = = 'Flat profile:'
\ && s :line2 = = ''
2017-11-09 17:41:45 -07:00
\ && s :line3 = ~ # '^Each sample counts as .* seconds.$'
2014-07-10 21:05:51 -07:00
set ft = gprof
" Erlang terms
" (See also: http://www.gnu.org/software/emacs/manual/html_node/emacs/Choosing-Modes.html#Choosing-Modes)
elseif s :line1 = ~ ? '-\*-.*erlang.*-\*-'
set ft = erlang
2020-03-06 17:04:42 -07:00
" YAML
elseif s :line1 = ~ # '^%YAML'
set ft = yaml
2021-11-16 05:03:57 -07:00
" MikroTik RouterOS script
elseif s :line1 = ~ # '^#.*by RouterOS.*$'
set ft = routeros
2022-01-15 06:47:25 -07:00
" Sed scripts
" #ncomment is allowed but most likely a false positive so require a space
" before any trailing comment text
elseif s :line1 = ~ # '^#n\%($\|\s\)'
set ft = sed
2014-07-10 21:05:51 -07:00
" CVS diff
else
let s :lnum = 1
2017-11-09 17:41:45 -07:00
while getline ( s :lnum ) = ~ # "^? " && s :lnum < line ( "$" )
2014-07-10 21:05:51 -07:00
let s :lnum + = 1
endwhile
2017-11-09 17:41:45 -07:00
if getline ( s :lnum ) = ~ # '^Index:\s\+\f\+$'
2014-07-10 21:05:51 -07:00
set ft = diff
" locale input files: Formal Definitions of Cultural Conventions
" filename must be like en_US, fr_FR@euro or en_US.UTF-8
2017-11-09 17:41:45 -07:00
elseif expand ( "%" ) = ~ # '\a\a_\a\a\($\|[.@]\)\|i18n$\|POSIX$\|translit_'
2014-07-10 21:05:51 -07:00
let s :lnum = 1
while s :lnum < 100 && s :lnum < line ( "$" )
2017-11-09 17:41:45 -07:00
if getline ( s :lnum ) = ~ # '^LC_\(IDENTIFICATION\|CTYPE\|COLLATE\|MONETARY\|NUMERIC\|TIME\|MESSAGES\|PAPER\|TELEPHONE\|MEASUREMENT\|NAME\|ADDRESS\)$'
2014-07-10 21:05:51 -07:00
setf fdcc
break
endif
let s :lnum + = 1
endwhile
endif
unlet s :lnum
endif
unlet s :line2 s :line3 s :line4 s :line5
endif
" Restore 'cpoptions'
let &cpo = s :cpo_save
unlet s :cpo_save s :line1