mirror of
https://github.com/sheerun/vim-polyglot.git
synced 2025-11-08 11:33:52 -05:00
Fix detection of indentation, #537
This commit is contained in:
149
plugin/polyglot.vim
Normal file
149
plugin/polyglot.vim
Normal file
@@ -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
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user