vim-schemer

Vim plugin to make writing colorschemes easier by providing a clean slate, and using a simpler/more readable syntax.
git clone git://git.alex.balgavy.eu:vim-schemer.git
Log | Files | Refs | README | LICENSE

schemer.vim (84096B)


      1 if exists('g:loaded_schemer_autoload')
      2   finish
      3 endif
      4 let g:loaded_schemer_autoload = 1
      5 
      6 " Color functions from https://github.com/chrisbra/Colorizer
      7 " the 6 value iterations in the xterm color cube
      8 let s:valuerange6 = [ 0x00, 0x5F, 0x87, 0xAF, 0xD7, 0xFF ]
      9 
     10 "" the 4 value iterations in the 88 color xterm cube
     11 let s:valuerange4 = [ 0x00, 0x8B, 0xCD, 0xFF ]
     12 "
     13 "" 16 basic colors
     14 let s:basic16 = [
     15       \ [ 0x00, 0x00, 0x00 ],
     16       \ [ 0xCD, 0x00, 0x00 ],
     17       \ [ 0x00, 0xCD, 0x00 ],
     18       \ [ 0xCD, 0xCD, 0x00 ],
     19       \ [ 0x00, 0x00, 0xEE ],
     20       \ [ 0xCD, 0x00, 0xCD ],
     21       \ [ 0x00, 0xCD, 0xCD ],
     22       \ [ 0xE5, 0xE5, 0xE5 ],
     23       \ [ 0x7F, 0x7F, 0x7F ],
     24       \ [ 0xFF, 0x00, 0x00 ],
     25       \ [ 0x00, 0xFF, 0x00 ],
     26       \ [ 0xFF, 0xFF, 0x00 ],
     27       \ [ 0x5C, 0x5C, 0xFF ],
     28       \ [ 0xFF, 0x00, 0xFF ],
     29       \ [ 0x00, 0xFF, 0xFF ],
     30       \ [ 0xFF, 0xFF, 0xFF ]
     31       \ ]
     32 
     33 " Cygwin / Window console / ConEmu has different color codes
     34 if ($ComSpec =~# '^\%(command\.com\|cmd\.exe\)$' &&
     35       \ !s:HasGui()) ||
     36       \ (exists("$ConEmuPID") &&
     37       \ $ConEmuANSI ==# "OFF") ||
     38       \ ($TERM ==# 'cygwin' && &t_Co == 16)  " Cygwin terminal
     39 
     40   " command.com/ConEmu Color Cube (currently only supports 16 colors)
     41   let s:basic16 = [
     42         \ [ 0x00, 0x00, 0x00 ],
     43         \ [ 0x00, 0x00, 0x80 ],
     44         \ [ 0x00, 0x80, 0x00 ],
     45         \ [ 0x00, 0x80, 0x80 ],
     46         \ [ 0x80, 0x00, 0x00 ],
     47         \ [ 0x80, 0x00, 0x80 ],
     48         \ [ 0xFF, 0xFF, 0x00 ],
     49         \ [ 0xFF, 0xFF, 0xFF ],
     50         \ [ 0xC0, 0xC0, 0xC0 ],
     51         \ [ 0x00, 0x00, 0xFF ],
     52         \ [ 0x00, 0xFF, 0x00 ],
     53         \ [ 0x00, 0xFF, 0xFF ],
     54         \ [ 0xFF, 0x00, 0x00 ],
     55         \ [ 0xFF, 0x00, 0xFF ],
     56         \ [ 0xFF, 0xFF, 0x00 ],
     57         \ [ 0xFF, 0xFF, 0xFF ]
     58         \ ]
     59   let &t_Co=16
     60 endif
     61 
     62 " xterm-8 colors
     63 let s:xterm_8colors = {
     64       \ 'black':          '#000000',
     65       \ 'darkblue':       '#00008B',
     66       \ 'darkgreen':      '#00CD00',
     67       \ 'darkcyan':       '#00CDCD',
     68       \ 'darkred':        '#CD0000',
     69       \ 'darkmagenta':    '#8B008B',
     70       \ 'brown':          '#CDCD00',
     71       \ 'darkyellow':     '#CDCD00',
     72       \ 'lightgrey':      '#E5E5E5',
     73       \ 'lightgray':      '#E5E5E5',
     74       \ 'gray':           '#E5E5E5',
     75       \ 'grey':           '#E5E5E5'
     76       \ }
     77 
     78 " xterm-16 colors
     79 let s:xterm_16colors = {
     80       \ 'darkgrey':       '#7F7F7F',
     81       \ 'darkgray':       '#7F7F7F',
     82       \ 'blue':           '#5C5CFF',
     83       \ 'lightblue':      '#5C5CFF',
     84       \ 'green':          '#00FF00',
     85       \ 'lightgreen':     '#00FF00',
     86       \ 'cyan':           '#00FFFF',
     87       \ 'lightcyan':      '#00FFFF',
     88       \ 'red':            '#FF0000',
     89       \ 'lightred':       '#FF0000',
     90       \ 'magenta':        '#FF00FF',
     91       \ 'lightmagenta':   '#FF00FF',
     92       \ 'yellow':         '#FFFF00',
     93       \ 'lightyellow':    '#FFFF00',
     94       \ 'white':          '#FFFFFF',
     95       \ }
     96 " add the items from the 8 color xterm variable to the 16 color xterm
     97 call extend(s:xterm_16colors, s:xterm_8colors)
     98 
     99 " W3C Colors
    100 let s:w3c_color_names = {
    101       \ 'aliceblue': '#F0F8FF',
    102       \ 'antiquewhite': '#FAEBD7',
    103       \ 'aqua': '#00FFFF',
    104       \ 'aquamarine': '#7FFFD4',
    105       \ 'azure': '#F0FFFF',
    106       \ 'beige': '#F5F5DC',
    107       \ 'bisque': '#FFE4C4',
    108       \ 'black': '#000000',
    109       \ 'blanchedalmond': '#FFEBCD',
    110       \ 'blue': '#0000FF',
    111       \ 'blueviolet': '#8A2BE2',
    112       \ 'brown': '#A52A2A',
    113       \ 'burlywood': '#DEB887',
    114       \ 'cadetblue': '#5F9EA0',
    115       \ 'chartreuse': '#7FFF00',
    116       \ 'chocolate': '#D2691E',
    117       \ 'coral': '#FF7F50',
    118       \ 'cornflowerblue': '#6495ED',
    119       \ 'cornsilk': '#FFF8DC',
    120       \ 'crimson': '#DC143C',
    121       \ 'cyan': '#00FFFF',
    122       \ 'darkblue': '#00008B',
    123       \ 'darkcyan': '#008B8B',
    124       \ 'darkgoldenrod': '#B8860B',
    125       \ 'darkgray': '#A9A9A9',
    126       \ 'darkgreen': '#006400',
    127       \ 'darkkhaki': '#BDB76B',
    128       \ 'darkmagenta': '#8B008B',
    129       \ 'darkolivegreen': '#556B2F',
    130       \ 'darkorange': '#FF8C00',
    131       \ 'darkorchid': '#9932CC',
    132       \ 'darkred': '#8B0000',
    133       \ 'darksalmon': '#E9967A',
    134       \ 'darkseagreen': '#8FBC8F',
    135       \ 'darkslateblue': '#483D8B',
    136       \ 'darkslategray': '#2F4F4F',
    137       \ 'darkturquoise': '#00CED1',
    138       \ 'darkviolet': '#9400D3',
    139       \ 'deeppink': '#FF1493',
    140       \ 'deepskyblue': '#00BFFF',
    141       \ 'dimgray': '#696969',
    142       \ 'dodgerblue': '#1E90FF',
    143       \ 'firebrick': '#B22222',
    144       \ 'floralwhite': '#FFFAF0',
    145       \ 'forestgreen': '#228B22',
    146       \ 'fuchsia': '#FF00FF',
    147       \ 'gainsboro': '#DCDCDC',
    148       \ 'ghostwhite': '#F8F8FF',
    149       \ 'gold': '#FFD700',
    150       \ 'goldenrod': '#DAA520',
    151       \ 'gray': '#808080',
    152       \ 'green': '#008000',
    153       \ 'greenyellow': '#ADFF2F',
    154       \ 'honeydew': '#F0FFF0',
    155       \ 'hotpink': '#FF69B4',
    156       \ 'indianred': '#CD5C5C',
    157       \ 'indigo': '#4B0082',
    158       \ 'ivory': '#FFFFF0',
    159       \ 'khaki': '#F0E68C',
    160       \ 'lavender': '#E6E6FA',
    161       \ 'lavenderblush': '#FFF0F5',
    162       \ 'lawngreen': '#7CFC00',
    163       \ 'lemonchiffon': '#FFFACD',
    164       \ 'lightblue': '#ADD8E6',
    165       \ 'lightcoral': '#F08080',
    166       \ 'lightcyan': '#E0FFFF',
    167       \ 'lightgoldenrodyellow': '#FAFAD2',
    168       \ 'lightgray': '#D3D3D3',
    169       \ 'lightgreen': '#90EE90',
    170       \ 'lightpink': '#FFB6C1',
    171       \ 'lightsalmon': '#FFA07A',
    172       \ 'lightseagreen': '#20B2AA',
    173       \ 'lightskyblue': '#87CEFA',
    174       \ 'lightslategray': '#778899',
    175       \ 'lightsteelblue': '#B0C4DE',
    176       \ 'lightyellow': '#FFFFE0',
    177       \ 'lime': '#00FF00',
    178       \ 'limegreen': '#32CD32',
    179       \ 'linen': '#FAF0E6',
    180       \ 'magenta': '#FF00FF',
    181       \ 'maroon': '#800000',
    182       \ 'mediumaquamarine': '#66CDAA',
    183       \ 'mediumblue': '#0000CD',
    184       \ 'mediumorchid': '#BA55D3',
    185       \ 'mediumpurple': '#9370D8',
    186       \ 'mediumseagreen': '#3CB371',
    187       \ 'mediumslateblue': '#7B68EE',
    188       \ 'mediumspringgreen': '#00FA9A',
    189       \ 'mediumturquoise': '#48D1CC',
    190       \ 'mediumvioletred': '#C71585',
    191       \ 'midnightblue': '#191970',
    192       \ 'mintcream': '#F5FFFA',
    193       \ 'mistyrose': '#FFE4E1',
    194       \ 'moccasin': '#FFE4B5',
    195       \ 'navajowhite': '#FFDEAD',
    196       \ 'navy': '#000080',
    197       \ 'oldlace': '#FDF5E6',
    198       \ 'olive': '#808000',
    199       \ 'olivedrab': '#6B8E23',
    200       \ 'orange': '#FFA500',
    201       \ 'orangered': '#FF4500',
    202       \ 'orchid': '#DA70D6',
    203       \ 'palegoldenrod': '#EEE8AA',
    204       \ 'palegreen': '#98FB98',
    205       \ 'paleturquoise': '#AFEEEE',
    206       \ 'palevioletred': '#D87093',
    207       \ 'papayawhip': '#FFEFD5',
    208       \ 'peachpuff': '#FFDAB9',
    209       \ 'peru': '#CD853F',
    210       \ 'pink': '#FFC0CB',
    211       \ 'plum': '#DDA0DD',
    212       \ 'powderblue': '#B0E0E6',
    213       \ 'purple': '#800080',
    214       \ 'red': '#FF0000',
    215       \ 'rosybrown': '#BC8F8F',
    216       \ 'royalblue': '#4169E1',
    217       \ 'saddlebrown': '#8B4513',
    218       \ 'salmon': '#FA8072',
    219       \ 'sandybrown': '#F4A460',
    220       \ 'seagreen': '#2E8B57',
    221       \ 'seashell': '#FFF5EE',
    222       \ 'sienna': '#A0522D',
    223       \ 'silver': '#C0C0C0',
    224       \ 'skyblue': '#87CEEB',
    225       \ 'slateblue': '#6A5ACD',
    226       \ 'slategray': '#708090',
    227       \ 'snow': '#FFFAFA',
    228       \ 'springgreen': '#00FF7F',
    229       \ 'steelblue': '#4682B4',
    230       \ 'tan': '#D2B48C',
    231       \ 'teal': '#008080',
    232       \ 'thistle': '#D8BFD8',
    233       \ 'tomato': '#FF6347',
    234       \ 'turquoise': '#40E0D0',
    235       \ 'violet': '#EE82EE',
    236       \ 'wheat': '#F5DEB3',
    237       \ 'white': '#FFFFFF',
    238       \ 'whitesmoke': '#F5F5F5',
    239       \ 'yellow': '#FFFF00',
    240       \ 'yellowgreen': '#9ACD32'
    241       \ }
    242 
    243 " X11 color names taken from
    244 " http://cvsweb.xfree86.org/cvsweb/*checkout*/xc/programs/rgb/rgb.txt?rev=1.2
    245 let s:x11_color_names = {
    246       \ 'snow': '#FFFAFA',
    247       \ 'ghostwhite': '#F8F8FF',
    248       \ 'whitesmoke': '#F5F5F5',
    249       \ 'gainsboro': '#DCDCDC',
    250       \ 'floralwhite': '#FFFAF0',
    251       \ 'oldlace': '#FDF5E6',
    252       \ 'linen': '#FAF0E6',
    253       \ 'antiquewhite': '#FAEBD7',
    254       \ 'papayawhip': '#FFEFD5',
    255       \ 'blanchedalmond': '#FFEBCD',
    256       \ 'bisque': '#FFE4C4',
    257       \ 'peachpuff': '#FFDAB9',
    258       \ 'navajowhite': '#FFDEAD',
    259       \ 'moccasin': '#FFE4B5',
    260       \ 'cornsilk': '#FFF8DC',
    261       \ 'ivory': '#FFFFF0',
    262       \ 'lemonchiffon': '#FFFACD',
    263       \ 'seashell': '#FFF5EE',
    264       \ 'honeydew': '#F0FFF0',
    265       \ 'mintcream': '#F5FFFA',
    266       \ 'azure': '#F0FFFF',
    267       \ 'aliceblue': '#F0F8FF',
    268       \ 'lavender': '#E6E6FA',
    269       \ 'lavenderblush': '#FFF0F5',
    270       \ 'mistyrose': '#FFE4E1',
    271       \ 'white': '#FFFFFF',
    272       \ 'black': '#000000',
    273       \ 'darkslategray': '#2F4F4F',
    274       \ 'darkslategrey': '#2F4F4F',
    275       \ 'dimgray': '#696969',
    276       \ 'dimgrey': '#696969',
    277       \ 'slategray': '#708090',
    278       \ 'slategrey': '#708090',
    279       \ 'lightslategray': '#778899',
    280       \ 'lightslategrey': '#778899',
    281       \ 'gray': '#BEBEBE',
    282       \ 'grey': '#BEBEBE',
    283       \ 'lightgrey': '#D3D3D3',
    284       \ 'lightgray': '#D3D3D3',
    285       \ 'midnightblue': '#191970',
    286       \ 'navy': '#000080',
    287       \ 'navyblue': '#000080',
    288       \ 'cornflowerblue': '#6495ED',
    289       \ 'darkslateblue': '#483D8B',
    290       \ 'slateblue': '#6A5ACD',
    291       \ 'mediumslateblue': '#7B68EE',
    292       \ 'lightslateblue': '#8470FF',
    293       \ 'mediumblue': '#0000CD',
    294       \ 'royalblue': '#4169E1',
    295       \ 'blue': '#0000FF',
    296       \ 'dodgerblue': '#1E90FF',
    297       \ 'deepskyblue': '#00BFFF',
    298       \ 'skyblue': '#87CEEB',
    299       \ 'lightskyblue': '#87CEFA',
    300       \ 'steelblue': '#4682B4',
    301       \ 'lightsteelblue': '#B0C4DE',
    302       \ 'lightblue': '#ADD8E6',
    303       \ 'powderblue': '#B0E0E6',
    304       \ 'paleturquoise': '#AFEEEE',
    305       \ 'darkturquoise': '#00CED1',
    306       \ 'mediumturquoise': '#48D1CC',
    307       \ 'turquoise': '#40E0D0',
    308       \ 'cyan': '#00FFFF',
    309       \ 'lightcyan': '#E0FFFF',
    310       \ 'cadetblue': '#5F9EA0',
    311       \ 'mediumaquamarine': '#66CDAA',
    312       \ 'aquamarine': '#7FFFD4',
    313       \ 'darkgreen': '#006400',
    314       \ 'darkolivegreen': '#556B2F',
    315       \ 'darkseagreen': '#8FBC8F',
    316       \ 'seagreen': '#2E8B57',
    317       \ 'mediumseagreen': '#3CB371',
    318       \ 'lightseagreen': '#20B2AA',
    319       \ 'palegreen': '#98FB98',
    320       \ 'springgreen': '#00FF7F',
    321       \ 'lawngreen': '#7CFC00',
    322       \ 'green': '#00FF00',
    323       \ 'chartreuse': '#7FFF00',
    324       \ 'mediumspringgreen': '#00FA9A',
    325       \ 'greenyellow': '#ADFF2F',
    326       \ 'limegreen': '#32CD32',
    327       \ 'yellowgreen': '#9ACD32',
    328       \ 'forestgreen': '#228B22',
    329       \ 'olivedrab': '#6B8E23',
    330       \ 'darkkhaki': '#BDB76B',
    331       \ 'khaki': '#F0E68C',
    332       \ 'palegoldenrod': '#EEE8AA',
    333       \ 'lightgoldenrodyellow': '#FAFAD2',
    334       \ 'lightyellow': '#FFFFE0',
    335       \ 'yellow': '#FFFF00',
    336       \ 'gold': '#FFD700',
    337       \ 'lightgoldenrod': '#EEDD82',
    338       \ 'goldenrod': '#DAA520',
    339       \ 'darkgoldenrod': '#B8860B',
    340       \ 'rosybrown': '#BC8F8F',
    341       \ 'indianred': '#CD5C5C',
    342       \ 'saddlebrown': '#8B4513',
    343       \ 'sienna': '#A0522D',
    344       \ 'peru': '#CD853F',
    345       \ 'burlywood': '#DEB887',
    346       \ 'beige': '#F5F5DC',
    347       \ 'wheat': '#F5DEB3',
    348       \ 'sandybrown': '#F4A460',
    349       \ 'tan': '#D2B48C',
    350       \ 'chocolate': '#D2691E',
    351       \ 'firebrick': '#B22222',
    352       \ 'brown': '#A52A2A',
    353       \ 'darksalmon': '#E9967A',
    354       \ 'salmon': '#FA8072',
    355       \ 'lightsalmon': '#FFA07A',
    356       \ 'orange': '#FFA500',
    357       \ 'darkorange': '#FF8C00',
    358       \ 'coral': '#FF7F50',
    359       \ 'lightcoral': '#F08080',
    360       \ 'tomato': '#FF6347',
    361       \ 'orangered': '#FF4500',
    362       \ 'red': '#FF0000',
    363       \ 'hotpink': '#FF69B4',
    364       \ 'deeppink': '#FF1493',
    365       \ 'pink': '#FFC0CB',
    366       \ 'lightpink': '#FFB6C1',
    367       \ 'palevioletred': '#DB7093',
    368       \ 'maroon': '#B03060',
    369       \ 'mediumvioletred': '#C71585',
    370       \ 'violetred': '#D02090',
    371       \ 'magenta': '#FF00FF',
    372       \ 'violet': '#EE82EE',
    373       \ 'plum': '#DDA0DD',
    374       \ 'orchid': '#DA70D6',
    375       \ 'mediumorchid': '#BA55D3',
    376       \ 'darkorchid': '#9932CC',
    377       \ 'darkviolet': '#9400D3',
    378       \ 'blueviolet': '#8A2BE2',
    379       \ 'purple': '#A020F0',
    380       \ 'mediumpurple': '#9370DB',
    381       \ 'thistle': '#D8BFD8',
    382       \ 'snow1': '#FFFAFA',
    383       \ 'snow2': '#EEE9E9',
    384       \ 'snow3': '#CDC9C9',
    385       \ 'snow4': '#8B8989',
    386       \ 'seashell1': '#FFF5EE',
    387       \ 'seashell2': '#EEE5DE',
    388       \ 'seashell3': '#CDC5BF',
    389       \ 'seashell4': '#8B8682',
    390       \ 'antiquewhite1': '#FFEFDB',
    391       \ 'antiquewhite2': '#EEDFCC',
    392       \ 'antiquewhite3': '#CDC0B0',
    393       \ 'antiquewhite4': '#8B8378',
    394       \ 'bisque1': '#FFE4C4',
    395       \ 'bisque2': '#EED5B7',
    396       \ 'bisque3': '#CDB79E',
    397       \ 'bisque4': '#8B7D6B',
    398       \ 'peachpuff1': '#FFDAB9',
    399       \ 'peachpuff2': '#EECBAD',
    400       \ 'peachpuff3': '#CDAF95',
    401       \ 'peachpuff4': '#8B7765',
    402       \ 'navajowhite1': '#FFDEAD',
    403       \ 'navajowhite2': '#EECFA1',
    404       \ 'navajowhite3': '#CDB38B',
    405       \ 'navajowhite4': '#8B795E',
    406       \ 'lemonchiffon1': '#FFFACD',
    407       \ 'lemonchiffon2': '#EEE9BF',
    408       \ 'lemonchiffon3': '#CDC9A5',
    409       \ 'lemonchiffon4': '#8B8970',
    410       \ 'cornsilk1': '#FFF8DC',
    411       \ 'cornsilk2': '#EEE8CD',
    412       \ 'cornsilk3': '#CDC8B1',
    413       \ 'cornsilk4': '#8B8878',
    414       \ 'ivory1': '#FFFFF0',
    415       \ 'ivory2': '#EEEEE0',
    416       \ 'ivory3': '#CDCDC1',
    417       \ 'ivory4': '#8B8B83',
    418       \ 'honeydew1': '#F0FFF0',
    419       \ 'honeydew2': '#E0EEE0',
    420       \ 'honeydew3': '#C1CDC1',
    421       \ 'honeydew4': '#838B83',
    422       \ 'lavenderblush1': '#FFF0F5',
    423       \ 'lavenderblush2': '#EEE0E5',
    424       \ 'lavenderblush3': '#CDC1C5',
    425       \ 'lavenderblush4': '#8B8386',
    426       \ 'mistyrose1': '#FFE4E1',
    427       \ 'mistyrose2': '#EED5D2',
    428       \ 'mistyrose3': '#CDB7B5',
    429       \ 'mistyrose4': '#8B7D7B',
    430       \ 'azure1': '#F0FFFF',
    431       \ 'azure2': '#E0EEEE',
    432       \ 'azure3': '#C1CDCD',
    433       \ 'azure4': '#838B8B',
    434       \ 'slateblue1': '#836FFF',
    435       \ 'slateblue2': '#7A67EE',
    436       \ 'slateblue3': '#6959CD',
    437       \ 'slateblue4': '#473C8B',
    438       \ 'royalblue1': '#4876FF',
    439       \ 'royalblue2': '#436EEE',
    440       \ 'royalblue3': '#3A5FCD',
    441       \ 'royalblue4': '#27408B',
    442       \ 'blue1': '#0000FF',
    443       \ 'blue2': '#0000EE',
    444       \ 'blue3': '#0000CD',
    445       \ 'blue4': '#00008B',
    446       \ 'dodgerblue1': '#1E90FF',
    447       \ 'dodgerblue2': '#1C86EE',
    448       \ 'dodgerblue3': '#1874CD',
    449       \ 'dodgerblue4': '#104E8B',
    450       \ 'steelblue1': '#63B8FF',
    451       \ 'steelblue2': '#5CACEE',
    452       \ 'steelblue3': '#4F94CD',
    453       \ 'steelblue4': '#36648B',
    454       \ 'deepskyblue1': '#00BFFF',
    455       \ 'deepskyblue2': '#00B2EE',
    456       \ 'deepskyblue3': '#009ACD',
    457       \ 'deepskyblue4': '#00688B',
    458       \ 'skyblue1': '#87CEFF',
    459       \ 'skyblue2': '#7EC0EE',
    460       \ 'skyblue3': '#6CA6CD',
    461       \ 'skyblue4': '#4A708B',
    462       \ 'lightskyblue1': '#B0E2FF',
    463       \ 'lightskyblue2': '#A4D3EE',
    464       \ 'lightskyblue3': '#8DB6CD',
    465       \ 'lightskyblue4': '#607B8B',
    466       \ 'slategray1': '#C6E2FF',
    467       \ 'slategray2': '#B9D3EE',
    468       \ 'slategray3': '#9FB6CD',
    469       \ 'slategray4': '#6C7B8B',
    470       \ 'lightsteelblue1': '#CAE1FF',
    471       \ 'lightsteelblue2': '#BCD2EE',
    472       \ 'lightsteelblue3': '#A2B5CD',
    473       \ 'lightsteelblue4': '#6E7B8B',
    474       \ 'lightblue1': '#BFEFFF',
    475       \ 'lightblue2': '#B2DFEE',
    476       \ 'lightblue3': '#9AC0CD',
    477       \ 'lightblue4': '#68838B',
    478       \ 'lightcyan1': '#E0FFFF',
    479       \ 'lightcyan2': '#D1EEEE',
    480       \ 'lightcyan3': '#B4CDCD',
    481       \ 'lightcyan4': '#7A8B8B',
    482       \ 'paleturquoise1': '#BBFFFF',
    483       \ 'paleturquoise2': '#AEEEEE',
    484       \ 'paleturquoise3': '#96CDCD',
    485       \ 'paleturquoise4': '#668B8B',
    486       \ 'cadetblue1': '#98F5FF',
    487       \ 'cadetblue2': '#8EE5EE',
    488       \ 'cadetblue3': '#7AC5CD',
    489       \ 'cadetblue4': '#53868B',
    490       \ 'turquoise1': '#00F5FF',
    491       \ 'turquoise2': '#00E5EE',
    492       \ 'turquoise3': '#00C5CD',
    493       \ 'turquoise4': '#00868B',
    494       \ 'cyan1': '#00FFFF',
    495       \ 'cyan2': '#00EEEE',
    496       \ 'cyan3': '#00CDCD',
    497       \ 'cyan4': '#008B8B',
    498       \ 'darkslategray1': '#97FFFF',
    499       \ 'darkslategray2': '#8DEEEE',
    500       \ 'darkslategray3': '#79CDCD',
    501       \ 'darkslategray4': '#528B8B',
    502       \ 'aquamarine1': '#7FFFD4',
    503       \ 'aquamarine2': '#76EEC6',
    504       \ 'aquamarine3': '#66CDAA',
    505       \ 'aquamarine4': '#458B74',
    506       \ 'darkseagreen1': '#C1FFC1',
    507       \ 'darkseagreen2': '#B4EEB4',
    508       \ 'darkseagreen3': '#9BCD9B',
    509       \ 'darkseagreen4': '#698B69',
    510       \ 'seagreen1': '#54FF9F',
    511       \ 'seagreen2': '#4EEE94',
    512       \ 'seagreen3': '#43CD80',
    513       \ 'seagreen4': '#2E8B57',
    514       \ 'palegreen1': '#9AFF9A',
    515       \ 'palegreen2': '#90EE90',
    516       \ 'palegreen3': '#7CCD7C',
    517       \ 'palegreen4': '#548B54',
    518       \ 'springgreen1': '#00FF7F',
    519       \ 'springgreen2': '#00EE76',
    520       \ 'springgreen3': '#00CD66',
    521       \ 'springgreen4': '#008B45',
    522       \ 'green1': '#00FF00',
    523       \ 'green2': '#00EE00',
    524       \ 'green3': '#00CD00',
    525       \ 'green4': '#008B00',
    526       \ 'chartreuse1': '#7FFF00',
    527       \ 'chartreuse2': '#76EE00',
    528       \ 'chartreuse3': '#66CD00',
    529       \ 'chartreuse4': '#458B00',
    530       \ 'olivedrab1': '#C0FF3E',
    531       \ 'olivedrab2': '#B3EE3A',
    532       \ 'olivedrab3': '#9ACD32',
    533       \ 'olivedrab4': '#698B22',
    534       \ 'darkolivegreen1': '#CAFF70',
    535       \ 'darkolivegreen2': '#BCEE68',
    536       \ 'darkolivegreen3': '#A2CD5A',
    537       \ 'darkolivegreen4': '#6E8B3D',
    538       \ 'khaki1': '#FFF68F',
    539       \ 'khaki2': '#EEE685',
    540       \ 'khaki3': '#CDC673',
    541       \ 'khaki4': '#8B864E',
    542       \ 'lightgoldenrod1': '#FFEC8B',
    543       \ 'lightgoldenrod2': '#EEDC82',
    544       \ 'lightgoldenrod3': '#CDBE70',
    545       \ 'lightgoldenrod4': '#8B814C',
    546       \ 'lightyellow1': '#FFFFE0',
    547       \ 'lightyellow2': '#EEEED1',
    548       \ 'lightyellow3': '#CDCDB4',
    549       \ 'lightyellow4': '#8B8B7A',
    550       \ 'yellow1': '#FFFF00',
    551       \ 'yellow2': '#EEEE00',
    552       \ 'yellow3': '#CDCD00',
    553       \ 'yellow4': '#8B8B00',
    554       \ 'gold1': '#FFD700',
    555       \ 'gold2': '#EEC900',
    556       \ 'gold3': '#CDAD00',
    557       \ 'gold4': '#8B7500',
    558       \ 'goldenrod1': '#FFC125',
    559       \ 'goldenrod2': '#EEB422',
    560       \ 'goldenrod3': '#CD9B1D',
    561       \ 'goldenrod4': '#8B6914',
    562       \ 'darkgoldenrod1': '#FFB90F',
    563       \ 'darkgoldenrod2': '#EEAD0E',
    564       \ 'darkgoldenrod3': '#CD950C',
    565       \ 'darkgoldenrod4': '#8B6508',
    566       \ 'rosybrown1': '#FFC1C1',
    567       \ 'rosybrown2': '#EEB4B4',
    568       \ 'rosybrown3': '#CD9B9B',
    569       \ 'rosybrown4': '#8B6969',
    570       \ 'indianred1': '#FF6A6A',
    571       \ 'indianred2': '#EE6363',
    572       \ 'indianred3': '#CD5555',
    573       \ 'indianred4': '#8B3A3A',
    574       \ 'sienna1': '#FF8247',
    575       \ 'sienna2': '#EE7942',
    576       \ 'sienna3': '#CD6839',
    577       \ 'sienna4': '#8B4726',
    578       \ 'burlywood1': '#FFD39B',
    579       \ 'burlywood2': '#EEC591',
    580       \ 'burlywood3': '#CDAA7D',
    581       \ 'burlywood4': '#8B7355',
    582       \ 'wheat1': '#FFE7BA',
    583       \ 'wheat2': '#EED8AE',
    584       \ 'wheat3': '#CDBA96',
    585       \ 'wheat4': '#8B7E66',
    586       \ 'tan1': '#FFA54F',
    587       \ 'tan2': '#EE9A49',
    588       \ 'tan3': '#CD853F',
    589       \ 'tan4': '#8B5A2B',
    590       \ 'chocolate1': '#FF7F24',
    591       \ 'chocolate2': '#EE7621',
    592       \ 'chocolate3': '#CD661D',
    593       \ 'chocolate4': '#8B4513',
    594       \ 'firebrick1': '#FF3030',
    595       \ 'firebrick2': '#EE2C2C',
    596       \ 'firebrick3': '#CD2626',
    597       \ 'firebrick4': '#8B1A1A',
    598       \ 'brown1': '#FF4040',
    599       \ 'brown2': '#EE3B3B',
    600       \ 'brown3': '#CD3333',
    601       \ 'brown4': '#8B2323',
    602       \ 'salmon1': '#FF8C69',
    603       \ 'salmon2': '#EE8262',
    604       \ 'salmon3': '#CD7054',
    605       \ 'salmon4': '#8B4C39',
    606       \ 'lightsalmon1': '#FFA07A',
    607       \ 'lightsalmon2': '#EE9572',
    608       \ 'lightsalmon3': '#CD8162',
    609       \ 'lightsalmon4': '#8B5742',
    610       \ 'orange1': '#FFA500',
    611       \ 'orange2': '#EE9A00',
    612       \ 'orange3': '#CD8500',
    613       \ 'orange4': '#8B5A00',
    614       \ 'darkorange1': '#FF7F00',
    615       \ 'darkorange2': '#EE7600',
    616       \ 'darkorange3': '#CD6600',
    617       \ 'darkorange4': '#8B4500',
    618       \ 'coral1': '#FF7256',
    619       \ 'coral2': '#EE6A50',
    620       \ 'coral3': '#CD5B45',
    621       \ 'coral4': '#8B3E2F',
    622       \ 'tomato1': '#FF6347',
    623       \ 'tomato2': '#EE5C42',
    624       \ 'tomato3': '#CD4F39',
    625       \ 'tomato4': '#8B3626',
    626       \ 'orangered1': '#FF4500',
    627       \ 'orangered2': '#EE4000',
    628       \ 'orangered3': '#CD3700',
    629       \ 'orangered4': '#8B2500',
    630       \ 'red1': '#FF0000',
    631       \ 'red2': '#EE0000',
    632       \ 'red3': '#CD0000',
    633       \ 'red4': '#8B0000',
    634       \ 'deeppink1': '#FF1493',
    635       \ 'deeppink2': '#EE1289',
    636       \ 'deeppink3': '#CD1076',
    637       \ 'deeppink4': '#8B0A50',
    638       \ 'hotpink1': '#FF6EB4',
    639       \ 'hotpink2': '#EE6AA7',
    640       \ 'hotpink3': '#CD6090',
    641       \ 'hotpink4': '#8B3A62',
    642       \ 'pink1': '#FFB5C5',
    643       \ 'pink2': '#EEA9B8',
    644       \ 'pink3': '#CD919E',
    645       \ 'pink4': '#8B636C',
    646       \ 'lightpink1': '#FFAEB9',
    647       \ 'lightpink2': '#EEA2AD',
    648       \ 'lightpink3': '#CD8C95',
    649       \ 'lightpink4': '#8B5F65',
    650       \ 'palevioletred1': '#FF82AB',
    651       \ 'palevioletred2': '#EE799F',
    652       \ 'palevioletred3': '#CD6889',
    653       \ 'palevioletred4': '#8B475D',
    654       \ 'maroon1': '#FF34B3',
    655       \ 'maroon2': '#EE30A7',
    656       \ 'maroon3': '#CD2990',
    657       \ 'maroon4': '#8B1C62',
    658       \ 'violetred1': '#FF3E96',
    659       \ 'violetred2': '#EE3A8C',
    660       \ 'violetred3': '#CD3278',
    661       \ 'violetred4': '#8B2252',
    662       \ 'magenta1': '#FF00FF',
    663       \ 'magenta2': '#EE00EE',
    664       \ 'magenta3': '#CD00CD',
    665       \ 'magenta4': '#8B008B',
    666       \ 'orchid1': '#FF83FA',
    667       \ 'orchid2': '#EE7AE9',
    668       \ 'orchid3': '#CD69C9',
    669       \ 'orchid4': '#8B4789',
    670       \ 'plum1': '#FFBBFF',
    671       \ 'plum2': '#EEAEEE',
    672       \ 'plum3': '#CD96CD',
    673       \ 'plum4': '#8B668B',
    674       \ 'mediumorchid1': '#E066FF',
    675       \ 'mediumorchid2': '#D15FEE',
    676       \ 'mediumorchid3': '#B452CD',
    677       \ 'mediumorchid4': '#7A378B',
    678       \ 'darkorchid1': '#BF3EFF',
    679       \ 'darkorchid2': '#B23AEE',
    680       \ 'darkorchid3': '#9A32CD',
    681       \ 'darkorchid4': '#68228B',
    682       \ 'purple1': '#9B30FF',
    683       \ 'purple2': '#912CEE',
    684       \ 'purple3': '#7D26CD',
    685       \ 'purple4': '#551A8B',
    686       \ 'mediumpurple1': '#AB82FF',
    687       \ 'mediumpurple2': '#9F79EE',
    688       \ 'mediumpurple3': '#8968CD',
    689       \ 'mediumpurple4': '#5D478B',
    690       \ 'thistle1': '#FFE1FF',
    691       \ 'thistle2': '#EED2EE',
    692       \ 'thistle3': '#CDB5CD',
    693       \ 'thistle4': '#8B7B8B',
    694       \ 'gray0': '#000000',
    695       \ 'grey0': '#000000',
    696       \ 'gray1': '#030303',
    697       \ 'grey1': '#030303',
    698       \ 'gray2': '#050505',
    699       \ 'grey2': '#050505',
    700       \ 'gray3': '#080808',
    701       \ 'grey3': '#080808',
    702       \ 'gray4': '#0A0A0A',
    703       \ 'grey4': '#0A0A0A',
    704       \ 'gray5': '#0D0D0D',
    705       \ 'grey5': '#0D0D0D',
    706       \ 'gray6': '#0F0F0F',
    707       \ 'grey6': '#0F0F0F',
    708       \ 'gray7': '#121212',
    709       \ 'grey7': '#121212',
    710       \ 'gray8': '#141414',
    711       \ 'grey8': '#141414',
    712       \ 'gray9': '#171717',
    713       \ 'grey9': '#171717',
    714       \ 'gray10': '#1A1A1A',
    715       \ 'grey10': '#1A1A1A',
    716       \ 'gray11': '#1C1C1C',
    717       \ 'grey11': '#1C1C1C',
    718       \ 'gray12': '#1F1F1F',
    719       \ 'grey12': '#1F1F1F',
    720       \ 'gray13': '#212121',
    721       \ 'grey13': '#212121',
    722       \ 'gray14': '#242424',
    723       \ 'grey14': '#242424',
    724       \ 'gray15': '#262626',
    725       \ 'grey15': '#262626',
    726       \ 'gray16': '#292929',
    727       \ 'grey16': '#292929',
    728       \ 'gray17': '#2B2B2B',
    729       \ 'grey17': '#2B2B2B',
    730       \ 'gray18': '#2E2E2E',
    731       \ 'grey18': '#2E2E2E',
    732       \ 'gray19': '#303030',
    733       \ 'grey19': '#303030',
    734       \ 'gray20': '#333333',
    735       \ 'grey20': '#333333',
    736       \ 'gray21': '#363636',
    737       \ 'grey21': '#363636',
    738       \ 'gray22': '#383838',
    739       \ 'grey22': '#383838',
    740       \ 'gray23': '#3B3B3B',
    741       \ 'grey23': '#3B3B3B',
    742       \ 'gray24': '#3D3D3D',
    743       \ 'grey24': '#3D3D3D',
    744       \ 'gray25': '#404040',
    745       \ 'grey25': '#404040',
    746       \ 'gray26': '#424242',
    747       \ 'grey26': '#424242',
    748       \ 'gray27': '#454545',
    749       \ 'grey27': '#454545',
    750       \ 'gray28': '#474747',
    751       \ 'grey28': '#474747',
    752       \ 'gray29': '#4A4A4A',
    753       \ 'grey29': '#4A4A4A',
    754       \ 'gray30': '#4D4D4D',
    755       \ 'grey30': '#4D4D4D',
    756       \ 'gray31': '#4F4F4F',
    757       \ 'grey31': '#4F4F4F',
    758       \ 'gray32': '#525252',
    759       \ 'grey32': '#525252',
    760       \ 'gray33': '#545454',
    761       \ 'grey33': '#545454',
    762       \ 'gray34': '#575757',
    763       \ 'grey34': '#575757',
    764       \ 'gray35': '#595959',
    765       \ 'grey35': '#595959',
    766       \ 'gray36': '#5C5C5C',
    767       \ 'grey36': '#5C5C5C',
    768       \ 'gray37': '#5E5E5E',
    769       \ 'grey37': '#5E5E5E',
    770       \ 'gray38': '#616161',
    771       \ 'grey38': '#616161',
    772       \ 'gray39': '#636363',
    773       \ 'grey39': '#636363',
    774       \ 'gray40': '#666666',
    775       \ 'grey40': '#666666',
    776       \ 'gray41': '#696969',
    777       \ 'grey41': '#696969',
    778       \ 'gray42': '#6B6B6B',
    779       \ 'grey42': '#6B6B6B',
    780       \ 'gray43': '#6E6E6E',
    781       \ 'grey43': '#6E6E6E',
    782       \ 'gray44': '#707070',
    783       \ 'grey44': '#707070',
    784       \ 'gray45': '#737373',
    785       \ 'grey45': '#737373',
    786       \ 'gray46': '#757575',
    787       \ 'grey46': '#757575',
    788       \ 'gray47': '#787878',
    789       \ 'grey47': '#787878',
    790       \ 'gray48': '#7A7A7A',
    791       \ 'grey48': '#7A7A7A',
    792       \ 'gray49': '#7D7D7D',
    793       \ 'grey49': '#7D7D7D',
    794       \ 'gray50': '#7F7F7F',
    795       \ 'grey50': '#7F7F7F',
    796       \ 'gray51': '#828282',
    797       \ 'grey51': '#828282',
    798       \ 'gray52': '#858585',
    799       \ 'grey52': '#858585',
    800       \ 'gray53': '#878787',
    801       \ 'grey53': '#878787',
    802       \ 'gray54': '#8A8A8A',
    803       \ 'grey54': '#8A8A8A',
    804       \ 'gray55': '#8C8C8C',
    805       \ 'grey55': '#8C8C8C',
    806       \ 'gray56': '#8F8F8F',
    807       \ 'grey56': '#8F8F8F',
    808       \ 'gray57': '#919191',
    809       \ 'grey57': '#919191',
    810       \ 'gray58': '#949494',
    811       \ 'grey58': '#949494',
    812       \ 'gray59': '#969696',
    813       \ 'grey59': '#969696',
    814       \ 'gray60': '#999999',
    815       \ 'grey60': '#999999',
    816       \ 'gray61': '#9C9C9C',
    817       \ 'grey61': '#9C9C9C',
    818       \ 'gray62': '#9E9E9E',
    819       \ 'grey62': '#9E9E9E',
    820       \ 'gray63': '#A1A1A1',
    821       \ 'grey63': '#A1A1A1',
    822       \ 'gray64': '#A3A3A3',
    823       \ 'grey64': '#A3A3A3',
    824       \ 'gray65': '#A6A6A6',
    825       \ 'grey65': '#A6A6A6',
    826       \ 'gray66': '#A8A8A8',
    827       \ 'grey66': '#A8A8A8',
    828       \ 'gray67': '#ABABAB',
    829       \ 'grey67': '#ABABAB',
    830       \ 'gray68': '#ADADAD',
    831       \ 'grey68': '#ADADAD',
    832       \ 'gray69': '#B0B0B0',
    833       \ 'grey69': '#B0B0B0',
    834       \ 'gray70': '#B3B3B3',
    835       \ 'grey70': '#B3B3B3',
    836       \ 'gray71': '#B5B5B5',
    837       \ 'grey71': '#B5B5B5',
    838       \ 'gray72': '#B8B8B8',
    839       \ 'grey72': '#B8B8B8',
    840       \ 'gray73': '#BABABA',
    841       \ 'grey73': '#BABABA',
    842       \ 'gray74': '#BDBDBD',
    843       \ 'grey74': '#BDBDBD',
    844       \ 'gray75': '#BFBFBF',
    845       \ 'grey75': '#BFBFBF',
    846       \ 'gray76': '#C2C2C2',
    847       \ 'grey76': '#C2C2C2',
    848       \ 'gray77': '#C4C4C4',
    849       \ 'grey77': '#C4C4C4',
    850       \ 'gray78': '#C7C7C7',
    851       \ 'grey78': '#C7C7C7',
    852       \ 'gray79': '#C9C9C9',
    853       \ 'grey79': '#C9C9C9',
    854       \ 'gray80': '#CCCCCC',
    855       \ 'grey80': '#CCCCCC',
    856       \ 'gray81': '#CFCFCF',
    857       \ 'grey81': '#CFCFCF',
    858       \ 'gray82': '#D1D1D1',
    859       \ 'grey82': '#D1D1D1',
    860       \ 'gray83': '#D4D4D4',
    861       \ 'grey83': '#D4D4D4',
    862       \ 'gray84': '#D6D6D6',
    863       \ 'grey84': '#D6D6D6',
    864       \ 'gray85': '#D9D9D9',
    865       \ 'grey85': '#D9D9D9',
    866       \ 'gray86': '#DBDBDB',
    867       \ 'grey86': '#DBDBDB',
    868       \ 'gray87': '#DEDEDE',
    869       \ 'grey87': '#DEDEDE',
    870       \ 'gray88': '#E0E0E0',
    871       \ 'grey88': '#E0E0E0',
    872       \ 'gray89': '#E3E3E3',
    873       \ 'grey89': '#E3E3E3',
    874       \ 'gray90': '#E5E5E5',
    875       \ 'grey90': '#E5E5E5',
    876       \ 'gray91': '#E8E8E8',
    877       \ 'grey91': '#E8E8E8',
    878       \ 'gray92': '#EBEBEB',
    879       \ 'grey92': '#EBEBEB',
    880       \ 'gray93': '#EDEDED',
    881       \ 'grey93': '#EDEDED',
    882       \ 'gray94': '#F0F0F0',
    883       \ 'grey94': '#F0F0F0',
    884       \ 'gray95': '#F2F2F2',
    885       \ 'grey95': '#F2F2F2',
    886       \ 'gray96': '#F5F5F5',
    887       \ 'grey96': '#F5F5F5',
    888       \ 'gray97': '#F7F7F7',
    889       \ 'grey97': '#F7F7F7',
    890       \ 'gray98': '#FAFAFA',
    891       \ 'grey98': '#FAFAFA',
    892       \ 'gray99': '#FCFCFC',
    893       \ 'grey99': '#FCFCFC',
    894       \ 'gray100': '#FFFFFF',
    895       \ 'grey100': '#FFFFFF',
    896       \ 'darkgrey': '#A9A9A9',
    897       \ 'darkgray': '#A9A9A9',
    898       \ 'darkblue': '#00008B',
    899       \ 'darkcyan': '#008B8B',
    900       \ 'darkmagenta': '#8B008B',
    901       \ 'darkred': '#8B0000',
    902       \ 'lightgreen': '#90EE90'
    903       \ }
    904 
    905 " Functions, to highlight certain types {{{1
    906 function! s:ColorRGBValues(val)
    907   let s:position = getpos('.')
    908   if <sid>IsInComment()
    909     " skip coloring comments
    910     return
    911   endif
    912   " strip parantheses and split on comma
    913   let rgb = s:StripParentheses(a:val)
    914   if empty(rgb)
    915     call s:Warn("Error in expression". a:val. "! Please report as bug.")
    916     return
    917   endif
    918   for i in range(3)
    919     if rgb[i][-1:-1] == '%'
    920       let val = matchstr(rgb[i], '\d\+')
    921       if (val + 0 > 100)
    922         let rgb[1] = 100
    923       endif
    924       let rgb[i] = float2nr((val + 0.0)*255/100)
    925     else
    926       if rgb[i] + 0 > 255
    927         let rgb[i] = 255
    928       endif
    929     endif
    930   endfor
    931   if len(rgb) == 4
    932     let rgb = s:ApplyAlphaValue(rgb)
    933   endif
    934   let clr = printf("%02X%02X%02X", rgb[0],rgb[1],rgb[2])
    935   call s:SetMatcher(a:val, {'bg': clr})
    936   if s:use_virtual_text
    937     return a:val
    938   endif
    939 endfunction
    940 
    941 function! s:ColorHSLValues(val)
    942   let s:position = getpos('.')
    943   if <sid>IsInComment()
    944     " skip coloring comments
    945     return
    946   endif
    947   " strip parantheses and split on comma
    948   let hsl = s:StripParentheses(a:val)
    949   if empty(hsl)
    950     call s:Warn("Error in expression". a:val. "! Please report as bug.")
    951     return
    952   endif
    953   let str = s:PrepareHSLArgs(hsl)
    954 
    955   call s:SetMatcher(a:val, {'bg': str})
    956   if s:use_virtual_text
    957     return a:val
    958   endif
    959 endfu
    960 
    961 function! s:PreviewColorName(color)
    962   let s:position = getpos('.')
    963   let name=tolower(a:color)
    964   let clr = s:colors[name]
    965   " Skip color-name, e.g. white-space property
    966   call s:SetMatcher('-\@<!\<'.name.'\>\c-\@!', {'bg': clr[1:]})
    967   if s:use_virtual_text
    968     return a:color
    969   endif
    970 endfu
    971 
    972 function! s:PreviewColorHex(match)
    973   let s:position = getpos('.')
    974   if <sid>IsInComment()
    975     " skip coloring comments
    976     return
    977   endif
    978   " Make sure the pattern matches the complete string, so anchor it
    979   " explicitly at the end (see #64)
    980   let color = matchstr(a:match, s:hex_pattern[1]."$")
    981   let pattern = color
    982   if len(color) == 3
    983     let color = substitute(color, '.', '&&', 'g')
    984   endif
    985   if &t_Co == 8 && !s:HasGui()
    986     " The first 12 color names, can be displayed by 8 color terminals
    987     let list = values(s:xterm_8colors)
    988     let idx = match(list, a:match)
    989     if idx == -1
    990       " Color can't be displayed by 8 color terminal
    991       return
    992     else
    993       let color = list[idx]
    994     endif
    995   endif
    996   if len(split(pattern, '\zs')) == 8
    997     " apply alpha value
    998     let l = split(pattern, '..\zs')
    999     call map(l, 'printf("%2d", "0x".v:val)')
   1000     let l[3] = string(str2float(l[3])/255)  " normalize to 0-1
   1001     let l = s:ApplyAlphaValue(l)
   1002     let color = printf("%02X%02X%02X", l[0], l[1], l[2])
   1003   endif
   1004   call s:SetMatcher(s:hex_pattern[0]. pattern. s:hex_pattern[2], {'bg': color})
   1005   if s:use_virtual_text
   1006     return a:match
   1007   endif
   1008 endfunction
   1009 
   1010 function! s:PreviewColorTerm(pre, text, post)
   1011   " a:pre: Ansi-Sequences determining the highlighting
   1012   " a:text: Text to color
   1013   " a:post: Ansi-Sequences resetting the coloring (might be empty)
   1014   let s:position = getpos('.')
   1015   let color = s:Ansi2Color(a:pre)
   1016   let clr_Dict = {}
   1017 
   1018   if &t_Co == 8 && !s:HasGui()
   1019     " The first 12 color names, can be displayed by 8 color terminals
   1020     let i = 0
   1021     for clr in color
   1022       let list = values(s:xterm_8colors)
   1023       let idx = match(list, clr)
   1024       if idx == -1
   1025         " Color can't be displayed by 8 color terminal
   1026         let color[i] = NONE
   1027       else
   1028         let color[i] = list[idx]
   1029       endif
   1030       let i+=1
   1031     endfor
   1032   endif
   1033   let clr_Dict.fg = color[0]
   1034   let clr_Dict.bg = color[1]
   1035   let pre  = escape(a:pre,  '[]')
   1036   let post = escape(a:post, '[]')
   1037   let txt  = escape(a:text, '\^$.*~[]')
   1038   " limit the pattern to the belonging line (should make syntax matching
   1039   " faster!)
   1040   let pattern = '\%(\%'.line('.').'l\)\%('. pre. '\)\@<='.txt. '\('.post.'\)\@='
   1041   " needs matchaddpos
   1042   let clr_Dict.pos = [[ line('.'), col('.'), strlen(a:pre. a:text. a:post)]]
   1043   call s:SetMatcher(pattern, clr_Dict)
   1044   if s:use_virtual_text
   1045     return a:pre . a:text. a:post
   1046   endif
   1047 endfunction
   1048 function! s:PreviewColorNroff(match)
   1049   let s:position = getpos('.')
   1050   let clr_Dict = {}
   1051   let color = []
   1052   if a:match[0] == '_'
   1053     let special = 'underline'
   1054   else
   1055     let special = 'bold'
   1056   endif
   1057   let synid=synIDtrans(synID(line('.'), col('.'), 1))
   1058   if synid == 0
   1059     let synid = hlID('Normal')
   1060   endif
   1061   let color=[synIDattr(synid, 'fg'), synIDattr(synid, 'bg')]
   1062   if color == [0, 0] || color == ['', '']
   1063     let color = [synIDattr(hlID('Normal'), 'fg'), synIDattr(hlID('Normal'), 'bg')]
   1064   endif
   1065 
   1066   let clr_Dict.fg = color[0]
   1067   let clr_Dict.bg = color[1]
   1068   let clr_Dict.special=special
   1069   " limit the pattern to the belonging line (should make syntax matching
   1070   " faster!)
   1071   let pattern = '\%(\%'.line('.').'l\)'.a:match
   1072   " needs matchaddpos
   1073   let clr_Dict.pos = [[ line('.'), col('.'), 3]]
   1074   call s:SetMatcher(pattern, clr_Dict)
   1075   if s:use_virtual_text
   1076     return a:match
   1077   endif
   1078 endfunction
   1079 function! s:PreviewTaskWarriorColors(submatch)
   1080   " a:submatch is something like 'black on rgb141'
   1081 
   1082   " this highlighting should overrule e.g. colorname highlighting
   1083   let s:position = getpos('.')
   1084   let s:default_match_priority += 1
   1085   let color = ['', 'NONE', 'NONE']
   1086   let color_Dict = {}
   1087   " The submatch is everything after the first equalsign!
   1088   let tpat = '\(inverse\|underline\|bright\|bold\)\?\%(\s*\)\(\S\{3,}\)'.
   1089         \ '\?\%(\s*\)\?\%(on\s\+'.
   1090         \ '\%(inverse\|underline\|bright\|bold\)\?\%(\s*\)\(\S\{3,}\)\)\?'
   1091   let colormatch = matchlist(a:submatch, tpat)
   1092   try
   1093     if !empty(colormatch) && !empty(colormatch[0])
   1094       let i=-1
   1095       for m in colormatch[1:3]
   1096         let i+=1
   1097         if i == 0
   1098           if (!empty(colormatch[1]))
   1099             let color_Dict.special=colormatch[1]
   1100           else
   1101             continue
   1102           endif
   1103         endif
   1104         if match(keys(s:colors), '\<'.m.'\>') > -1
   1105           if i == 1
   1106             let color_Dict.fg = s:colors[m][1:] " skip the # sign
   1107           elseif i == 2
   1108             let color_Dict.bg = s:colors[m][1:] " skip the # sign
   1109           endif
   1110           continue
   1111         elseif match(m, '^rgb...') > -1
   1112           let color[i] = m[3] * 36 + m[4] * 6 + m[5] + 16 " (start at index 16)
   1113           if color[i] > 231
   1114             " invalid color
   1115             return
   1116           endif
   1117         elseif match(m, '^color') > -1
   1118           let color[i] = matchstr(m, '\d\+')+0
   1119           if color[i] > 231
   1120             " invalid color
   1121             return
   1122           endif
   1123         elseif match(m, '^gray') > -1
   1124           let color[i] = matchstr(m, '\d\+') + 232
   1125           if color[i] > 231
   1126             " invalid color
   1127             return
   1128           endif
   1129         endif
   1130         if i == 1
   1131           let color_Dict.ctermfg = color[i]
   1132         elseif i == 2
   1133           let color_Dict.ctermbg = color[i]
   1134         endif
   1135       endfor
   1136 
   1137       let cname = get(color_Dict, 'fg', 'NONE')
   1138       if cname ==# 'NONE' && get(color_Dict, 'ctermfg')
   1139         let cname = s:Term2RGB(color_Dict.ctermfg)
   1140       endif
   1141       call s:SetMatcher('=\s*\zs\<'.a:submatch.'\>$', color_Dict)
   1142       if s:use_virtual_text
   1143         return a:submatch
   1144       endif
   1145     endif
   1146   finally
   1147     let s:default_match_priority -= 1
   1148     let s:stop = 1
   1149   endtry
   1150 endfunction
   1151 
   1152 function! s:PreviewVimColors(submatch)
   1153   " a:submatch is something like 'black on rgb141'
   1154 
   1155   " this highlighting should overrule e.g. colorname highlighting
   1156   let s:position = getpos('.')
   1157   let s:default_match_priority += 1
   1158   if !exists("s:x11_color_pattern")
   1159     let s:x11_color_pattern =  s:GetColorPattern(keys(s:x11_color_names))
   1160   endif
   1161   let color_Dict = {}
   1162   let pat1 = '\%(\(cterm[fb]g\)\s*=\s*\)\@<=\<\(\d\+\)\>'
   1163   let pat2 = '\%(\(gui[fb]g\)\s*=\s*\)\@<=#\(\x\{6}\)\>'
   1164   let pat3 = '\%#=1\%(\(gui[fb]g\)\s*=\s*\)\@<=\('.s:x11_color_pattern.'\)'
   1165 
   1166   let cterm = matchlist(a:submatch, pat1)
   1167   let gui   = matchlist(a:submatch, pat2)
   1168   if (!empty(gui) && (gui[2] ==# 'bg' ||
   1169         \ gui[2] ==# 'fg' ||
   1170         \ gui[2] ==# 'foreground' ||
   1171         \ gui[2] ==# 'background'))
   1172     let gui=[]
   1173   endif
   1174   if  empty(gui)
   1175     let gui   = matchlist(a:submatch, pat3)
   1176     if !empty(gui)
   1177       let gui[2] = s:x11_color_names[tolower(gui[2])]
   1178     endif
   1179   endif
   1180   try
   1181     if !empty(cterm)
   1182       let color_Dict.ctermbg = cterm[2]
   1183     elseif !empty(gui)
   1184       let color_Dict.bg = gui[2]
   1185     endif
   1186 
   1187     if empty(gui) && empty(cterm)
   1188       return
   1189     endif
   1190 
   1191     call s:SetMatcher('\<'.a:submatch.'\>', color_Dict)
   1192     if s:use_virtual_text
   1193       return a:submatch
   1194     endif
   1195   finally
   1196     let s:default_match_priority -= 1
   1197   endtry
   1198 endfunction
   1199 
   1200 function! s:PreviewVimHighlightDump(match)
   1201   " highlights dumps of :hi
   1202   " e.g
   1203   "SpecialKey     xxx term=bold cterm=bold ctermfg=124 guifg=Cyan
   1204   let s:position = getpos('.')
   1205   let s:default_match_priority += 1
   1206   let dict = {}
   1207   try
   1208     let match = split(a:match, '\_s\+')
   1209     if a:match =~# 'cleared'
   1210       " ipaddr         xxx cleared
   1211       return
   1212     elseif a:match =~# 'links to'
   1213       " try to find a non-cleared group
   1214       let c1 =  <sid>SynID(match[0])
   1215       let group = match[0]
   1216       if empty(c1)
   1217         let group = match[-1]
   1218       endif
   1219       call s:SetMatch('Color_'.group, '^'.s:GetPatternLiteral(a:match), {})
   1220     else
   1221       let dict.name = 'Color_'.match[0]
   1222       call remove(match, 0, 1)
   1223       let dict = s:DictFromList(dict, match)
   1224       call s:SetMatcher(s:GetPatternLiteral(a:match), dict)
   1225       if s:use_virtual_text
   1226         return a:match
   1227       endif
   1228     endif
   1229   finally
   1230     let s:default_match_priority -= 1
   1231     " other highlighting functions shouldn't run anymore
   1232     let s:stop = 1
   1233   endtry
   1234 endfunction
   1235 
   1236 function! s:PreviewVimHighlight(match)
   1237   " like colorhighlight plugin,
   1238   " schemer highlight statements in .vim files
   1239   let s:position = getpos('.')
   1240   let tmatch = a:match
   1241   let def    = []
   1242   let dict   = {}
   1243   try
   1244     if a:match =~ '^\s*hi\%[ghlight]\s\+clear'
   1245       " highlight clear lines, don't colorize!
   1246       return
   1247     endif
   1248     " Special case:
   1249     " HtmlHiLink foo bar -> links foo to bar
   1250     " hi! def link foo bar -> links foo to bar
   1251     let match = matchlist(tmatch, '\C\%(\%[Html\]HiLink\|hi\%[ghlight]!\?\s*\%(def\%[ault]\s*\)\?link\)\s\+\(\w\+\)\s\+\(\w\+\)')
   1252     " Hopefully tmatch[1] has already been defined ;(
   1253     if len(match)
   1254       call s:SetMatch('Color_'.match[1], '^\V'.escape(a:match, '\\'), {})
   1255       return
   1256     endif
   1257     let tmatch = substitute(tmatch, '^\c\s*hi\%[ghlight]!\?\(\s*def\%[ault]\)\?', '', '')
   1258     let match = map(split(tmatch), 'substitute(v:val, ''^\s\+\|\s\+$'', "", "g")')
   1259     if len(match) < 2
   1260       return
   1261     else
   1262       let dict.name = 'Color_'.get(match, 0)
   1263       let dict = s:DictFromList(dict, match)
   1264       call s:SetMatcher(s:GetPatternLiteral(a:match), dict)
   1265       if s:use_virtual_text
   1266         return a:match
   1267       endif
   1268     endif
   1269   endtry
   1270 endfunction
   1271 
   1272 function! s:IsInComment()
   1273   return s:skip_comments &&
   1274         \ synIDattr(synIDtrans(synID(line('.'), col('.'),1)), 'name') == "Comment"
   1275 endfu
   1276 
   1277 function! s:DictFromList(dict, list)
   1278   let dict = copy(a:dict)
   1279   let match = filter(a:list, 'v:val =~# ''=''')
   1280   for item in match
   1281     let [t1, t2] = split(item, '=')
   1282     let dict[t1] = t2
   1283   endfor
   1284   return dict
   1285 endfunction
   1286 
   1287 function! s:GetPatternLiteral(pat)
   1288   return '\V'. substitute(escape(a:pat, '\\'), "\n", '\\n', 'g')
   1289 endfu
   1290 function! s:Term2RGB(index)
   1291   " Return index in colortable in RRGGBB form
   1292   return join(map(copy(s:colortable[a:index]), 'printf("%02X", v:val)'),'')
   1293 endfu
   1294 
   1295 function! s:Reltime(...)
   1296   return exists("a:1") ? reltime(a:1) : reltime()
   1297 endfu
   1298 
   1299 function! s:PrintColorStatistics()
   1300   if get(g:, 'schemer_debug', 0)
   1301     echohl Title
   1302     echom printf("Colorstatistics at: %s", strftime("%H:%M"))
   1303     echom printf("Duration: %s", reltimestr(s:relstop))
   1304     for name in sort(keys(extend(s:color_patterns, s:color_patterns_special)))
   1305       let value = get(extend(s:color_patterns, s:color_patterns_special), name)
   1306       echom printf("%15s: %ss", name, (value[-1] == [] ? '  0.000000' : reltimestr(value[-1])))
   1307     endfor
   1308     echohl Normal
   1309   endif
   1310 endfu
   1311 
   1312 function! s:ColorInit(...)
   1313   let s:force_hl = !empty(a:1)
   1314   let s:term_true_color = (exists('+tgc') && &tgc)
   1315   let s:stop = 0
   1316   let s:use_virtual_text = has("nvim") && get(g:, 'schemer_use_virtual_text', 0)
   1317 
   1318   " default matchadd priority
   1319   let s:default_match_priority = -2
   1320 
   1321   " pattern/function dict
   1322   " Needed for s:ColorMatchingLines(), disabled, as this is too slow.
   1323   "let s:pat_func = {'#\x\{3,6\}': function('<sid>PreviewColorHex'),
   1324   "            \ 'rgba\=(\s*\%(\d\+%\?\D*\)\{3,4})':
   1325   "            \ function('<sid>ColorRGBValues'),
   1326   "            \ 'hsla\=(\s*\%(\d\+%\?\D*\)\{3,4})':
   1327   "            \ function('s:ColorHSLValues')}
   1328 
   1329   " Cache old values
   1330   if !exists("s:old_tCo")
   1331     let s:old_tCo = &t_Co
   1332   endif
   1333 
   1334   if !exists("s:swap_fg_bg")
   1335     let s:swap_fg_bg = 0
   1336   endif
   1337 
   1338   if !exists("s:round")
   1339     let s:round = 0
   1340   endif
   1341 
   1342   " Enable Autocommands
   1343   if exists("g:schemer_auto_color")
   1344     call s:AutoCmds(g:schemer_auto_color)
   1345   endif
   1346 
   1347   " disable terminal coloring for all filetypes except text files
   1348   " it's too expensive and probably does not make sense to enable it for
   1349   " other filetypes
   1350   let s:schemer_term_disable = !(empty(&filetype) || &filetype != 'text')
   1351   let s:schemer_nroff_disable = !(empty(&filetype) || &filetype != 'text')
   1352 
   1353   " Debugging
   1354   let s:debug = get(g:, 'schemer_debug', 0)
   1355 
   1356   " Don't highlight comment?
   1357   let s:skip_comments = get(g:, 'schemer_skip_comments', 0)
   1358 
   1359   " foreground / background contrast
   1360   let s:predefined_fgcolors = {}
   1361   let s:predefined_fgcolors['dark']  = ['444444', '222222', '000000']
   1362   let s:predefined_fgcolors['light'] = ['bbbbbb', 'dddddd', 'ffffff']
   1363   if !exists('g:schemer_fgcontrast')
   1364     " Default to black / white
   1365     let g:schemer_fgcontrast = len(s:predefined_fgcolors['dark']) - 1
   1366   elseif g:schemer_fgcontrast >= len(s:predefined_fgcolors['dark'])
   1367     call s:Warn("g:schemer_fgcontrast value invalid, using default")
   1368     let g:schemer_fgcontrast = len(s:predefined_fgcolors['dark']) - 1
   1369   endif
   1370 
   1371   if !exists("s:old_fgcontrast")
   1372     " if the value was changed since last time,
   1373     " be sure to clear the old highlighting.
   1374     let s:old_fgcontrast = g:schemer_fgcontrast
   1375   endif
   1376 
   1377   if exists("g:schemer_swap_fgbg")
   1378     if s:swap_fg_bg != g:schemer_swap_fgbg
   1379       let s:force_hl = 1
   1380     endif
   1381     let s:swap_fg_bg = g:schemer_swap_fgbg
   1382   endif
   1383 
   1384   if exists("g:schemer_colornames")
   1385     if exists("s:color_names") &&
   1386           \ s:color_names != g:schemer_colornames
   1387       let s:force_hl = 1
   1388     endif
   1389     let s:color_names = g:schemer_colornames
   1390   else
   1391     let s:color_names = 1
   1392   endif
   1393 
   1394   let s:color_syntax = get(g:, 'schemer_syntax', 0)
   1395   if get(g:, 'schemer_only_unfolded', 0) && exists(":foldd") == 1
   1396     let s:color_unfolded = 'foldd '
   1397   else
   1398     let s:color_unfolded = ''
   1399   endif
   1400 
   1401   if hlID('Color_Error') == 0
   1402     hi default link Color_Error Error
   1403   endif
   1404 
   1405   if !s:force_hl && s:old_fgcontrast != g:schemer_fgcontrast
   1406         \ && s:swap_fg_bg == 0
   1407     " Doesn't work with swapping fg bg colors
   1408     let s:force_hl = 1
   1409     let s:old_fgcontrast = g:schemer_fgcontrast
   1410   endif
   1411 
   1412   " User manually changed the &t_Co option, so reset it
   1413   if s:old_tCo != &t_Co
   1414     unlet! s:colortable
   1415   endif
   1416 
   1417   if !exists("s:init_css") || !exists("s:colortable") ||
   1418         \ empty(s:colortable)
   1419     " Only calculate the colortable when running
   1420     if &t_Co == 8
   1421       let s:colortable = map(range(0,7), 's:Xterm2rgb16(v:val)')
   1422     elseif &t_Co == 16
   1423       let s:colortable = map(range(0,15), 's:Xterm2rgb16(v:val)')
   1424     elseif &t_Co == 88
   1425       let s:colortable = map(range(0,87), 's:Xterm2rgb88(v:val)')
   1426       " terminal with 256 colors or gVim
   1427     elseif &t_Co == 256 || empty(&t_Co)
   1428       let s:colortable = map(range(0,255), 's:Xterm2rgb256(v:val)')
   1429     endif
   1430     if s:debug && exists("s:colortable")
   1431       let g:colortable = s:colortable
   1432     endif
   1433     let s:init_css = 1
   1434   elseif s:force_hl
   1435     call s:ColorOff()
   1436   endif
   1437   let s:conceal = [&l:cole, &l:cocu]
   1438 
   1439   let s:hex_pattern = get(g:, 'schemer_hex_pattern',
   1440         \ ['#', '\%(\x\{3}\|\x\{6}\|\x\{8\}\)', '\%(\>\|[-_]\)\@='])
   1441 
   1442   if s:HasGui() || &t_Co >= 8 || s:HasColorPattern()
   1443     " The list of available match() patterns
   1444     let w:match_list = s:GetMatchList()
   1445     " If the syntax highlighting got reset, force recreating it
   1446     if ((empty(w:match_list) || !hlexists(w:match_list[0].group) ||
   1447           \ (empty(<sid>SynID(w:match_list[0].group)) && !s:force_hl)))
   1448       let s:force_hl = 1
   1449     endif
   1450     if &t_Co > 16 || s:HasGui()
   1451       let s:colors = (exists("g:schemer_x11_names") ?
   1452             \ s:x11_color_names : s:w3c_color_names)
   1453     elseif &t_Co == 16
   1454       " should work with 16 colors terminals
   1455       let s:colors = s:xterm_16colors
   1456     else
   1457       let s:colors = s:xterm_8colors
   1458     endif
   1459     if exists("g:schemer_custom_colors")
   1460       call extend(s:colors, g:schemer_custom_colors, 'force')
   1461     endif
   1462     let s:colornamepattern =  s:GetColorPattern(keys(s:colors))
   1463     "call map(w:match_list, 'v:val.pattern')
   1464   else
   1465     throw "nocolor"
   1466   endif
   1467 
   1468   " Dictionary, containing all information on what to color
   1469   " Key: Name
   1470   " Value: List, containing 1) Pattern to find color
   1471   "                         2) func ref to call on the match of 1
   1472   "                         3) Name of variable, to enable or this enty
   1473   "                         4) condition, that must be fullfilled, before
   1474   "                            using this entry
   1475   "                       ´ 5) reltime for dumping statistics
   1476   let s:color_patterns = {
   1477         \ 'rgb': ['rgb(\s*\%(\d\+%\?[^)]*\)\{3})',
   1478         \ function("s:ColorRGBValues"), 'schemer_rgb', 1, [] ],
   1479         \ 'rgba': ['rgba(\s*\%(\d\+%\?\D*\)\{3}\%(\%(0\?\%(.\d\+\)\?\)\|1\))',
   1480         \ function("s:ColorRGBValues"), 'schemer_rgba', 1, [] ],
   1481         \ 'hsla': ['hsla\=(\s*\%(\d\+%\?\D*\)\{3}\%(\%(0\?\%(.\d\+\)\?\)\|1\)\=)',
   1482         \ function("s:ColorHSLValues"), 'schemer_hsla', 1, [] ],
   1483         \ 'vimcolors':  ['\%(gui[fb]g\|cterm[fb]g\)\s*=\s*\<\%(\d\+\|#\x\{6}\|\w\+\)\>',
   1484         \ function("s:PreviewVimColors"), 'schemer_vimcolors', '&ft ==# "vim"', [] ],
   1485         \ 'vimhighlight': ['^\s*\%(\%[Html]HiLink\s\+\w\+\s\+\w\+\)\|'.
   1486         \ '\(^\s*hi\%[ghlight]!\?\s\+\(clear\)\@!\S\+.*\)',
   1487         \ function("s:PreviewVimHighlight"), 'schemer_vimhighlight', '&ft ==# "vim"', [] ],
   1488         \ 'taskwarrior':  ['^color[^=]*=\zs.\+$',
   1489         \ function("s:PreviewTaskWarriorColors"), 'schemer_taskwarrior', 'expand("%:e") ==# "theme"', [] ],
   1490         \ 'hex': [join(s:hex_pattern, ''), function("s:PreviewColorHex"), 'schemer_hex', 1, [] ],
   1491         \ 'vimhighl_dump': ['^\v\w+\s+<xxx>%((\s+(term|cterm%([bf]g)?|gui%(%([bf]g|sp))?)\='.
   1492         \ '[#0-9A-Za-z_,]+)+)?%(\_\s+links to \w+)?%( cleared)@!$',
   1493         \ function("s:PreviewVimHighlightDump"), 'schemer_vimhighl_dump', 'empty(&ft)', [] ]
   1494         \ }
   1495 
   1496   " term_conceal: patterns to hide, currently: $ and the color patterns 
   1497   let s:color_patterns_special = {
   1498         \ 'term': ['\%(\%(\%x1b\|\\033\)\[0m\)\?\(\%(\%(\%x1b\|\\033\)\[\d\+\%([:;]\d\+\)*m\)\+\)\([^\e]*\)\(\%(\%x1b\|\\033\)\%(\[0m\|\[K\)\)\=',
   1499         \ function("s:PreviewColorTerm"), 'schemer_term', [] ],
   1500         \ 'term_nroff': ['\%(\(.\)\%u8\1\)\|\%(_\%u8.\)', function("s:PreviewColorNroff"), 'schemer_nroff', [] ],
   1501         \ 'term_conceal': [ ['\%(\(\%(\%x1b\[0m\)\?\%x1b\[\d\+\%([;:]\d\+\)*\a\)\|\%x1b\[K$\)',
   1502         \ '\%d13', '\%(\%x1b\[K\)', '\%(\%x1b\]\d\+;\d\+;\)', '\%(\%x1b\\\)',
   1503         \ '\%x1b(B\%x1b\[m', '\%x1b\[m\%(\%x0f\)\?', '_\%u8.\@=', '\(.\)\%u8\%(\1\)\@='],
   1504         \ '',
   1505         \ 'schemer_term_conceal', [] ]
   1506         \ }
   1507 
   1508   if exists("s:colornamepattern") && s:color_names
   1509     let s:color_patterns["colornames"] = [ s:colornamepattern,
   1510           \ function("s:PreviewColorName"), 'schemer_colornames', 1, [] ]
   1511   endif
   1512 endfu
   1513 
   1514 function! s:AddOffset(list)
   1515   return a:list
   1516   let result=[]
   1517   for val in a:list
   1518     let val = ('0X'.val) + 0
   1519     if val < get(g:, 'schemer_min_offset', 0)
   1520       let val = get(g:, 'schemer_add_offset', 0)
   1521     endif
   1522     call add(result, val)
   1523   endfor
   1524   return result
   1525 endfu
   1526 function! s:SwapColors(list)
   1527   if empty(a:list[0]) && empty(a:list[1])
   1528     return a:list
   1529   elseif s:swap_fg_bg > 0
   1530     return [a:list[1]] + ['NONE']
   1531   elseif s:swap_fg_bg == -1
   1532     return [a:list[1], a:list[0]]
   1533   else
   1534     return a:list
   1535   endif
   1536 endfu
   1537 
   1538 function! s:FGforBG(bg)
   1539   " takes a 6hex color code and returns a matching color that is visible
   1540   let fgc = g:schemer_fgcontrast
   1541   if fgc == -1
   1542     return a:bg
   1543   endif
   1544   if a:bg ==# 'NONE'
   1545     return (&bg==#'dark' ? s:predefined_fgcolors['dark'][fgc] : s:predefined_fgcolors['light'][fgc])
   1546   endif
   1547   let r = '0x'.a:bg[0:1]+0
   1548   let g = '0x'.a:bg[2:3]+0
   1549   let b = '0x'.a:bg[4:5]+0
   1550   if r*30 + g*59 + b*11 > 12000
   1551     return s:predefined_fgcolors['dark'][fgc]
   1552   else
   1553     return s:predefined_fgcolors['light'][fgc]
   1554   end
   1555 endfunction
   1556 
   1557 function! s:DidColor(clr, pat)
   1558   let idx = index(w:match_list, a:pat)
   1559   if idx > -1
   1560     let attr = <sid>SynID(a:clr)
   1561     if (!empty(attr) && get(w:match_list, idx) ==# a:pat)
   1562       return 1
   1563     endif
   1564   endif
   1565   return 0
   1566 endfu
   1567 
   1568 function! s:DoHlGroup(group, Dict)
   1569   if !s:force_hl
   1570     let syn = <sid>SynID(a:group)
   1571     if !empty(syn)
   1572       " highlighting already exists
   1573       return
   1574     endif
   1575   endif
   1576 
   1577   if empty(a:Dict)
   1578     " try to link the given highlight group
   1579     call s:Exe("hi link ". a:group. " ". matchstr(a:group, 'Color_\zs.*'))
   1580     return
   1581   endif
   1582 
   1583   let hi = printf('hi %s ', a:group)
   1584   let fg = get(a:Dict, 'fg', '')
   1585   let bg = get(a:Dict, 'bg', '')
   1586   let [fg, bg] = s:SwapColors([fg, bg])
   1587   let [fg, bg] = s:AddOffset([fg, bg])
   1588 
   1589   if !empty(fg) && fg[0] !=# '#' && fg !=# 'NONE'
   1590     let fg='#'.fg
   1591   endif
   1592   if !empty(bg) && bg[0] !=# '#' && bg !=# 'NONE'
   1593     let bg='#'.bg
   1594   endif
   1595   let hi .= printf('guifg=%s', fg)
   1596   if has_key(a:Dict, "gui")
   1597     let hi.=printf(" gui=%s ", a:Dict['gui'])
   1598   endif
   1599   if has_key(a:Dict, "guifg")
   1600     let hi.=printf(" guifg=%s ", a:Dict['guifg'])
   1601   endif
   1602   let hi .= printf(' guibg=%s', bg)
   1603   let hi .= printf('%s', !empty(get(a:Dict, 'special', '')) ?
   1604         \ (' gui='. a:Dict.special) : '')
   1605 
   1606   if !s:HasGui()
   1607     let fg = get(a:Dict, 'ctermfg', '')
   1608     let bg = get(a:Dict, 'ctermbg', '')
   1609     let [fg, bg] = s:SwapColors([fg, bg])
   1610     if !empty(bg) || bg == 0
   1611       let hi.= printf(' ctermbg=%s', bg)
   1612     endif
   1613     if !empty(fg) || fg == 0
   1614       let hi.= printf(' ctermfg=%s', fg)
   1615     endif
   1616     let hi .= printf('%s', !empty(get(a:Dict, 'special','')) ?
   1617           \ (' cterm='. a:Dict.special) : '')
   1618     if has_key(a:Dict, "term")
   1619       let hi.=printf(" term=%s ", a:Dict['term'])
   1620     endif
   1621     if has_key(a:Dict, "cterm")
   1622       let hi.=printf(" cterm=%s ", a:Dict['cterm'])
   1623     endif
   1624   endif
   1625   call s:Exe(hi)
   1626 endfunction
   1627 
   1628 function! s:Exe(stmt)
   1629   "Don't error out for invalid colors
   1630   try
   1631     exe a:stmt
   1632   catch
   1633     " Only report errors, when debugging info is turned on
   1634     if s:debug
   1635       call s:Warn("Invalid statement: ".a:stmt)
   1636     endif
   1637   endtry
   1638 endfu
   1639 
   1640 function! s:SynID(group, ...)
   1641   let property = exists("a:1") ? a:1 : 'fg'
   1642   let c1 = synIDattr(synIDtrans(hlID(a:group)), property)
   1643   " since when can c1 be negative? Is this a vim bug?
   1644   " it used to be empty on errors or non-existing properties...
   1645   if empty(c1) || c1 < 0
   1646     return ''
   1647   else
   1648     return c1
   1649   endif
   1650 endfu
   1651 
   1652 function! s:GenerateColors(dict)
   1653   let result=copy(a:dict)
   1654 
   1655   if !has_key(result, 'bg') && has_key(result, 'ctermbg')
   1656     let result.bg = s:Term2RGB(result.ctermbg)
   1657   elseif !has_key(result, 'bg') && has_key(result, 'guibg')
   1658     let result.bg = result.guibg
   1659   endif
   1660   if !has_key(result, 'fg') && has_key(result, 'ctermfg')
   1661     let result.fg = s:Term2RGB(result.ctermfg)
   1662   elseif !has_key(result, 'fg') && has_key(result, 'guifg')
   1663     let result.fg = result.guifg
   1664   endif
   1665 
   1666   if !has_key(result, 'fg') &&
   1667         \ has_key(result, 'bg')
   1668     let result.fg = toupper(s:FGforBG(result.bg))
   1669   endif
   1670   if !has("gui_running")
   1671     " need to make sure, we have ctermfg/ctermbg values
   1672     if !has_key(result, 'ctermfg') &&
   1673           \ has_key(result, 'fg')
   1674       let result.ctermfg  = (s:term_true_color ? result.fg : s:Rgb2xterm(result.fg))
   1675     endif
   1676     if !has_key(result, 'ctermbg') &&
   1677           \ has_key(result, 'bg')
   1678       let result.ctermbg  = (s:term_true_color ? result.bg : s:Rgb2xterm(result.bg))
   1679     endif
   1680   endif
   1681   for key in keys(result)
   1682     if empty(result[key])
   1683       let result[key] = 0
   1684     endif
   1685   endfor
   1686   return result
   1687 endfunction
   1688 
   1689 function! s:SetMatcher(pattern, Dict)
   1690   let param = s:GenerateColors(a:Dict)
   1691   let clr = get(param, 'name', '')
   1692   if empty(clr)
   1693     let clr = 'Color_'. get(param, 'fg'). '_'. get(param, 'bg').
   1694           \ (!empty(get(param, 'special', '')) ?
   1695           \ ('_'. get(param, 'special')) : '')
   1696   endif
   1697   call s:SetMatch(clr, a:pattern, param)
   1698 endfunction
   1699 
   1700 function! s:SetMatch(group, pattern, param_dict)
   1701   call s:DoHlGroup(a:group, a:param_dict)
   1702   if has_key(a:param_dict, 'pos')
   1703     call matchaddpos(a:group, a:param_dict.pos, s:default_match_priority)
   1704     " do not add the pattern to the matchlist
   1705     call add(w:match_list, a:pattern)
   1706     return
   1707   endif
   1708   if s:DidColor(a:group, a:pattern)
   1709     return
   1710   endif
   1711   " let 'hls' overrule our syntax highlighting
   1712 
   1713   if s:use_virtual_text
   1714     call nvim_buf_set_virtual_text(0, 0, line('.')-1, [['  ', a:group]], {})
   1715   else
   1716     call matchadd(a:group, a:pattern, s:default_match_priority)
   1717     call add(w:match_list, a:pattern)
   1718   endif
   1719 endfunction
   1720 function! s:Xterm2rgb16(color)
   1721   " 16 basic colors
   1722   let r=0
   1723   let g=0
   1724   let b=0
   1725   let r = s:basic16[a:color][0]
   1726   let g = s:basic16[a:color][1]
   1727   let b = s:basic16[a:color][2]
   1728   return [ r, g, b ]
   1729 endfunction
   1730 
   1731 function! s:Xterm2rgb88(color)
   1732   " 16 basic colors
   1733   let r=0
   1734   let g=0
   1735   let b=0
   1736   if a:color < 16
   1737     return s:Xterm2rgb16(a:color)
   1738 
   1739     " 4x4x4 color cube
   1740   elseif a:color >= 16 && a:color < 80
   1741     let color=a:color-16
   1742     let r = s:valuerange4[(color/16)%4]
   1743     let g = s:valuerange4[(color/4)%4]
   1744     let b = s:valuerange4[color%4]
   1745     " gray tone
   1746   elseif a:color >= 80 && a:color <= 87
   1747     let color = (a:color-80) + 0.0
   1748     let r = 46.36363636 + color * 23.18181818 +
   1749           \ (color > 0.0 ? 23.18181818 : 0.0) +  0.0
   1750     let r = float2nr(r)
   1751     let g = r
   1752     let b = r
   1753   endif
   1754 
   1755   let rgb=[r,g,b]
   1756   return rgb
   1757 endfunction
   1758 
   1759 function! s:Xterm2rgb256(color)
   1760   " 16 basic colors
   1761   let r=0
   1762   let g=0
   1763   let b=0
   1764   if a:color < 16
   1765     return s:Xterm2rgb16(a:color)
   1766 
   1767     " color cube color
   1768   elseif a:color >= 16 && a:color < 232
   1769     let color=a:color-16
   1770     let r = s:valuerange6[(color/36)%6]
   1771     let g = s:valuerange6[(color/6)%6]
   1772     let b = s:valuerange6[color%6]
   1773 
   1774     " gray tone
   1775   elseif a:color >= 232 && a:color <= 255
   1776     let r = 8 + (a:color-232) * 0x0a
   1777     let g = r
   1778     let b = r
   1779   endif
   1780   let rgb=[r,g,b]
   1781   return rgb
   1782 endfunction
   1783 
   1784 function! s:RoundColor(...)
   1785   let result = []
   1786   let minlist = []
   1787   let min    = 1000
   1788   let list = (&t_Co == 256 ? s:valuerange6 : s:valuerange4)
   1789   if &t_Co > 16
   1790     for item in a:000
   1791       for val in list
   1792         let t = abs(val - item)
   1793         if (min > t)
   1794           let min = t
   1795           let r   = val
   1796         endif
   1797       endfor
   1798       call add(result, r)
   1799       call add(minlist, min)
   1800       let min = 1000
   1801     endfor
   1802   endif
   1803   if &t_Co <= 16
   1804     let result  = [ a:1, a:2, a:3 ]
   1805     let minlist = [ 255, 255, 255 ]
   1806   endif
   1807   " Check with the values from the 16 color xterm, if the difference
   1808   " is lower
   1809   let result = s:Check16ColorTerm(result, minlist)
   1810   return result
   1811 endfunction
   1812 
   1813 function! s:Check16ColorTerm(rgblist, minlist)
   1814   " We only check those values for 256 color terminals here:
   1815   " [205,0,0] [0,205,0] [205,205,0] [205,0,205]
   1816   " [0,205,205] [0,0,238] [92,92,255]
   1817   " The other values are already included in the s:colortable list
   1818   let min = a:minlist[0] + a:minlist[1] + a:minlist[2]
   1819   if &t_Co == 256
   1820     for value in [[205,0,0], [0,205,0], [205,205,0], [205,0,205],
   1821           \ [0,205,205], [0,0,238], [92,92,255]]
   1822       " euclidian distance would be needed,
   1823       " but this works good enough and is faster.
   1824       let t = abs(value[0] - a:rgblist[0]) +
   1825             \ abs(value[1] - a:rgblist[1]) +
   1826             \ abs(value[2] - a:rgblist[2])
   1827       if min > t
   1828         return value
   1829       endif
   1830     endfor
   1831   elseif &t_Co == 88
   1832     for value in [[0,0,238], [229,229,229], [127,127,127], [92,92,255]]
   1833       let t = abs(value[0] - a:rgblist[0]) +
   1834             \ abs(value[1] - a:rgblist[1]) +
   1835             \ abs(value[2] - a:rgblist[2])
   1836       if min > t
   1837         return value
   1838       endif
   1839     endfor
   1840   else " 16 color terminal
   1841     " Check for values from 16 color terminal
   1842     let best = []
   1843     let min  = 100000
   1844     let list = (&t_Co == 16 ? s:basic16 : s:basic16[:7])
   1845     for value in list
   1846       let t = abs(value[0] - a:rgblist[0]) +
   1847             \ abs(value[1] - a:rgblist[1]) +
   1848             \ abs(value[2] - a:rgblist[2])
   1849       if min > t
   1850         let min = t
   1851         let best = value
   1852       endif
   1853     endfor
   1854     return best
   1855   endif
   1856   return a:rgblist
   1857 endfunction
   1858 
   1859 function! s:Ansi2Color(chars)
   1860   " chars look like this
   1861   " 
   1862   if !exists("s:term2ansi")
   1863     let s:term2ansi = {}
   1864     " Color values taken from
   1865     " https://en.wikipedia.org/wiki/ANSI_escape_code#Colors
   1866     let s:term2ansi.std = { 30: printf("%.2X%.2X%.2X", 0,     0,   0),
   1867           \       31: printf("%.2X%.2X%.2X", 205,   0,   0),
   1868           \       32: printf("%.2X%.2X%.2X", 0,   205,   0),
   1869           \       33: printf("%.2X%.2X%.2X", 205, 205,   0),
   1870           \       34: printf("%.2X%.2X%.2X", 0,     0, 238),
   1871           \       35: printf("%.2X%.2X%.2X", 205,   0, 205),
   1872           \       36: printf("%.2X%.2X%.2X", 0,   205, 205),
   1873           \       37: printf("%.2X%.2X%.2X", 229, 229, 229),
   1874           \       90: printf("%.2X%.2X%.2X", 127, 127, 127),
   1875           \       91: printf("%.2X%.2X%.2X", 255,   0,   0),
   1876           \       92: printf("%.2X%.2X%.2X",   0, 255,   0),
   1877           \       93: printf("%.2X%.2X%.2X", 255, 255,   0),
   1878           \       94: printf("%.2X%.2X%.2X",  92,  92, 255),
   1879           \       95: printf("%.2X%.2X%.2X", 255,   0, 255),
   1880           \       96: printf("%.2X%.2X%.2X",   0, 255, 255),
   1881           \       97: printf("%.2X%.2X%.2X", 255, 255, 255)
   1882           \ }
   1883     let s:term2ansi.bold = { 30: printf("%.2X%.2X%.2X", 127, 127, 127),
   1884           \        31: printf("%.2X%.2X%.2X", 255,   0,   0),
   1885           \        32: printf("%.2X%.2X%.2X", 0,   255,   0),
   1886           \        33: printf("%.2X%.2X%.2X", 255, 255,   0),
   1887           \        34: printf("%.2X%.2X%.2X",  92,  92, 255),
   1888           \        35: printf("%.2X%.2X%.2X", 255,   0, 255),
   1889           \        36: printf("%.2X%.2X%.2X", 0,   255, 255),
   1890           \        37: printf("%.2X%.2X%.2X", 255, 255, 255),
   1891           \        90: printf("%.2X%.2X%.2X", 127, 127, 127),
   1892           \        91: printf("%.2X%.2X%.2X", 255,   0,   0),
   1893           \        92: printf("%.2X%.2X%.2X",   0, 255,   0),
   1894           \        93: printf("%.2X%.2X%.2X", 255, 255,   0),
   1895           \        94: printf("%.2X%.2X%.2X",  92,  92, 255),
   1896           \        95: printf("%.2X%.2X%.2X", 255,   0, 255),
   1897           \        96: printf("%.2X%.2X%.2X",   0, 255, 255),
   1898           \        97: printf("%.2X%.2X%.2X", 255, 255, 255)
   1899           \ }
   1900   endif
   1901 
   1902   let fground = ""
   1903   let bground = ""
   1904   let check = [0,0] " check fground and bground color
   1905 
   1906   if a:chars =~ '48;5;\d\+'
   1907     let check[0] = 0
   1908   elseif a:chars=~ '.*[39][0-7]\(;1\)\?[m;]'  " Check 30-37 and 90-97 colors
   1909     let check[0] = 1
   1910   elseif a:chars =~ '.*38\([:;]\)2\1'
   1911     let check[0] = 2 " Uses True Color Support
   1912   endif
   1913   if a:chars =~ '48;5;\d\+'
   1914     let check[1] = 3
   1915   elseif a:chars =~ '.*48\([:;]\)2\1'
   1916     let check[1] = 2
   1917   elseif a:chars=~ '.*4[0-7]\(;1\)\?[m;]'
   1918     let check[1] = 1
   1919   elseif a:chars=~ '.*10[0-7]\(;1\)\?[m;]'  " Same as 40-47
   1920     let check[1] = 1
   1921   endif
   1922 
   1923   if check[0] == 2
   1924     " Check for TrueColor Support
   1925     " Esc[38;2;<red>;<green>;<blue>
   1926     " 38: background color
   1927     " 48: foregournd color
   1928     " delimiter could be either : or ;
   1929     " skip leading ESC [ and trailing m char
   1930     let pat = split(a:chars[2:-2], '[:;]')
   1931     if pat[0] == 38 " background color
   1932       let fground = printf("%.2X%.2X%.2X", pat[2], pat[3], pat[4])
   1933     elseif a:pat[1] == 48 " foreground color
   1934       let bground = printf("%.2X%.2X%.2X", pat[2], pat[3], pat[4])
   1935     endif
   1936   elseif check[1] == 3
   1937     let nr = matchstr(a:chars, '\%x1b\[48;5;\zs\d\+\zem')
   1938     let bground = s:Term2RGB(nr)
   1939   else
   1940     for val in ["std", "bold"]
   1941       for key in keys(s:term2ansi[val])
   1942         let bright = (val == "std" ? "" : ";1")
   1943 
   1944         if check[0] " Check for a match of the foreground color
   1945           if a:chars =~ ".*".key.bright."[m;]"
   1946             let fground = s:term2ansi[val][key]
   1947           endif
   1948         endif
   1949         if check[1] "Check for background color
   1950           if a:chars =~ ".*".(key+10).bright."[m;]"
   1951             let bground = s:term2ansi[val][key]
   1952           endif
   1953         endif
   1954         if !empty(bground) && !empty(fground)
   1955           break
   1956         endif
   1957       endfor
   1958       if !empty(fground) && !empty(bground)
   1959         break
   1960       endif
   1961     endfor
   1962   endif
   1963   return [(empty(fground) ? 'NONE' : fground), (empty(bground) ? "NONE" : bground)]
   1964 endfunction
   1965 
   1966 function! s:TermConceal(pattern)
   1967   " Conceals a list of patterns
   1968   if exists("b:Schemer_did_syntax")
   1969     return
   1970   endif
   1971   let s:position = getpos('.')
   1972   " concealing
   1973   for pat in a:pattern
   1974     exe "syn match ColorTermESC /". pat. "/ conceal containedin=ALL"
   1975   endfor
   1976   setl cocu=nv cole=2
   1977   let b:Schemer_did_syntax=1
   1978 endfu
   1979 function! s:GetColorPattern(list)
   1980   "let list = map(copy(a:list), ' ''\%(-\@<!\<'' . v:val . ''\>-\@!\)'' ')
   1981   "let list = map(copy(a:list), ' ''\%(-\@<!\<'' . v:val . ''\>-\@!\)'' ')
   1982   let list = copy(a:list)
   1983   " Force the old re engine. It should be faster without backtracking.
   1984   return '\%#=1\%(\<\('.join(copy(a:list), '\|').'\)\>\)'
   1985 endfunction
   1986 
   1987 function! s:GetMatchList()
   1988   " this is window-local!
   1989   return filter(getmatches(), 'v:val.group =~ ''^\(Color_\w\+\)\|NONE''')
   1990 endfunction
   1991 
   1992 function! s:CheckTimeout(pattern, force)
   1993   " Abort, if pattern is not found within 100 ms and force
   1994   " is not set
   1995   return (!empty(a:force) || search(a:pattern, 'cnw', '', 100))
   1996 endfunction
   1997 
   1998 function! s:SaveRestoreOptions(save, dict, list)
   1999   if a:save
   2000     return s:SaveOptions(a:list)
   2001   else
   2002     for [key, value] in items(a:dict)
   2003       if key !~ '@'
   2004         call setbufvar('', '&'. key, value)
   2005       else
   2006         call call('setreg', [key[1]] + value)
   2007       endif
   2008       unlet value
   2009     endfor
   2010   endif
   2011 endfun
   2012 
   2013 function! s:SaveOptions(list)
   2014   let save = {}
   2015   for item in a:list
   2016     if item !~ '^@'
   2017       exe "let save.". item. " = &l:". item
   2018     else
   2019       let save[item] = []
   2020       call add(save[item], getreg(item[1]))
   2021       call add(save[item], getregtype(item))
   2022     endif
   2023     if item == 'ma' && !&l:ma
   2024       setl ma
   2025     elseif item == 'ro' && &l:ro
   2026       setl noro
   2027     elseif item == 'lz' && &l:lz
   2028       setl lz
   2029     elseif item == 'ed' && &g:ed
   2030       setl noed
   2031     elseif item == 'gd' && &g:gd
   2032       setl nogd
   2033     endif
   2034   endfor
   2035   return save
   2036 endfunction
   2037 
   2038 function! s:StripParentheses(val)
   2039   return split(matchstr(a:val, '^\(hsl\|rgb\)a\?\s*(\zs[^)]*\ze)'), '\s*,\s*')
   2040 endfunction
   2041 
   2042 function! s:ApplyAlphaValue(rgb)
   2043   " Add Alpha Value to RGB values
   2044   " takes a list of [ rr, gg, bb, aa] values
   2045   " alpha can be 0-1
   2046   let bg = <sid>SynID('Normal', 'bg')
   2047   if empty(bg)
   2048     return a:rgb[0:3]
   2049   else
   2050     if (bg =~? '\d\{1,3}') && bg < 256
   2051       " Xterm color code
   2052       " (add dummy in front of it, will be split later)
   2053       let bg = '#'.join(s:colortable[bg])
   2054     endif
   2055     let rgb = []
   2056     let bg_ = split(bg[1:], '..\zs')
   2057     let alpha = str2float(a:rgb[3])
   2058     if alpha > 1
   2059       let alpha = 1 + 0.0
   2060     elseif alpha < 0
   2061       let alpha = 0 + 0.0
   2062     endif
   2063     let i = 0
   2064     for value in a:rgb[0:2]
   2065       let value += 0 " convert to nr
   2066       let value = float2nr(ceil(value * alpha) + ceil((bg_[i]+0)*(1-alpha)))
   2067       if value > 255
   2068         let value = 255
   2069       elseif value < 0
   2070         let value = 0
   2071       endif
   2072       call add(rgb, value)
   2073       let i+=1
   2074       unlet value " reset type of value
   2075     endfor
   2076     return rgb
   2077   endif
   2078 endfunction
   2079 
   2080 function! s:HSL2RGB(h, s, l, ...)
   2081   let s = a:s + 0.0
   2082   let l = a:l + 0.0
   2083   if  l <= 0.5
   2084     let m2 = l * (s + 1)
   2085   else
   2086     let m2 = l + s - l * s
   2087   endif
   2088   let m1 = l * 2 - m2
   2089   let r = float2nr(s:Hue2RGB(m1, m2, a:h + 120))
   2090   let g = float2nr(s:Hue2RGB(m1, m2, a:h))
   2091   let b = float2nr(s:Hue2RGB(m1, m2, a:h - 120))
   2092   if a:0
   2093     let rgb = s:ApplyAlphaValue([r, g, b, a:1])
   2094   endif
   2095   return printf("%02X%02X%02X", r, g, b)
   2096 endfunction
   2097 
   2098 function! s:Hue2RGB(m1, m2, h)
   2099   let h = (a:h + 0.0)/360
   2100   if h < 0
   2101     let h = h + 1
   2102   elseif h > 1
   2103     let h = h - 1
   2104   endif
   2105   if h * 6 < 1
   2106     let res = a:m1 + (a:m2 - a:m1) * h * 6
   2107   elseif h * 2 < 1
   2108     let res = a:m2
   2109   elseif h * 3 < 2
   2110     let res = a:m1 + (a:m2 - a:m1) * (2.0/3.0 - h) * 6
   2111   else
   2112     let res = a:m1
   2113   endif
   2114   return round(res * 255)
   2115 endfunction
   2116 
   2117 function! s:Rgb2xterm(color)
   2118   " selects the nearest xterm color for a rgb value like #FF0000
   2119   " hard code values for 000000 and FFFFFF, they will be called many times
   2120   " so make this fast
   2121   if a:color ==# 'NONE'
   2122     return 'NONE'
   2123   endif
   2124   if len(a:color) <= 3
   2125     " a:color is already a terminal color
   2126     return a:color
   2127   endif
   2128   if !exists("s:colortable")
   2129     call s:ColorInit('')
   2130   endif
   2131   let color = (a:color[0] == '#' ? a:color[1:] : a:color)
   2132   if ( color == '000000')
   2133     return 0
   2134   elseif (color == 'FFFFFF')
   2135     return 15
   2136   else
   2137     let r = '0x'.color[0:1]+0
   2138     let g = '0x'.color[2:3]+0
   2139     let b = '0x'.color[4:5]+0
   2140 
   2141     " Try exact match first
   2142     let i = index(s:colortable, [r, g, b])
   2143     if i > -1
   2144       return i
   2145     endif
   2146 
   2147     " Grey scale ?
   2148     if ( r == g &&  r == b )
   2149       if &t_Co == 256
   2150         " 0 and 15 have already been take care of
   2151         if r < 5
   2152           return 0 " black
   2153         elseif r > 244
   2154           return 15 " white
   2155         endif
   2156         " grey cube starts at index 232
   2157         return 232+(r-5)/10
   2158       elseif &t_Co == 88
   2159         if r < 23
   2160           return 0 " black
   2161         elseif r < 69
   2162           return 80
   2163         elseif r > 250
   2164           return 15 " white
   2165         else
   2166           " should be good enough
   2167           return 80 + (r-69)/23
   2168         endif
   2169       endif
   2170     endif
   2171 
   2172     " Round to the next step in the xterm color cube
   2173     " euclidian distance would be needed,
   2174     " but this works good enough and is faster.
   2175     let round = s:RoundColor(r, g, b)
   2176     " Return closest match or -1 if not found
   2177     return index(s:colortable, round)
   2178   endif
   2179 endfunction
   2180 
   2181 function! s:Warn(msg)
   2182   let msg = 'Schemer: '. a:msg
   2183   echohl WarningMsg
   2184   echomsg msg
   2185   echohl None
   2186   let v:errmsg = msg
   2187 endfu
   2188 
   2189 function! s:LoadSyntax(file)
   2190   unlet! b:current_syntax
   2191   exe "sil! ru! syntax/".a:file. ".vim"
   2192 endfu
   2193 function! s:HasGui()
   2194   return has("gui_running") || (exists("+tgc") && &tgc)
   2195 endfu
   2196 function! s:HasColorPattern()
   2197   let _pos    = winsaveview()
   2198   try
   2199     if !exists("s:colornamepattern")
   2200       let s:colornamepattern = s:GetColorPattern(keys(s:colors))
   2201     endif
   2202     let pattern = values(s:color_patterns) + [s:colornamepattern]
   2203     call cursor(1,1)
   2204     for pat in pattern
   2205       if s:CheckTimeout(pat, '')
   2206         return 1
   2207       endif
   2208     endfor
   2209     return 0
   2210 
   2211   finally
   2212     call winrestview(_pos)
   2213   endtry
   2214 endfunction
   2215 
   2216 function! s:PrepareHSLArgs(list)
   2217   let hsl=a:list
   2218   let hsl[0] = (matchstr(hsl[0], '\d\+') + 360)%360
   2219   let hsl[1] = (matchstr(hsl[1], '\d\+') + 0.0)/100
   2220   let hsl[2] = (matchstr(hsl[2], '\d\+') + 0.0)/100
   2221   if len(hsl) == 4
   2222     return s:HSL2RGB(hsl[0], hsl[1], hsl[2], hsl[3])
   2223   endif
   2224   return s:HSL2RGB(hsl[0], hsl[1], hsl[2])
   2225 endfu
   2226 function! s:SyntaxMatcher(enable)
   2227   if !a:enable
   2228     return
   2229   endif
   2230   let did_clean = {}
   2231   "
   2232   let list=s:GetMatchList()
   2233   if len(list) > 1000
   2234     " This will probably slow
   2235     call s:Warn("Schemer many colors detected, syntax highlighting will probably slow down Vim considerably!")
   2236   endif
   2237   if &ft =~? 'css'
   2238     " cssColor defines some color names like yellow or red and overrules
   2239     " our colors
   2240     sil! syn clear cssColor
   2241   endif
   2242   for hi in list
   2243     if !get(did_clean, hi.group, 0)
   2244       let did_clean[hi.group] = 1
   2245       exe "sil! syn clear" hi.group
   2246     endif
   2247     if a:enable
   2248       if has_key(hi, 'pattern')
   2249         exe "syn match" hi.group "excludenl /". escape(hi.pattern, '/'). "/ display containedin=ALL"
   2250       else
   2251         " matchaddpos()
   2252         let line=hi.pos1[0]
   2253         let pos =hi.pos1[1]-1
   2254         let len =hi.pos1[1]+hi.pos1[2]-2
   2255         exe printf('syn match %s excludenl /\%%%dl\%%>%dc\&.*\%%<%dc/ display containedin=ALL', hi.group, line, pos, len)
   2256       endif
   2257       " We have syntax highlighting, can clear the matching
   2258       " ignore errors (just in case)
   2259       sil! call matchdelete(hi.id)
   2260     endif
   2261   endfor
   2262 endfu
   2263 
   2264 function! s:ColorOff()
   2265   for _match in s:GetMatchList()
   2266     sil! call matchdelete(_match.id)
   2267   endfor
   2268   call s:LocalFTAutoCmds(0)
   2269   if exists("s:conceal")
   2270     let [&l:cole, &l:cocu] = s:conceal
   2271     if !empty(hlID('ColorTermESC'))
   2272       syn clear ColorTermESC
   2273     endif
   2274   endif
   2275   unlet! b:Schemer_did_syntax w:match_list s:conceal
   2276 endfu
   2277 
   2278 function! s:DoColor(force, line1, line2, ...)
   2279   " initialize plugin
   2280   try
   2281     if v:version < 800 && !has('nvim')
   2282       call s:Warn("Schemer needs Vim 8.0")
   2283       return
   2284     endif
   2285     call s:ColorInit(a:force)
   2286     if exists("a:1") && !empty(a:1)
   2287       let s:color_syntax = ( a:1 =~# '^\%(syntax\|nomatch\)$' )
   2288     endif
   2289   catch /nocolor/
   2290     " nothing to do
   2291     call s:Warn("Your terminal doesn't support colors or no colors".
   2292           \ 'found in the current buffer!')
   2293     return
   2294   endtry
   2295   let error = ""
   2296 
   2297   let _a   = winsaveview()
   2298   let save = s:SaveRestoreOptions(1, {},
   2299         \ ['mod', 'ro', 'ma', 'lz', 'ed', 'gd', '@/'])
   2300   let s:relstart = s:Reltime()
   2301   let s_flags = s:use_virtual_text ? 'egi' : 'egin'
   2302 
   2303   " highlight Hex Codes:
   2304   "
   2305   " The :%s command is a lot faster than this:
   2306   ":g/#\x\{3,6}\>/call s:ColorMatchingLines(line('.'))
   2307   " Should color #FF0000
   2308   "              #F0F
   2309   "              #FFF
   2310   "
   2311   if &t_Co > 16 || s:HasGui()
   2312     " Also support something like
   2313     " CSS rgb(255,0,0)
   2314     "     rgba(255,0,0,1)
   2315     "     rgba(255,0,0,0.8)
   2316     "     rgba(255,0,0,0.2)
   2317     "     rgb(10%,0,100%)
   2318     "     hsl(0,100%,50%) -> hsl2rgb conversion RED
   2319     "     hsla(120,100%,50%,1) Lime
   2320     "     hsl(120,100%,25%) Darkgreen
   2321     "     hsl(120, 100%, 75%) lightgreen
   2322     "     hsl(120, 75%, 75%) pastelgreen
   2323     " highlight rgb(X,X,X) values
   2324     for Pat in values(s:color_patterns)
   2325       let start = s:Reltime()
   2326       if !get(g:, Pat[2], 1) || (get(g:, Pat[2]. '_disable', 0) > 0)
   2327         let Pat[4] = s:Reltime(start)
   2328         " Coloring disabled
   2329         continue
   2330       endif
   2331 
   2332       " 4th element in pattern is condition, that must be fullfilled,
   2333       " before we continue
   2334       if !empty(Pat[3]) && !eval(Pat[3])
   2335         let Pat[4] = s:Reltime(start)
   2336         continue
   2337       endif
   2338 
   2339       " Check, the pattern isn't too costly...
   2340       if s:CheckTimeout(Pat[0], a:force) && !s:IsInComment()
   2341         let cmd = printf(':sil keeppatterns %d,%d%ss/%s/\=call(Pat[1], [submatch(0)])/'. s_flags,
   2342               \ a:line1, a:line2, s:color_unfolded, Pat[0])
   2343         try
   2344           if Pat[2] ==# 'schemer_vimhighlight' && !empty(bufname(''))
   2345             " try to load the corresponding syntax file so the syntax
   2346             " groups will be defined
   2347             let s:extension = fnamemodify(expand('%'), ':t:r')
   2348             let s:old_syntax = exists("b:current_syntax") ? b:current_syntax : ''
   2349             call s:LoadSyntax(s:extension)
   2350           endif
   2351 
   2352           exe cmd
   2353           let Pat[4] = s:Reltime(start)
   2354 
   2355           if s:stop
   2356             break
   2357           endif
   2358 
   2359         catch
   2360           " some error occured, stop when finished (and don't setup auto
   2361           " comands
   2362           let error.=" Colorize: ". string(Pat)
   2363           break
   2364 
   2365         finally
   2366           if exists("s:extension")
   2367             call s:LoadSyntax(&ft)
   2368             unlet! s:extension
   2369           endif
   2370         endtry
   2371       endif
   2372     endfor
   2373   else
   2374     call s:Warn('Color configuration seems wrong, skipping colorization! Check t_Co setting!')
   2375   endif
   2376 
   2377   for Pat in [ s:color_patterns_special.term, s:color_patterns_special.term_nroff ]
   2378     if !get(g:, Pat[2], 1) || (get(s:, Pat[2]. '_disable', 0) > 0)
   2379       " Coloring disabled, skip
   2380       continue
   2381     endif
   2382     let start = s:Reltime()
   2383     if (s:CheckTimeout(Pat[0], a:force)) && !s:IsInComment()
   2384 
   2385 
   2386       if Pat[2] is# 'schemer_nroff'
   2387         let arg = '[submatch(0)]'
   2388       else
   2389         let arg = '[submatch(1), submatch(2), submatch(3)]'
   2390       endif
   2391       let cmd = printf(':sil keeppatterns %d,%d%ss/%s/\=call(Pat[1],%s)/'. s_flags,
   2392             \ a:line1, a:line2,  s:color_unfolded, Pat[0], arg)
   2393       try
   2394         exe cmd
   2395         let Pat[3] = s:Reltime(start)
   2396         " Hide ESC Terminal Chars
   2397         let start = s:Reltime()
   2398         call s:TermConceal(s:color_patterns_special.term_conceal[0])
   2399         let s:color_patterns_special.term_conceal[3] = s:Reltime(start)
   2400       catch
   2401         " some error occured, stop when finished (and don't setup auto
   2402         " comands
   2403         let error=" ColorTerm "
   2404         break
   2405       endtry
   2406     endif
   2407   endfor
   2408 
   2409   " convert matches into synatx highlighting, so TOhtml can display it
   2410   " correctly
   2411   call s:SyntaxMatcher(s:color_syntax)
   2412   if !exists("#FTSchemer#BufWinEnter#<buffer>") && empty(error)
   2413     " Initialise current window.
   2414     call s:LocalFTAutoCmds(1)
   2415     call s:ColorWinEnter(1, 1) " don't call DoColor recursively!
   2416   endif
   2417   let s:relstop = s:Reltime(s:relstart)
   2418   if !empty(error)
   2419     " Some error occured, stop trying to color the file
   2420     call s:ColorOff()
   2421     call s:Warn("Some error occured here: ". error)
   2422     if exists("s:position")
   2423       call s:Warn("Position: ". string(s:position))
   2424       call matchadd('Color_Error', '\%'.s:position[1].'l\%'.s:position[2].'c.*\>')
   2425     endif
   2426   endif
   2427   call s:PrintColorStatistics()
   2428   call s:SaveRestoreOptions(0, save, [])
   2429   call winrestview(_a)
   2430 endfu
   2431 
   2432 function! s:rgb2term(arg,bang)
   2433   if a:arg =~ '^rgb'
   2434     let clr    = s:StripParentheses(a:arg)
   2435     let color  = printf("#%02X%02X%02X", clr[0], clr[1], clr[2])
   2436   else
   2437     let color  = a:arg[0] == '#' ? a:arg : '#'.a:arg
   2438   endif
   2439 
   2440   call s:ColorInit(1)
   2441   let tcolor = s:Rgb2xterm(color)
   2442   if empty(a:bang)
   2443     call s:DoHlGroup("Color_". color[1:], s:GenerateColors({'bg': color[1:]}))
   2444     exe "echohl" "Color_".color[1:]
   2445     echo a:arg. " => ". tcolor
   2446     echohl None
   2447   endif
   2448   return tcolor
   2449 endfu
   2450 
   2451 function! s:AutoCmds(enable)
   2452   if a:enable && !get(g:, 'schemer_debug', 0)
   2453     aug Schemer
   2454       au!
   2455       if get(g:, 'schemer_insertleave', 1)
   2456         au InsertLeave *  sil call s:ColorLine('', line('w0'), line('w$'))
   2457       endif
   2458       if get(g:, 'schemer_textchangedi', 1)
   2459         au TextChangedI * sil call s:ColorLine('', line('.'),line('.'))
   2460       endif
   2461       if get(g:, 'schemer_guienter', 1)
   2462         au GUIEnter * sil call s:DoColor('!', 1, line('$'))
   2463       endif
   2464       if get(g:, 'schemer_colorscheme', 1)
   2465         au ColorScheme * sil call s:DoColor('!', 1, line('$'))
   2466       endif
   2467       if get(g:, 'schemer_bufwinenter', 1)
   2468         au BufWinEnter * sil call s:ColorWinEnter()
   2469       endif
   2470       if get(g:, 'schemer_winenter', 1)
   2471         au WinEnter * sil call s:ColorWinEnter()
   2472       endif
   2473     aug END
   2474   else
   2475     aug Schemer
   2476       au!
   2477     aug END
   2478     aug! Schemer
   2479   endif
   2480 endfu
   2481 
   2482 function! s:LocalFTAutoCmds(enable)
   2483   if a:enable
   2484     aug FTSchemer
   2485       au!
   2486       if !exists("#Schemer#InsertLeave") && get(g:, 'schemer_insertleave', 1)
   2487         " InsertLeave autocommand already exists
   2488         au InsertLeave <buffer> silent call
   2489               \ s:ColorLine('', line('w0'), line('w$'))
   2490       endif
   2491       if get(g:, 'schemer_cursormovedi', 1)
   2492         au CursorMovedI <buffer> call s:ColorLine('',line('.'), line('.'))
   2493       endif
   2494       if get(g:, 'schemer_cursormoved', 1)
   2495         au CursorMoved <buffer> call s:ColorLine('',line('.'), line('.'))
   2496       endif
   2497       if !exists("#Schemer#BufWinEnter") && get(g:, 'schemer_bufwinenter', 1)
   2498         au BufWinEnter <buffer> silent call s:ColorWinEnter()
   2499       endif
   2500       if !exists("#Schemer#WinEnter") && get(g:, 'schemer_winenter', 1)
   2501         au WinEnter <buffer> silent call s:ColorWinEnter()
   2502       endif
   2503       " disables colorizing on switching buffers inside a single window
   2504       if get(g:, 'schemer_bufleave', 1)
   2505         au BufLeave <buffer> if !get(g:, 'schemer_disable_bufleave', 0) | call s:ColorOff() |endif
   2506       endif
   2507       if !exists("#Schemer#GUIEnter") && get(g:, 'schemer_guienter', 1)
   2508         au GUIEnter <buffer> silent call s:DoColor('!', 1, line('$'))
   2509       endif
   2510       if !exists("#Schemer#ColorScheme") && get(g:, 'schemer_colorscheme', 1)
   2511         au ColorScheme <buffer> silent call s:DoColor('!', 1, line('$'))
   2512       endif
   2513     aug END
   2514     if !exists("b:undo_ftplugin")
   2515       " simply unlet a dummy variable
   2516       let b:undo_ftplugin = 'unlet! b:Schemer_foobar'
   2517     endif
   2518     " Delete specific auto commands, because the filetype
   2519     " has been changed.
   2520     let b:undo_ftplugin .= '| exe "sil! au! FTSchemer"'
   2521     let b:undo_ftplugin .= '| exe "sil! aug! FTSchemer"'
   2522     let b:undo_ftplugin .= '| exe ":call s:ColorOff()"'
   2523   else
   2524     aug FTSchemer
   2525       au!
   2526     aug END
   2527     aug! FTSchemer
   2528   endif
   2529 endfu
   2530 
   2531 function! s:ColorWinEnter(...)
   2532   let force = a:0 ? a:1 : 0
   2533   " be fast!
   2534   if !force
   2535     let ft_list = split(get(g:, "schemer_auto_filetype", ""), ',')
   2536     if match(ft_list, "^".&ft."$") == -1
   2537       " current filetype doesn't match g:schemer_auto_filetype,
   2538       " so nothing to do
   2539       return
   2540     endif
   2541     if get(b:, 'Schemer_changedtick', 0) == b:changedtick &&
   2542           \ !empty(getmatches())
   2543       " nothing to do
   2544       return
   2545     endif
   2546   endif
   2547   let g:schemer_only_unfolded = 1
   2548   let _c = getpos('.')
   2549   if !exists("a:2")
   2550     " don't call it recursively!
   2551     call s:DoColor('', 1, line('$'))
   2552   endif
   2553   let b:Schemer_changedtick = b:changedtick
   2554   unlet! g:schemer_only_unfolded
   2555   call setpos('.', _c)
   2556 endfu
   2557 
   2558 function! s:ColorLine(force, start, end)
   2559   if get(b:, 'Schemer_changedtick', 0) == b:changedtick && empty(a:force)
   2560     " nothing to do
   2561     return
   2562   else
   2563     call s:DoColor(a:force, a:start, a:end)
   2564     let b:Schemer_changedtick = b:changedtick
   2565   endif
   2566 endfu
   2567 
   2568 function! Schemer#ProcessFile(file) abort
   2569   let primary = []
   2570   let links = {}
   2571   let background = "light"
   2572 
   2573   let lines = readfile(a:file)
   2574   let nlines = len(lines)
   2575 
   2576   let colornames = {}
   2577   let ansis = []
   2578 
   2579   let cursor = 0
   2580 
   2581   while cursor < nlines
   2582     let line = lines[cursor]->trim()
   2583 
   2584     if line =~ "^palette:"
   2585       while 1
   2586         let cursor += 1
   2587         let line = lines[cursor]
   2588         if line->empty() || line =~ "^\""
   2589           continue
   2590         endif
   2591 
   2592         let entry = line->trim()->split()
   2593         if entry[1] !~ "\\.$"
   2594           let entry[1] = entry[1]->substitute(",", "", "g")
   2595           let colornames[entry[0]] = entry[1]
   2596         else
   2597           let entry[1] = entry[1]->substitute("\\.", "", "g")
   2598           let colornames[entry[0]] = entry[1]
   2599           break
   2600         endif
   2601       endwhile
   2602     elseif line =~ "^ansi:"
   2603       let ansis = split(line)[1:]->map({key, val -> (val->substitute(",", "", "")->trim())})
   2604     elseif line =~ "^link"
   2605       let splitline = line->split()
   2606       let from = splitline[1]->trim()
   2607       let to = splitline[2]->trim()
   2608 
   2609       for from_group in from->split(',')
   2610         let links[from_group] = to
   2611       endfor
   2612     elseif line->empty() || line =~ "^\""
   2613       " Do nothing
   2614     elseif line =~ "^background"
   2615       let background = line->split()[-1]
   2616     else
   2617       let line_arr = line->split()
   2618       let group = line_arr[0]
   2619       let rest = line_arr[1:-1]->join(' ')
   2620 
   2621       let rest_split = rest->split('\.')
   2622       let colors = rest_split[0]->split(',')->map('trim(v:val)')
   2623 
   2624       let fg = colors[0]
   2625       let fg = (fg !~ '^#' && fg !=# 'NONE') ? colornames[colors[0]] : colors[0]
   2626 
   2627       if len(colors) ==# 2 && !empty(colors[1]) && colors[1] !=# 'NONE'
   2628         let bg = (colors[1] =~ "^#") ? colors[1] : colornames[colors[1]]
   2629       else
   2630         let bg = 'NONE'
   2631       endif
   2632 
   2633       if len(rest_split) ==# 2
   2634         let attrs = rest_split[1]->split(',')->map('trim(v:val)')->join(',')
   2635       else
   2636         let attrs = 'NONE'
   2637       endif
   2638 
   2639       let primary = primary->add([group, fg, bg, attrs])
   2640     endif
   2641 
   2642     let cursor += 1
   2643   endwhile
   2644 
   2645   let outlines = []
   2646 
   2647   " Insert the preamble
   2648   call add(outlines, "set background=".background)
   2649   call add(outlines, "if version > 580")
   2650   call add(outlines, "  highlight clear")
   2651   call add(outlines, "  if exists(\"syntax_on\")")
   2652   call add(outlines, "    syntax reset")
   2653   call add(outlines, "  endif")
   2654   call add(outlines, "endif")
   2655   call add(outlines, "let g:colors_name = \"".(a:file->substitute(".*/", "", "")->substitute("\.schemer", "", ""))."\"")
   2656 
   2657   call add(outlines, "\"ANSI colors for :terminal")
   2658   call add(outlines, "let g:terminal_ansi_colors = [".ansis->map("'\"'.v:val.'\"'")->join(', ')."]")
   2659 
   2660   call add(outlines, "\" Highlight group definitions")
   2661   for item in primary
   2662     let itemline = "hi ".item[0]." guifg=".item[1]." guibg=".item[2]
   2663     let itemline .= " ctermfg=".(item[1] ==# "NONE" ? "NONE" : s:rgb2term(item[1][1:-1], 1))
   2664     let itemline .= " ctermbg=".(item[2] ==# "NONE" ? "NONE" : s:rgb2term(item[2][1:-1], 1))
   2665     let itemline .= " cterm=".item[3]." gui=".item[3]
   2666     call add(outlines, itemline)
   2667   endfor
   2668 
   2669   call add(outlines, "\" Link definitions")
   2670   for from_grp in keys(links)
   2671     let to_grp = links[from_grp]
   2672     call add(outlines, "hi! link ".from_grp." ".to_grp)
   2673   endfor
   2674 
   2675 
   2676   call add(outlines, "\" Code to clear any groups that are not defined")
   2677 
   2678   " Inspired by https://github.com/george-b/zenchrome
   2679   let defined_groups = links->keys()->extend(primary->deepcopy()->map("v:val[0]"))
   2680   call add(outlines, "let s:DefinedColors=".string(defined_groups->deepcopy()->map('tolower(v:val)')))
   2681   call add(outlines, "function! s:ClearUndefinedColors(colors)")
   2682   call add(outlines, "  let undefined_groups = filter(a:colors->keys()->map('tolower(v:val)'), 'index(s:DefinedColors, tolower(v:val)) < 0')")
   2683   call add(outlines, "  call map(undefined_groups, \"execute('highlight' . ' ' . v:val . ' ' . 'NONE')\")")
   2684   call add(outlines, "endfunction")
   2685   call add(outlines, "function! s:GetHighlights()")
   2686   call add(outlines, "  let highlights  = execute('highlight')")
   2687   call add(outlines, "  let highlights  = substitute(highlights, '\\n\\s\\+', ' ', 'g')")
   2688   call add(outlines, "  let highlights  = split(highlights, '\\n')")
   2689   call add(outlines, "  call map(highlights, \"split(v:val, '\\\\s\\\\+xxx\\\\s\\\\+')\")")
   2690   call add(outlines, "  call map(highlights, \"[copy(v:val)[0], split(copy(v:val)[1])]\")")
   2691   call add(outlines, "  return highlights")
   2692   call add(outlines, "endfunction")
   2693   call add(outlines, "function! s:GetColors()")
   2694   call add(outlines, "  let colors = {}")
   2695   call add(outlines, "  for [group, values] in <SID>GetHighlights()")
   2696   call add(outlines, "    let attributes = {}")
   2697   call add(outlines, "    if values[0] ==# 'links'")
   2698   call add(outlines, "      let attributes['links'] = values[-1]")
   2699   call add(outlines, "    elseif values[0] !=# 'cleared'")
   2700   call add(outlines, "      call map(values, \"split(v:val, '=')\")")
   2701   call add(outlines, "      call map(values, \"len(v:val) == 2 ? {v:val[0]: v:val[1]} : {v:val[0] : v:val[0]}\")")
   2702   call add(outlines, "      call map(values, \"extend(attributes, v:val)\")")
   2703   call add(outlines, "    endif")
   2704   call add(outlines, "    let colors[group] = attributes")
   2705   call add(outlines, "  endfor")
   2706   call add(outlines, "  return colors")
   2707   call add(outlines, "endfunction")
   2708   call add(outlines, "call <SID>ClearUndefinedColors(<SID>GetColors())")
   2709   let targetfile = getenv('HOME').'/.vim/colors/'.(a:file->substitute(".*/", "", "")->substitute('\.schemer', '.vim', ''))
   2710   call writefile(outlines, targetfile, "w")
   2711 
   2712   echom "Written to ~/.vim/colors/".(a:file->substitute(".*/", "", "")->substitute('\.schemer', '.vim', ''))
   2713 endfunction
   2714