From eb51238c0e8b4aca8fe2c43f52703b450e461f32 Mon Sep 17 00:00:00 2001 From: ChangZhuo Chen Date: Thu, 11 Oct 2012 21:12:22 +0800 Subject: [PATCH 1/6] Count leading tab and space --- plugin/detectindent.vim | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/plugin/detectindent.vim b/plugin/detectindent.vim index 4801de1..04e95a4 100644 --- a/plugin/detectindent.vim +++ b/plugin/detectindent.vim @@ -46,8 +46,8 @@ fun! IsCommentLine(line) endfun fun! DetectIndent() - let l:has_leading_tabs = 0 - let l:has_leading_spaces = 0 + let l:leading_tab_count = 0 + let leading_space_count = 0 let l:shortest_leading_spaces_run = 0 let l:shortest_leading_spaces_idx = 0 let l:longest_leading_spaces_run = 0 @@ -94,13 +94,13 @@ fun! DetectIndent() let l:leading_char = strpart(l:line, 0, 1) if l:leading_char == "\t" - let l:has_leading_tabs = 1 + let l:leading_tab_count = l:leading_tab_count + 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 leading_space_count = leading_space_count + 1 let l:spaces = strlen(matchstr(l:line, '^ \+')) if l:shortest_leading_spaces_run == 0 || \ l:spaces < l:shortest_leading_spaces_run @@ -124,7 +124,7 @@ fun! DetectIndent() endwhile - if l:has_leading_tabs && ! l:has_leading_spaces + if l:leading_tab_count && ! leading_space_count " tabs only, no spaces let l:verbose_msg = "Detected tabs only and no spaces" setl noexpandtab @@ -133,14 +133,14 @@ fun! DetectIndent() let &l:tabstop = g:detectindent_preferred_indent endif - elseif l:has_leading_spaces && ! l:has_leading_tabs + elseif leading_space_count && ! l:leading_tab_count " 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 + elseif leading_space_count && l:leading_tab_count " spaces and tabs let l:verbose_msg = "Detected spaces and tabs" setl noexpandtab @@ -177,8 +177,8 @@ fun! DetectIndent() if &verbose >= g:detectindent_verbosity echo l:verbose_msg - \ ."; has_leading_tabs:" l:has_leading_tabs - \ .", has_leading_spaces:" l:has_leading_spaces + \ ."; leading_tab_count:" l:leading_tab_count + \ .", leading_space_count:" leading_space_count \ .", 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 From a0e20a6df142550d06fef02423e45008c850da6d Mon Sep 17 00:00:00 2001 From: ChangZhuo Chen Date: Thu, 11 Oct 2012 21:18:07 +0800 Subject: [PATCH 2/6] Use leading tab & space count to determine indent style --- plugin/detectindent.vim | 29 +++++------------------------ 1 file changed, 5 insertions(+), 24 deletions(-) diff --git a/plugin/detectindent.vim b/plugin/detectindent.vim index 04e95a4..c4cb4c2 100644 --- a/plugin/detectindent.vim +++ b/plugin/detectindent.vim @@ -124,40 +124,21 @@ fun! DetectIndent() endwhile - if l:leading_tab_count && ! leading_space_count - " tabs only, no spaces - let l:verbose_msg = "Detected tabs only and no spaces" + if l:leading_tab_count > leading_space_count + let l:verbose_msg = "Use tab to indent." setl noexpandtab if exists("g:detectindent_preferred_indent") let &l:shiftwidth = g:detectindent_preferred_indent let &l:tabstop = g:detectindent_preferred_indent endif - elseif leading_space_count && ! l:leading_tab_count - " spaces only, no tabs - let l:verbose_msg = "Detected spaces only and no tabs" + elseif leading_space_count > l:leading_tab_count + let l:verbose_msg = "Use space to indent." setl expandtab let &l:shiftwidth = l:shortest_leading_spaces_run let &l:softtabstop = l:shortest_leading_spaces_run - - elseif leading_space_count && l:leading_tab_count - " 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 = "Detected no spaces and no tabs" + let l:verbose_msg = "Cannot determine indent. Use default to indent." if exists("g:detectindent_preferred_indent") && \ exists("g:detectindent_preferred_expandtab") setl expandtab From c2ff5498e0fe4c62d14c39a2d3551be2444700d9 Mon Sep 17 00:00:00 2001 From: Aaron Lindsay Date: Tue, 4 Dec 2012 19:25:18 -0500 Subject: [PATCH 3/6] Add .h files to C-style comment detection --- plugin/detectindent.vim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin/detectindent.vim b/plugin/detectindent.vim index c4cb4c2..5bd4869 100644 --- a/plugin/detectindent.vim +++ b/plugin/detectindent.vim @@ -29,7 +29,7 @@ if !exists('g:detectindent_verbosity') endif fun! HasCStyleComments() - return index(["c", "cpp", "java", "javascript", "php"], &ft) != -1 + return index(["c", "cpp", "h", "java", "javascript", "php"], &ft) != -1 endfun fun! IsCommentStart(line) From fd89a725e5bd147c306fd01bd8bcba0498e3a3d4 Mon Sep 17 00:00:00 2001 From: Aaron Lindsay Date: Tue, 4 Dec 2012 19:32:39 -0500 Subject: [PATCH 4/6] Make leading_space_count a local variable --- plugin/detectindent.vim | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/plugin/detectindent.vim b/plugin/detectindent.vim index 5bd4869..ccc0eab 100644 --- a/plugin/detectindent.vim +++ b/plugin/detectindent.vim @@ -47,7 +47,7 @@ endfun fun! DetectIndent() let l:leading_tab_count = 0 - let leading_space_count = 0 + let l:leading_space_count = 0 let l:shortest_leading_spaces_run = 0 let l:shortest_leading_spaces_idx = 0 let l:longest_leading_spaces_run = 0 @@ -100,7 +100,7 @@ fun! DetectIndent() " only interested if we don't have a run of spaces followed by a " tab. if -1 == match(l:line, '^ \+\t') - let leading_space_count = leading_space_count + 1 + let l:leading_space_count = l:leading_space_count + 1 let l:spaces = strlen(matchstr(l:line, '^ \+')) if l:shortest_leading_spaces_run == 0 || \ l:spaces < l:shortest_leading_spaces_run @@ -124,7 +124,7 @@ fun! DetectIndent() endwhile - if l:leading_tab_count > leading_space_count + if l:leading_tab_count > l:leading_space_count let l:verbose_msg = "Use tab to indent." setl noexpandtab if exists("g:detectindent_preferred_indent") @@ -132,7 +132,7 @@ fun! DetectIndent() let &l:tabstop = g:detectindent_preferred_indent endif - elseif leading_space_count > l:leading_tab_count + elseif l:leading_space_count > l:leading_tab_count let l:verbose_msg = "Use space to indent." setl expandtab let &l:shiftwidth = l:shortest_leading_spaces_run @@ -159,7 +159,7 @@ fun! DetectIndent() if &verbose >= g:detectindent_verbosity echo l:verbose_msg \ ."; leading_tab_count:" l:leading_tab_count - \ .", leading_space_count:" leading_space_count + \ .", leading_space_count:" l:leading_space_count \ .", 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 From 8924eaa303ef4ea72a43811f081ed41510948fb6 Mon Sep 17 00:00:00 2001 From: Aaron Lindsay Date: Tue, 4 Dec 2012 20:35:45 -0500 Subject: [PATCH 5/6] Set shiftwidth based on the GCD of the most common tab spacings. The previous method of using the shortest existing tab spacing worked some of the time, but isn't as robust as the GCD method (i.e. if there was one or two lines that started with only one space, but the rest of the lines started with four spaces, the old method would set shiftwidth to 1). --- plugin/detectindent.vim | 52 +++++++++++++++++++++++++++-------------- 1 file changed, 34 insertions(+), 18 deletions(-) diff --git a/plugin/detectindent.vim b/plugin/detectindent.vim index ccc0eab..6a7e8ed 100644 --- a/plugin/detectindent.vim +++ b/plugin/detectindent.vim @@ -45,12 +45,22 @@ fun! IsCommentLine(line) return HasCStyleComments() && a:line =~ '^\s\+//' endfun +fun! GCD(x, y) + let l:a = a:x + let l:b = a:y + while l:b > 0 + let l:temp = l:b + let l:b = l:a % l:b + let l:a = l:temp + endwhile + return l:a +endfun + fun! DetectIndent() let l:leading_tab_count = 0 let l:leading_space_count = 0 - let l:shortest_leading_spaces_run = 0 - let l:shortest_leading_spaces_idx = 0 - let l:longest_leading_spaces_run = 0 + let l:leading_space_dict = {} + let l:leading_spaces_gcd = 0 let l:max_lines = 1024 if exists("g:detectindent_max_lines_to_analyse") let l:max_lines = g:detectindent_max_lines_to_analyse @@ -102,14 +112,7 @@ fun! DetectIndent() if -1 == match(l:line, '^ \+\t') let l:leading_space_count = l:leading_space_count + 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 + let l:leading_space_dict[l:spaces] = get(l:leading_space_dict, l:spaces) + 1 endif endif @@ -133,10 +136,25 @@ fun! DetectIndent() endif elseif l:leading_space_count > l:leading_tab_count - let l:verbose_msg = "Use space to indent." - setl expandtab - let &l:shiftwidth = l:shortest_leading_spaces_run - let &l:softtabstop = l:shortest_leading_spaces_run + " Filter out those tab stops which occurred in < 10% of the lines + call filter(l:leading_space_dict, '100*v:val/l:leading_space_count >= 10') + + " Find the greatest common divisor of the remaining tab stop lengths + let l:leading_spaces_gcd = 0 + for length in keys(l:leading_space_dict) + if l:leading_spaces_gcd == 0 + let l:leading_spaces_gcd = length + else + let l:leading_spaces_gcd = GCD(length, l:leading_spaces_gcd) + endif + endfor + + if l:leading_spaces_gcd != 0 + let l:verbose_msg = "Use space to indent." + setl expandtab + let &l:shiftwidth = l:leading_spaces_gcd + let &l:softtabstop = l:leading_spaces_gcd + endif else let l:verbose_msg = "Cannot determine indent. Use default to indent." if exists("g:detectindent_preferred_indent") && @@ -160,9 +178,7 @@ fun! DetectIndent() echo l:verbose_msg \ ."; leading_tab_count:" l:leading_tab_count \ .", leading_space_count:" l:leading_space_count - \ .", 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 + \ .", leading_spaces_gcd:" l:leading_spaces_gcd let changed_msg = [] for [setting, oldval] in items(b:detectindent_cursettings) From 736b001e9c23b407bda38fbad91cb4d6f05b4000 Mon Sep 17 00:00:00 2001 From: Aaron Lindsay Date: Fri, 15 Nov 2013 10:39:39 -0500 Subject: [PATCH 6/6] Bail out if we detect a version of vim < 7 --- plugin/detectindent.vim | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/plugin/detectindent.vim b/plugin/detectindent.vim index 6a7e8ed..b4024b5 100644 --- a/plugin/detectindent.vim +++ b/plugin/detectindent.vim @@ -17,7 +17,12 @@ " " impossible: " :let g:detectindent_preferred_indent = 4 " -" Requirements: Untested on Vim versions below 6.2 +" Requirements: Does not work on Vim versions below 7.0 + +" Bail out if we're on an old version of vim +if version < 700 + finish +endif if exists("loaded_detectindent") finish