mirror of
https://github.com/ohmyzsh/ohmyzsh.git
synced 2026-01-23 02:35:38 +01:00
added yafia
This commit is contained in:
parent
3484243c18
commit
1252ecdbec
1 changed files with 472 additions and 0 deletions
472
vim_plugins/yaifa.vim
Normal file
472
vim_plugins/yaifa.vim
Normal file
|
|
@ -0,0 +1,472 @@
|
|||
" YAIFA: Yet Another Indent Finder, Almost...
|
||||
" Version: 1.3
|
||||
" Modified: 2010-08-17
|
||||
" Author: Israel Chauca F. <israelchauca@gmail.com>
|
||||
"
|
||||
" This plug-in will try to detect the kind of indentation in your file and set
|
||||
" Vim's options to keep it that way. It recognizes three types of indentation:
|
||||
"
|
||||
" 1.- Space: Only spaces are used to indent.
|
||||
"
|
||||
" 2.- Tab: Only tabs are used.
|
||||
"
|
||||
" 3.- Mixed: A combination of tabs and space is used. e.g.: a tab stands for 8
|
||||
" spaces, but each indentation level is 4 spaces.
|
||||
"
|
||||
" Use :YAIFAMagic to manually set the indenting settings for the current file.
|
||||
"
|
||||
" Depending on the system set-up and the file size scanning too many lines can
|
||||
" be painfully slow, so YAIFA processes 2048 lines by default, that value can
|
||||
" be changed with the following line in your .vimrc:
|
||||
"
|
||||
" let yaifa_max_lines = 4096
|
||||
"
|
||||
" This script is a port to VimL from Philippe Fremy's Python script Indent
|
||||
" Finder, hence the "Almost" part of the name.
|
||||
|
||||
if exists('g:loaded_yaifa')
|
||||
finish
|
||||
endif
|
||||
|
||||
let g:loaded_yaifa = 1
|
||||
|
||||
" Depending on your system and file size, scanning too many lines can be
|
||||
" painfully slow.
|
||||
if exists('g:yaifa_max_lines')
|
||||
let s:max_lines = g:yaifa_max_lines
|
||||
else
|
||||
let s:max_lines = 1024*2
|
||||
endif
|
||||
|
||||
redir => redir | silent verbose set sw? | redir END
|
||||
let s:swset = len(split(redir,"\n")) > 1
|
||||
|
||||
if &expandtab
|
||||
let s:default_indent = 'space'
|
||||
let s:default_tab_width = s:swset ? &sw : 2
|
||||
else
|
||||
let s:default_indent = 'tab'
|
||||
let s:default_tab_width = s:swset ? &sw : 4
|
||||
endif
|
||||
|
||||
|
||||
let s:verbose_quiet = 0
|
||||
let s:verbose_info = 1
|
||||
let s:verbose_debug = 2
|
||||
let s:verbose_deep = 3
|
||||
if exists('g:yaifa_verbosity')
|
||||
let s:verbosity = g:yaifa_verbosity
|
||||
else
|
||||
let s:default_verbosity = s:verbose_quiet
|
||||
let s:verbosity = s:default_verbosity
|
||||
endif
|
||||
|
||||
let s:default_result = [s:default_indent, s:default_tab_width]
|
||||
let s:nb_processed_lines = 0
|
||||
|
||||
let s:NoIndent = "NoIndent"
|
||||
let s:SpaceOnly = "SpaceOnly"
|
||||
let s:TabOnly = "TabOnly"
|
||||
let s:Mixed = "Mixed"
|
||||
let s:BeginSpace = "BeginSpace"
|
||||
let s:indent_re = '\m^\(\s\+\)\(\S.\+\)$'
|
||||
let s:mixed_re = '\m^\(\t\)\+\( \+\)$'
|
||||
|
||||
function! s:log(level, s)
|
||||
if a:level <= s:verbosity
|
||||
echomsg s:nb_processed_lines . ':' . a:s
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:info(s)
|
||||
call s:log(s:verbose_info, 'info:' . a:s)
|
||||
endfunction
|
||||
|
||||
function! s:dbg(s)
|
||||
call s:log(s:verbose_debug, 'dbg:' . a:s)
|
||||
endfunction
|
||||
|
||||
function! s:deepdbg(s)
|
||||
call s:log(s:verbose_deep, 'deep:' . a:s)
|
||||
endfunction
|
||||
|
||||
function! s:clear()
|
||||
let s:lines = {}
|
||||
for i in range(2,9)
|
||||
let s:lines[i] = 0
|
||||
let s:lines[-1 * i ] = 0
|
||||
endfor
|
||||
let s:lines.tab = 0
|
||||
|
||||
let s:nb_processed_lines = 0
|
||||
let s:nb_indent_hint = 0
|
||||
let s:skip_next_line = 0
|
||||
let s:previous_line_info = []
|
||||
endfunction
|
||||
|
||||
function! s:parse_file()
|
||||
"let nb_lines = line('$') < s:max_lines ? line('$') : s:max_lines
|
||||
let nb_lines = line('$')
|
||||
let i = 1
|
||||
"while i <= nb_lines
|
||||
while i <= nb_lines && s:nb_processed_lines < s:max_lines
|
||||
call s:analyse_line(getline(i))
|
||||
let i += 1
|
||||
endw
|
||||
endf
|
||||
|
||||
function! s:analyse_line(line)
|
||||
let line = substitute(a:line, '\m\n', '', '')
|
||||
call s:deepdbg('analyse_line: ' . substitute(substitute(line, '\m\t', '\\t', 'g'), '\m ', '·','g'))
|
||||
let s:nb_processed_lines += 1
|
||||
let skip_current_line = s:skip_next_line
|
||||
let s:skip_next_line = 0
|
||||
if line =~ '\m\\$'
|
||||
call s:deepdbg('analyse_line: Ignoring next line!')
|
||||
let s:skip_next_line = 1
|
||||
endif
|
||||
|
||||
if skip_current_line
|
||||
call s:deepdbg('analyse_line: Ignoring next line!')
|
||||
return
|
||||
endif
|
||||
let ret = s:analyse_line_indentation(line)
|
||||
if ret
|
||||
let s:nb_indent_hint += 1
|
||||
call s:deepdbg('analyse_line: Result of line analysis: ' . ret)
|
||||
endif
|
||||
return ret
|
||||
endfunction
|
||||
|
||||
function! s:analyse_line_type(line)
|
||||
let mixed_mode = 0
|
||||
let tab_part = ""
|
||||
let space_part = ""
|
||||
|
||||
if a:line !~ '\m^$' && a:line !~ '\m^\s'
|
||||
cal s:deepdbg('analyse_line_type: line is not empty and not indented: ')
|
||||
return [s:NoIndent, '']
|
||||
endif
|
||||
|
||||
if a:line !~ s:indent_re
|
||||
cal s:deepdbg('analyse_line_type: line is not indented')
|
||||
return []
|
||||
else
|
||||
let indent_part = substitute(a:line, s:indent_re, '\1', '')
|
||||
let text_part = substitute(a:line, s:indent_re, '\2', '')
|
||||
endif
|
||||
call s:deepdbg('analyse_line_type: indent_part="' . substitute(substitute(substitute(indent_part, '\m\n', '\\n', 'g'), '\m\t', '\\t', 'g'), ' ', '·', 'g') . '"')
|
||||
|
||||
if text_part =~ '\m^\*'
|
||||
" continuation of a C/C++ comment, unlikely to be indented correctly
|
||||
return []
|
||||
endif
|
||||
|
||||
if a:line =~ '\m^(/\*\|#)'
|
||||
" python, C/C++ comment, might not be indented correctly
|
||||
return []
|
||||
endif
|
||||
|
||||
if indent_part =~ '\m\t' && indent_part =~ '\m '
|
||||
"Mixed mode
|
||||
"let mo = indent_part =~ s:mixed_re
|
||||
if indent_part !~ s:mixed_re
|
||||
" Line is not composed of "\t\t\t "
|
||||
return []
|
||||
endif
|
||||
let mixed_mode = 1
|
||||
let tab_part = substitute(indent_part, s:mixed_re, '\1','')
|
||||
let space_part = substitute(indent_part, s:mixed_re, '\2','')
|
||||
endif
|
||||
|
||||
if mixed_mode
|
||||
if len(space_part) >= 8
|
||||
"this is not mixed mode, this is garbage !
|
||||
return []
|
||||
endif
|
||||
return [s:Mixed, tab_part, space_part]
|
||||
endif"
|
||||
|
||||
if indent_part =~ '\m\t'
|
||||
return [s:TabOnly, indent_part]
|
||||
endif
|
||||
|
||||
if indent_part =~ '\m '
|
||||
if len(indent_part) < 8
|
||||
" this could be mixed mode too
|
||||
return [s:BeginSpace, indent_part]
|
||||
else
|
||||
" this is really a line indented with spaces
|
||||
return [s:SpaceOnly, indent_part]
|
||||
endif
|
||||
endif
|
||||
echoerr 'We should never get here!'
|
||||
endfunction
|
||||
|
||||
function! s:analyse_line_indentation(line)
|
||||
let previous_line_info = s:previous_line_info
|
||||
let current_line_info = s:analyse_line_type(a:line)
|
||||
let s:previous_line_info = current_line_info
|
||||
|
||||
if len(current_line_info) == 0 || len(previous_line_info) == 0
|
||||
"call s:deepdbg('analyse_line_indentation: Not enough info to analyse line : ' . string(previous_line_info) . ':' . string(current_line_info))
|
||||
return 0
|
||||
endif
|
||||
|
||||
let t = [previous_line_info[0], current_line_info[0]]
|
||||
call s:deepdbg('analyse_line_indentation: Indent analysis: ' . string(t))
|
||||
|
||||
if t == [s:TabOnly, s:TabOnly]
|
||||
\ || t == [s:NoIndent, s:TabOnly]
|
||||
if len(current_line_info[1]) - len(previous_line_info[1]) == 1
|
||||
let s:lines['tab'] += 1
|
||||
return 'tab'
|
||||
endif
|
||||
elseif t == [s:SpaceOnly, s:SpaceOnly]
|
||||
\ || t == [s:BeginSpace, s:SpaceOnly]
|
||||
\ || t == [s:NoIndent, s:SpaceOnly]
|
||||
let nb_space = len(current_line_info[1]) - len(previous_line_info[1])
|
||||
if 1 < nb_space && nb_space <= 8
|
||||
"execute 'let key = "space' . nb_space . '"'
|
||||
let key = nb_space
|
||||
let s:lines[key] += 1
|
||||
return key
|
||||
endif
|
||||
elseif t == [s:BeginSpace, s:BeginSpace]
|
||||
\ || t == [s:NoIndent, s:BeginSpace]
|
||||
let nb_space = len(current_line_info[1]) - len(previous_line_info[1])
|
||||
if 1 < nb_space && nb_space <= 8
|
||||
"execute 'let key1 = "space' . nb_space . '"'
|
||||
"execute 'let key2 = "mixed' . nb_space . '"'
|
||||
let key1 = nb_space
|
||||
let key2 = -1 * nb_space
|
||||
let s:lines[key1] += 1
|
||||
let s:lines[key2] += 1
|
||||
return key1
|
||||
endif
|
||||
elseif t == [s:BeginSpace, s:TabOnly]
|
||||
" We assume that mixed indentation used 8 chars tabs
|
||||
if len(current_line_info[1]) == 1
|
||||
let nb_space = len(current_line_info[1]) - len(previous_line_info[1])
|
||||
if 1 < nb_space && nb_space <= 8
|
||||
"execute 'let key = "mixed' . nb_space . '"'
|
||||
let key = -1 * nb_space
|
||||
let s:lines[key] += 1
|
||||
return key
|
||||
endif
|
||||
endif
|
||||
elseif t == [s:TabOnly, s:Mixed]
|
||||
let tab_part = current_line_info[1]
|
||||
let space_part = current_line_info[2]
|
||||
if len(previous_line_info[1]) == len(tab_part)
|
||||
let nb_space = len(space_part)
|
||||
if 1 < nb_space && nb_space <= 8
|
||||
"execute 'let key = "mixed' . nb_space . '"'
|
||||
let key = -1 * nb_space
|
||||
let s:lines[key] += 1
|
||||
return key
|
||||
endif
|
||||
endif
|
||||
elseif t == [s:Mixed, s:TabOnly]
|
||||
let tab_part = previous_line_info[1]
|
||||
let space_part = previous_line_info[2]
|
||||
if len(tab_part) + 1 == len(current_line_info[1])
|
||||
let nb_space = 8 - len(space_part)
|
||||
if 1 < nb_space && nb_space <= 8
|
||||
"execute 'let key = "mixed' . nb_space . '"'
|
||||
let key = -1 * nb_space
|
||||
let s:lines[key] += 1
|
||||
return key
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
return 0
|
||||
endfunction
|
||||
|
||||
function! s:results()
|
||||
call s:dbg( "Nb of scanned lines : " . s:nb_processed_lines)
|
||||
call s:dbg( "Nb of indent hint : " . s:nb_indent_hint)
|
||||
"call s:dbg( "Collected data:")
|
||||
for key in keys(s:lines)
|
||||
if s:lines[key] > 0
|
||||
call s:dbg( ' Key ' . key . ' => ' . s:lines[key])
|
||||
endif
|
||||
endfor
|
||||
let spaces = []
|
||||
let mixed = []
|
||||
for i in range(2,9)
|
||||
"execute 'let spaces = add(spaces, s:lines.space' . i . ')'
|
||||
let spaces = add(spaces, s:lines[i])
|
||||
"execute 'let mixed = add(mixed, s:lines.mixed' . i . ')'
|
||||
let mixed = add(mixed, s:lines[-1 * i])
|
||||
endfor
|
||||
let max_line_space = max(spaces)
|
||||
let max_line_mixed = max(mixed)
|
||||
let max_line_tab = s:lines.tab
|
||||
|
||||
call s:dbg( 'max_line_space: ' . max_line_space )
|
||||
call s:dbg( 'max_line_mixed: ' . max_line_mixed )
|
||||
call s:dbg( 'max_line_tab: ' . max_line_tab )
|
||||
|
||||
|
||||
""" Result analysis
|
||||
"
|
||||
" 1. Space indented file
|
||||
" - lines indented with less than 8 space will fill mixed and space array
|
||||
" - lines indented with 8 space or more will fill only the space array
|
||||
" - almost no lines indented with tab
|
||||
"
|
||||
" => more lines with space than lines with mixed
|
||||
" => more a lot more lines with space than tab
|
||||
"
|
||||
" 2. Tab indented file
|
||||
" - most lines will be tab only
|
||||
" - very few lines as mixed
|
||||
" - very few lines as space only
|
||||
"
|
||||
" => a lot more lines with tab than lines with mixed
|
||||
" => a lot more lines with tab than lines with space
|
||||
"
|
||||
" 3. Mixed tab/space indented file
|
||||
" - some lines are tab-only (lines with exactly 8 step indentation)
|
||||
" - some lines are space only (less than 8 space)
|
||||
" - all other lines are mixed
|
||||
"
|
||||
" If mixed is tab + 2 space indentation:
|
||||
" - a lot more lines with mixed than with tab
|
||||
" If mixed is tab + 4 space indentation
|
||||
" - as many lines with mixed than with tab
|
||||
"
|
||||
" If no lines exceed 8 space, there will be only lines with space
|
||||
" and tab but no lines with mixed. Impossible to detect mixed indentation
|
||||
" in this case, the file looks like it's actually indented as space only
|
||||
" and will be detected so.
|
||||
"
|
||||
" => same or more lines with mixed than lines with tab only
|
||||
" => same or more lines with mixed than lines with space only
|
||||
"
|
||||
|
||||
let result = []
|
||||
" Detect space indented file
|
||||
if max_line_space >= max_line_mixed && max_line_space > max_line_tab
|
||||
let nb = 0
|
||||
let indent_value = 0
|
||||
for i in range(8,2,-1)
|
||||
"execute 'let m = s:lines.space' . i . ' > floor(nb * 1.1)'
|
||||
"if s:lines[i] > floor(nb * 1.1)
|
||||
if s:lines[i] * 10 > nb * 11
|
||||
let indent_value = i
|
||||
"execute 'let nb = s:lines.space' . i
|
||||
let nb = s:lines[i]
|
||||
endif
|
||||
endfor
|
||||
|
||||
if indent_value == 0
|
||||
let result = s:default_result
|
||||
else
|
||||
let result = ['space', indent_value]
|
||||
endif
|
||||
|
||||
" Detect tab files
|
||||
elseif max_line_tab > max_line_mixed && max_line_tab > max_line_space
|
||||
let result = ['tab', s:default_tab_width]
|
||||
|
||||
" Detect mixed files
|
||||
elseif max_line_mixed >= max_line_tab && max_line_mixed > max_line_space
|
||||
let nb = 0
|
||||
let indent_value = 0
|
||||
for i in range(-8,-2)
|
||||
"execute 'let m = s:lines.mixed' . i . ' > floor(nb * 1.1)'
|
||||
"let m = s:lines[i] > floor(nb * 1.1)
|
||||
"if s:lines[i] > floor(nb * 1.1)
|
||||
if s:lines[i] * 10 > nb * 11
|
||||
let indent_value = -1 * i
|
||||
"execute 'let nb = s:lines.mixed' . i
|
||||
let nb = s:lines[i]
|
||||
endif
|
||||
endfor
|
||||
|
||||
if indent_value == 0
|
||||
let result = s:default_result
|
||||
else
|
||||
let result = ['mixed', [8, indent_value]]
|
||||
endif
|
||||
|
||||
" Not enough information to make a decision
|
||||
else
|
||||
let result = s:default_result
|
||||
endif
|
||||
call s:info('Result: ' . string(result))
|
||||
return result
|
||||
endfunction
|
||||
|
||||
function! YAIFA(...)
|
||||
|
||||
" The magic starts here
|
||||
call s:clear()
|
||||
call s:parse_file()
|
||||
|
||||
let result = s:results()
|
||||
|
||||
if result[0] == 'space'
|
||||
call s:info('space')
|
||||
"spaces:
|
||||
" => set sts to the number of spaces
|
||||
" => set tabstop to 8
|
||||
" => expand tabs to spaces
|
||||
" => set shiftwidth to the number of spaces
|
||||
let cmd = 'set sts=' . result[1] . ' | set tabstop=8 | set expandtab | set shiftwidth=' . result[1]
|
||||
elseif result[0] == 'tab'
|
||||
call s:info('tab')
|
||||
"tab:
|
||||
" => set sts to 0
|
||||
" => set tabstop to preferred value
|
||||
" => set expandtab to false
|
||||
" => set shiftwidth to tabstop
|
||||
let cmd = 'set sts=0 | set tabstop=' . s:default_tab_width . ' | set noexpandtab | set shiftwidth=' . s:default_tab_width
|
||||
elseif result[0] == 'mixed'
|
||||
call s:info('mixed')
|
||||
"tab:
|
||||
" => set sts to 0
|
||||
" => set tabstop to tab_indent
|
||||
" => set expandtab to false
|
||||
" => set shiftwidth to space_indent
|
||||
let s:ts = result[1][0]
|
||||
let s:sw = result[1][1]
|
||||
"echom "s:sw: " . s:sw
|
||||
"if s:sw == "" && (s:ts - (2*(s:ts/2))) == 0 " l mod 2
|
||||
if s:sw == "" && s:ts > 2
|
||||
let s:sw = s:ts/2
|
||||
elseif s:sw == ""
|
||||
let s:sw = s:ts
|
||||
endif
|
||||
|
||||
let cmd = 'set sts=' . s:sw . ' | set tabstop=' . s:ts . ' | set noexpandtab | set shiftwidth=' . s:sw
|
||||
endif
|
||||
execute cmd
|
||||
let b:yaifa_set = 1
|
||||
if a:0 > 0
|
||||
if a:1 == 2
|
||||
if result[0] == "space"
|
||||
return "space" . result[1]
|
||||
elseif result[0] == "tab"
|
||||
return "tab"
|
||||
else
|
||||
return "mixed" . s:sw
|
||||
endif
|
||||
endif
|
||||
else
|
||||
echom cmd
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! YAIFAGetVar(var)
|
||||
exec "return s:".a:var
|
||||
endfunction
|
||||
|
||||
augroup YAIFA
|
||||
au! YAIFA
|
||||
au BufRead * call YAIFA(1)
|
||||
augroup End
|
||||
|
||||
command -nargs=0 -bar YAIFAMagic call YAIFA()
|
||||
Loading…
Add table
Add a link
Reference in a new issue