" Util: function! s:define_type_checker() "{{{1 " dynamically define s:is_Number(v) etc.. let types = { \ "Number": 0, \ "String": 1, \ "Funcref": 2, \ "List": 3, \ "Dictionary": 4, \ "Float": 5, \ } for [type, number] in items(types) let s = '' let s .= 'function! s:is_' . type . '(v)' . "\n" let s .= ' return type(a:v) is ' . number . "\n" let s .= 'endfunction' . "\n" execute s endfor endfunction "}}} call s:define_type_checker() unlet! s:define_type_checker " Copied from vim-airline's airline#init#gui_mode function let s:SCREEN = (has('gui_running') || \ (has('termtruecolor') && &guicolors == 1) || \ (has('termguicolors') && &termguicolors == 1) || \ (has('nvim') && exists('$NVIM_TUI_ENABLE_TRUE_COLOR') \ && !exists('+termguicolors'))) ? 'gui' : 'cterm' " Main: let s:hlmgr = {} function! s:hlmgr.new(prefix) "{{{1 let R = deepcopy(self) call R.init(a:prefix) return R endfunction function! s:hlmgr.init(prefix) "{{{1 let self._colors = {} let self._specs = {} let self.prefix = a:prefix return self endfunction function! s:hlmgr.register_auto(spec) "{{{1 if s:is_String(a:spec) return a:spec endif if s:is_Dictionary(a:spec) let spec = string(a:spec[s:SCREEN]) let name = get(self._specs, spec, '') if !empty(name) " If color is already defined for spec provided. " return that color return name endif endif return self.register(self.color_next(), a:spec) endfunction function! s:hlmgr.register(name, spec) "{{{1 call self.define(a:name, a:spec) let self._colors[a:name] = a:spec " This might overwrite existing spec but its OK since _specs is simple color " re-using mechanizm for performance. let self._specs[string(a:spec[s:SCREEN])] = a:name return a:name endfunction function! s:hlmgr.define(name, color) "{{{1 let command = printf('highlight %s %s', a:name, self.hl_defstr(a:color)) silent execute command endfunction function! s:hlmgr.refresh() "{{{1 for [name, color] in items(self._colors) call self.define(name, color) endfor endfunction function! s:hlmgr.color_next() "{{{1 return printf(self.prefix . '%05d', len(self._colors)) endfunction function! s:hlmgr.reset() "{{{1 call self.clear() call self.init(self.prefix) endfunction function! s:hlmgr.spec_for(color) "{{{1 return get(self._colors, a:color, '') endfunction function! s:hlmgr.parse(spec, ...) "{{{1 " return dictionary from string " 'guifg=#25292c guibg=#afb0ae' => {'gui': ['#afb0ae', '#25292c']} let R = {} if empty(a:spec) return R endif let screens = empty(a:000) ? [s:SCREEN] : ['gui', 'cterm' ] for screen in screens let R[screen] = ['',''] for def in split(a:spec) let [key,val] = split(def, '=') if key ==# screen . 'bg' | let R[screen][0] = val elseif key ==# screen . 'fg' | let R[screen][1] = val elseif key ==# screen | call add(R[screen], val) endif endfor endfor return R endfunction function! s:hlmgr.parse_full(spec) "{{{1 return self.parse(a:spec, 1) endfunction function! s:hlmgr.capture(hlname) "{{{1 let hlname = a:hlname if empty(hlID(hlname)) " if hl not exists, return empty string return '' endif redir => HL_SAVE execute 'silent! highlight ' . hlname redir END if !empty(matchstr(HL_SAVE, 'xxx cleared$')) return '' endif " follow highlight link let link = matchstr(HL_SAVE, 'xxx links to \zs.*') if !empty(link) return self.capture(link) endif return matchstr(HL_SAVE, 'xxx \zs.*') endfunction function! s:hlmgr.clear() "{{{1 for color in self.colors() silent execute 'highlight clear' color endfor endfunction function! s:hlmgr.colors() "{{{1 return keys(self._colors) endfunction function! s:hlmgr.hl_defstr(color) "{{{1 " return 'guibg=DarkGreen gui=bold' (Type: String) let color = a:color[s:SCREEN] let R = [] "[NOTE] empty() is not appropriate, cterm color is specified with number for [idx, s] in [[ 0, 'bg' ], [ 1, 'fg' ] ,[ 2, ''] ] let c = get(color, idx, -1) if (s:is_String(c) && empty(c)) || (s:is_Number(c) && c ==# -1) continue endif call add(R, printf('%s%s=%s', s:SCREEN, s, color[idx])) endfor return join(R) endfunction function! s:hlmgr.convert(hlname) "{{{1 return self.parse(self.capture(a:hlname)) endfunction function! s:hlmgr.convert_full(hlname) "{{{1 return self.parse_full(self.capture(a:hlname)) endfunction function! s:hlmgr.dump() "{{{1 return PP(self) endfunction "}}} " API: function! choosewin#hlmanager#new(prefix) "{{{1 return s:hlmgr.new(a:prefix) endfunction "}}} " vim: foldmethod=marker