Last active
February 22, 2020 23:32
-
-
Save adscriven/60888c29d8928ccad773d3452ce05953 to your computer and use it in GitHub Desktop.
Vim: guess indentation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
" guessindent.vim -- Guess indentation settings. | |
" [ ] Don't match continuation lines | |
" This works better for code rather than for arbitrarily formatted files | |
" such as the help files, though it sometimes gets those right too. If | |
" somebody has edited with `set noet ts=4` in a file where `set et sw=4` | |
" should be used, there's no easy way to detect that. You'll probably | |
" get ts=8 in that situation, but the file will need fixing anyway. | |
fun! s:guessindent() | |
let view = winsaveview() | |
" Try to avoid funky formatting at the start of a file by | |
" starting at line 100 or midway, whichever is sooner. | |
let mid = line('$') / 2 | |
exe mid > 100 ? 100 : mid | |
call search('^\\\@!\S.*\(\s*\n\)*\s*\S', 'b') | |
let tabindent = search('^\t\s*\S', 'cn') | |
let &l:et = !tabindent | |
" Shortest run of spaces for indentation. Ignore <2 and >8. | |
let shortpat = '^ \{2,8}\ze\\\@!\S' | |
let short = len(matchstr(getline(search(shortpat, 'cn')), shortpat)) | |
" Longest run of spaces before a tab. | |
let longpat = '^ \+\ze\S.*\n\%(\s*\n\)*\t' | |
let long = len(matchstr(getline(search(longpat, 'cn')), longpat)) | |
" If we've a short run of spaces, that must be the 'sw'. | |
" If there are tabs but no spaces, set 'sw' to zero. | |
" Otherwise give up and use the existing value of 'sw'. | |
let &l:sw = short ? short : (tabindent ? 0 : &sw) | |
" Let 'sts' track 'sw'. Don't overcomplicate matters. | |
let &l:sts = -1 | |
" If there are spaces as well as tabs for indentation, | |
" 'ts' is probably the shortest run plus the longest, since | |
" 'sw' < 'ts' was probably used with 'noet' when creating the | |
" file (e.g. `set ts=8 sw=2 noet`). | |
let ts = short + long | |
" Sanity check for this fool's errand. | |
" 'ts' has to be a multiple of four and > 'sw'. Otherwise default to 8. | |
let &l:ts = ts%4 || ts<=&l:sw ? 8 : ts | |
call winrestview(view) | |
endfun | |
augroup guessindent | |
au! | |
au stdinreadpost,filterreadpost,filereadpost,bufreadpost,bufwritepost | |
\ * call s:guessindent() | |
augroup END | |
com! Guessindent call s:guessindent() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment