diff options
Diffstat (limited to 'plugin')
-rw-r--r-- | plugin/polyglot.vim | 149 | ||||
-rw-r--r-- | plugin/sleuth.vim | 166 |
2 files changed, 149 insertions, 166 deletions
diff --git a/plugin/polyglot.vim b/plugin/polyglot.vim new file mode 100644 index 00000000..db2976e6 --- /dev/null +++ b/plugin/polyglot.vim @@ -0,0 +1,149 @@ +" 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 + +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 diff --git a/plugin/sleuth.vim b/plugin/sleuth.vim deleted file mode 100644 index a0bba8c4..00000000 --- a/plugin/sleuth.vim +++ /dev/null @@ -1,166 +0,0 @@ -" Heuristically set buffer options -" -" Modified version of vim-sleuth: -" - softtab and tabstop reduced from 8 to 2 -" - number of considered lines reduced from 1024 to 64 -" - maximum 6 other files are checked instead of 20 -" - check maximum of files 2 per directory level instead of 8 -" - maximum of 3 directory levels are checked -" - globs are concatenated for performance -" - tabstop setting is not configured, it's up to user -if exists('g:polyglot_disabled') && index(g:polyglot_disabled, 'autoindent') != -1 - finish -endif - -if exists("g:loaded_sleuth") || exists("g:polyglot_disabled") || v:version < 700 || &cp - finish -endif - -let g:loaded_sleuth = 1 - -function! s:guess(lines) abort - let options = {} - let heuristics = {'spaces': 0, 'hard': 0, 'soft': 0} - let ccomment = 0 - let podcomment = 0 - let triplequote = 0 - let backtick = 0 - let xmlcomment = 0 - let softtab = repeat(' ', 2) - - 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 - - if line =~# '^\t' - let heuristics.hard += 1 - elseif line =~# '^' . softtab - let heuristics.soft += 1 - endif - if line =~# '^ ' - let heuristics.spaces += 1 - endif - let indent = len(matchstr(substitute(line, '\t', softtab, 'g'), '^ *')) - if indent > 1 && (indent < 4 || indent % 2 == 0) && - \ get(options, 'shiftwidth', 99) > indent - let options.shiftwidth = indent - endif - endfor - - if heuristics.hard && !heuristics.spaces - return {'expandtab': 0, 'shiftwidth': &tabstop} - elseif heuristics.soft != heuristics.hard - let options.expandtab = heuristics.soft > heuristics.hard - endif - - return options -endfunction - -function! s:apply_if_ready(options) abort - if !has_key(a:options, 'expandtab') || !has_key(a:options, 'shiftwidth') - return 0 - else - for [option, value] in items(a:options) - call setbufvar('', '&'.option, value) - endfor - return 1 - endif -endfunction - -function! s:detect() abort - if &buftype ==# 'help' - return - endif - - let options = s:guess(getline(1, 64)) - if s:apply_if_ready(options) - return - endif - let c = 6 - let pattern = c > 0 ? sleuth#GlobForFiletype(&filetype) : '' - let dir = expand('%:p:h') - let level = 3 - while isdirectory(dir) && dir !=# fnamemodify(dir, ':h') && c > 0 && level > 0 - let level -= 1 - for neighbor in glob(dir.'/'.pattern,0,1)[0:1] - if neighbor !=# expand('%:p') && filereadable(neighbor) - call extend(options, s:guess(readfile(neighbor, '', 32)), 'keep') - let c -= 1 - endif - if s:apply_if_ready(options) - let b:sleuth_culprit = neighbor - return - endif - if c <= 0 - break - endif - endfor - if c <= 0 - break - endif - let dir = fnamemodify(dir, ':h') - endwhile - if has_key(options, 'shiftwidth') - return s:apply_if_ready(extend({'expandtab': 1}, options)) - endif -endfunction - -setglobal smarttab - -if !exists('g:did_indent_on') - filetype indent on -endif - -augroup polyglot - autocmd! - autocmd FileType * call s:detect() -augroup END |