dotfiles

My personal shell configs and stuff
git clone git://git.alex.balgavy.eu/dotfiles.git
Log | Files | Refs | Submodules | README | LICENSE

color.vim (7738B)


      1 " File: color.vim
      2 " Author: romgrk
      3 " Date: 15 Mar 2016
      4 " Description: vimscript RGB/HSL color parsing
      5 " This is mostly a transcript from a javascript color parsing module.
      6 " !::exe [so %]
      7 
      8 " Example:
      9 " Lighten/darken the color under the cursor with Alt-minus/Alt-equal
     10 
     11 " nnoremap <expr><M--> color#Test(expand('<cword>'))
     12             " \? '"_ciw' . color#Darken(expand('<cword>')) . "\<Esc>"
     13             " \: "\<Nop>"
     14 " nnoremap <expr><M-=> color#Test(expand('<cword>'))
     15             " \? '"_ciw' . color#Lighten(expand('<cword>')) . "\<Esc>"
     16             " \: "\<Nop>"
     17 
     18 " #00f6ff
     19 " #00a7cd
     20 " #007691
     21 
     22 
     23 " ================================================================================
     24 " Definitions: {{{1
     25 " In function names:
     26 "  • “Hex” refers to hexadecimal color format e.g. #599eff
     27 "  • “RGB” refers to an array of numbers [r, g, b]
     28 "                                      where   r,g,b ∈ [0, 255]
     29 "  • “HSL” refers to an array of floats  [h, s, l]
     30 "                                      where   h,s,l ∈ [0, 1.0]
     31 " }}}1
     32 " ================================================================================
     33 " Color-format patterns:
     34 " {{{1
     35 
     36 let s:patterns = {}
     37 
     38 " 6 hex-numbers, optionnal #-prefix
     39 let s:patterns['hex']      = '\v#?(\x{2})(\x{2})(\x{2})'
     40 
     41 " short version is strict: starting # mandatory
     42 let s:patterns['shortHex'] = '\v#(\x{1})(\x{1})(\x{1})'
     43 
     44 " Disabled
     45 "let s:patterns['rgb']  = '\vrgb\s*\((\d+)\s*,(\d+)\s*,(\d+)\s*)\s*'
     46 "let s:patterns['rgba'] = '\vrgba\s*\((\d+)\s*,(\d+)\s*,(\d+)\s*,(\d+)\s*)\s*'
     47 
     48 " }}}1
     49 " ================================================================================
     50 " Functions:
     51 " {{{1
     52 
     53 " @params  String       string   The string to test
     54 " @returns Boolean     [0 or 1]  if string matches: rrggbb OR #rrggbb OR #rgb
     55 fu! color#Test (string)
     56     for key in keys(s:patterns)
     57         if a:string =~# s:patterns[key]
     58             return 1
     59         end
     60     endfor
     61     return 0
     62 endfu
     63 
     64 " @params (r, g, b)
     65 " @params ([r, g, b])
     66 " @returns String           A RGB color
     67 fu! color#RGBtoHex (...)
     68     let [r, g, b] = ( a:0==1 ? a:1 : a:000 )
     69     let num = printf('%02x', float2nr(r)) . ''
     70           \ . printf('%02x', float2nr(g)) . ''
     71           \ . printf('%02x', float2nr(b)) . ''
     72     return '#' . num
     73 endfu
     74 
     75 " @param {String|Number} color   The color to parse
     76 fu! color#HexToRGB (color)
     77     if type(a:color) == 2
     78         let color = printf('%x', a:color)
     79     else
     80         let color = a:color | end
     81 
     82     let matches = matchlist(color, s:patterns['hex'])
     83     let factor  = 0x1
     84 
     85     if empty(matches)
     86         let matches = matchlist(color, s:patterns['shortHex'])
     87         let factor  = 0x10
     88     end
     89 
     90     if len(matches) < 4
     91         throw 'Couldnt parse ' . string(color) . ' ' .  string(matches)
     92     end
     93 
     94     let r = str2nr(matches[1], 16) * factor
     95     let g = str2nr(matches[2], 16) * factor
     96     let b = str2nr(matches[3], 16) * factor
     97 
     98     return [r, g, b]
     99 endfu
    100 
    101 
    102 " Converts an HSL color value to RGB. Conversion formula
    103 " adapted from http://en.wikipedia.org/wiki/HSL_color_space.
    104 " Assumes h, s, and l are contained in the set [0, 1] and
    105 " returns r, g, and b in the set [0, 255].
    106 " @param   Number  h     OR     @param  Array [h, s, l]
    107 " @param   Number  s
    108 " @param   Number  l
    109 " @returns Array [r, g, b]     The RGB representation
    110 fu! color#HSLtoRGB(...) " (h, s, l)
    111     let [h, s, l] = ( a:0==1 ? a:1 : a:000 )
    112 
    113     if (s == 0.0) " achromatic
    114         let r = l
    115         let g = l
    116         let b = l
    117     else
    118         let q = l < 0.5 ? l * (1 + s) : l + s - l * s
    119         let p = 2 * l - q
    120         let r = color#Hue2RGB(p, q, h + 0.33333)
    121         let g = color#Hue2RGB(p, q, h)
    122         let b = color#Hue2RGB(p, q, h - 0.33333)
    123     end
    124 
    125     return [r * 255.0, g * 255.0, b * 255.0]
    126 endfu
    127 
    128 
    129 " @param   Number  r     OR     @param  Array [r, g, b]
    130 " @param   Number  g
    131 " @param   Number  b
    132 " @returns Array [h, s, l]     The HSL representation
    133 fu! color#RGBtoHSL(...)
    134     let [r, g, b] = ( a:0==1 ? a:1 : a:000 )
    135     let max = max([r, g, b])
    136     let min = min([r, g, b])
    137 
    138     let r   = str2float(r)
    139     let g   = str2float(g)
    140     let b   = str2float(b)
    141     let max = str2float(max)
    142     let min = str2float(min)
    143 
    144     let max = max / 255
    145     let min = min / 255
    146     let r = r / 255
    147     let g = g / 255
    148     let b = b / 255
    149     let h = str2float(0)
    150     let s = str2float(0)
    151     let l = (max + min) / 2
    152 
    153     if (max == min)
    154         let h = 0   " achromatic
    155         let s = 0   " achromatic
    156     else
    157         let d = max - min
    158         let s = (l > 0.5 ? d / (2 - max - min)
    159                        \ : d / (max + min)     )
    160         if (max == r)
    161             let h = (g - b) / d + (g < b ? 6 : 0)
    162         end
    163         if (max == g)
    164             let h = (b - r) / d + 2
    165         end
    166         if (max == b)
    167             let h = (r - g) / d + 4
    168         end
    169         let h = h / 6
    170     end
    171 
    172     return [h, s, l]
    173 endfu
    174 
    175 fu! color#Hue2RGB(...) " (p, q, t)
    176     let [p, q, t] = ( a:0==1 ? a:1 : a:000 )
    177 
    178     if(t < 0) | let t += 1 | end
    179     if(t > 1) | let t -= 1 | end
    180 
    181     if(t < 1.0/6) | return (p + (q - p) * 6.0 * t)           | end
    182     if(t < 1.0/2) | return (q)                               | end
    183     if(t < 2.0/3) | return (p + (q - p) * (2.0/3 - t) * 6.0) | end
    184 
    185     return p
    186 endfu
    187 
    188 " }}}1
    189 " ================================================================================
    190 " Composed functions:
    191 " {{{1
    192 
    193 fu! color#HexToHSL (color)
    194     let [r, g, b] = color#HexToRGB(a:color)
    195     return color#RGBtoHSL(r, g, b)
    196 endfu
    197 
    198 fu! color#HSLtoHex (...)
    199     let [h, s, l] = ( a:0==1 ? a:1 : a:000 )
    200     let [r, g, b] = color#HSLtoRGB(h, s, l)
    201     return color#RGBtoHex(r, g, b)
    202 endfu
    203 
    204 " @params String                 color      The color
    205 " @params {Number|String|Float} [amount=5]  The percentage of light
    206 fu! color#Lighten(color, ...)
    207     let amount = a:0 ?
    208                 \(type(a:1) < 2 ?
    209                     \str2float(a:1) : a:1 )
    210                 \: 5.0
    211 
    212     if(amount < 1.0)
    213         let amount = 1.0 + amount
    214     else
    215         let amount = 1.0 + (amount / 100.0)
    216     end
    217 
    218     let rgb = color#HexToRGB(a:color)
    219     let rgb = map(rgb, 'v:val * amount')
    220     let rgb = map(rgb, 'v:val > 255.0 ? 255.0 : v:val')
    221     let rgb = map(rgb, 'float2nr(v:val)')
    222     let hex = color#RGBtoHex(rgb)
    223     return hex
    224 endfu
    225 
    226 " @params String                 color      The color
    227 " @params {Number|String|Float} [amount=5]  The percentage of darkness
    228 fu! color#Darken(color, ...)
    229     let amount = a:0 ?
    230                 \(type(a:1) < 2 ?
    231                     \str2float(a:1) : a:1 )
    232                 \: 5.0
    233 
    234     if(amount < 1.0)
    235         let amount = 1.0 - amount
    236     else
    237         let amount = 1.0 - (amount / 100.0)
    238     end
    239 
    240     if(amount < 0.0)
    241         let amount = 0.0 | end
    242 
    243 
    244     let rgb = color#HexToRGB(a:color)
    245     let rgb = map(rgb, 'v:val * amount')
    246     let rgb = map(rgb, 'v:val > 255.0 ? 255.0 : v:val')
    247     let rgb = map(rgb, 'float2nr(v:val)')
    248     let hex = color#RGBtoHex(rgb)
    249     return hex
    250 endfu
    251 
    252 function! color#Decrease (...)
    253     if &background == 'light'
    254         return call(function('color#Lighten'), a:000)
    255     end
    256     return call(function('color#Darken'), a:000)
    257 endfunc
    258 
    259 function! color#Increase (...)
    260     if &background == 'light'
    261         return call(function('color#Darken'), a:000)
    262     end
    263     return call(function('color#Lighten'), a:000)
    264 endfunc
    265 
    266 function! color#Mix (a, b, ...)
    267     let amount = a:0 ? a:1 : 0.5
    268 
    269     let ca = color#HexToRGB(a:a)
    270     let cb = color#HexToRGB(a:b)
    271 
    272     let r = s:interpolate(ca[0], cb[0], amount)
    273     let g = s:interpolate(ca[1], cb[1], amount)
    274     let b = s:interpolate(ca[2], cb[2], amount)
    275 
    276     return color#RGBtoHex([r, g, b])
    277 endfunc
    278 
    279 function! s:interpolate (start, end, amount)
    280     let diff = a:end - a:start
    281     return a:start + (diff * a:amount)
    282 endfunc
    283 
    284 " }}}1
    285