summaryrefslogblamecommitdiffstats
path: root/autoload/polyglot.vim
blob: 29287ece84fc3b3731d41513b980f6e89b573b07 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
12



                                                             







                                                                         

                                       


                                     
            
       

          











                               
                       































































                                                                              
                          
 
                      


          
                                                   
 
                         


           
                                          
 
                                       
 


                                               


            
                                

       

                                      


                                         
                                     







                                        
                                  



                                             
                                    





                                  
                                        
       
                                



                                  
                                        



                                           
                                     

         
                                

       




                                                                                                                                                 
                                    
           
                                    


                               
                             

                                
                              
       
                             

       







                                                                                                                                                 
                                  

                       
                                    

                         
                                 

                                                     
                                    


                
                                

                           
                                      
       
                                





                                            
                                   

                                                                            
                                    

                                                                        
                                  


                            
                                       
       
                               

       



                                                                                                  
                                 
         
                                  


        



                                           
                                   

                                      
                                    




                                            
                                   

                              
                                    

                                                              
                                   

                                               
                                    

                             
                                   

                               
                                          

         
                                





                                             
                                    

         
                                 

       



                                                                   
                                

         
                               

       


                     
" Line continuation is used here, remove 'C' from 'cpoptions'
let s:cpo_save = &cpo
set cpo&vim

" We need it because scripts.vim in vim uses "set ft=" which cannot be
" overridden with setf (and we can't use set ft= so our scripts.vim work)
func! s:Setf(ft)
  if &filetype !~# '<'.a:ft.'>'
    let &filetype = a:ft
  endif
endfunc

func! polyglot#Heuristics()
  " Try to detect filetype from shebang
  let l:filetype = polyglot#Shebang()
  if l:filetype != ""
    exec "setf " . l:filetype
    return 1
  endif

  return 0
endfunc

let s:interpreters = {
  \ 'osascript': 'applescript',
  \ 'tcc': 'c',
  \ 'coffee': 'coffee',
  \ 'crystal': 'crystal',
  \ 'dart': 'dart',
  \ 'elixir': 'elixir',
  \ 'escript': 'erlang',
  \ 'fish': 'fish',
  \ 'gnuplot': 'gnuplot',
  \ 'groovy': 'groovy',
  \ 'runhaskell': 'haskell',
  \ 'chakra': 'javascript',
  \ 'd8': 'javascript',
  \ 'gjs': 'javascript',
  \ 'js': 'javascript',
  \ 'node': 'javascript',
  \ 'nodejs': 'javascript',
  \ 'qjs': 'javascript',
  \ 'rhino': 'javascript',
  \ 'v8': 'javascript',
  \ 'v8-shell': 'javascript',
  \ 'julia': 'julia',
  \ 'lua': 'lua',
  \ 'moon': 'moon',
  \ 'ocaml': 'ocaml',
  \ 'ocamlrun': 'ocaml',
  \ 'ocamlscript': 'ocaml',
  \ 'cperl': 'perl',
  \ 'perl': 'perl',
  \ 'php': 'php',
  \ 'pwsh': 'ps1',
  \ 'python': 'python',
  \ 'python2': 'python',
  \ 'python3': 'python',
  \ 'qmake': 'qmake',
  \ 'Rscript': 'r',
  \ 'racket': 'racket',
  \ 'perl6': 'raku',
  \ 'raku': 'raku',
  \ 'rakudo': 'raku',
  \ 'ruby': 'ruby',
  \ 'macruby': 'ruby',
  \ 'rake': 'ruby',
  \ 'jruby': 'ruby',
  \ 'rbx': 'ruby',
  \ 'scala': 'scala',
  \ 'ash': 'sh',
  \ 'bash': 'sh',
  \ 'dash': 'sh',
  \ 'ksh': 'sh',
  \ 'mksh': 'sh',
  \ 'pdksh': 'sh',
  \ 'rc': 'sh',
  \ 'sh': 'sh',
  \ 'zsh': 'sh',
  \ 'boolector': 'smt2',
  \ 'cvc4': 'smt2',
  \ 'mathsat5': 'smt2',
  \ 'opensmt': 'smt2',
  \ 'smtinterpol': 'smt2',
  \ 'smt-rat': 'smt2',
  \ 'stp': 'smt2',
  \ 'verit': 'smt2',
  \ 'yices2': 'smt2',
  \ 'z3': 'smt2',
  \ 'deno': 'typescript',
  \ 'ts-node': 'typescript',
  \ }

let s:r_hashbang = '^#!\s*\(\S\+\)\s*\(.*\)\s*'
let s:r_envflag = '%(\S\+=\S\+\|-[iS]\|--ignore-environment\|--split-string\)'
let s:r_env = '^\%(\' . s:r_envflag . '\s\+\)*\(\S\+\)'

func! polyglot#Shebang()
  let l:line1 = getline(1)

  if l:line1 !~# "^#!"
    return
  endif

  let l:pathrest = matchlist(l:line1, s:r_hashbang)

  if len(l:pathrest) == 0
    return 
  endif

  let [_, l:path, l:rest; __] = l:pathrest

  let l:script = split(l:path, "/")[-1]

  if l:script == "env"
    let l:argspath = matchlist(l:rest, s:r_env)
    if len(l:argspath) == 0
      return
    endif

    let l:script = l:argspath[1]
  endif

  if has_key(s:interpreters, l:script)
    return s:interpreters[l:script]
  endif

  for interpreter in keys(s:interpreters)
    if l:script =~# '^' . interpreter
      return s:interpreters[interpreter]
    endif
  endfor
endfunc

func! polyglot#DetectInpFiletype()
  let line = getline(1)
  if line =~# '^\*'
    call s:Setf('abaqus') | return
  endif
  for lnum in range(1, min([line("$"), 500]))
    let line = getline(lnum)
    if line =~? '^header surface data'
      call s:Setf('trasys') | return
    endif
  endfor
endfunc

func! polyglot#DetectAsaFiletype()
  if exists("g:filetype_asa")
    call s:Setf(g:filetype_asa) | return
  endif
  call s:Setf('aspvbs') | return
endfunc

func! polyglot#DetectAspFiletype()
  if exists("g:filetype_asp")
    call s:Setf(g:filetype_asp) | return
  endif
  for lnum in range(1, min([line("$"), 3]))
    let line = getline(lnum)
    if line =~? 'perlscript'
      call s:Setf('aspperl') | return
    endif
  endfor
  call s:Setf('aspvbs') | return
endfunc

func! polyglot#DetectHFiletype()
  for lnum in range(1, min([line("$"), 200]))
    let line = getline(lnum)
    if line =~# '^\s*\(@\(interface\|class\|protocol\|property\|end\|synchronised\|selector\|implementation\)\(\<\|\>\)\|#import\s\+.\+\.h[">]\)'
      if exists("g:c_syntax_for_h")
        call s:Setf('objc') | return
      endif
      call s:Setf('objcpp') | return
    endif
  endfor
  if exists("g:c_syntax_for_h")
    call s:Setf('c') | return
  endif
  if exists("g:ch_syntax_for_h")
    call s:Setf('ch') | return
  endif
  call s:Setf('cpp') | return
endfunc

func! polyglot#DetectMFiletype()
  let saw_comment = 0
  for lnum in range(1, min([line("$"), 100]))
    let line = getline(lnum)
    if line =~# '^\s*/\*'
      let saw_comment = 1
    endif
    if line =~# '^\s*\(@\(interface\|class\|protocol\|property\|end\|synchronised\|selector\|implementation\)\(\<\|\>\)\|#import\s\+.\+\.h[">]\)'
      call s:Setf('objc') | return
    endif
    if line =~# '^\s*%'
      call s:Setf('octave') | return
    endif
    if line =~# '^\s*(\*'
      call s:Setf('mma') | return
    endif
    if line =~? '^\s*\(\(type\|var\)\(\<\|\>\)\|--\)'
      call s:Setf('murphi') | return
    endif
  endfor
  if saw_comment
    call s:Setf('objc') | return
  endif
  if exists("g:filetype_m")
    call s:Setf(g:filetype_m) | return
  endif
  call s:Setf('octave') | return
endfunc

func! polyglot#DetectFsFiletype()
  for lnum in range(1, min([line("$"), 50]))
    let line = getline(lnum)
    if line =~# '^\(: \|new-device\)'
      call s:Setf('forth') | return
    endif
    if line =~# '^\s*\(#light\|import\|let\|module\|namespace\|open\|type\)'
      call s:Setf('fsharp') | return
    endif
    if line =~# '\s*\(#version\|precision\|uniform\|varying\|vec[234]\)'
      call s:Setf('glsl') | return
    endif
  endfor
  if exists("g:filetype_fs")
    call s:Setf(g:filetype_fs) | return
  endif
  call s:Setf('forth') | return
endfunc

func! polyglot#DetectReFiletype()
  for lnum in range(1, min([line("$"), 50]))
    let line = getline(lnum)
    if line =~# '^\s*#\%(\%(if\|ifdef\|define\|pragma\)\s\+\w\|\s*include\s\+[<"]\|template\s*<\)'
      call s:Setf('cpp') | return
    endif
    call s:Setf('reason') | return
  endfor
endfunc

func! polyglot#DetectIdrFiletype()
  for lnum in range(1, min([line("$"), 5]))
    let line = getline(lnum)
    if line =~# '^\s*--.*[Ii]dris \=1'
      call s:Setf('idris') | return
    endif
    if line =~# '^\s*--.*[Ii]dris \=2'
      call s:Setf('idris2') | return
    endif
  endfor
  for lnum in range(1, min([line("$"), 30]))
    let line = getline(lnum)
    if line =~# '^pkgs =.*'
      call s:Setf('idris') | return
    endif
    if line =~# '^depends =.*'
      call s:Setf('idris2') | return
    endif
    if line =~# '^%language \(TypeProviders\|ElabReflection\)'
      call s:Setf('idris') | return
    endif
    if line =~# '^%language PostfixProjections'
      call s:Setf('idris2') | return
    endif
    if line =~# '^%access .*'
      call s:Setf('idris') | return
    endif
    if exists("g:filetype_idr")
      call s:Setf(g:filetype_idr) | return
    endif
  endfor
  call s:Setf('idris2') | return
endfunc

func! polyglot#DetectLidrFiletype()
  for lnum in range(1, min([line("$"), 200]))
    let line = getline(lnum)
    if line =~# '^>\s*--.*[Ii]dris \=1'
      call s:Setf('lidris') | return
    endif
  endfor
  call s:Setf('lidris2') | return
endfunc

func! polyglot#DetectBasFiletype()
  for lnum in range(1, min([line("$"), 5]))
    let line = getline(lnum)
    if line =~? 'VB_Name\|Begin VB\.\(Form\|MDIForm\|UserControl\)'
      call s:Setf('vb') | return
    endif
  endfor
  call s:Setf('basic') | return
endfunc

" Restore 'cpoptions'
let &cpo = s:cpo_save
unlet s:cpo_save