summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHugues Hiegel <hugues.hiegel@anevia.com>2016-02-16 11:17:36 +0100
committerHugues Hiegel <hugues.hiegel@anevia.com>2016-03-09 12:39:19 +0100
commit4be4ad2c865cb6208d1b2b5eb955540e707145e2 (patch)
tree948295fb0eb5d9aa38d6039ed5f4606f2eddbf9a
parentd8319632b37b1c5161a7a881a1d2e07ff23f77ae (diff)
[tabs] try to detect indentation at each buffer... (well.. it tries..)
-rw-r--r--doc/detectindent.txt60
-rw-r--r--plugin/detectindent.vim211
-rw-r--r--vimrc11
3 files changed, 281 insertions, 1 deletions
diff --git a/doc/detectindent.txt b/doc/detectindent.txt
new file mode 100644
index 0000000..524b8b6
--- /dev/null
+++ b/doc/detectindent.txt
@@ -0,0 +1,60 @@
+*detectindent.txt* The Detect Indent Plugin 1.0, Jan 04, 2005
+
+Author: Ciaran McCreesh <ciaran.mccreesh at googlemail.com>
+
+==============================================================================
+1. Contents *detectindent* *detectindent-contents*
+
+ 1. Contents |detectindent-contents|
+ 2. :DetectIndent Command |:DetectIndent|
+ Settings |detectindent-settings|
+ 3. Uptime ChangeLog |uptime-changelog|
+
+==============================================================================
+2. :DetectIndent Command *:DetectIndent*
+
+ The :DetectIndent command tries to intelligently set the 'shiftwidth',
+ 'expandtab' and 'tabstop' options based upon the existing settings in
+ use in the active file.
+
+ Settings *detectindent-settings*
+
+ When the correct value for 'expandtab' cannot be determined, it will
+ usually retain its existing value. To specify that 'expandtab' should
+ be used where autodetection is impossible, set: >
+ :let g:detectindent_preferred_expandtab = 1
+< in your |vimrc| file.
+
+ To set a preferred value for 'shiftwidth' and 'tabstop' when they
+ cannot be automatically detected, set: >
+ :let g:detectindent_preferred_indent = 4
+< in your |vimrc| file.
+
+ To use the preferred values when both tabs and spaces are detected,
+ set: >
+ :let g:detectindent_preferred_when_mixed = 1
+< in your |vimrc| file.
+
+ To set limit for number of lines that will be analysed set: >
+ :let g:detectindent_max_lines_to_analyse = 1024
+< in your |vimrc| file.
+
+ To override |detectindent_preferred_expandtab| for specific filetypes
+ (example: use 4-character tabstops with tabs for python) set: >
+ :let b:detectindent_preferred_expandtab = 0
+ :let b:detectindent_preferred_indent = 4
+< after/ftplugin/FILETYPENAMEHERE.vim (example:
+ after/ftplugin/python.vim). Using 0 acts as if the option was never
+ set.
+
+==============================================================================
+3. DetectIndent ChangeLog *detectindent-changelog*
+
+ v1.1 (20150225)
+ * Add preferred_when_mixed.
+ * Add buffer-local options.
+ v1.0 (20050105)
+ * initial release after discussion on irc.freenode.net:#vim
+
+==============================================================================
+vim:tw=78:ts=8:ft=help
diff --git a/plugin/detectindent.vim b/plugin/detectindent.vim
new file mode 100644
index 0000000..d903948
--- /dev/null
+++ b/plugin/detectindent.vim
@@ -0,0 +1,211 @@
+" Name: detectindent (global plugin)
+" Version: 1.0
+" Author: Ciaran McCreesh <ciaran.mccreesh at googlemail.com>
+" Updates: http://github.com/ciaranm/detectindent
+" Purpose: Detect file indent settings
+"
+" License: You may redistribute this plugin under the same terms as Vim
+" itself.
+"
+" Usage: :DetectIndent
+"
+" " to prefer expandtab to noexpandtab when detection is
+" " impossible:
+" :let g:detectindent_preferred_expandtab = 1
+"
+" " to set a preferred indent level when detection is
+" " impossible:
+" :let g:detectindent_preferred_indent = 4
+"
+" " To use preferred values instead of guessing:
+" :let g:detectindent_preferred_when_mixed = 1
+"
+" Requirements: Untested on Vim versions below 6.2
+
+if exists("loaded_detectindent")
+ finish
+endif
+let loaded_detectindent = 1
+
+if !exists('g:detectindent_verbosity')
+ let g:detectindent_verbosity = 1
+endif
+
+fun! <SID>HasCStyleComments()
+ return index(["c", "cpp", "java", "javascript", "php", "vala"], &ft) != -1
+endfun
+
+fun! <SID>IsCommentStart(line)
+ " &comments aren't reliable
+ return <SID>HasCStyleComments() && a:line =~ '/\*'
+endfun
+
+fun! <SID>IsCommentEnd(line)
+ return <SID>HasCStyleComments() && a:line =~ '\*/'
+endfun
+
+fun! <SID>IsCommentLine(line)
+ return <SID>HasCStyleComments() && a:line =~ '^\s\+//'
+endfun
+
+fun! s:GetValue(option)
+ if exists('b:'. a:option)
+ return get(b:, a:option)
+ else
+ return get(g:, a:option)
+ endif
+endfun
+
+fun! <SID>DetectIndent()
+ let l:has_leading_tabs = 0
+ let l:has_leading_spaces = 0
+ let l:shortest_leading_spaces_run = 0
+ let l:shortest_leading_spaces_idx = 0
+ let l:longest_leading_spaces_run = 0
+ let l:max_lines = 1024
+ if exists("g:detectindent_max_lines_to_analyse")
+ let l:max_lines = g:detectindent_max_lines_to_analyse
+ endif
+
+ let verbose_msg = ''
+ if ! exists("b:detectindent_cursettings")
+ " remember initial values for comparison
+ let b:detectindent_cursettings = {'expandtab': &et, 'shiftwidth': &sw, 'tabstop': &ts, 'softtabstop': &sts}
+ endif
+
+ let l:idx_end = line("$")
+ let l:idx = 1
+ while l:idx <= l:idx_end
+ let l:line = getline(l:idx)
+
+ " try to skip over comment blocks, they can give really screwy indent
+ " settings in c/c++ files especially
+ if <SID>IsCommentStart(l:line)
+ while l:idx <= l:idx_end && ! <SID>IsCommentEnd(l:line)
+ let l:idx = l:idx + 1
+ let l:line = getline(l:idx)
+ endwhile
+ let l:idx = l:idx + 1
+ continue
+ endif
+
+ " Skip comment lines since they are not dependable.
+ if <SID>IsCommentLine(l:line)
+ let l:idx = l:idx + 1
+ continue
+ endif
+
+ " Skip lines that are solely whitespace, since they're less likely to
+ " be properly constructed.
+ if l:line !~ '\S'
+ let l:idx = l:idx + 1
+ continue
+ endif
+
+ let l:leading_char = strpart(l:line, 0, 1)
+
+ if l:leading_char == "\t"
+ let l:has_leading_tabs = 1
+
+ elseif l:leading_char == " "
+ " only interested if we don't have a run of spaces followed by a
+ " tab.
+ if -1 == match(l:line, '^ \+\t')
+ let l:has_leading_spaces = 1
+ let l:spaces = strlen(matchstr(l:line, '^ \+'))
+ if l:shortest_leading_spaces_run == 0 ||
+ \ l:spaces < l:shortest_leading_spaces_run
+ let l:shortest_leading_spaces_run = l:spaces
+ let l:shortest_leading_spaces_idx = l:idx
+ endif
+ if l:spaces > l:longest_leading_spaces_run
+ let l:longest_leading_spaces_run = l:spaces
+ endif
+ endif
+
+ endif
+
+ let l:idx = l:idx + 1
+
+ let l:max_lines = l:max_lines - 1
+
+ if l:max_lines == 0
+ let l:idx = l:idx_end + 1
+ endif
+
+ endwhile
+
+ if l:has_leading_tabs && ! l:has_leading_spaces
+ " tabs only, no spaces
+ let l:verbose_msg = "Detected tabs only and no spaces"
+ setl noexpandtab
+ if s:GetValue("detectindent_preferred_indent")
+ let &l:shiftwidth = g:detectindent_preferred_indent
+ let &l:tabstop = g:detectindent_preferred_indent
+ endif
+
+ elseif l:has_leading_spaces && ! l:has_leading_tabs
+ " spaces only, no tabs
+ let l:verbose_msg = "Detected spaces only and no tabs"
+ setl expandtab
+ let &l:shiftwidth = l:shortest_leading_spaces_run
+ let &l:softtabstop = l:shortest_leading_spaces_run
+
+ elseif l:has_leading_spaces && l:has_leading_tabs && ! s:GetValue("detectindent_preferred_when_mixed")
+ " spaces and tabs
+ let l:verbose_msg = "Detected spaces and tabs"
+ setl noexpandtab
+ let &l:shiftwidth = l:shortest_leading_spaces_run
+
+ " mmmm, time to guess how big tabs are
+ if l:longest_leading_spaces_run <= 2
+ let &l:tabstop = 2
+ elseif l:longest_leading_spaces_run <= 4
+ let &l:tabstop = 4
+ else
+ let &l:tabstop = 8
+ endif
+
+ else
+ " no spaces, no tabs
+ let l:verbose_msg = s:GetValue("detectindent_preferred_when_mixed") ? "preferred_when_mixed is active" : "Detected no spaces and no tabs"
+ if s:GetValue("detectindent_preferred_indent") &&
+ \ (s:GetValue("detectindent_preferred_expandtab"))
+ setl expandtab
+ let &l:shiftwidth = g:detectindent_preferred_indent
+ let &l:softtabstop = g:detectindent_preferred_indent
+ elseif s:GetValue("detectindent_preferred_indent")
+ setl noexpandtab
+ let &l:shiftwidth = g:detectindent_preferred_indent
+ let &l:tabstop = g:detectindent_preferred_indent
+ elseif s:GetValue("detectindent_preferred_expandtab")
+ setl expandtab
+ else
+ setl noexpandtab
+ endif
+
+ endif
+
+ if &verbose >= g:detectindent_verbosity
+ echo l:verbose_msg
+ \ ."; has_leading_tabs:" l:has_leading_tabs
+ \ .", has_leading_spaces:" l:has_leading_spaces
+ \ .", shortest_leading_spaces_run:" l:shortest_leading_spaces_run
+ \ .", shortest_leading_spaces_idx:" l:shortest_leading_spaces_idx
+ \ .", longest_leading_spaces_run:" l:longest_leading_spaces_run
+
+ let changed_msg = []
+ for [setting, oldval] in items(b:detectindent_cursettings)
+ exec 'let newval = &'.setting
+ if oldval != newval
+ let changed_msg += [ setting." changed from ".oldval." to ".newval ]
+ end
+ endfor
+ if len(changed_msg)
+ echo "Initial buffer settings changed:" join(changed_msg, ", ")
+ endif
+ endif
+endfun
+
+command! -bar -nargs=0 DetectIndent call <SID>DetectIndent()
+
diff --git a/vimrc b/vimrc
index 1885ee1..500f6f8 100644
--- a/vimrc
+++ b/vimrc
@@ -1,4 +1,8 @@
+filetype plugin indent on
+" To ignore plugin indent changes, instead use:
+"filetype plugin on
+
color default
"syntax clear
@@ -265,7 +269,12 @@ set mousem=extend
set tabstop=4
set shiftwidth=4
-set noexpandtab
+set expandtab
+let g:detectindent_preferred_expandtab = 1
+let g:detectindent_preferred_indent = 4
+augroup DetectIndentation
+ autocmd BufRead * DetectIndent
+augroup END
" Draws underline (waits for char input)
noremap U yyp0<C-v>$r