" colorizer.vim Colorize all text in the form #rrggbb or #rgb; autoload functions " Maintainer: lilydjwg " Version: 1.4.2 " License: Vim License (see vim's :help license) " " See plugin/colorizer.vim for more info. let s:keepcpo = &cpo set cpo&vim function! s:FGforBG(bg) "{{{1 " takes a 6hex color code and returns a matching color that is visible let pure = substitute(a:bg,'^#','','') let r = str2nr(pure[0:1], 16) let g = str2nr(pure[2:3], 16) let b = str2nr(pure[4:5], 16) let fgc = g:colorizer_fgcontrast if r*30 + g*59 + b*11 > 12000 return s:predefined_fgcolors['dark'][fgc] else return s:predefined_fgcolors['light'][fgc] end endfunction function! s:Rgb2xterm(color) "{{{1 " selects the nearest xterm color for a rgb value like #FF0000 let best_match=0 let smallest_distance = 10000000000 let r = str2nr(a:color[1:2], 16) let g = str2nr(a:color[3:4], 16) let b = str2nr(a:color[5:6], 16) let colortable = s:GetXterm2rgbTable() for c in range(0,254) let d = pow(colortable[c][0]-r,2) + pow(colortable[c][1]-g,2) + pow(colortable[c][2]-b,2) if d=16 && a:color<=232 let l:color=a:color-16 let r = s:valuerange[(l:color/36)%6] let g = s:valuerange[(l:color/6)%6] let b = s:valuerange[l:color%6] endif " gray tone if a:color>=233 && a:color<=253 let r=8+(a:color-232)*0x0a let g=r let b=r endif let rgb=[r,g,b] return rgb endfunction function! s:SetMatcher(color, pat) "{{{1 " "color" is the converted color and "pat" is what to highlight let group = 'Color' . strpart(a:color, 1) if !hlexists(group) || s:force_group_update let fg = g:colorizer_fgcontrast < 0 ? a:color : s:FGforBG(a:color) if &t_Co == 256 exe 'hi '.group.' ctermfg='.s:Rgb2xterm(fg).' ctermbg='.s:Rgb2xterm(a:color) endif " Always set gui* as user may switch to GUI version and it's cheap exe 'hi '.group.' guifg='.fg.' guibg='.a:color endif if !exists("w:colormatches[a:pat]") let w:colormatches[a:pat] = matchadd(group, a:pat) endif endfunction " Color Converters {{{1 function! s:RgbBgColor() "{{{2 let bg = synIDattr(synIDtrans(hlID("Normal")), "bg") let r = str2nr(bg[1:2], 16) let g = str2nr(bg[3:4], 16) let b = str2nr(bg[5:6], 16) return [r,g,b] endfunction function! s:Hexa2Rgba(hex,alpha) "{{{2 let r = str2nr(a:hex[1:2], 16) let g = str2nr(a:hex[3:4], 16) let b = str2nr(a:hex[5:6], 16) let alpha = printf("%.2f", str2float(str2nr(a:alpha,16)) / 255.0) return [r,g,b,alpha] endfunction function! s:Rgba2Rgb(r,g,b,alpha,percent,rgb_bg) "{{{2 " converts matched r,g,b values and percentages to [0:255] " if possible, overlays r,g,b with alpha on given rgb_bg color if a:percent let r = a:r * 255 / 100 let g = a:g * 255 / 100 let b = a:b * 255 / 100 else let r = a:r let g = a:g let b = a:b endif if r > 255 || g > 255 || b > 255 return [] endif if empty(a:rgb_bg) return [r,g,b] endif let alpha = str2float(a:alpha) if alpha < 0 let alpha = 0.0 elseif alpha > 1 let alpha = 1.0 endif if alpha == 1.0 return [r,g,b] endif let r = float2nr(ceil(r * alpha) + ceil(a:rgb_bg[0] * (1 - alpha))) let g = float2nr(ceil(g * alpha) + ceil(a:rgb_bg[1] * (1 - alpha))) let b = float2nr(ceil(b * alpha) + ceil(a:rgb_bg[2] * (1 - alpha))) if r > 255 let r = 255 endif if g > 255 let g = 255 endif if b > 255 let b = 255 endif return [r,g,b] endfunction "ColorFinders {{{1 function! s:HexCode(str, lineno) "{{{2 " finds RGB: #00f #0000ff and RGBA: #00f8 #0000ff88 (or ARGB: #800f #880000ff) if has("gui_running") let rgb_bg = s:RgbBgColor() else " translucent colors would display incorrectly, so ignore the alpha value let rgb_bg = [] endif let ret = [] let place = 0 let colorpat = '#[0-9A-Fa-f]\{3\}\>\|#[0-9A-Fa-f]\{6\}\>\|#[0-9A-Fa-f]\{8\}\>\|#[0-9A-Fa-f]\{4\}\>' while 1 let foundcolor = matchstr(a:str, colorpat, place) if foundcolor == '' break endif let place = matchend(a:str, colorpat, place) let pat = foundcolor . '\>' let colorlen = len(foundcolor) if get(g:, 'colorizer_hex_alpha_first') == 1 if colorlen == 4 || colorlen == 5 let ha = tolower(foundcolor[1]) let hr = tolower(foundcolor[2]) let hg = tolower(foundcolor[3]) let hb = tolower(foundcolor[4]) let foundcolor = substitute(foundcolor, '[[:xdigit:]]', '&&', 'g') else let ha = tolower(foundcolor[1:2]) let hr = tolower(foundcolor[3:4]) let hg = tolower(foundcolor[5:6]) let hb = tolower(foundcolor[7:8]) endif if len(foundcolor) == 9 let alpha = foundcolor[1:2] let foundcolor = '#'.foundcolor[3:8] else let alpha = 'ff' endif if empty(rgb_bg) if colorlen == 5 let pat = printf('\c#\x\zs%s%s%s\ze\>', hr,hg,hb) elseif colorlen == 9 let pat = printf('\c#\x\x\zs%s%s%s\ze\>', hr,hg,hb) endif endif else if colorlen == 4 || colorlen == 5 let hr = tolower(foundcolor[1]) let hg = tolower(foundcolor[2]) let hb = tolower(foundcolor[3]) let ha = tolower(foundcolor[4]) let foundcolor = substitute(foundcolor, '[[:xdigit:]]', '&&', 'g') else let hr = tolower(foundcolor[1:2]) let hg = tolower(foundcolor[3:4]) let hb = tolower(foundcolor[5:6]) let ha = tolower(foundcolor[7:8]) endif if len(foundcolor) == 9 let alpha = foundcolor[7:8] let foundcolor = foundcolor[0:6] else let alpha = 'ff' endif if empty(rgb_bg) if colorlen == 5 let pat = printf('\c#%s%s%s\ze\x\>', hr,hg,hb) elseif colorlen == 9 let pat = printf('\c#%s%s%s\ze\x\x\>', hr,hg,hb) endif endif endif if empty(rgb_bg) || tolower(alpha) == 'ff' call add(ret, [foundcolor, pat]) else let rgba = s:Hexa2Rgba(foundcolor, alpha) let rgb = s:Rgba2Rgb(rgba[0], rgba[1], rgba[2], rgba[3], 0, rgb_bg) let l:color = printf('#%02x%02x%02x', rgb[0], rgb[1], rgb[2]) call add(ret, [l:color, pat]) endif endwhile return ret endfunction function! s:RgbColor(str, lineno) "{{{2 let ret = [] let place = 0 let colorpat = '\ 255 || g > 255 || b > 255 break endif let pat = printf('\ 0) && (g:colorizer_maxlines <= line('$')) return end let w:colormatches = {} if g:colorizer_fgcontrast != s:saved_fgcontrast || (exists("a:1") && a:1 == '!') let s:force_group_update = 1 endif for i in range(1, line("$")) call s:PreviewColorInLine(i) endfor let s:force_group_update = 0 let s:saved_fgcontrast = g:colorizer_fgcontrast augroup Colorizer au! if exists('##TextChanged') autocmd TextChanged * silent call s:TextChanged() if v:version > 704 || v:version == 704 && has('patch143') autocmd TextChangedI * silent call s:TextChanged() else " TextChangedI does not work as expected autocmd CursorMovedI * silent call s:CursorMoved() endif else autocmd CursorMoved,CursorMovedI * silent call s:CursorMoved() endif " rgba handles differently, so need updating autocmd GUIEnter * silent call colorizer#ColorHighlight(1) autocmd BufEnter * silent call colorizer#ColorHighlight(1) autocmd WinEnter * silent call colorizer#ColorHighlight(1) autocmd ColorScheme * let s:force_group_update=1 | silent call colorizer#ColorHighlight(1) augroup END endfunction function! colorizer#ColorClear() "{{{1 augroup Colorizer au! augroup END augroup! Colorizer let save_tab = tabpagenr() let save_win = winnr() tabdo windo call s:ClearMatches() exe 'tabn '.save_tab exe save_win . 'wincmd w' endfunction function! s:ClearMatches() "{{{1 if !exists('w:colormatches') return endif for i in values(w:colormatches) try call matchdelete(i) catch /.*/ " matches have been cleared in other ways, e.g. user has called clearmatches() endtry endfor unlet w:colormatches endfunction function! colorizer#ColorToggle() "{{{1 if exists('#Colorizer') call colorizer#ColorClear() echomsg 'Disabled color code highlighting.' else call colorizer#ColorHighlight(0) echomsg 'Enabled color code highlighting.' endif endfunction function! colorizer#AlphaPositionToggle() "{{{1 if exists('#Colorizer') if get(g:, 'colorizer_hex_alpha_first') == 1 let g:colorizer_hex_alpha_first = 0 else let g:colorizer_hex_alpha_first = 1 endif call colorizer#ColorHighlight(1) endif endfunction function! s:GetXterm2rgbTable() "{{{1 if !exists('s:table_xterm2rgb') let s:table_xterm2rgb = [] for c in range(0, 254) let s:color = s:Xterm2rgb(c) call add(s:table_xterm2rgb, s:color) endfor endif return s:table_xterm2rgb endfun " Setups {{{1 let s:ColorFinder = [function('s:HexCode'), function('s:RgbColor'), function('s:RgbaColor')] let s:force_group_update = 0 let s:predefined_fgcolors = {} let s:predefined_fgcolors['dark'] = ['#444444', '#222222', '#000000'] let s:predefined_fgcolors['light'] = ['#bbbbbb', '#dddddd', '#ffffff'] if !exists("g:colorizer_fgcontrast") " Default to black / white let g:colorizer_fgcontrast = len(s:predefined_fgcolors['dark']) - 1 elseif g:colorizer_fgcontrast >= len(s:predefined_fgcolors['dark']) echohl WarningMsg echo "g:colorizer_fgcontrast value invalid, using default" echohl None let g:colorizer_fgcontrast = len(s:predefined_fgcolors['dark']) - 1 endif let s:saved_fgcontrast = g:colorizer_fgcontrast " Restoration and modelines {{{1 let &cpo = s:keepcpo unlet s:keepcpo " vim:ft=vim:fdm=marker:fmr={{{,}}}:ts=8:sw=2:sts=2:et