311 lines
7.8 KiB
VimL
311 lines
7.8 KiB
VimL
"======================================================================
|
|
"
|
|
" highlight.vim -
|
|
"
|
|
" Created by skywind on 2021/12/12
|
|
" Last Modified: 2021/12/13 18:32
|
|
"
|
|
"======================================================================
|
|
|
|
" vim: set ts=4 sw=4 tw=78 noet :
|
|
|
|
|
|
"----------------------------------------------------------------------
|
|
" internal
|
|
"----------------------------------------------------------------------
|
|
let s:has_hlget = exists('*hlget')? 1 : 0
|
|
let s:has_hlset = exists('*hlset')? 1 : 0
|
|
|
|
|
|
"----------------------------------------------------------------------
|
|
" get highlighting group
|
|
"----------------------------------------------------------------------
|
|
function! s:sim_hlget(name)
|
|
let error = 0
|
|
redir => g:quickui_highlight_tmp
|
|
try
|
|
exec 'silent hi ' . a:name
|
|
catch
|
|
let error = 1
|
|
endtry
|
|
redir END
|
|
if error != 0
|
|
return []
|
|
endif
|
|
let capture = g:quickui_highlight_tmp
|
|
let items = []
|
|
for text in split(capture, '\n')
|
|
let text = quickui#core#string_strip(text)
|
|
if text == ''
|
|
continue
|
|
endif
|
|
let item = {}
|
|
let item.name = matchstr(text, '^\w\+')
|
|
if item.name == ''
|
|
continue
|
|
endif
|
|
let parts = split(text, ' ')
|
|
if empty(parts)
|
|
continue
|
|
endif
|
|
if text =~ ' cleared$'
|
|
let item.cleared = v:true
|
|
elseif text =~ ' links to \w\+$'
|
|
let links = matchstr(text, ' links to \zs\w\+$')
|
|
let item.linksto = quickui#core#string_strip(links)
|
|
else
|
|
for part in parts[1:]
|
|
if part =~ '\w\+='
|
|
let key = matchstr(part, '^\w\+')
|
|
let val = matchstr(part, '^\w\+=\zs\%(\\.\|\S\)*')
|
|
if key == 'term' || key == 'cterm' || key == 'gui'
|
|
let opts = {}
|
|
for element in split(val, ',')
|
|
let opts[element] = v:true
|
|
endfor
|
|
let item[key] = opts
|
|
else
|
|
let item[key] = val
|
|
endif
|
|
elseif part == 'cleared'
|
|
endif
|
|
endfor
|
|
endif
|
|
let items += [item]
|
|
endfor
|
|
return items
|
|
endfunc
|
|
|
|
|
|
"----------------------------------------------------------------------
|
|
" simulate hlset
|
|
"----------------------------------------------------------------------
|
|
function! s:sim_hlset(items)
|
|
let skip = {'name':1, 'id':1, 'linksto':1, 'force':1}
|
|
for item in a:items
|
|
let name = get(item, 'name', '')
|
|
if name == ''
|
|
continue
|
|
endif
|
|
let force = get(item, 'force', v:false)
|
|
let cmd = (force == 0)? 'hi ' : 'hi! '
|
|
if get(item, 'cleared', v:false) == v:true
|
|
exec cmd . 'clear ' . name
|
|
else
|
|
let part = []
|
|
for key in keys(item)
|
|
if has_key(skip, key) == 0
|
|
let val = item[key]
|
|
if type(val) == v:t_dict
|
|
let r = join(keys(val), ',')
|
|
else
|
|
let r = val
|
|
endif
|
|
let part += [key . '=' . r]
|
|
endif
|
|
endfor
|
|
let text = cmd . ' ' . name . ' ' . join(part, ' ')
|
|
exec text
|
|
endif
|
|
endfor
|
|
endfunc
|
|
|
|
|
|
"----------------------------------------------------------------------
|
|
" get highlighting info
|
|
"----------------------------------------------------------------------
|
|
function! quickui#highlight#get(name, ...)
|
|
let resolve = (a:0 > 0)? (a:1) : 0
|
|
if s:has_hlget
|
|
" return hlget(a:name, resolve)
|
|
endif
|
|
if !resolve
|
|
return s:sim_hlget(a:name)
|
|
endif
|
|
let items = []
|
|
for item in s:sim_hlget(a:name)
|
|
if has_key(item, 'linksto') == 0
|
|
let items += [item]
|
|
continue
|
|
endif
|
|
let info = item
|
|
while 1
|
|
if has_key(info, 'linksto') == 0
|
|
break
|
|
endif
|
|
let links = info.linksto
|
|
let hr = s:sim_hlget(links)
|
|
if empty(hr)
|
|
break
|
|
endif
|
|
let info = hr[0]
|
|
endwhile
|
|
let info.name = item.name
|
|
let items += [info]
|
|
endfor
|
|
return items
|
|
endfunc
|
|
|
|
|
|
"----------------------------------------------------------------------
|
|
" set highlight group
|
|
"----------------------------------------------------------------------
|
|
function! quickui#highlight#set(items)
|
|
if s:has_hlset
|
|
" return hlset(a:items)
|
|
endif
|
|
call s:sim_hlset(a:items)
|
|
endfunc
|
|
|
|
|
|
"----------------------------------------------------------------------
|
|
" clear highlight
|
|
"----------------------------------------------------------------------
|
|
function! quickui#highlight#clear(name)
|
|
if s:has_hlset
|
|
let info = {'name': a:name, 'cleared': v:true}
|
|
call hlset([info])
|
|
else
|
|
exec 'hi! clear ' . a:name
|
|
endif
|
|
endfunc
|
|
|
|
|
|
"----------------------------------------------------------------------
|
|
" term add feature
|
|
"----------------------------------------------------------------------
|
|
function! quickui#highlight#term_add(info, what)
|
|
let info = a:info
|
|
let what = a:what
|
|
if has_key(info, 'term')
|
|
if type(info.term) == v:t_dict
|
|
let info.term[what] = v:true
|
|
elseif type(info.term) == v:t_string
|
|
let opts = {}
|
|
for key in split(info.term, ',')
|
|
let opts[key] = v:true
|
|
endfor
|
|
let opts[what] = v:true
|
|
let info.term = opts
|
|
endif
|
|
else
|
|
let info.term = {}
|
|
let info.term[what] = v:true
|
|
endif
|
|
endfunc
|
|
|
|
|
|
"----------------------------------------------------------------------
|
|
" cterm add feature
|
|
"----------------------------------------------------------------------
|
|
function! quickui#highlight#cterm_add(info, what)
|
|
let info = a:info
|
|
let what = a:what
|
|
if has_key(info, 'cterm')
|
|
if type(info.cterm) == v:t_dict
|
|
let info.cterm[what] = v:true
|
|
elseif type(info.cterm) == v:t_string
|
|
let opts = {}
|
|
for key in split(info.cterm, ',')
|
|
let opts[key] = v:true
|
|
endfor
|
|
let opts[what] = v:true
|
|
let info.cterm = opts
|
|
endif
|
|
else
|
|
let info.cterm = {}
|
|
let info.cterm[what] = v:true
|
|
endif
|
|
endfunc
|
|
|
|
|
|
"----------------------------------------------------------------------
|
|
" gui add feature
|
|
"----------------------------------------------------------------------
|
|
function! quickui#highlight#gui_add(info, what)
|
|
let info = a:info
|
|
let what = a:what
|
|
if has_key(info, 'gui')
|
|
if type(info.gui) == v:t_dict
|
|
let info.gui[what] = v:true
|
|
elseif type(info.gui) == v:t_string
|
|
let opts = {}
|
|
for key in split(info.gui, ',')
|
|
let opts[key] = v:true
|
|
endfor
|
|
let opts[what] = v:true
|
|
let info.gui = opts
|
|
endif
|
|
else
|
|
let info.gui = {}
|
|
let info.gui[what] = v:true
|
|
endif
|
|
endfunc
|
|
|
|
|
|
"----------------------------------------------------------------------
|
|
" new underline
|
|
"----------------------------------------------------------------------
|
|
function! quickui#highlight#grant_underline(info)
|
|
let info = a:info
|
|
call quickui#highlight#term_add(info, 'underline')
|
|
call quickui#highlight#cterm_add(info, 'underline')
|
|
call quickui#highlight#gui_add(info, 'underline')
|
|
return info
|
|
endfunc
|
|
|
|
|
|
"----------------------------------------------------------------------
|
|
" add colors
|
|
"----------------------------------------------------------------------
|
|
function! quickui#highlight#grant_color(info, colors)
|
|
for key in keys(a:colors)
|
|
let a:info[key] = a:colors[key]
|
|
endfor
|
|
return a:info
|
|
endfunc
|
|
|
|
|
|
"----------------------------------------------------------------------
|
|
" add underline feature
|
|
"----------------------------------------------------------------------
|
|
function! quickui#highlight#make_underline(newname, name)
|
|
let hr = quickui#highlight#get(a:name, 1)
|
|
if len(hr) == 0
|
|
return -1
|
|
endif
|
|
let info = (len(hr) == 0)? {} : hr[0]
|
|
call quickui#highlight#term_add(info, 'underline')
|
|
call quickui#highlight#cterm_add(info, 'underline')
|
|
call quickui#highlight#gui_add(info, 'underline')
|
|
if has_key(info, 'id')
|
|
unlet info['id']
|
|
endif
|
|
let info.name = a:newname
|
|
let info.force = v:true
|
|
call quickui#highlight#set([info])
|
|
return info
|
|
endfunc
|
|
|
|
|
|
|
|
"----------------------------------------------------------------------
|
|
" combine foreground and background colors
|
|
"----------------------------------------------------------------------
|
|
function! quickui#highlight#overlay(newname, background, foreground)
|
|
let hr1 = quickui#highlight#get(a:background, 1)
|
|
let hr2 = quickui#highlight#get(a:foreground, 1)
|
|
let info1 = empty(hr1)? {} : hr1[0]
|
|
let info2 = empty(hr2)? {} : hr2[0]
|
|
for key in ['ctermfg', 'guifg']
|
|
if has_key(info2, key)
|
|
let info1[key] = info2[key]
|
|
endif
|
|
endfor
|
|
let info1.name = a:newname
|
|
let info1.force = v:true
|
|
call quickui#highlight#set([info1])
|
|
endfunc
|
|
|
|
|