diff options
author | Josh Rahm <rahm@google.com> | 2021-09-23 10:38:10 -0600 |
---|---|---|
committer | Josh Rahm <rahm@google.com> | 2021-09-23 10:38:10 -0600 |
commit | 4b81c42c1495d65145011aafc4387a7e92c27128 (patch) | |
tree | 75bbfe18a5b361ec6d82b44247932ea00a87b08d /autoload/spectral.py | |
download | spectral.vim-4b81c42c1495d65145011aafc4387a7e92c27128.tar.gz spectral.vim-4b81c42c1495d65145011aafc4387a7e92c27128.tar.bz2 spectral.vim-4b81c42c1495d65145011aafc4387a7e92c27128.zip |
Initial commit for Spectral.vim.
Diffstat (limited to 'autoload/spectral.py')
-rw-r--r-- | autoload/spectral.py | 492 |
1 files changed, 492 insertions, 0 deletions
diff --git a/autoload/spectral.py b/autoload/spectral.py new file mode 100644 index 0000000..f7903aa --- /dev/null +++ b/autoload/spectral.py @@ -0,0 +1,492 @@ +import os + +import vim +import colormath +import colormath.color_diff +from colormath.color_objects import LabColor, sRGBColor +from colormath.color_conversions import convert_color +import sys +import math + +xterm_tbl = { + "000000": "016", + "00005f": "017", + "000087": "018", + "0000af": "019", + "0000d7": "020", + "0000ff": "021", + "005f00": "022", + "005f5f": "023", + "005f87": "024", + "005faf": "025", + "005fd7": "026", + "005fff": "027", + "008700": "028", + "00875f": "029", + "008787": "030", + "0087af": "031", + "0087d7": "032", + "0087ff": "033", + "00af00": "034", + "00af5f": "035", + "00af87": "036", + "00afaf": "037", + "00afd7": "038", + "00afff": "039", + "00d700": "040", + "00d75f": "041", + "00d787": "042", + "00d7af": "043", + "00d7d7": "044", + "00d7ff": "045", + "00ff00": "046", + "00ff5f": "047", + "00ff87": "048", + "00ffaf": "049", + "00ffd7": "050", + "00ffff": "051", + "5fff00": "082", + "5fff5f": "083", + "5fff87": "084", + "5fffaf": "085", + "5fffd7": "086", + "5fffff": "087", + "5fd700": "076", + "5fd75f": "077", + "5fd787": "078", + "5fd7af": "079", + "5fd7d7": "080", + "5fd7ff": "081", + "5faf00": "070", + "5faf5f": "071", + "5faf87": "072", + "5fafaf": "073", + "5fafd7": "074", + "5fafff": "075", + "5f8700": "064", + "5f875f": "065", + "5f8787": "066", + "5f87af": "067", + "5f87d7": "068", + "5f87ff": "069", + "5f5f00": "058", + "5f5f5f": "059", + "5f5f87": "060", + "5f5faf": "061", + "5f5fd7": "062", + "5f5fff": "063", + "5f0000": "052", + "5f005f": "053", + "5f0087": "054", + "5f00af": "055", + "5f00d7": "056", + "5f00ff": "057", + "8700ff": "093", + "8700d7": "092", + "8700af": "091", + "870087": "090", + "87005f": "089", + "870000": "088", + "875fff": "099", + "875fd7": "098", + "875faf": "097", + "875f87": "096", + "875f5f": "095", + "875f00": "094", + "8787ff": "105", + "8787d7": "104", + "8787af": "103", + "878787": "102", + "87875f": "101", + "878700": "100", + "87afff": "111", + "87afd7": "110", + "87afaf": "109", + "87af87": "108", + "87af5f": "107", + "87af00": "106", + "87d7ff": "117", + "87d7d7": "116", + "87d7af": "115", + "87d787": "114", + "87d75f": "113", + "87d700": "112", + "87ffff": "123", + "87ffd7": "122", + "87ffaf": "121", + "87ff87": "120", + "87ff5f": "119", + "87ff00": "118", + "afffff": "159", + "afffd7": "158", + "afffaf": "157", + "afff87": "156", + "afff5f": "155", + "afff00": "154", + "afd7ff": "153", + "afd7d7": "152", + "afd7af": "151", + "afd787": "150", + "afd75f": "149", + "afd700": "148", + "afafff": "147", + "afafd7": "146", + "afafaf": "145", + "afaf87": "144", + "afaf5f": "143", + "afaf00": "142", + "af87ff": "141", + "af87d7": "140", + "af87af": "139", + "af8787": "138", + "af875f": "137", + "af8700": "136", + "af5fff": "135", + "af5fd7": "134", + "af5faf": "133", + "af5f87": "132", + "af5f5f": "131", + "af5f00": "130", + "af00ff": "129", + "af00d7": "128", + "af00af": "127", + "af0087": "126", + "af005f": "125", + "af0000": "124", + "d70000": "160", + "d7005f": "161", + "d70087": "162", + "d700af": "163", + "d700d7": "164", + "d700ff": "165", + "d75f00": "166", + "d75f5f": "167", + "d75f87": "168", + "d75faf": "169", + "d75fd7": "170", + "d75fff": "171", + "d78700": "172", + "d7875f": "173", + "d78787": "174", + "d787af": "175", + "d787d7": "176", + "d787ff": "177", + "dfaf00": "178", + "dfaf5f": "179", + "dfaf87": "180", + "dfafaf": "181", + "dfafdf": "182", + "dfafff": "183", + "dfdf00": "184", + "dfdf5f": "185", + "dfdf87": "186", + "dfdfaf": "187", + "dfdfdf": "188", + "dfdfff": "189", + "dfff00": "190", + "dfff5f": "191", + "dfff87": "192", + "dfffaf": "193", + "dfffdf": "194", + "dfffff": "195", + "ffff00": "226", + "ffff5f": "227", + "ffff87": "228", + "ffffaf": "229", + "ffffdf": "230", + "ffffff": "231", + "ffdf00": "220", + "ffdf5f": "221", + "ffdf87": "222", + "ffdfaf": "223", + "ffdfdf": "224", + "ffdfff": "225", + "ffaf00": "214", + "ffaf5f": "215", + "ffaf87": "216", + "ffafaf": "217", + "ffafdf": "218", + "ffafff": "219", + "ff8700": "208", + "ff875f": "209", + "ff8787": "210", + "ff87af": "211", + "ff87df": "212", + "ff87ff": "213", + "ff5f00": "202", + "ff5f5f": "203", + "ff5f87": "204", + "ff5faf": "205", + "ff5fdf": "206", + "ff5fff": "207", + "ff0000": "196", + "ff005f": "197", + "ff0087": "198", + "ff00af": "199", + "ff00df": "200", + "ff00ff": "201", + "080808": "232", + "121212": "233", + "1c1c1c": "234", + "262626": "235", + "303030": "236", + "3a3a3a": "237", + "444444": "238", + "4e4e4e": "239", + "585858": "240", + "626262": "241", + "6c6c6c": "242", + "767676": "243", + "eeeeee": "255", + "e4e4e4": "254", + "dadada": "253", + "d0d0d0": "252", + "c6c6c6": "251", + "bcbcbc": "250", + "b2b2b2": "249", + "a8a8a8": "248", + "9e9e9e": "247", + "949494": "246", + "8a8a8a": "245", + "808080": "244", + "000000": "000", + "800000": "001", + "008000": "002", + "808000": "003", + "000080": "004", + "800080": "005", + "008080": "006", + "c0c0c0": "007", + "808080": "008", + "ff0000": "009", + "00ff00": "010", + "ffff00": "011", + "0000ff": "012", + "ff00ff": "013", + "00ffff": "014", + "ffffff": "015" +} + +xterm_tbl_lab = [(convert_color(sRGBColor.new_from_rgb_hex("#" + k), + LabColor), v) for (k, v) in xterm_tbl.items()] + + +def colors_name_from_file(file): + basename = os.path.basename(file) + if basename.endswith(".vim"): + return basename[:-4] + return basename + + +flip_algs = { + 'sqrt': math.sqrt, + 'cbrt': lambda x: math.pow(x, 1/3.), + '2/3': lambda x: math.pow(x, 2/3.), + 'linear': lambda x: x, + 'log': math.log +} + +class Vivid: + + def __init__(self, outfile): + self.outfilename = outfile + self.outfile = open(outfile, "w") + self.params = vim.eval("g:spectral_parameters") + self.default_bg = self.params.get("default_bg", "dark") + self.filter_fg = self.params.get("filter_fg", + [[1, 0, 0], [0, 1, 0], [0, 0, 1]]) + self.filter_bg = self.params.get("filter_bg", + [[1, 0, 0], [0, 1, 0], [0, 0, 1]]) + self.flip_algorithm = self.params.get("flip_algorithm", "sqrt") + + self.dark_highlights = [] + self.light_highlights = [] + self.after_highlights = [] + + def writeln(self, str): + self.outfile.write(str + "\n") + + def start(self): + self.writeln(""" +hi clear +if exists('syntax_on') + syntax reset +endif +" Default BG = """ + self.default_bg + """ +" Filter FG = """ + str(self.filter_fg) + """ +" Filter BG = """ + str(self.filter_bg) + """ +let g:colors_name="%s" +""" % (colors_name_from_file(self.outfilename))) + + def highlight_dark(self, name, fg, bg, sp, extra): + self._highlight_dark(name, apply_filter(self.filter_fg, fg), + apply_filter(self.filter_bg, bg), sp, extra) + + def highlight_light(self, name, fg, bg, sp, extra): + self._highlight_light(name, apply_filter(self.filter_fg, fg), + apply_filter(self.filter_bg, bg), sp, extra) + + def _highlight_dark(self, name, fg, bg, sp, extra): + self.dark_highlights.append( + "highlight! %s guifg=%s guibg=%s guisp=%s ctermfg=%s ctermbg=%s %s %s" % + (name, fg, bg, sp, self.project(fg), self.project(bg), + to_gui(",".join(extra)), to_cterm(",".join(extra)))) + + def _highlight_light(self, name, fg, bg, sp, extra): + self.light_highlights.append( + "highlight! %s guifg=%s guibg=%s guisp=%s ctermfg=%s ctermbg=%s %s %s" % + (name, fg, bg, sp, self.project(fg), self.project(bg), + to_gui(",".join(extra)), to_cterm(",".join(extra)))) + + def highlight_after(self, name, fg, bg, sp, extra): + self.after_highlights.append( + "highlight! %s guifg=%s guibg=%s guisp=%s ctermfg=%s ctermbg=%s %s %s" % + (name, fg, bg, sp, self.project(fg), self.project(bg), + to_gui(",".join(extra)), to_cterm(",".join(extra)))) + + def highlight(self, name, fg, bg, sp, extra): + if self.default_bg == "light": + self.highlight_light(name, fg, bg, sp, extra) + self.highlight_dark( + name, + self.flip_brightness(fg), + self.flip_brightness(bg), + self.flip_brightness(sp), + extra) + else: + self.highlight_dark(name, fg, bg, sp, extra) + self.highlight_light( + name, + self.flip_brightness(fg), + self.flip_brightness(bg), + self.flip_brightness(sp), + extra) + + def project(self, color_hex): + if color_hex == "None": + return "None" + + lab_color = convert_color(sRGBColor.new_from_rgb_hex(color_hex), LabColor) + + min_value = "0" + min_number = 100000000 + + for (k, v) in xterm_tbl_lab: + number = colormath.color_diff.delta_e_cie2000(k, lab_color) + if number < min_number: + min_number = number + min_value = v + + return min_value + + def finish(self): + self.writeln("if &bg == 'dark'") + for l in self.dark_highlights: + self.writeln(l) + self.writeln("else") + for l in self.light_highlights: + self.writeln(l) + self.writeln("endif") + for l in self.after_highlights: + self.writeln(l) + + self.outfile.flush() + self.outfile.close() + + def flip_brightness(self, color_hex): + if color_hex == "None": + return color_hex + + color = sRGBColor.new_from_rgb_hex(color_hex) + color_lab = convert_color(color, LabColor) + (l, a, b) = color_lab.get_value_tuple() + + lf = l / 100.0 + lf = 1 - lf + + lf = flip_algs[self.flip_algorithm](lf) + + new_lab = LabColor(lf * 100, a, b) + + return get_rgb_hex(convert_color(new_lab, sRGBColor)) + +def spectral_flip_brightness(color_hex): + c = spectral_ctx.flip_brightness(color_hex) + vim.command('let g:return="%s"' % c) + +def spectral_highlight(name, fg, bg): + spectral_ctx.highlight(name, fg, bg) + + +def spectral_start(outfile): + global spectral_ctx + spectral_ctx = Vivid(outfile) + spectral_ctx.start() + + +def lighter(color, amt): + if isinstance(color, str): + color = sRGBColor.new_from_rgb_hex(color) + + color_lab = convert_color(color, LabColor) + (l, a, b) = color_lab.get_value_tuple() + new_lab = LabColor(l * amt, a, b) + + return convert_color(new_lab, sRGBColor) + + +def spectral_lighter(color, amt): + c = lighter(color, amt) + vim.command('let g:return="#%02x%02x%02x"' % + (int(c.clamped_rgb_r * 255), int( + c.clamped_rgb_g * 255), int(c.clamped_rgb_b * 255))) + + +def get_rgb_hex(c): + # why colormath no clip values?! + (r, g, b) = c.get_upscaled_value_tuple() + return "#%02x%02x%02x" % (min(r, 255), min(g, 255), min(b, 255)) + + +def to_gui(s): + if s: + return "gui=" + s + else: + return "" + + +def to_cterm(s): + if s: + return "cterm=" + s + else: + return "" + + +def spectral_finish(): + spectral_ctx.finish() + + +def apply_filter(filter, color_hex): + if color_hex == "None": + return "None" + + r = int(color_hex[1:3], 16) / 255. + g = int(color_hex[3:5], 16) / 255. + b = int(color_hex[5:7], 16) / 255. + + rn = ( + float(filter[0][0]) * r + float(filter[0][1]) * g + + float(filter[0][2]) * b) + + gn = ( + float(filter[1][0]) * r + float(filter[1][1]) * g + + float(filter[1][2]) * b) + + bn = ( + float(filter[2][0]) * r + float(filter[2][1]) * g + + float(filter[2][2]) * b) + + def clip(n): + return int(max(min(n, 255), 0)) + + return "#%02x%02x%02x" % (clip(rn * 255), clip(gn * 255), clip(bn * 255)) |