From 7f0186d6bcec860aae1f49d5998f80b92ad36691 Mon Sep 17 00:00:00 2001 From: Matt Wozniski Date: Sat, 9 Mar 2013 01:52:55 -0500 Subject: [PATCH] Refactor color string to RGB code into autoloads Expose 2 more functions as autoloads: csapprox#common#color_name_to_hex(name) - Resolve a color name (like PapayaWhip) to hex (#ffefd5) csapprox#common#hex_to_rgb(hex) - Split a hex color (like #ffefd5) to a list ([ 255, 239, 213 ]) --- autoload/csapprox/common.vim | 143 +++++++++++++++++++++++++++++++++++ plugin/CSApprox.vim | 132 ++------------------------------ 2 files changed, 149 insertions(+), 126 deletions(-) diff --git a/autoload/csapprox/common.vim b/autoload/csapprox/common.vim index cf61379..c61af3c 100644 --- a/autoload/csapprox/common.vim +++ b/autoload/csapprox/common.vim @@ -23,6 +23,8 @@ " (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS " SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +" {>1} Handle terminal color cubes + let s:xterm_colors = [ 0x00, 0x5F, 0x87, 0xAF, 0xD7, 0xFF ] let s:eterm_colors = [ 0x00, 0x2A, 0x55, 0x7F, 0xAA, 0xD4 ] let s:konsole_colors = [ 0x00, 0x33, 0x66, 0x99, 0xCC, 0xFF ] @@ -76,3 +78,144 @@ endfunction function! csapprox#common#Colors() return s:{csapprox#common#PaletteType()}_colors endfunction + +" {>1} Handle color names + +" Place to store rgb.txt name to color mappings - lazy loaded if needed +let s:rgb = {} + +" {>2} Builtin gui color names +" gui_x11.c and gui_gtk_x11.c have some default colors names that are searched +" if the x server doesn't know about a color. If 'showrgb' is available, +" we'll default to using these color names and values, and overwrite them with +" other values if 'showrgb' tells us about those colors. +let s:rgb_defaults = { "lightred" : "#FFBBBB", + \ "lightgreen" : "#88FF88", + \ "lightmagenta" : "#FFBBFF", + \ "darkcyan" : "#008888", + \ "darkblue" : "#0000BB", + \ "darkred" : "#BB0000", + \ "darkmagenta" : "#BB00BB", + \ "darkgrey" : "#BBBBBB", + \ "darkyellow" : "#BBBB00", + \ "gray10" : "#1A1A1A", + \ "grey10" : "#1A1A1A", + \ "gray20" : "#333333", + \ "grey20" : "#333333", + \ "gray30" : "#4D4D4D", + \ "grey30" : "#4D4D4D", + \ "gray40" : "#666666", + \ "grey40" : "#666666", + \ "gray50" : "#7F7F7F", + \ "grey50" : "#7F7F7F", + \ "gray60" : "#999999", + \ "grey60" : "#999999", + \ "gray70" : "#B3B3B3", + \ "grey70" : "#B3B3B3", + \ "gray80" : "#CCCCCC", + \ "grey80" : "#CCCCCC", + \ "gray90" : "#E5E5E5", + \ "grey90" : "#E5E5E5" } + +" {>2} Colors that vim will use by name in one of the default schemes, either +" for bg=light or for bg=dark. This lets us avoid loading the entire rgb.txt +" database when the scheme itself doesn't ask for colors by name. +let s:rgb_presets = { "black" : "#000000", + \ "blue" : "#0000ff", + \ "brown" : "#a52a2a", + \ "cyan" : "#00ffff", + \ "darkblue" : "#00008b", + \ "darkcyan" : "#008b8b", + \ "darkgrey" : "#a9a9a9", + \ "darkmagenta" : "#8b008b", + \ "green" : "#00ff00", + \ "grey" : "#bebebe", + \ "grey40" : "#666666", + \ "grey90" : "#e5e5e5", + \ "lightblue" : "#add8e6", + \ "lightcyan" : "#e0ffff", + \ "lightgrey" : "#d3d3d3", + \ "lightmagenta" : "#ffbbff", + \ "magenta" : "#ff00ff", + \ "red" : "#ff0000", + \ "seagreen" : "#2e8b57", + \ "white" : "#ffffff", + \ "yellow" : "#ffff00" } + +" {>2} Find available color names +" Find the valid named colors. By default, use our own rgb list, but try to +" retrieve the system's list if g:CSApprox_use_showrgb is set to true. Store +" the color names and color values to the dictionary s:rgb - the keys are +" color names (in lowercase), the values are strings representing color values +" (as '#rrggbb'). +function! s:UpdateRgbHash() + try + if !exists("g:CSApprox_use_showrgb") || !g:CSApprox_use_showrgb + throw "Not using showrgb" + endif + + " We want to use the 'showrgb' program, if it's around + let lines = split(system('showrgb'), '\n') + + if v:shell_error || !exists('lines') || empty(lines) + throw "'showrgb' didn't give us an rgb.txt" + endif + + let s:rgb = copy(s:rgb_defaults) + + " fmt is (blanks?)(red)(blanks)(green)(blanks)(blue)(blanks)(name) + let parsepat = '^\s*\(\d\+\)\s\+\(\d\+\)\s\+\(\d\+\)\s\+\(.*\)$' + + for line in lines + let v = matchlist(line, parsepat) + if len(v) < 0 + throw "CSApprox: Bad RGB line: " . string(line) + endif + let s:rgb[tolower(v[4])] = printf("#%02x%02x%02x", v[1], v[2], v[3]) + endfor + catch + try + let s:rgb = csapprox#rgb() + catch + echohl ErrorMsg + echomsg "Can't call rgb() from autoload/csapprox.vim" + echomsg "Named colors will not be available!" + echohl None + endtry + endtry + + return 0 +endfunction + +" {>2} Resolve color names +" Given a color name, return the color as "#rrggbb". Throws if the name +" cannot be resolved. +function! csapprox#common#color_name_to_hex(name) + let val = tolower(a:name) + + try + " First see if it is in our preset-by-vim rgb list + let val = s:rgb_presets[val] + catch + " Then try loading and checking our real rgb list + if empty(s:rgb) + call s:UpdateRgbHash() + endif + let val = s:rgb[val] " Throws if the key can't be found + endtry + + return val +endfunction + +" {>2} Hex color to r, g, b +" Given a hex color string ("#rrggbb", with or without the leading '#'), +" return the a list containing the red, green, and blue components as ints. +function! csapprox#common#hex_to_rgb(hex) + let val = substitute(a:hex, '^#', '', '') + let r = str2nr(val[0:1], 16) + let g = str2nr(val[2:3], 16) + let b = str2nr(val[4:5], 16) + return [r, g, b] +endfunction + +" {0} vim:sw=2:sts=2:et:fdm=expr:fde=substitute(matchstr(getline(v\:lnum),'^\\s*"\\s*{\\zs.\\{-}\\ze}'),'^$','=','') diff --git a/plugin/CSApprox.vim b/plugin/CSApprox.vim index 383f398..6cdadbb 100644 --- a/plugin/CSApprox.vim +++ b/plugin/CSApprox.vim @@ -175,114 +175,6 @@ function! s:SynGuiSpAttr(idx) return synIDattr(a:idx, 'sp#', 'gui') endfunction -" {>1} Handle color names - -" Place to store rgb.txt name to color mappings - lazy loaded if needed -let s:rgb = {} - -" {>2} Builtin gui color names -" gui_x11.c and gui_gtk_x11.c have some default colors names that are searched -" if the x server doesn't know about a color. If 'showrgb' is available, -" we'll default to using these color names and values, and overwrite them with -" other values if 'showrgb' tells us about those colors. -let s:rgb_defaults = { "lightred" : "#FFBBBB", - \ "lightgreen" : "#88FF88", - \ "lightmagenta" : "#FFBBFF", - \ "darkcyan" : "#008888", - \ "darkblue" : "#0000BB", - \ "darkred" : "#BB0000", - \ "darkmagenta" : "#BB00BB", - \ "darkgrey" : "#BBBBBB", - \ "darkyellow" : "#BBBB00", - \ "gray10" : "#1A1A1A", - \ "grey10" : "#1A1A1A", - \ "gray20" : "#333333", - \ "grey20" : "#333333", - \ "gray30" : "#4D4D4D", - \ "grey30" : "#4D4D4D", - \ "gray40" : "#666666", - \ "grey40" : "#666666", - \ "gray50" : "#7F7F7F", - \ "grey50" : "#7F7F7F", - \ "gray60" : "#999999", - \ "grey60" : "#999999", - \ "gray70" : "#B3B3B3", - \ "grey70" : "#B3B3B3", - \ "gray80" : "#CCCCCC", - \ "grey80" : "#CCCCCC", - \ "gray90" : "#E5E5E5", - \ "grey90" : "#E5E5E5" } - -" {>2} Colors that vim will use by name in one of the default schemes, either -" for bg=light or for bg=dark. This lets us avoid loading the entire rgb.txt -" database when the scheme itself doesn't ask for colors by name. -let s:rgb_presets = { "black" : "#000000", - \ "blue" : "#0000ff", - \ "brown" : "#a52a2a", - \ "cyan" : "#00ffff", - \ "darkblue" : "#00008b", - \ "darkcyan" : "#008b8b", - \ "darkgrey" : "#a9a9a9", - \ "darkmagenta" : "#8b008b", - \ "green" : "#00ff00", - \ "grey" : "#bebebe", - \ "grey40" : "#666666", - \ "grey90" : "#e5e5e5", - \ "lightblue" : "#add8e6", - \ "lightcyan" : "#e0ffff", - \ "lightgrey" : "#d3d3d3", - \ "lightmagenta" : "#ffbbff", - \ "magenta" : "#ff00ff", - \ "red" : "#ff0000", - \ "seagreen" : "#2e8b57", - \ "white" : "#ffffff", - \ "yellow" : "#ffff00" } - -" {>2} Find available color names -" Find the valid named colors. By default, use our own rgb list, but try to -" retrieve the system's list if g:CSApprox_use_showrgb is set to true. Store -" the color names and color values to the dictionary s:rgb - the keys are -" color names (in lowercase), the values are strings representing color values -" (as '#rrggbb'). -function! s:UpdateRgbHash() - try - if !exists("g:CSApprox_use_showrgb") || !g:CSApprox_use_showrgb - throw "Not using showrgb" - endif - - " We want to use the 'showrgb' program, if it's around - let lines = split(system('showrgb'), '\n') - - if v:shell_error || !exists('lines') || empty(lines) - throw "'showrgb' didn't give us an rgb.txt" - endif - - let s:rgb = copy(s:rgb_defaults) - - " fmt is (blanks?)(red)(blanks)(green)(blanks)(blue)(blanks)(name) - let parsepat = '^\s*\(\d\+\)\s\+\(\d\+\)\s\+\(\d\+\)\s\+\(.*\)$' - - for line in lines - let v = matchlist(line, parsepat) - if len(v) < 0 - throw "CSApprox: Bad RGB line: " . string(line) - endif - let s:rgb[tolower(v[4])] = printf("#%02x%02x%02x", v[1], v[2], v[3]) - endfor - catch - try - let s:rgb = csapprox#rgb() - catch - echohl ErrorMsg - echomsg "Can't call rgb() from autoload/csapprox.vim" - echomsg "Named colors will not be available!" - echohl None - endtry - endtry - - return 0 -endfunction - " {>1} Derive and set cterm attributes " {>2} List of all possible attributes @@ -452,22 +344,13 @@ function! s:SetCtermFromGui(hl) " rgb.txt color to a #rrggbb color if val !~? '^[fb]g$' && val !~ '^#\=\x\{6}$' try - " First see if it is in our preset-by-vim rgb list - let val = s:rgb_presets[tolower(val)] + let val = csapprox#common#color_name_to_hex(val) catch - " Then try loading and checking our real rgb list - if empty(s:rgb) - call s:UpdateRgbHash() + " Barf if we can't resolve the color name + if &verbose + echomsg "CSApprox: Colorscheme uses unknown color \"" . val . "\"" endif - try - let val = s:rgb[tolower(val)] - catch - " And then barf if we still haven't found it - if &verbose - echomsg "CSApprox: Colorscheme uses unknown color \"" . val . "\"" - endif - continue - endtry + continue endtry endif @@ -475,10 +358,7 @@ function! s:SetCtermFromGui(hl) exe 'hi ' . hl.name . ' cterm' . which . '=' . val let hl.cterm[which] = val elseif val =~ '^#\=\x\{6}$' - let val = substitute(val, '^#', '', '') - let r = str2nr(val[0:1], 16) - let g = str2nr(val[2:3], 16) - let b = str2nr(val[4:5], 16) + let [r, g, b] = csapprox#common#hex_to_rgb(val) let hl.cterm[which] = g:CSApprox_approximator_function(r, g, b) exe 'hi ' . hl.name . ' cterm' . which . '=' . hl.cterm[which] else