From 2840cd5252db9decc4422844945b3460868ee691 Mon Sep 17 00:00:00 2001 From: Chris Morgan Date: Tue, 16 Aug 2022 23:47:31 +1000 Subject: [PATCH] Significantly improve syntax support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Things now supported: • Fractions: hsl(25.7, 100%, 53.3%) = #f71. • Hue units deg, rad, grad, turn. • Negative hue rotations. • The fairly new commaless syntax: rgb(0 255 0) = rgb(0, 255, 0), hsl(210 50% 50% / 50%) = hsla(210, 50%, 50%, 0.5). I’ve added just one simple demonstration test. I’m too lazy to add it to more sample files. --- autoload/css_color.vim | 36 +++++++++++++++++++++++++----------- tests/example.css | 2 ++ 2 files changed, 27 insertions(+), 11 deletions(-) diff --git a/autoload/css_color.vim b/autoload/css_color.vim index b5a0dc4..e70dd02 100644 --- a/autoload/css_color.vim +++ b/autoload/css_color.vim @@ -11,17 +11,31 @@ if ! ( v:version >= 700 && has('syntax') && ( has('gui_running') || has('nvim') finish endif -function! s:rgb2color(r,g,b) +" (v = value, u = unit) +function! s:rgb2color(rv,ru,gv,gu,bv,bu) " Convert 80% -> 204, 100% -> 255, etc. - let rgb = map( [a:r,a:g,a:b], 'v:val =~ "%$" ? ( 255 * v:val ) / 100 : v:val' ) - return printf( '%02x%02x%02x', rgb[0], rgb[1], rgb[2] ) + return printf('%02x%02x%02x', + \ a:ru == "%" ? a:rv * 255 : a:rv, + \ a:gu == "%" ? a:gv * 255 : a:gv, + \ a:bu == "%" ? a:bv * 255 : a:bv) endfunction -function! s:hsl2color(h,s,l) +function! s:hsl2color(hv,hu,sv,su,lv,lu) " Convert 80% -> 0.8, 100% -> 1.0, etc. - let [s,l] = map( [a:s, a:l], 'v:val =~ "%$" ? v:val / 100.0 : v:val + 0.0' ) + let s = a:su == "%" ? str2float(a:sv) / 100.0 : str2float(a:sv) + let l = a:lu == "%" ? str2float(a:lv) / 100.0 : str2float(a:lv) + " Units: convert turn, grad, rad, assume anything else is unitless or deg. + let hh = str2float(a:hv) / ( + \ a:hu == "turn" ? 1.0 : + \ a:hu == "grad" ? 400.0 : + \ a:hu == "rad" ? 6.283185307179586 : + \ 360.0 + \ ) + " Get the floored remainder, so negative values work correctly. + " (Can’t use % with floats, and it’s truncated modulo anyway.) + let hh = hh < 0 ? hh - float2nr(hh) + 1 : hh - float2nr(hh) + " Now hh is in the range [0, 1), as required. " algorithm transcoded to vim from http://www.w3.org/TR/css3-color/#hsl-color - let hh = ( a:h % 360 ) / 360.0 let m2 = l <= 0.5 ? l * ( s + 1 ) : l + s - l * s let m1 = l * 2 - m2 let rgb = [] @@ -187,8 +201,8 @@ function! s:create_syn_match() let funcname = submatch(2) let rgb_color - \ = funcname == 'rgb' ? s:rgb2color(submatch(3),submatch(4),submatch(5)) - \ : funcname == 'hsl' ? s:hsl2color(submatch(3),submatch(4),submatch(5)) + \ = funcname == 'rgb' ? s:rgb2color(submatch(3),submatch(4),submatch(5),submatch(6),submatch(7),submatch(8)) + \ : funcname == 'hsl' ? s:hsl2color(submatch(3),submatch(4),submatch(5),submatch(6),submatch(7),submatch(8)) \ : strlen(hex) >= 6 ? tolower(hex[0:5]) \ : strlen(hex) >= 3 ? tolower(hex[0].hex[0].hex[1].hex[1].hex[2].hex[2]) \ : '' @@ -247,9 +261,9 @@ let s:_hexcolor = '#\(\x\{3}\%(\>\|\x\{3}\>\)\)' " submatch 1 let s:_rgbacolor = '#\(\x\{3}\%(\>\|\x\%(\>\|\x\{2}\%(\>\|\x\{2}\>\)\)\)\)' " submatch 1 let s:_funcname = '\(rgb\|hsl\)a\?' " submatch 2 let s:_ws_ = '\s*' -let s:_numval = s:_ws_ . '\(\d\{1,3}%\?\)' " submatch 3,4,5 -let s:_listsep = s:_ws_ . ',' -let s:_otherargs_ = '\%(,[^)]*\)\?' +let s:_numval = s:_ws_ . '\(-\?\%(\d\+\%(\.\d\+\)\?\|\.\d\+\)\)\(%\|deg\|grad\|rad\|turn\)\?' " submatch 3,4,5,6,7,8 +let s:_listsep = '\%(\s*,\|\s\+\)' +let s:_otherargs_ = '\%([,/][^)]*\)\?' let s:_funcexpr = s:_funcname . '[(]' . s:_numval . s:_listsep . s:_numval . s:_listsep . s:_numval . s:_ws_ . s:_otherargs_ . '[)]' let s:_csscolor = s:_rgbacolor . '\|' . s:_funcexpr " N.B. sloppy heuristic constants for performance reasons: diff --git a/tests/example.css b/tests/example.css index d420cbd..fd976f6 100644 --- a/tests/example.css +++ b/tests/example.css @@ -2,11 +2,13 @@ i { background: #359 } b { background: #335599 } u { background: rgba(144, 0, 0, .5) } s { background: hsl(0, 100%, 50%) } +a { background: hsl(-12.3rad 45.6% 78.9% / 01.2%) } *::color1 { -x-: #359 } *::color2 { -x-: #335599 } *::color3 { -x-: rgba(144, 0, 0, .5) } *::color4 { -x-: hsl(0, 100%, 50%) } +*::color5 { -x-: hsl(-12.3rad 45.6% 78.9% / 01.2%) } /* * #123, #456