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 ])
This commit is contained in:
Matt Wozniski 2013-03-09 01:52:55 -05:00
parent e0a472238c
commit 7f0186d6bc
2 changed files with 149 additions and 126 deletions

View File

@ -23,6 +23,8 @@
" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS " (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
" SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. " 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:xterm_colors = [ 0x00, 0x5F, 0x87, 0xAF, 0xD7, 0xFF ]
let s:eterm_colors = [ 0x00, 0x2A, 0x55, 0x7F, 0xAA, 0xD4 ] let s:eterm_colors = [ 0x00, 0x2A, 0x55, 0x7F, 0xAA, 0xD4 ]
let s:konsole_colors = [ 0x00, 0x33, 0x66, 0x99, 0xCC, 0xFF ] let s:konsole_colors = [ 0x00, 0x33, 0x66, 0x99, 0xCC, 0xFF ]
@ -76,3 +78,144 @@ endfunction
function! csapprox#common#Colors() function! csapprox#common#Colors()
return s:{csapprox#common#PaletteType()}_colors return s:{csapprox#common#PaletteType()}_colors
endfunction 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}'),'^$','=','')

View File

@ -175,114 +175,6 @@ function! s:SynGuiSpAttr(idx)
return synIDattr(a:idx, 'sp#', 'gui') return synIDattr(a:idx, 'sp#', 'gui')
endfunction 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 " {>1} Derive and set cterm attributes
" {>2} List of all possible attributes " {>2} List of all possible attributes
@ -452,22 +344,13 @@ function! s:SetCtermFromGui(hl)
" rgb.txt color to a #rrggbb color " rgb.txt color to a #rrggbb color
if val !~? '^[fb]g$' && val !~ '^#\=\x\{6}$' if val !~? '^[fb]g$' && val !~ '^#\=\x\{6}$'
try try
" First see if it is in our preset-by-vim rgb list let val = csapprox#common#color_name_to_hex(val)
let val = s:rgb_presets[tolower(val)]
catch catch
" Then try loading and checking our real rgb list " Barf if we can't resolve the color name
if empty(s:rgb) if &verbose
call s:UpdateRgbHash() echomsg "CSApprox: Colorscheme uses unknown color \"" . val . "\""
endif endif
try continue
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
endtry endtry
endif endif
@ -475,10 +358,7 @@ function! s:SetCtermFromGui(hl)
exe 'hi ' . hl.name . ' cterm' . which . '=' . val exe 'hi ' . hl.name . ' cterm' . which . '=' . val
let hl.cterm[which] = val let hl.cterm[which] = val
elseif val =~ '^#\=\x\{6}$' elseif val =~ '^#\=\x\{6}$'
let val = substitute(val, '^#', '', '') let [r, g, b] = csapprox#common#hex_to_rgb(val)
let r = str2nr(val[0:1], 16)
let g = str2nr(val[2:3], 16)
let b = str2nr(val[4:5], 16)
let hl.cterm[which] = g:CSApprox_approximator_function(r, g, b) let hl.cterm[which] = g:CSApprox_approximator_function(r, g, b)
exe 'hi ' . hl.name . ' cterm' . which . '=' . hl.cterm[which] exe 'hi ' . hl.name . ' cterm' . which . '=' . hl.cterm[which]
else else