2020-06-11 04:18:30 +08:00
|
|
|
" MIT License. Copyright (c) 2013-2020 Bailey Ling et al.
|
2013-08-21 23:14:12 +08:00
|
|
|
" vim: et ts=2 sts=2 sw=2
|
2013-08-07 08:17:33 +08:00
|
|
|
|
2013-08-07 09:48:00 +08:00
|
|
|
" http://got-ravings.blogspot.com/2008/10/vim-pr0n-statusline-whitespace-flags.html
|
2013-08-07 08:48:53 +08:00
|
|
|
|
2016-09-24 08:16:30 +08:00
|
|
|
scriptencoding utf-8
|
|
|
|
|
2016-01-28 22:54:14 +08:00
|
|
|
let s:show_message = get(g:, 'airline#extensions#whitespace#show_message', 1)
|
2013-08-27 22:12:03 +08:00
|
|
|
let s:symbol = get(g:, 'airline#extensions#whitespace#symbol', g:airline_symbols.whitespace)
|
2019-04-26 20:38:13 +08:00
|
|
|
let s:default_checks = ['indent', 'trailing', 'mixed-indent-file', 'conflicts']
|
2013-08-20 02:19:26 +08:00
|
|
|
|
2014-04-20 06:39:43 +08:00
|
|
|
let s:enabled = get(g:, 'airline#extensions#whitespace#enabled', 1)
|
2018-04-27 14:25:49 +08:00
|
|
|
let s:skip_check_ft = {'make': ['indent', 'mixed-indent-file']}
|
2016-03-17 07:10:55 +08:00
|
|
|
|
2014-04-20 02:27:14 +08:00
|
|
|
function! s:check_mixed_indent()
|
2017-07-01 03:37:37 +08:00
|
|
|
let indent_algo = get(g:, 'airline#extensions#whitespace#mixed_indent_algo', 0)
|
|
|
|
if indent_algo == 1
|
2014-04-20 02:27:14 +08:00
|
|
|
" [<tab>]<space><tab>
|
|
|
|
" spaces before or between tabs are not allowed
|
|
|
|
let t_s_t = '(^\t* +\t\s*\S)'
|
|
|
|
" <tab>(<space> x count)
|
2015-04-29 01:25:26 +08:00
|
|
|
" count of spaces at the end of tabs should be less than tabstop value
|
2014-04-20 02:27:14 +08:00
|
|
|
let t_l_s = '(^\t+ {' . &ts . ',}' . '\S)'
|
|
|
|
return search('\v' . t_s_t . '|' . t_l_s, 'nw')
|
2017-07-01 03:37:37 +08:00
|
|
|
elseif indent_algo == 2
|
2015-04-15 01:01:08 +08:00
|
|
|
return search('\v(^\t* +\t\s*\S)', 'nw')
|
2014-04-20 22:52:06 +08:00
|
|
|
else
|
|
|
|
return search('\v(^\t+ +)|(^ +\t+)', 'nw')
|
2014-04-20 02:27:14 +08:00
|
|
|
endif
|
|
|
|
endfunction
|
|
|
|
|
2016-02-07 00:44:59 +08:00
|
|
|
function! s:check_mixed_indent_file()
|
2017-07-01 03:37:37 +08:00
|
|
|
let c_like_langs = get(g:, 'airline#extensions#c_like_langs',
|
2018-06-18 04:50:36 +08:00
|
|
|
\ [ 'arduino', 'c', 'cpp', 'cuda', 'go', 'javascript', 'ld', 'php' ])
|
2017-07-01 03:37:37 +08:00
|
|
|
if index(c_like_langs, &ft) > -1
|
2016-03-17 07:10:55 +08:00
|
|
|
" for C-like languages: allow /** */ comment style with one space before the '*'
|
2016-02-26 21:29:51 +08:00
|
|
|
let head_spc = '\v(^ +\*@!)'
|
|
|
|
else
|
|
|
|
let head_spc = '\v(^ +)'
|
|
|
|
endif
|
2016-02-07 00:44:59 +08:00
|
|
|
let indent_tabs = search('\v(^\t+)', 'nw')
|
2016-02-26 21:29:51 +08:00
|
|
|
let indent_spc = search(head_spc, 'nw')
|
2016-02-07 00:44:59 +08:00
|
|
|
if indent_tabs > 0 && indent_spc > 0
|
|
|
|
return printf("%d:%d", indent_tabs, indent_spc)
|
|
|
|
else
|
|
|
|
return ''
|
|
|
|
endif
|
|
|
|
endfunction
|
|
|
|
|
2019-04-26 20:38:13 +08:00
|
|
|
function! s:conflict_marker()
|
|
|
|
" Checks for git conflict markers
|
|
|
|
let annotation = '\%([0-9A-Za-z_.:]\+\)\?'
|
2019-12-10 23:14:08 +08:00
|
|
|
if &ft is# 'rst'
|
|
|
|
" rst filetypes use '=======' as header
|
|
|
|
let pattern = '^\%(\%(<\{7} '.annotation. '\)\|\%(>\{7\} '.annotation.'\)\)$'
|
|
|
|
else
|
|
|
|
let pattern = '^\%(\%(<\{7} '.annotation. '\)\|\%(=\{7\}\)\|\%(>\{7\} '.annotation.'\)\)$'
|
|
|
|
endif
|
2019-04-27 04:08:26 +08:00
|
|
|
return search(pattern, 'nw')
|
2019-04-26 20:38:13 +08:00
|
|
|
endfunction
|
|
|
|
|
2013-08-07 09:48:00 +08:00
|
|
|
function! airline#extensions#whitespace#check()
|
2017-07-01 03:37:37 +08:00
|
|
|
let max_lines = get(g:, 'airline#extensions#whitespace#max_lines', 20000)
|
|
|
|
if &readonly || !&modifiable || !s:enabled || line('$') > max_lines
|
2016-05-15 03:56:48 +08:00
|
|
|
\ || get(b:, 'airline_whitespace_disabled', 0)
|
2013-08-07 10:29:03 +08:00
|
|
|
return ''
|
|
|
|
endif
|
2018-04-27 14:25:49 +08:00
|
|
|
let skip_check_ft = extend(s:skip_check_ft,
|
|
|
|
\ get(g:, 'airline#extensions#whitespace#skip_indent_check_ft', {}), 'force')
|
2013-08-07 10:29:03 +08:00
|
|
|
|
2013-08-07 09:48:00 +08:00
|
|
|
if !exists('b:airline_whitespace_check')
|
|
|
|
let b:airline_whitespace_check = ''
|
2016-09-22 20:27:07 +08:00
|
|
|
let checks = get(b:, 'airline_whitespace_checks', get(g:, 'airline#extensions#whitespace#checks', s:default_checks))
|
2013-08-20 02:19:26 +08:00
|
|
|
|
|
|
|
let trailing = 0
|
2018-04-28 13:34:59 +08:00
|
|
|
let check = 'trailing'
|
|
|
|
if index(checks, check) > -1 && index(get(skip_check_ft, &ft, []), check) < 0
|
2016-01-27 21:18:28 +08:00
|
|
|
try
|
|
|
|
let regexp = get(g:, 'airline#extensions#whitespace#trailing_regexp', '\s$')
|
|
|
|
let trailing = search(regexp, 'nw')
|
|
|
|
catch
|
2018-11-14 04:28:47 +08:00
|
|
|
call airline#util#warning(printf('Whitespace: error occurred evaluating "%s"', regexp))
|
2016-01-27 21:18:28 +08:00
|
|
|
echomsg v:exception
|
|
|
|
return ''
|
|
|
|
endtry
|
2013-08-20 02:19:26 +08:00
|
|
|
endif
|
|
|
|
|
|
|
|
let mixed = 0
|
2016-02-10 03:16:12 +08:00
|
|
|
let check = 'indent'
|
2018-04-27 14:25:49 +08:00
|
|
|
if index(checks, check) > -1 && index(get(skip_check_ft, &ft, []), check) < 0
|
2014-04-20 02:27:14 +08:00
|
|
|
let mixed = s:check_mixed_indent()
|
2013-08-20 02:19:26 +08:00
|
|
|
endif
|
2013-08-07 08:48:53 +08:00
|
|
|
|
2016-02-07 00:44:59 +08:00
|
|
|
let mixed_file = ''
|
2016-02-10 03:16:12 +08:00
|
|
|
let check = 'mixed-indent-file'
|
2018-04-27 14:25:49 +08:00
|
|
|
if index(checks, check) > -1 && index(get(skip_check_ft, &ft, []), check) < 0
|
2016-02-07 00:44:59 +08:00
|
|
|
let mixed_file = s:check_mixed_indent_file()
|
|
|
|
endif
|
|
|
|
|
2015-09-23 23:45:46 +08:00
|
|
|
let long = 0
|
|
|
|
if index(checks, 'long') > -1 && &tw > 0
|
|
|
|
let long = search('\%>'.&tw.'v.\+', 'nw')
|
|
|
|
endif
|
|
|
|
|
2019-04-26 20:38:13 +08:00
|
|
|
let conflicts = 0
|
|
|
|
if index(checks, 'conflicts') > -1
|
|
|
|
let conflicts = s:conflict_marker()
|
|
|
|
endif
|
|
|
|
|
|
|
|
if trailing != 0 || mixed != 0 || long != 0 || !empty(mixed_file) || conflicts != 0
|
2013-09-12 05:01:25 +08:00
|
|
|
let b:airline_whitespace_check = s:symbol
|
2016-10-02 16:22:50 +08:00
|
|
|
if strlen(s:symbol) > 0
|
|
|
|
let space = (g:airline_symbols.space)
|
|
|
|
else
|
|
|
|
let space = ''
|
|
|
|
endif
|
|
|
|
|
2013-08-20 08:35:48 +08:00
|
|
|
if s:show_message
|
2013-08-07 10:02:53 +08:00
|
|
|
if trailing != 0
|
2017-07-01 03:37:37 +08:00
|
|
|
let trailing_fmt = get(g:, 'airline#extensions#whitespace#trailing_format', '[%s]trailing')
|
2017-07-01 06:45:21 +08:00
|
|
|
let b:airline_whitespace_check .= space.printf(trailing_fmt, trailing)
|
2013-08-07 09:48:00 +08:00
|
|
|
endif
|
2014-03-10 09:56:36 +08:00
|
|
|
if mixed != 0
|
2017-07-01 03:37:37 +08:00
|
|
|
let mixed_indent_fmt = get(g:, 'airline#extensions#whitespace#mixed_indent_format', '[%s]mixed-indent')
|
|
|
|
let b:airline_whitespace_check .= space.printf(mixed_indent_fmt, mixed)
|
2013-08-07 09:48:00 +08:00
|
|
|
endif
|
2015-09-23 23:45:46 +08:00
|
|
|
if long != 0
|
2017-07-01 03:37:37 +08:00
|
|
|
let long_fmt = get(g:, 'airline#extensions#whitespace#long_format', '[%s]long')
|
|
|
|
let b:airline_whitespace_check .= space.printf(long_fmt, long)
|
2015-09-23 23:45:46 +08:00
|
|
|
endif
|
2016-02-07 00:44:59 +08:00
|
|
|
if !empty(mixed_file)
|
2017-07-01 03:37:37 +08:00
|
|
|
let mixed_indent_file_fmt = get(g:, 'airline#extensions#whitespace#mixed_indent_file_format', '[%s]mix-indent-file')
|
|
|
|
let b:airline_whitespace_check .= space.printf(mixed_indent_file_fmt, mixed_file)
|
2016-02-07 00:44:59 +08:00
|
|
|
endif
|
2019-04-27 04:08:26 +08:00
|
|
|
if conflicts != 0
|
2019-04-26 20:38:13 +08:00
|
|
|
let conflicts_fmt = get(g:, 'airline#extensions#whitespace#conflicts_format', '[%s]conflicts')
|
|
|
|
let b:airline_whitespace_check .= space.printf(conflicts_fmt, conflicts)
|
|
|
|
endif
|
2013-08-07 08:48:53 +08:00
|
|
|
endif
|
|
|
|
endif
|
|
|
|
endif
|
2016-07-02 15:49:05 +08:00
|
|
|
return airline#util#shorten(b:airline_whitespace_check, 120, 9)
|
2015-01-04 08:38:17 +08:00
|
|
|
endfunction
|
2013-08-07 08:48:53 +08:00
|
|
|
|
2013-08-08 22:42:27 +08:00
|
|
|
function! airline#extensions#whitespace#toggle()
|
2013-08-20 08:35:48 +08:00
|
|
|
if s:enabled
|
2014-04-20 02:16:36 +08:00
|
|
|
augroup airline_whitespace
|
|
|
|
autocmd!
|
|
|
|
augroup END
|
2013-08-31 08:57:34 +08:00
|
|
|
augroup! airline_whitespace
|
2013-08-20 08:35:48 +08:00
|
|
|
let s:enabled = 0
|
2013-08-10 21:09:52 +08:00
|
|
|
else
|
|
|
|
call airline#extensions#whitespace#init()
|
2013-08-20 08:35:48 +08:00
|
|
|
let s:enabled = 1
|
2013-08-08 22:42:27 +08:00
|
|
|
endif
|
2014-04-20 22:52:06 +08:00
|
|
|
|
2014-04-20 06:39:43 +08:00
|
|
|
if exists("g:airline#extensions#whitespace#enabled")
|
|
|
|
let g:airline#extensions#whitespace#enabled = s:enabled
|
2014-04-20 22:52:06 +08:00
|
|
|
if s:enabled && match(g:airline_section_warning, '#whitespace#check') < 0
|
|
|
|
let g:airline_section_warning .= airline#section#create(['whitespace'])
|
2014-04-20 06:39:43 +08:00
|
|
|
call airline#update_statusline()
|
|
|
|
endif
|
|
|
|
endif
|
2018-11-14 04:28:47 +08:00
|
|
|
call airline#util#warning(printf('Whitespace checking: %s',(s:enabled ? 'Enabled' : 'Disabled')))
|
2013-08-08 22:42:27 +08:00
|
|
|
endfunction
|
|
|
|
|
2017-02-16 04:59:12 +08:00
|
|
|
function! airline#extensions#whitespace#disable()
|
|
|
|
if s:enabled
|
|
|
|
call airline#extensions#whitespace#toggle()
|
|
|
|
endif
|
|
|
|
endfunction
|
|
|
|
|
2013-08-24 00:42:55 +08:00
|
|
|
function! airline#extensions#whitespace#init(...)
|
2013-08-31 06:07:45 +08:00
|
|
|
call airline#parts#define_function('whitespace', 'airline#extensions#whitespace#check')
|
2013-08-07 09:48:00 +08:00
|
|
|
|
2013-08-20 08:35:48 +08:00
|
|
|
unlet! b:airline_whitespace_check
|
2013-08-07 09:48:00 +08:00
|
|
|
augroup airline_whitespace
|
|
|
|
autocmd!
|
Do not draw separators for empty sections
This is a little bit a hack, because by the time the separators are
added, it is not clear, if the following section is empty, therefore
we need to parse the content of the following section and eval the
expressions to find out, if this is empty
Remarks:
- catch all exceptions when eval'ing statusline
- make sure, that the seperators are highlighted
even when skipping empty regions (highlight group
names need to be adjusted)
- if a section is defined as empty, it will be removed completly from
the statusline. This means, it won't be called on the next update
and may not refresh properly (e.g. when the whitespace check
triggers, therefore, the whitesapce extension has to call an
explicit redraw whenever it is supposed to be refreshed)
2016-04-18 21:33:47 +08:00
|
|
|
autocmd CursorHold,BufWritePost * call <sid>ws_refresh()
|
2013-08-07 09:48:00 +08:00
|
|
|
augroup END
|
2013-08-07 08:17:33 +08:00
|
|
|
endfunction
|
Do not draw separators for empty sections
This is a little bit a hack, because by the time the separators are
added, it is not clear, if the following section is empty, therefore
we need to parse the content of the following section and eval the
expressions to find out, if this is empty
Remarks:
- catch all exceptions when eval'ing statusline
- make sure, that the seperators are highlighted
even when skipping empty regions (highlight group
names need to be adjusted)
- if a section is defined as empty, it will be removed completly from
the statusline. This means, it won't be called on the next update
and may not refresh properly (e.g. when the whitespace check
triggers, therefore, the whitesapce extension has to call an
explicit redraw whenever it is supposed to be refreshed)
2016-04-18 21:33:47 +08:00
|
|
|
|
|
|
|
function! s:ws_refresh()
|
2017-06-26 16:01:00 +08:00
|
|
|
if get(b:, 'airline_ws_changedtick', 0) == b:changedtick
|
|
|
|
return
|
|
|
|
endif
|
Do not draw separators for empty sections
This is a little bit a hack, because by the time the separators are
added, it is not clear, if the following section is empty, therefore
we need to parse the content of the following section and eval the
expressions to find out, if this is empty
Remarks:
- catch all exceptions when eval'ing statusline
- make sure, that the seperators are highlighted
even when skipping empty regions (highlight group
names need to be adjusted)
- if a section is defined as empty, it will be removed completly from
the statusline. This means, it won't be called on the next update
and may not refresh properly (e.g. when the whitespace check
triggers, therefore, the whitesapce extension has to call an
explicit redraw whenever it is supposed to be refreshed)
2016-04-18 21:33:47 +08:00
|
|
|
unlet! b:airline_whitespace_check
|
|
|
|
if get(g:, 'airline_skip_empty_sections', 0)
|
2019-04-26 16:16:40 +08:00
|
|
|
exe ':AirlineRefresh!'
|
Do not draw separators for empty sections
This is a little bit a hack, because by the time the separators are
added, it is not clear, if the following section is empty, therefore
we need to parse the content of the following section and eval the
expressions to find out, if this is empty
Remarks:
- catch all exceptions when eval'ing statusline
- make sure, that the seperators are highlighted
even when skipping empty regions (highlight group
names need to be adjusted)
- if a section is defined as empty, it will be removed completly from
the statusline. This means, it won't be called on the next update
and may not refresh properly (e.g. when the whitespace check
triggers, therefore, the whitesapce extension has to call an
explicit redraw whenever it is supposed to be refreshed)
2016-04-18 21:33:47 +08:00
|
|
|
endif
|
2017-06-26 16:01:00 +08:00
|
|
|
let b:airline_ws_changedtick = b:changedtick
|
Do not draw separators for empty sections
This is a little bit a hack, because by the time the separators are
added, it is not clear, if the following section is empty, therefore
we need to parse the content of the following section and eval the
expressions to find out, if this is empty
Remarks:
- catch all exceptions when eval'ing statusline
- make sure, that the seperators are highlighted
even when skipping empty regions (highlight group
names need to be adjusted)
- if a section is defined as empty, it will be removed completly from
the statusline. This means, it won't be called on the next update
and may not refresh properly (e.g. when the whitespace check
triggers, therefore, the whitesapce extension has to call an
explicit redraw whenever it is supposed to be refreshed)
2016-04-18 21:33:47 +08:00
|
|
|
endfunction
|