1- " This script tests a color scheme for some errors. Load the scheme and source
2- " this script. e.g. :e colors/desert.vim | :so check_colors.vim
3- " Will output possible errors.
1+ " This script tests a color scheme for some errors and lists potential errors.
2+ " Load the scheme and source this script, like this:
3+ " :edit colors/desert.vim | :so colors/tools/check_colors.vim
44
55let s: save_cpo= &cpo
66set cpo &vim
77
88func ! Test_check_colors ()
9+ let l: savedview = winsaveview ()
910 call cursor (1 ,1 )
1011 let err= {}
1112
@@ -17,11 +18,69 @@ func! Test_check_colors()
1718 endif
1819
1920 " 2) Check for some well-defined highlighting groups
20- " Some items, check several groups, e.g. Diff, Spell
21- let hi_groups = [' ColorColumn' , ' Diff' , ' ErrorMsg' , ' Folded' ,
22- \ ' FoldColumn' , ' IncSearch' , ' LineNr' , ' ModeMsg' , ' MoreMsg' , ' NonText' ,
23- \ ' Normal' , ' Pmenu' , ' Todo' , ' Search' , ' Spell' , ' StatusLine' , ' TabLine' ,
24- \ ' Title' , ' Visual' , ' WarningMsg' , ' WildMenu' ]
21+ let hi_groups = [
22+ \ ' ColorColumn' ,
23+ \ ' Comment' ,
24+ \ ' Conceal' ,
25+ \ ' Constant' ,
26+ \ ' Cursor' ,
27+ \ ' CursorColumn' ,
28+ \ ' CursorLine' ,
29+ \ ' CursorLineNr' ,
30+ \ ' DiffAdd' ,
31+ \ ' DiffChange' ,
32+ \ ' DiffDelete' ,
33+ \ ' DiffText' ,
34+ \ ' Directory' ,
35+ \ ' EndOfBuffer' ,
36+ \ ' Error' ,
37+ \ ' ErrorMsg' ,
38+ \ ' FoldColumn' ,
39+ \ ' Folded' ,
40+ \ ' Identifier' ,
41+ \ ' Ignore' ,
42+ \ ' IncSearch' ,
43+ \ ' LineNr' ,
44+ \ ' MatchParen' ,
45+ \ ' ModeMsg' ,
46+ \ ' MoreMsg' ,
47+ \ ' NonText' ,
48+ \ ' Normal' ,
49+ \ ' Pmenu' ,
50+ \ ' PmenuSbar' ,
51+ \ ' PmenuSel' ,
52+ \ ' PmenuThumb' ,
53+ \ ' PreProc' ,
54+ \ ' Question' ,
55+ \ ' QuickFixLine' ,
56+ \ ' Search' ,
57+ \ ' SignColumn' ,
58+ \ ' Special' ,
59+ \ ' SpecialKey' ,
60+ \ ' SpellBad' ,
61+ \ ' SpellCap' ,
62+ \ ' SpellLocal' ,
63+ \ ' SpellRare' ,
64+ \ ' Statement' ,
65+ \ ' StatusLine' ,
66+ \ ' StatusLineNC' ,
67+ \ ' StatusLineTerm' ,
68+ \ ' StatusLineTermNC' ,
69+ \ ' TabLine' ,
70+ \ ' TabLineFill' ,
71+ \ ' TabLineSel' ,
72+ \ ' Title' ,
73+ \ ' Todo' ,
74+ \ ' ToolbarButton' ,
75+ \ ' ToolbarLine' ,
76+ \ ' Type' ,
77+ \ ' Underlined' ,
78+ \ ' VertSplit' ,
79+ \ ' Visual' ,
80+ \ ' VisualNOS' ,
81+ \ ' WarningMsg' ,
82+ \ ' WildMenu' ,
83+ \ ]
2584 let groups= {}
2685 for group in hi_groups
2786 if search (' \c@suppress\s\+' .group, ' cnW' )
@@ -30,6 +89,9 @@ func! Test_check_colors()
3089 let groups[group] = ' Ignoring ' .group
3190 continue
3291 endif
92+ if search (' hi\%[ghlight]!\= \+link \+' .group, ' cnW' ) " Linked group
93+ continue
94+ endif
3395 if ! search (' hi\%[ghlight] \+' .group, ' cnW' )
3496 let groups[group] = ' No highlight definition for ' .group
3597 continue
@@ -43,12 +105,15 @@ func! Test_check_colors()
43105 let groups[group] = ' Missing bg terminal color for ' .group
44106 continue
45107 endif
46- call search (' hi\%[ghlight] \+' .group, ' cW' )
47- " only check in the current line
48- if ! search (' guifg' , ' cnW' , line (' .' )) || ! search (' ctermfg' , ' cnW' , line (' .' ))
49- " do not check for background colors, they could be intentionally left out
50- let groups[group] = ' Missing fg definition for ' .group
108+ if ! search (' hi\%[ghlight] \+' .group. ' .*guifg=' , ' cnW' )
109+ let groups[group] = ' Missing guifg definition for ' .group
110+ continue
51111 endif
112+ if ! search (' hi\%[ghlight] \+' .group. ' .*ctermfg=' , ' cnW' )
113+ let groups[group] = ' Missing ctermfg definition for ' .group
114+ continue
115+ endif
116+ " do not check for background colors, they could be intentionally left out
52117 call cursor (1 ,1 )
53118 endfor
54119 let err[' highlight' ] = groups
@@ -91,27 +156,55 @@ func! Test_check_colors()
91156 endif
92157
93158 " 7) Does not define filetype specific groups like vimCommand, htmlTag,
94- let hi_groups = [' vim' , ' html' , ' python' , ' sh' , ' ruby' ]
159+ let hi_groups = filter (getcompletion (' ' , ' filetype' ), { _,v - > v !~# ' \%[no]syn\%(color\|load\|tax\)' })
160+ let ft_groups = []
161+ " let group = '\%('.join(hi_groups, '\|').'\)' " More efficient than a for loop, but less informative
95162 for group in hi_groups
96- let pat= ' \Chi\%[ghlight]\s*\zs' .group.' \w\+\>'
163+ let pat= ' \Chi\%[ghlight]!\= *\%[link] \+\zs' .group.' \w\+\>\ze \+.' " Skips `hi clear`
164+ if search (pat, ' cW' )
165+ call add (ft_groups, matchstr (getline (' .' ), pat))
166+ endif
167+ call cursor (1 ,1 )
168+ endfor
169+ if ! empty (ft_groups)
170+ let err[' filetype' ] = get (err, ' filetype' , ' Should not define: ' ) . join (uniq (sort (ft_groups)))
171+ endif
172+
173+ " 8) Were debugPC and debugBreakpoint defined?
174+ for group in [' debugPC' , ' debugBreakpoint' ]
175+ let pat= ' \Chi\%[ghlight]!\= *\%[link] \+\zs' .group.' \>'
97176 if search (pat, ' cnW' )
98177 let line = search (pat, ' cW' )
99178 let err[' filetype' ] = get (err, ' filetype' , ' Should not define: ' ) . matchstr (getline (' .' ), pat). ' '
100179 endif
101180 call cursor (1 ,1 )
102181 endfor
182+
183+ " 9) Normal should be defined first, not use reverse, fg or bg
184+ call cursor (1 ,1 )
185+ let pat = ' hi\%[light] \+\%(link\|clear\)\@!\w\+\>'
186+ call search (pat, ' cW' ) " Look for the first hi def, skipping `hi link` and `hi clear`
187+ if getline (' .' ) !~# ' \m\<Normal\>'
188+ let err[' highlight' ][' Normal' ] = ' Should be defined first'
189+ elseif getline (' .' ) = ~# ' \m\%(=\%(fg\|bg\)\)'
190+ let err[' highlight' ][' Normal' ] = " Should not use 'fg' or 'bg'"
191+ elseif getline (' .' ) = ~# ' \m=\%(inv\|rev\)erse'
192+ let err[' highlight' ][' Normal' ] = ' Should not use reverse mode'
193+ endif
194+
195+ call winrestview (l: savedview )
103196 let g: err = err
104197
105198 " print Result
106199 call Result (err)
107200endfu
108201
109202fu ! Result (err)
110- let do_roups = 0
203+ let do_groups = 0
111204 echohl Title |echomsg " ---------------" |echohl Normal
112205 for key in sort (keys (a: err ))
113206 if key is # ' highlight'
114- let do_groups = 1
207+ let do_groups = ! empty ( a: err [ key ])
115208 continue
116209 else
117210 if a: err [key ] !~ ' OK'
0 commit comments