summaryrefslogblamecommitdiffstats
path: root/plugin/polyglot.vim
blob: ccdef1128f538dc82f702fdf039fdab5446f7e8d (plain) (tree)




















                                                                                  




                                                             































































































































                                                                       
" Heuristically set expandtab and shiftwidth options
"
" Modified version of vim-sleuth:
"   - tabstop is not set, it's up to user to set it
"   - check maximum of 32 lines, instead of 1024
"   - check maximum 6 files, instead of 20
"   - check maximum of 2 filer per directory level, instead of 8
"   - check maximum of 3 directory levels
"   - check only to the nearest .git, .hg, or .svn directory
"   - globs are concatenated for performance
if exists('g:polyglot_disabled') && index(g:polyglot_disabled, 'autoindent') != -1
  finish
endif

if exists("g:loaded_polyglot") || v:version < 700 || &cp
  finish
endif

let g:loaded_sleuth = 1
let g:loaded_polyglot = 1

" Makes shiftwidth to be synchronized with tabstop by default
if &shiftwidth == &tabstop
  let &shiftwidth = 0
endif

function! s:guess(lines) abort
  let options = {}
  let ccomment = 0
  let podcomment = 0
  let triplequote = 0
  let backtick = 0
  let xmlcomment = 0
  let minindent = 10
  let spaces_minus_tabs = 0

  for line in a:lines
    if !len(line) || line =~# '^\s*$'
      continue
    endif

    if line =~# '^\s*/\*'
      let ccomment = 1
    endif
    if ccomment
      if line =~# '\*/'
        let ccomment = 0
      endif
      continue
    endif

    if line =~# '^=\w'
      let podcomment = 1
    endif
    if podcomment
      if line =~# '^=\%(end\|cut\)\>'
        let podcomment = 0
      endif
      continue
    endif

    if triplequote
      if line =~# '^[^"]*"""[^"]*$'
        let triplequote = 0
      endif
      continue
    elseif line =~# '^[^"]*"""[^"]*$'
      let triplequote = 1
    endif

    if backtick
      if line =~# '^[^`]*`[^`]*$'
        let backtick = 0
      endif
      continue
    elseif &filetype ==# 'go' && line =~# '^[^`]*`[^`]*$'
      let backtick = 1
    endif

    if line =~# '^\s*<\!--'
      let xmlcomment = 1
    endif
    if xmlcomment
      if line =~# '-->'
        let xmlcomment = 0
      endif
      continue
    endif

    let spaces_minus_tabs += line[0] == "\t" ? 1 : -1

    if line[0] == "\t"
      setlocal noexpandtab
      return 1
    elseif line[0] == " "
      let indent = len(matchstr(line, '^ *'))
      if indent % 2 == 0 && indent < minindent
        let minindent = indent
      endif
    endif
  endfor

  if minindent < 10
    setlocal expandtab
    let &shiftwidth=minindent
    return 1
  endif

  return 0
endfunction

function! s:detect_indent() abort
  if &buftype ==# 'help'
    return
  endif

  if s:guess(getline(1, 32))
    return
  endif
  let pattern = sleuth#GlobForFiletype(&filetype)
  if len(pattern) == 0
    return
  endif
  let pattern = '{' . pattern . ',.git,.svn,.hg}'
  let dir = expand('%:p:h')
  let level = 3
  while isdirectory(dir) && dir !=# fnamemodify(dir, ':h') && level > 0
    for neighbor in glob(dir . '/' . pattern, 0, 1)[0:level]
      " Do not consider directories above .git, .svn or .hg
      if fnamemodify(neighbor, ":h:t")[0] == "."
        return
      endif
      if neighbor !=# expand('%:p') && filereadable(neighbor)
        if s:guess(readfile(neighbor, '', 32))
          return
        endif
      endif
    endfor

    let dir = fnamemodify(dir, ':h')
    let level -= 1
  endwhile
endfunction

setglobal smarttab

if !exists('g:did_indent_on')
  filetype indent on
endif

augroup polyglot
  autocmd!
  autocmd FileType * call s:detect_indent()
augroup END