aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--runtime/autoload/dist/ft.vim741
-rw-r--r--runtime/filetype.vim834
-rw-r--r--runtime/scripts.vim191
-rw-r--r--src/nvim/fileio.c133
4 files changed, 976 insertions, 923 deletions
diff --git a/runtime/autoload/dist/ft.vim b/runtime/autoload/dist/ft.vim
new file mode 100644
index 0000000000..2603c6822f
--- /dev/null
+++ b/runtime/autoload/dist/ft.vim
@@ -0,0 +1,741 @@
+" Vim functions for file type detection
+"
+" Maintainer: Bram Moolenaar <Bram@vim.org>
+" Last Change: 2017 Nov 11
+
+" 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 dist#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 dist#ft#FTasm()
+ " make sure b:asmsyntax exists
+ if !exists("b:asmsyntax")
+ let b:asmsyntax = ""
+ endif
+
+ if b:asmsyntax == ""
+ call dist#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 dist#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 dist#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 dist#ft#FTbtm()
+ if exists("g:dosbatch_syntax_for_btm") && g:dosbatch_syntax_for_btm
+ setf dosbatch
+ else
+ setf btm
+ endif
+endfunc
+
+func dist#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 dist#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 dist#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", "//" ir "/*" it's probably ch.
+" Otherwise CHILL is assumed.
+func dist#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 dist#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 dist#ft#EuphoriaCheck()
+ if exists('g:filetype_euphoria')
+ exe 'setf ' . g:filetype_euphoria
+ else
+ setf euphoria3
+ endif
+endfunc
+
+func dist#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 dist#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 dist#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 html
+endfunc
+
+" Distinguish between standard IDL and MS-IDL
+func dist#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 dist#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 dist#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 dist#ft#FTmms()
+ let n = 1
+ while n < 10
+ 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 dist#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 dist#ft#FTmm()
+ let n = 1
+ while n < 10
+ let line = getline(n)
+ if line =~ '^\s*\(#\s*\(include\|import\)\>\|@import\>\|/\*\)'
+ setf objcpp
+ return
+ endif
+ let n = n + 1
+ endwhile
+ setf nroff
+endfunc
+
+func dist#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 dist#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 dist#ft#FTasmsyntax()
+ if exists("b:asmsyntax")
+ exe "setf " . fnameescape(b:asmsyntax)
+ else
+ setf pov
+ endif
+ endif
+ endif
+endfunc
+
+func dist#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 dist#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 dist#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 dist#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 dist#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 dist#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 dist#ft#SetFileTypeSH(name)
+ if expand("<amatch>") =~ g:ft_ignore_pat
+ return
+ endif
+ if a:name =~ '\<csh\>'
+ " Some .sh scripts contain #!/bin/csh.
+ call dist#ft#SetFileTypeShell("csh")
+ return
+ elseif a:name =~ '\<tcsh\>'
+ " Some .sh scripts contain #!/bin/tcsh.
+ call dist#ft#SetFileTypeShell("tcsh")
+ return
+ elseif a:name =~ '\<zsh\>'
+ " Some .sh scripts contain #!/bin/zsh.
+ call dist#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 dist#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 dist#ft#SetFileTypeShell(name)
+ 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 dist#ft#CSH()
+ if exists("g:filetype_csh")
+ call dist#ft#SetFileTypeShell(g:filetype_csh)
+ elseif &shell =~ "tcsh"
+ call dist#ft#SetFileTypeShell("tcsh")
+ else
+ call dist#ft#SetFileTypeShell("csh")
+ endif
+endfunc
+
+let s:ft_rules_udev_rules_pattern = '^\s*\cudev_rules\s*=\s*"\([^"]\{-1,}\)/*".*'
+func dist#ft#FTRules()
+ let path = expand('<amatch>:p')
+ if path =~ '^/\(etc/udev/\%(rules\.d/\)\=.*\.rules\|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 dist#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 dist#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
+ if search('^use\s\s*\k', 'nc', 30)
+ 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 "latex" or to g:tex_flavor, can be set in user's vimrc.
+func dist#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 dist#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 dist#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 dist#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/runtime/filetype.vim b/runtime/filetype.vim
index 4e0f145c18..f8a29fa2b3 100644
--- a/runtime/filetype.vim
+++ b/runtime/filetype.vim
@@ -52,27 +52,7 @@ endfunc
au BufNewFile,BufRead $VIMRUNTIME/doc/*.txt setf help
" Abaqus or Trasys
-au BufNewFile,BufRead *.inp call s:Check_inp()
-
-func! s: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
+au BufNewFile,BufRead *.inp call dist#ft#Check_inp()
" A-A-P recipe
au BufNewFile,BufRead *.aap setf aap
@@ -170,44 +150,7 @@ au BufNewFile,BufRead */boot/grub/menu.lst,*/boot/grub/grub.conf,*/etc/grub.conf
" Assembly (all kinds)
" *.lst is not pure assembly, it has two extra columns (address, byte codes)
-au BufNewFile,BufRead *.asm,*.[sS],*.[aA],*.mac,*.lst call s:FTasm()
-
-" 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! s:FTasm()
- " make sure b:asmsyntax exists
- if !exists("b:asmsyntax")
- let b:asmsyntax = ""
- endif
-
- if b:asmsyntax == ""
- call s: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! s: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
+au BufNewFile,BufRead *.asm,*.[sS],*.[aA],*.mac,*.lst call dist#ft#FTasm()
" Macro (VAX)
au BufNewFile,BufRead *.mar setf vmasm
@@ -237,17 +180,7 @@ au BufNewFile,BufRead *.awk setf awk
au BufNewFile,BufRead *.mch,*.ref,*.imp setf b
" BASIC or Visual Basic
-au BufNewFile,BufRead *.bas call s:FTVB("basic")
-
-" 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! s: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
+au BufNewFile,BufRead *.bas call dist#ft#FTVB("basic")
" Visual Basic Script (close to Visual Basic) or Visual Basic .NET
au BufNewFile,BufRead *.vb,*.vbs,*.dsm,*.ctl setf vb
@@ -265,14 +198,7 @@ au BufNewFile,BufRead *.cmd
\ if getline(1) =~ '^/\*' | setf rexx | else | setf dosbatch | endif
" Batch file for 4DOS
-au BufNewFile,BufRead *.btm call s:FTbtm()
-func! s:FTbtm()
- if exists("g:dosbatch_syntax_for_btm") && g:dosbatch_syntax_for_btm
- setf dosbatch
- else
- setf btm
- endif
-endfunc
+au BufNewFile,BufRead *.btm call dist#ft#FTbtm()
" BC calculator
au BufNewFile,BufRead *.bc setf bc
@@ -292,15 +218,7 @@ au BufNewFile,BufRead named*.conf,rndc*.conf,rndc*.key setf named
" BIND zone
au BufNewFile,BufRead named.root setf bindzone
-au BufNewFile,BufRead *.db call s:BindzoneCheck('')
-
-func! s: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
+au BufNewFile,BufRead *.db call dist#ft#BindzoneCheck('')
" Blank
au BufNewFile,BufRead *.bl setf blank
@@ -309,27 +227,14 @@ au BufNewFile,BufRead *.bl setf blank
au BufNewFile,BufRead */etc/blkid.tab,*/etc/blkid.tab.old setf xml
" Bazel (http://bazel.io)
-autocmd BufRead,BufNewFile *.bzl,WORKSPACE setfiletype bzl
+autocmd BufRead,BufNewFile *.bzl,WORKSPACE setf bzl
if has("fname_case")
- autocmd BufRead,BufNewFile BUILD setfiletype bzl
+ " There is another check for BUILD further below.
+ autocmd BufRead,BufNewFile BUILD setf bzl
endif
" C or lpc
-au BufNewFile,BufRead *.c call s:FTlpc()
-
-func! s: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
+au BufNewFile,BufRead *.c call dist#ft#FTlpc()
" Calendar
au BufNewFile,BufRead calendar setf calendar
@@ -383,23 +288,7 @@ endif
" .h files can be C, Ch C++, ObjC or ObjC++.
" Set c_syntax_for_h if you want C, ch_syntax_for_h if you want Ch. ObjC is
" detected automatically.
-au BufNewFile,BufRead *.h call s:FTheader()
-
-func! s: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
+au BufNewFile,BufRead *.h call dist#ft#FTheader()
" Ch (CHscript)
au BufNewFile,BufRead *.chf setf ch
@@ -433,36 +322,7 @@ au BufNewFile,BufRead NEWS
au BufNewFile,BufRead *..ch setf chill
" Changes for WEB and CWEB or CHILL
-au BufNewFile,BufRead *.ch call s:FTchange()
-
-" 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", "//" ir "/*" it's probably ch.
-" Otherwise CHILL is assumed.
-func! s: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
+au BufNewFile,BufRead *.ch call dist#ft#FTchange()
" ChordPro
au BufNewFile,BufRead *.chopro,*.crd,*.cho,*.crdpro,*.chordpro setf chordpro
@@ -474,27 +334,7 @@ au BufNewFile,BufRead *.dcl,*.icl setf clean
au BufNewFile,BufRead *.eni setf cl
" Clever or dtd
-au BufNewFile,BufRead *.ent call s:FTent()
-
-func! s: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
+au BufNewFile,BufRead *.ent call dist#ft#FTent()
" Clipper (or FoxPro; could also be eviews)
au BufNewFile,BufRead *.prg
@@ -549,19 +389,11 @@ au BufNewFile,BufRead *enlightenment/*.cfg setf c
au BufNewFile,BufRead *Eterm/*.cfg setf eterm
" Euphoria 3 or 4
-au BufNewFile,BufRead *.eu,*.ew,*.ex,*.exu,*.exw call s:EuphoriaCheck()
+au BufNewFile,BufRead *.eu,*.ew,*.ex,*.exu,*.exw call dist#ft#EuphoriaCheck()
if has("fname_case")
- au BufNewFile,BufRead *.EU,*.EW,*.EX,*.EXU,*.EXW call s:EuphoriaCheck()
+ au BufNewFile,BufRead *.EU,*.EW,*.EX,*.EXU,*.EXW call dist#ft#EuphoriaCheck()
endif
-func! s:EuphoriaCheck()
- if exists('g:filetype_euphoria')
- exe 'setf ' . g:filetype_euphoria
- else
- setf euphoria3
- endif
-endfunc
-
" Lynx config files
au BufNewFile,BufRead lynx.cfg setf lynx
@@ -606,19 +438,7 @@ au BufNewFile,BufRead */etc/dnsmasq.conf setf dnsmasq
au BufNewFile,BufRead *.desc setf desc
" the D language or dtrace
-au BufNewFile,BufRead *.d call s:DtraceCheck()
-
-func! s: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
+au BufNewFile,BufRead *.d call dist#ft#DtraceCheck()
" Desktop files
au BufNewFile,BufRead *.desktop,.directory setf desktop
@@ -650,7 +470,7 @@ au BufNewFile,BufRead *.rul
\ endif
" DCL (Digital Command Language - vms) or DNS zone file
-au BufNewFile,BufRead *.com call s:BindzoneCheck('dcl')
+au BufNewFile,BufRead *.com call dist#ft#BindzoneCheck('dcl')
" DOT
au BufNewFile,BufRead *.dot setf dot
@@ -698,27 +518,11 @@ au BufNewFile,BufRead .editorconfig setf dosini
au BufNewFile,BufRead *.ecd setf ecd
" Eiffel or Specman or Euphoria
-au BufNewFile,BufRead *.e,*.E call s:FTe()
+au BufNewFile,BufRead *.e,*.E call dist#ft#FTe()
" Elinks configuration
au BufNewFile,BufRead */etc/elinks.conf,*/.elinks/elinks.conf setf elinks
-func! s: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
-
" ERicsson LANGuage; Yaws is erlang too
au BufNewFile,BufRead *.erl,*.hrl,*.yaws setf erlang
@@ -887,24 +691,7 @@ au BufNewFile,BufRead *.hex,*.h32 setf hex
au BufNewFile,BufRead *.t.html setf tilde
" HTML (.shtml and .stm for server side)
-au BufNewFile,BufRead *.html,*.htm,*.shtml,*.stm call s:FThtml()
-
-" Distinguish between HTML, XHTML and Django
-func! s: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 html
-endfunc
+au BufNewFile,BufRead *.html,*.htm,*.shtml,*.stm call dist#ft#FThtml()
" HTML with Ruby - eRuby
au BufNewFile,BufRead *.erb,*.rhtml setf eruby
@@ -931,20 +718,7 @@ au BufNewFile,BufRead *.htt,*.htb setf httest
au BufNewFile,BufRead *.icn setf icon
" IDL (Interface Description Language)
-au BufNewFile,BufRead *.idl call s:FTidl()
-
-" Distinguish between standard IDL and MS-IDL
-func! s: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
+au BufNewFile,BufRead *.idl call dist#ft#FTidl()
" Microsoft IDL (Interface Description Language) Also *.idl
" MOF = WMI (Windows Management Instrumentation) Managed Object Format
@@ -955,25 +729,10 @@ au BufNewFile,BufRead */.icewm/menu setf icemenu
" Indent profile (must come before IDL *.pro!)
au BufNewFile,BufRead .indent.pro setf indent
-au BufNewFile,BufRead indent.pro call s:ProtoCheck('indent')
+au BufNewFile,BufRead indent.pro call dist#ft#ProtoCheck('indent')
" IDL (Interactive Data Language)
-au BufNewFile,BufRead *.pro call s:ProtoCheck('idlang')
-
-" Distinguish between "default" and Cproto prototype file. */
-func! s: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
-
+au BufNewFile,BufRead *.pro call dist#ft#ProtoCheck('idlang')
" Indent RC
au BufNewFile,BufRead indentrc setf indent
@@ -1187,51 +946,7 @@ au BufNewFile,BufRead *.markdown,*.mdown,*.mkd,*.mkdn,*.mdwn,*.md setf markdown
au BufNewFile,BufRead *.mason,*.mhtml,*.comp setf mason
" Mathematica, Matlab, Murphi or Objective C
-au BufNewFile,BufRead *.m call s:FTm()
-
-func! s: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
+au BufNewFile,BufRead *.m call dist#ft#FTm()
" Mathematica notebook
au BufNewFile,BufRead *.nb setf mma
@@ -1261,29 +976,11 @@ au BufNewFile,BufRead *.mgl setf mgl
au BufNewFile,BufRead *.mix,*.mixal setf mix
" MMIX or VMS makefile
-au BufNewFile,BufRead *.mms call s:FTmms()
+au BufNewFile,BufRead *.mms call dist#ft#FTmms()
" Symbian meta-makefile definition (MMP)
au BufNewFile,BufRead *.mmp setf mmp
-func! s:FTmms()
- let n = 1
- while n < 10
- 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
-
-
" Modsim III (or LambdaProlog)
au BufNewFile,BufRead *.mod
\ if getline(1) =~ '\<module\>' |
@@ -1367,33 +1064,10 @@ au BufNewFile,BufRead *.me
\ setf nroff |
\ endif
au BufNewFile,BufRead *.tr,*.nr,*.roff,*.tmac,*.mom setf nroff
-au BufNewFile,BufRead *.[1-9] call s:FTnroff()
-
-" 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! s: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
+au BufNewFile,BufRead *.[1-9] call dist#ft#FTnroff()
" Nroff or Objective C++
-au BufNewFile,BufRead *.mm call s:FTmm()
-
-func! s:FTmm()
- let n = 1
- while n < 10
- let line = getline(n)
- if line =~ '^\s*\(#\s*\(include\|import\)\>\|@import\>\|/\*\)'
- setf objcpp
- return
- endif
- let n = n + 1
- endwhile
- setf nroff
-endfunc
+au BufNewFile,BufRead *.mm call dist#ft#FTmm()
" Not Quite C
au BufNewFile,BufRead *.nqc setf nqc
@@ -1448,28 +1122,13 @@ au BufNewFile,BufRead *.pcmk setf pcmk
" Perl
if has("fname_case")
- au BufNewFile,BufRead *.pl,*.PL call s:FTpl()
+ au BufNewFile,BufRead *.pl,*.PL call dist#ft#FTpl()
else
- au BufNewFile,BufRead *.pl call s:FTpl()
+ au BufNewFile,BufRead *.pl call dist#ft#FTpl()
endif
au BufNewFile,BufRead *.plx,*.al,*.psgi setf perl
au BufNewFile,BufRead *.p6,*.pm6,*.pl6 setf perl6
-func! s: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
-
" Perl, XPM or XPM2
au BufNewFile,BufRead *.pm
\ if getline(1) =~ "XPM2" |
@@ -1482,7 +1141,7 @@ au BufNewFile,BufRead *.pm
" Perl POD
au BufNewFile,BufRead *.pod setf pod
-au BufNewFile,BufRead *.pod6 setf pod6
+au BufNewFile,BufRead *.pod6 setf pod6
" Php, php3, php4, etc.
" Also Phtml (was used for PHP 2 in the past)
@@ -1532,29 +1191,7 @@ au BufNewFile,BufRead *.pov setf pov
au BufNewFile,BufRead .povrayrc setf povini
" Povray, PHP or assembly
-au BufNewFile,BufRead *.inc call s:FTinc()
-
-func! s: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 s:FTasmsyntax()
- if exists("b:asmsyntax")
- exe "setf " . fnameescape(b:asmsyntax)
- else
- setf pov
- endif
- endif
- endif
-endfunc
+au BufNewFile,BufRead *.inc call dist#ft#FTinc()
" Printcap and Termcap
au BufNewFile,BufRead *printcap
@@ -1583,74 +1220,13 @@ au BufNewFile,BufRead *.action setf privoxy
au BufNewFile,BufRead .procmail,.procmailrc setf procmail
" Progress or CWEB
-au BufNewFile,BufRead *.w call s:FTprogress_cweb()
-
-func! s: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
+au BufNewFile,BufRead *.w call dist#ft#FTprogress_cweb()
" Progress or assembly
-au BufNewFile,BufRead *.i call s:FTprogress_asm()
-
-func! s: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 s: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
+au BufNewFile,BufRead *.i call dist#ft#FTprogress_asm()
" Progress or Pascal
-au BufNewFile,BufRead *.p call s:FTprogress_pascal()
-
-func! s: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
-
+au BufNewFile,BufRead *.p call dist#ft#FTprogress_pascal()
" Software Distributor Product Specification File (POSIX 1387.2-1995)
au BufNewFile,BufRead *.psf setf psf
@@ -1736,40 +1312,7 @@ else
endif
" Rexx, Rebol or R
-au BufNewFile,BufRead *.r,*.R call s:FTr()
-
-func! s: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
+au BufNewFile,BufRead *.r,*.R call dist#ft#FTr()
" Remind
au BufNewFile,BufRead .reminders,*.remind,*.rem setf remind
@@ -1865,23 +1408,7 @@ au BufNewFile,BufRead *.siv setf sieve
au BufNewFile,BufRead sendmail.cf setf sm
" Sendmail .mc files are actually m4. Could also be MS Message text file.
-au BufNewFile,BufRead *.mc call s:McSetf()
-
-func! s: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
+au BufNewFile,BufRead *.mc call dist#ft#McSetf()
" Services
au BufNewFile,BufRead */etc/services setf services
@@ -1922,101 +1449,23 @@ au BufNewFile,BufRead sgml.catalog* call s:StarSetf('catalog')
" Shell scripts (sh, ksh, bash, bash2, csh); Allow .profile_foo etc.
" Gentoo ebuilds and Arch Linux PKGBUILDs are actually bash scripts
-au BufNewFile,BufRead .bashrc*,bashrc,bash.bashrc,.bash[_-]profile*,.bash[_-]logout*,.bash[_-]aliases*,*.bash,*/{,.}bash[_-]completion{,.d,.sh}{,/*},*.ebuild,*.eclass,PKGBUILD* call SetFileTypeSH("bash")
-au BufNewFile,BufRead .kshrc*,*.ksh call SetFileTypeSH("ksh")
-au BufNewFile,BufRead */etc/profile,.profile*,*.sh,*.env call SetFileTypeSH(getline(1))
+au BufNewFile,BufRead .bashrc*,bashrc,bash.bashrc,.bash[_-]profile*,.bash[_-]logout*,.bash[_-]aliases*,*.bash,*/{,.}bash[_-]completion{,.d,.sh}{,/*},*.ebuild,*.eclass,PKGBUILD* call dist#ft#SetFileTypeSH("bash")
+au BufNewFile,BufRead .kshrc*,*.ksh call dist#ft#SetFileTypeSH("ksh")
+au BufNewFile,BufRead */etc/profile,.profile*,*.sh,*.env call dist#ft#SetFileTypeSH(getline(1))
" Shell script (Arch Linux) or PHP file (Drupal)
au BufNewFile,BufRead *.install
\ if getline(1) =~ '<?php' |
\ setf php |
\ else |
- \ call SetFileTypeSH("bash") |
+ \ call dist#ft#SetFileTypeSH("bash") |
\ endif
-" Also called from scripts.vim.
-func! SetFileTypeSH(name)
- if expand("<amatch>") =~ g:ft_ignore_pat
- return
- endif
- if a:name =~ '\<csh\>'
- " Some .sh scripts contain #!/bin/csh.
- call SetFileTypeShell("csh")
- return
- elseif a:name =~ '\<tcsh\>'
- " Some .sh scripts contain #!/bin/tcsh.
- call SetFileTypeShell("tcsh")
- return
- elseif a:name =~ '\<zsh\>'
- " Some .sh scripts contain #!/bin/zsh.
- call 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 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! SetFileTypeShell(name)
- 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
-
" tcsh scripts
-au BufNewFile,BufRead .tcshrc*,*.tcsh,tcsh.tcshrc,tcsh.login call SetFileTypeShell("tcsh")
+au BufNewFile,BufRead .tcshrc*,*.tcsh,tcsh.tcshrc,tcsh.login call dist#ft#SetFileTypeShell("tcsh")
" csh scripts, but might also be tcsh scripts (on some systems csh is tcsh)
-au BufNewFile,BufRead .login*,.cshrc*,csh.cshrc,csh.login,csh.logout,*.csh,.alias call s:CSH()
-
-func! s:CSH()
- if exists("g:filetype_csh")
- call SetFileTypeShell(g:filetype_csh)
- elseif &shell =~ "tcsh"
- call SetFileTypeShell("tcsh")
- else
- call SetFileTypeShell("csh")
- endif
-endfunc
+au BufNewFile,BufRead .login*,.cshrc*,csh.cshrc,csh.login,csh.logout,*.csh,.alias call dist#ft#CSH()
" Z-Shell script
au BufNewFile,BufRead .zprofile,*/etc/zprofile,.zfbfmarks setf zsh
@@ -2087,42 +1536,7 @@ au BufNewFile,BufRead *.mib,*.my setf mib
" Snort Configuration
au BufNewFile,BufRead *.hog,snort.conf,vision.conf setf hog
-au BufNewFile,BufRead *.rules call s:FTRules()
-
-let s:ft_rules_udev_rules_pattern = '^\s*\cudev_rules\s*=\s*"\([^"]\{-1,}\)/*".*'
-func! s:FTRules()
- let path = expand('<amatch>:p')
- if path =~ '^/\(etc/udev/\%(rules\.d/\)\=.*\.rules\|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
-
+au BufNewFile,BufRead *.rules call dist#ft#FTRules()
" Spec (Linux RPM)
au BufNewFile,BufRead *.spec setf spec
@@ -2146,15 +1560,7 @@ au BufNewFile,BufRead squid.conf setf squid
au BufNewFile,BufRead *.tyb,*.typ,*.tyc,*.pkb,*.pks setf sql
" SQL
-au BufNewFile,BufRead *.sql call s:SQL()
-
-func! s:SQL()
- if exists("g:filetype_sql")
- exe "setf " . g:filetype_sql
- else
- setf sql
- endif
-endfunc
+au BufNewFile,BufRead *.sql call dist#ft#SQL()
" SQLJ
au BufNewFile,BufRead *.sqlj setf sqlj
@@ -2201,32 +1607,9 @@ au BufNewFile,BufRead */etc/sudoers,sudoers.tmp setf sudoers
" SVG (Scalable Vector Graphics)
au BufNewFile,BufRead *.svg setf svg
-" 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! s: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
- if search('^use\s\s*\k', 'nc', 30)
- setf perl
- return 1
- endif
- return 0
-endfunc
-
" Tads (or Nroff or Perl test file)
au BufNewFile,BufRead *.t
- \ if !s:FTnroff() && !s:FTperl() | setf tads | endif
+ \ if !dist#ft#FTnroff() && !dist#ft#FTperl() | setf tads | endif
" Tags
au BufNewFile,BufRead tags setf tags
@@ -2255,63 +1638,7 @@ au BufNewFile,BufRead *.ti setf terminfo
" TeX
au BufNewFile,BufRead *.latex,*.sty,*.dtx,*.ltx,*.bbl setf tex
-au BufNewFile,BufRead *.tex call s:FTtex()
-
-" 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 "latex" or to g:tex_flavor, can be set in user's vimrc.
-func! s: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
+au BufNewFile,BufRead *.tex call dist#ft#FTtex()
" ConTeXt
au BufNewFile,BufRead *.mkii,*.mkiv,*.mkvi setf context
@@ -2412,7 +1739,7 @@ au BufRead,BufNewFile *.hw,*.module,*.pkg
\ endif
" Visual Basic (also uses *.bas) or FORM
-au BufNewFile,BufRead *.frm call s:FTVB("form")
+au BufNewFile,BufRead *.frm call dist#ft#FTVB("form")
" SaxBasic is close to Visual Basic
au BufNewFile,BufRead *.sba setf vb
@@ -2502,36 +1829,10 @@ au BufNewFile,BufRead .Xdefaults,.Xpdefaults,.Xresources,xdm-config,*.ad setf xd
" Xmath
au BufNewFile,BufRead *.msc,*.msf setf xmath
au BufNewFile,BufRead *.ms
- \ if !s:FTnroff() | setf xmath | endif
+ \ if !dist#ft#FTnroff() | setf xmath | endif
" XML specific variants: docbk and xbl
-au BufNewFile,BufRead *.xml call s:FTxml()
-
-func! s: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
+au BufNewFile,BufRead *.xml call dist#ft#FTxml()
" XMI (holding UML models) is also XML
au BufNewFile,BufRead *.xmi setf xml
@@ -2574,25 +1875,7 @@ au BufNewFile,BufRead *.xsl,*.xslt setf xslt
au BufNewFile,BufRead *.yy,*.yxx,*.y++ setf yacc
" Yacc or racc
-au BufNewFile,BufRead *.y call s:FTy()
-
-func! s: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
-
+au BufNewFile,BufRead *.y call dist#ft#FTy()
" Yaml
au BufNewFile,BufRead *.yaml,*.yml setf yaml
@@ -2608,9 +1891,9 @@ au BufNewFile,BufRead *.zut setf zimbutempl
" Zope
" dtml (zope dynamic template markup language), pt (zope page template),
" cpt (zope form controller page template)
-au BufNewFile,BufRead *.dtml,*.pt,*.cpt call s:FThtml()
+au BufNewFile,BufRead *.dtml,*.pt,*.cpt call dist#ft#FThtml()
" zsql (zope sql method)
-au BufNewFile,BufRead *.zsql call s:SQL()
+au BufNewFile,BufRead *.zsql call dist#ft#SQL()
" Z80 assembler asz80
au BufNewFile,BufRead *.z8a setf z8a
@@ -2652,6 +1935,11 @@ au BufNewFile,BufRead *asterisk*/*voicemail.conf* call s:StarSetf('asteriskvm')
" Bazaar version control
au BufNewFile,BufRead bzr_log.* setf bzr
+" Bazel build file
+if !has("fname_case")
+ au BufNewFile,BufRead BUILD setf bzl
+endif
+
" BIND zone
au BufNewFile,BufRead */named/db.*,*/bind/db.* call s:StarSetf('bindzone')
@@ -2759,17 +2047,7 @@ au BufNewFile,BufRead *termcap*
" ReDIF
" Only used when the .rdf file was not detected to be XML.
-au BufRead,BufNewFile *.rdf call s:Redif()
-func! s:Redif()
- let lnum = 1
- while lnum <= 5 && lnum < line('$')
- if getline(lnum) =~ "^\ctemplate-type:"
- setf redif
- return
- endif
- let lnum = lnum + 1
- endwhile
-endfunc
+au BufRead,BufNewFile *.rdf call dist#ft#Redif()
" Remind
au BufNewFile,BufRead .reminders* call s:StarSetf('remind')
diff --git a/runtime/scripts.vim b/runtime/scripts.vim
index 63bf9efcf9..18263e2842 100644
--- a/runtime/scripts.vim
+++ b/runtime/scripts.vim
@@ -1,11 +1,15 @@
" Vim support file to detect file types in scripts
"
" Maintainer: Bram Moolenaar <Bram@vim.org>
-" Last change: 2017 Aug 27
+" Last change: 2017 Nov 11
" 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.
+"
+" 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.
" Only do the rest when the FileType autocommand has not been triggered yet.
@@ -28,12 +32,12 @@ set cpo&vim
let s:line1 = getline(1)
-if s:line1 =~ "^#!"
+if s:line1 =~# "^#!"
" A script that starts with "#!".
" Check for a line like "#!/usr/bin/env VAR=val bash". Turn it into
" "#!/usr/bin/bash" to make matching easier.
- if s:line1 =~ '^#!\s*\S*\<env\s'
+ if s:line1 =~# '^#!\s*\S*\<env\s'
let s:line1 = substitute(s:line1, '\S\+=\S\+', '', 'g')
let s:line1 = substitute(s:line1, '\<env\s\+', '', '')
endif
@@ -44,11 +48,11 @@ if s:line1 =~ "^#!"
" "#!/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 s:line1 =~ '^#!\s*\a:[/\\]'
+ if s:line1 =~# '^#!\s*\a:[/\\]'
let s:name = substitute(s:line1, '^#!.*[/\\]\(\i\+\).*', '\1', '')
- elseif s:line1 =~ '^#!.*\<env\>'
+ elseif s:line1 =~# '^#!.*\<env\>'
let s:name = substitute(s:line1, '^#!.*\<env\>\s\+\(\i\+\).*', '\1', '')
- elseif s:line1 =~ '^#!\s*[^/\\ ]*\>\([^/\\]\|$\)'
+ elseif s:line1 =~# '^#!\s*[^/\\ ]*\>\([^/\\]\|$\)'
let s:name = substitute(s:line1, '^#!\s*\([^/\\ ]*\>\).*', '\1', '')
else
let s:name = substitute(s:line1, '^#!\s*\S*[/\\]\(\i\+\).*', '\1', '')
@@ -56,116 +60,116 @@ if s:line1 =~ "^#!"
" 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'
+ if getline(3) =~# '^exec wish'
let s:name = 'wish'
endif
" Bourne-like shell scripts: bash bash2 ksh ksh93 sh
- if s:name =~ '^\(bash\d*\|\|ksh\d*\|sh\)\>'
- call SetFileTypeSH(s:line1) " defined in filetype.vim
+ if s:name =~# '^\(bash\d*\|\|ksh\d*\|sh\)\>'
+ call dist#ft#SetFileTypeSH(s:line1) " defined in filetype.vim
" csh scripts
- elseif s:name =~ '^csh\>'
+ elseif s:name =~# '^csh\>'
if exists("g:filetype_csh")
- call SetFileTypeShell(g:filetype_csh)
+ call dist#ft#SetFileTypeShell(g:filetype_csh)
else
- call SetFileTypeShell("csh")
+ call dist#ft#SetFileTypeShell("csh")
endif
" tcsh scripts
- elseif s:name =~ '^tcsh\>'
- call SetFileTypeShell("tcsh")
+ elseif s:name =~# '^tcsh\>'
+ call dist#ft#SetFileTypeShell("tcsh")
" Z shell scripts
- elseif s:name =~ '^zsh\>'
+ elseif s:name =~# '^zsh\>'
set ft=zsh
" TCL scripts
- elseif s:name =~ '^\(tclsh\|wish\|expectk\|itclsh\|itkwish\)\>'
+ elseif s:name =~# '^\(tclsh\|wish\|expectk\|itclsh\|itkwish\)\>'
set ft=tcl
" Expect scripts
- elseif s:name =~ '^expect\>'
+ elseif s:name =~# '^expect\>'
set ft=expect
" Gnuplot scripts
- elseif s:name =~ '^gnuplot\>'
+ elseif s:name =~# '^gnuplot\>'
set ft=gnuplot
" Makefiles
- elseif s:name =~ 'make\>'
+ elseif s:name =~# 'make\>'
set ft=make
" Lua
- elseif s:name =~ 'lua'
+ elseif s:name =~# 'lua'
set ft=lua
" Perl 6
- elseif s:name =~ 'perl6'
+ elseif s:name =~# 'perl6'
set ft=perl6
" Perl
- elseif s:name =~ 'perl'
+ elseif s:name =~# 'perl'
set ft=perl
" PHP
- elseif s:name =~ 'php'
+ elseif s:name =~# 'php'
set ft=php
" Python
- elseif s:name =~ 'python'
+ elseif s:name =~# 'python'
set ft=python
" Groovy
- elseif s:name =~ '^groovy\>'
+ elseif s:name =~# '^groovy\>'
set ft=groovy
" Ruby
- elseif s:name =~ 'ruby'
+ elseif s:name =~# 'ruby'
set ft=ruby
" JavaScript
- elseif s:name =~ 'node\(js\)\=\>' || s:name =~ 'rhino\>'
+ elseif s:name =~# 'node\(js\)\=\>' || s:name =~# 'rhino\>'
set ft=javascript
" BC calculator
- elseif s:name =~ '^bc\>'
+ elseif s:name =~# '^bc\>'
set ft=bc
" sed
- elseif s:name =~ 'sed\>'
+ elseif s:name =~# 'sed\>'
set ft=sed
" OCaml-scripts
- elseif s:name =~ 'ocaml'
+ elseif s:name =~# 'ocaml'
set ft=ocaml
" Awk scripts
- elseif s:name =~ 'awk\>'
+ elseif s:name =~# 'awk\>'
set ft=awk
" Website MetaLanguage
- elseif s:name =~ 'wml'
+ elseif s:name =~# 'wml'
set ft=wml
" Scheme scripts
- elseif s:name =~ 'scheme'
+ elseif s:name =~# 'scheme'
set ft=scheme
" CFEngine scripts
- elseif s:name =~ 'cfengine'
+ elseif s:name =~# 'cfengine'
set ft=cfengine
" Erlang scripts
- elseif s:name =~ 'escript'
+ elseif s:name =~# 'escript'
set ft=erlang
" Haskell
- elseif s:name =~ 'haskell'
+ elseif s:name =~# 'haskell'
set ft=haskell
" Scala
- elseif s:name =~ 'scala\>'
+ elseif s:name =~# 'scala\>'
set ft=scala
endif
@@ -180,28 +184,28 @@ else
let s:line5 = getline(5)
" Bourne-like shell scripts: sh ksh bash bash2
- if s:line1 =~ '^:$'
- call SetFileTypeSH(s:line1) " defined in filetype.vim
+ if s:line1 =~# '^:$'
+ call dist#ft#SetFileTypeSH(s:line1) " defined in filetype.vim
" Z shell scripts
- 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\>'
+ 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\>'
set ft=zsh
" ELM Mail files
- elseif s:line1 =~ '^From \([a-zA-Z][a-zA-Z_0-9\.=-]*\(@[^ ]*\)\=\|-\) .* \(19\|20\)\d\d$'
+ elseif s:line1 =~# '^From \([a-zA-Z][a-zA-Z_0-9\.=-]*\(@[^ ]*\)\=\|-\) .* \(19\|20\)\d\d$'
set ft=mail
" Mason
- elseif s:line1 =~ '^<[%&].*>'
+ elseif s:line1 =~# '^<[%&].*>'
set ft=mason
" Vim scripts (must have '" vim' as the first line to trigger this)
- elseif s:line1 =~ '^" *[vV]im$'
+ elseif s:line1 =~# '^" *[vV]im$'
set ft=vim
" MOO
- elseif s:line1 =~ '^\*\* LambdaMOO Database, Format Version \%([1-3]\>\)\@!\d\+ \*\*$'
+ elseif s:line1 =~# '^\*\* LambdaMOO Database, Format Version \%([1-3]\>\)\@!\d\+ \*\*$'
set ft=moo
" Diff file:
@@ -215,40 +219,45 @@ else
" - "=== ", "--- ", "+++ " (bzr diff, common case)
" - "=== (removed|added|renamed|modified)" (bzr diff, alternative)
" - "# HG changeset patch" in first line (Mercurial export format)
- 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\)')
+ 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\)')
set ft=diff
" PostScript Files (must have %!PS as the first line, like a2ps output)
- elseif s:line1 =~ '^%![ \t]*PS'
+ elseif s:line1 =~# '^%![ \t]*PS'
set ft=postscr
" M4 scripts: Guess there is a line that starts with "dnl".
- elseif s:line1 =~ '^\s*dnl\>'
- \ || s:line2 =~ '^\s*dnl\>'
- \ || s:line3 =~ '^\s*dnl\>'
- \ || s:line4 =~ '^\s*dnl\>'
- \ || s:line5 =~ '^\s*dnl\>'
+ elseif s:line1 =~# '^\s*dnl\>'
+ \ || s:line2 =~# '^\s*dnl\>'
+ \ || s:line3 =~# '^\s*dnl\>'
+ \ || s:line4 =~# '^\s*dnl\>'
+ \ || s:line5 =~# '^\s*dnl\>'
set ft=m4
+ " AmigaDos scripts
+ elseif $TERM == "amiga"
+ \ && (s:line1 =~# "^;" || s:line1 =~? '^\.bra')
+ set ft=amiga
+
" 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"
- elseif s:line1 =~ '^\*\*\*\* Purify'
+ elseif s:line1 =~# '^\*\*\*\* Purify'
set ft=purifylog
" XML
- elseif s:line1 =~ '<?\s*xml.*?>'
+ elseif s:line1 =~# '<?\s*xml.*?>'
set ft=xml
" XHTML (e.g.: PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN")
- elseif s:line1 =~ '\<DTD\s\+XHTML\s'
+ elseif s:line1 =~# '\<DTD\s\+XHTML\s'
set ft=xhtml
" HTML (e.g.: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN")
@@ -257,43 +266,43 @@ else
set ft=html
" PDF
- elseif s:line1 =~ '^%PDF-'
+ elseif s:line1 =~# '^%PDF-'
set ft=pdf
" XXD output
- elseif s:line1 =~ '^\x\{7}: \x\{2} \=\x\{2} \=\x\{2} \=\x\{2} '
+ elseif s:line1 =~# '^\x\{7}: \x\{2} \=\x\{2} \=\x\{2} \=\x\{2} '
set ft=xxd
" RCS/CVS log output
- elseif s:line1 =~ '^RCS file:' || s:line2 =~ '^RCS file:'
+ elseif s:line1 =~# '^RCS file:' || s:line2 =~# '^RCS file:'
set ft=rcslog
" CVS commit
- elseif s:line2 =~ '^CVS:' || getline("$") =~ '^CVS: '
+ elseif s:line2 =~# '^CVS:' || getline("$") =~# '^CVS: '
set ft=cvs
" Prescribe
- elseif s:line1 =~ '^!R!'
+ elseif s:line1 =~# '^!R!'
set ft=prescribe
" Send-pr
- elseif s:line1 =~ '^SEND-PR:'
+ elseif s:line1 =~# '^SEND-PR:'
set ft=sendpr
" SNNS files
- elseif s:line1 =~ '^SNNS network definition file'
+ elseif s:line1 =~# '^SNNS network definition file'
set ft=snnsnet
- elseif s:line1 =~ '^SNNS pattern definition file'
+ elseif s:line1 =~# '^SNNS pattern definition file'
set ft=snnspat
- elseif s:line1 =~ '^SNNS result file'
+ elseif s:line1 =~# '^SNNS result file'
set ft=snnsres
" Virata
- elseif s:line1 =~ '^%.\{-}[Vv]irata'
- \ || s:line2 =~ '^%.\{-}[Vv]irata'
- \ || s:line3 =~ '^%.\{-}[Vv]irata'
- \ || s:line4 =~ '^%.\{-}[Vv]irata'
- \ || s:line5 =~ '^%.\{-}[Vv]irata'
+ elseif s:line1 =~# '^%.\{-}[Vv]irata'
+ \ || s:line2 =~# '^%.\{-}[Vv]irata'
+ \ || s:line3 =~# '^%.\{-}[Vv]irata'
+ \ || s:line4 =~# '^%.\{-}[Vv]irata'
+ \ || s:line5 =~# '^%.\{-}[Vv]irata'
set ft=virata
" Strace
@@ -301,17 +310,17 @@ else
set ft=strace
" VSE JCL
- elseif s:line1 =~ '^\* $$ JOB\>' || s:line1 =~ '^// *JOB\>'
+ elseif s:line1 =~# '^\* $$ JOB\>' || s:line1 =~# '^// *JOB\>'
set ft=vsejcl
" TAK and SINDA
- elseif s:line4 =~ 'K & K Associates' || s:line2 =~ 'TAK 2000'
+ elseif s:line4 =~# 'K & K Associates' || s:line2 =~# 'TAK 2000'
set ft=takout
- elseif s:line3 =~ 'S Y S T E M S I M P R O V E D '
+ elseif s:line3 =~# 'S Y S T E M S I M P R O V E D '
set ft=sindaout
- elseif getline(6) =~ 'Run Date: '
+ elseif getline(6) =~# 'Run Date: '
set ft=takcmp
- elseif getline(9) =~ 'Node File 1'
+ elseif getline(9) =~# 'Node File 1'
set ft=sindacmp
" DNS zone files
@@ -319,34 +328,34 @@ else
set ft=bindzone
" BAAN
- elseif s:line1 =~ '|\*\{1,80}' && s:line2 =~ 'VRC '
- \ || s:line2 =~ '|\*\{1,80}' && s:line3 =~ 'VRC '
+ elseif s:line1 =~# '|\*\{1,80}' && s:line2 =~# 'VRC '
+ \ || s:line2 =~# '|\*\{1,80}' && s:line3 =~# 'VRC '
set ft=baan
" Valgrind
- elseif s:line1 =~ '^==\d\+== valgrind' || s:line3 =~ '^==\d\+== Using valgrind'
+ elseif s:line1 =~# '^==\d\+== valgrind' || s:line3 =~# '^==\d\+== Using valgrind'
set ft=valgrind
" Go docs
- elseif s:line1 =~ '^PACKAGE DOCUMENTATION$'
+ elseif s:line1 =~# '^PACKAGE DOCUMENTATION$'
set ft=godoc
" Renderman Interface Bytestream
- elseif s:line1 =~ '^##RenderMan'
+ elseif s:line1 =~# '^##RenderMan'
set ft=rib
" Scheme scripts
- elseif s:line1 =~ 'exec\s\+\S*scheme' || s:line2 =~ 'exec\s\+\S*scheme'
+ elseif s:line1 =~# 'exec\s\+\S*scheme' || s:line2 =~# 'exec\s\+\S*scheme'
set ft=scheme
" Git output
- elseif s:line1 =~ '^\(commit\|tree\|object\) \x\{40\}\>\|^tag \S\+$'
+ elseif s:line1 =~# '^\(commit\|tree\|object\) \x\{40\}\>\|^tag \S\+$'
set ft=git
" Gprof (gnu profiler)
elseif s:line1 == 'Flat profile:'
\ && s:line2 == ''
- \ && s:line3 =~ '^Each sample counts as .* seconds.$'
+ \ && s:line3 =~# '^Each sample counts as .* seconds.$'
set ft=gprof
" Erlang terms
@@ -357,18 +366,18 @@ else
" CVS diff
else
let s:lnum = 1
- while getline(s:lnum) =~ "^? " && s:lnum < line("$")
+ while getline(s:lnum) =~# "^? " && s:lnum < line("$")
let s:lnum += 1
endwhile
- if getline(s:lnum) =~ '^Index:\s\+\f\+$'
+ if getline(s:lnum) =~# '^Index:\s\+\f\+$'
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
- elseif expand("%") =~ '\a\a_\a\a\($\|[.@]\)\|i18n$\|POSIX$\|translit_'
+ elseif expand("%") =~# '\a\a_\a\a\($\|[.@]\)\|i18n$\|POSIX$\|translit_'
let s:lnum = 1
while s:lnum < 100 && s:lnum < line("$")
- if getline(s:lnum) =~ '^LC_\(IDENTIFICATION\|CTYPE\|COLLATE\|MONETARY\|NUMERIC\|TIME\|MESSAGES\|PAPER\|TELEPHONE\|MEASUREMENT\|NAME\|ADDRESS\)$'
+ if getline(s:lnum) =~# '^LC_\(IDENTIFICATION\|CTYPE\|COLLATE\|MONETARY\|NUMERIC\|TIME\|MESSAGES\|PAPER\|TELEPHONE\|MEASUREMENT\|NAME\|ADDRESS\)$'
setf fdcc
break
endif
diff --git a/src/nvim/fileio.c b/src/nvim/fileio.c
index 52686f6651..02f72dbce3 100644
--- a/src/nvim/fileio.c
+++ b/src/nvim/fileio.c
@@ -1,9 +1,7 @@
// This is an open source non-commercial project. Dear PVS-Studio, please check
// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
-/*
- * fileio.c: read from and write to a file
- */
+// fileio.c: read from and write to a file
#include <assert.h>
#include <errno.h>
@@ -65,57 +63,62 @@
#define BUFSIZE 8192 /* size of normal write buffer */
#define SMBUFSIZE 256 /* size of emergency write buffer */
-/*
- * The autocommands are stored in a list for each event.
- * Autocommands for the same pattern, that are consecutive, are joined
- * together, to avoid having to match the pattern too often.
- * The result is an array of Autopat lists, which point to AutoCmd lists:
- *
- * first_autopat[0] --> Autopat.next --> Autopat.next --> NULL
- * Autopat.cmds Autopat.cmds
- * | |
- * V V
- * AutoCmd.next AutoCmd.next
- * | |
- * V V
- * AutoCmd.next NULL
- * |
- * V
- * NULL
- *
- * first_autopat[1] --> Autopat.next --> NULL
- * Autopat.cmds
- * |
- * V
- * AutoCmd.next
- * |
- * V
- * NULL
- * etc.
- *
- * The order of AutoCmds is important, this is the order in which they were
- * defined and will have to be executed.
- */
+//
+// The autocommands are stored in a list for each event.
+// Autocommands for the same pattern, that are consecutive, are joined
+// together, to avoid having to match the pattern too often.
+// The result is an array of Autopat lists, which point to AutoCmd lists:
+//
+// last_autopat[0] -----------------------------+
+// V
+// first_autopat[0] --> Autopat.next --> Autopat.next --> NULL
+// Autopat.cmds Autopat.cmds
+// | |
+// V V
+// AutoCmd.next AutoCmd.next
+// | |
+// V V
+// AutoCmd.next NULL
+// |
+// V
+// NULL
+//
+// last_autopat[1] --------+
+// V
+// first_autopat[1] --> Autopat.next --> NULL
+// Autopat.cmds
+// |
+// V
+// AutoCmd.next
+// |
+// V
+// NULL
+// etc.
+//
+// The order of AutoCmds is important, this is the order in which they were
+// defined and will have to be executed.
+//
typedef struct AutoCmd {
- char_u *cmd; /* The command to be executed (NULL
- when command has been removed) */
- char nested; /* If autocommands nest here */
- char last; /* last command in list */
- scid_T scriptID; /* script ID where defined */
- struct AutoCmd *next; /* Next AutoCmd in list */
+ char_u *cmd; // The command to be executed (NULL
+ // when command has been removed)
+ char nested; // If autocommands nest here
+ char last; // last command in list
+ scid_T scriptID; // script ID where defined
+ struct AutoCmd *next; // Next AutoCmd in list
} AutoCmd;
typedef struct AutoPat {
- char_u *pat; /* pattern as typed (NULL when pattern
- has been removed) */
- regprog_T *reg_prog; /* compiled regprog for pattern */
- AutoCmd *cmds; /* list of commands to do */
- struct AutoPat *next; /* next AutoPat in AutoPat list */
- int group; /* group ID */
- int patlen; /* strlen() of pat */
- int buflocal_nr; /* !=0 for buffer-local AutoPat */
- char allow_dirs; /* Pattern may match whole path */
- char last; /* last pattern for apply_autocmds() */
+ struct AutoPat *next; // next AutoPat in AutoPat list; MUST
+ // be the first entry
+ char_u *pat; // pattern as typed (NULL when pattern
+ // has been removed)
+ regprog_T *reg_prog; // compiled regprog for pattern
+ AutoCmd *cmds; // list of commands to do
+ int group; // group ID
+ int patlen; // strlen() of pat
+ int buflocal_nr; // !=0 for buffer-local AutoPat
+ char allow_dirs; // Pattern may match whole path
+ char last; // last pattern for apply_autocmds()
} AutoPat;
/*
@@ -226,6 +229,15 @@ void filemess(buf_T *buf, char_u *name, char_u *s, int attr)
msg_scrolled_ign = FALSE;
}
+static AutoPat *last_autopat[NUM_EVENTS] = {
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
/*
* Read lines from file "fname" into the buffer after line "from".
*
@@ -5528,6 +5540,15 @@ static void au_cleanup(void)
/* remove the pattern if it has been marked for deletion */
if (ap->pat == NULL) {
+ if (ap->next == NULL) {
+ if (prev_ap == &(first_autopat[(int)event])) {
+ last_autopat[(int)event] = NULL;
+ } else {
+ // this depends on the "next" field being the first in
+ // the struct
+ last_autopat[(int)event] = (AutoPat *)prev_ap;
+ }
+ }
*prev_ap = ap->next;
vim_regfree(ap->reg_prog);
xfree(ap);
@@ -6120,10 +6141,13 @@ static int do_autocmd_event(event_T event, char_u *pat, int nested, char_u *cmd,
patlen = (int)STRLEN(buflocal_pat); /* but not endpat */
}
- /*
- * Find AutoPat entries with this pattern.
- */
- prev_ap = &first_autopat[(int)event];
+ // Find AutoPat entries with this pattern. When adding a command it
+ // always goes at or after the last one, so start at the end.
+ if (!forceit && *cmd != NUL && last_autopat[(int)event] != NULL) {
+ prev_ap = &last_autopat[(int)event];
+ } else {
+ prev_ap = &first_autopat[(int)event];
+ }
while ((ap = *prev_ap) != NULL) {
if (ap->pat != NULL) {
/* Accept a pattern when:
@@ -6209,6 +6233,7 @@ static int do_autocmd_event(event_T event, char_u *pat, int nested, char_u *cmd,
}
ap->cmds = NULL;
*prev_ap = ap;
+ last_autopat[(int)event] = ap;
ap->next = NULL;
if (group == AUGROUP_ALL)
ap->group = current_augroup;