#!/usr/bin/env python3 """ Based on labwc-gtktheme.py: Create labwc theme based on the current Gtk theme SPDX-License-Identifier: GPL-2.0-only Copyright (C) @Misko_2083 2019 Copyright (C) Johan Malm 2019-2022 """ import os import errno from tokenize import tokenize, NUMBER, NAME, OP from io import BytesIO import gi gi.require_version("Gtk", "3.0") from gi.repository import Gtk def parse(tokens): """ Parse css color expression token list and return red/green/blue values Valid name-tokens include 'rgb' and 'rgba', whereas 'alpha', 'shade' and 'mix' are ignored. @other-color references are still to be implemented. """ nr_colors_to_parse = 0 in_label = False color = [] for toknum, tokval, _, _, _ in tokens: if '@' in tokval: in_label = True continue if toknum == NAME and in_label: color.clear() color.append(f"@{tokval}") return color if nr_colors_to_parse > 0: if toknum == OP and tokval in ')': print("warn: still parsing numbers; did not expect ')'") if toknum == NUMBER: color.append(tokval) nr_colors_to_parse -= 1 continue if toknum == NAME and tokval in 'rgb': nr_colors_to_parse = 3 elif toknum == NAME and tokval in 'rgba': nr_colors_to_parse = 4 return color def color_hex(color): """ return rrggbb color hex from list [r, g, b,...] """ if not color: return "None" elif len(color) < 3: return f"{color[0]}" return '{:02x}{:02x}{:02x}'.format(*(int(x) for x in color[:3])) def hex_from_expr(line): """ parse color expression to return hex style rrggbb """ tokens = tokenize(BytesIO(line.encode('utf-8')).readline) color = parse(tokens) return color_hex(color) def parse_section(lines, name): theme = {} inside = False for line in lines: if f"{name} {{" in line: inside = True continue if inside: if "}" in line or "{" in line: inside = False break if 'color' not in line: continue key, value = line.strip().split(":", maxsplit=1) theme[f'{name}.{key.replace(" ", "")}'] = hex_from_expr(value) return theme def resolve_labels(theme): for key, label in theme.items(): if '@' in label: for tmp, value in theme.items(): if tmp == label[1:]: theme[key] = value return resolve_labels(theme) return theme def main(): """ main """ gset = Gtk.Settings.get_default() themename = gset.get_property("gtk-theme-name") css = Gtk.CssProvider.get_named(themename).to_string() lines = css.split("\n") theme = {} # Parse @define-color lines using syntax "@define-color " for line in lines: if "@define-color" not in line: continue x = line.split(" ", maxsplit=2) theme[x[1]] = hex_from_expr(x[2]) # Add the color definitions in the headerbar{} and menu{} sections theme |= parse_section(lines, "headerbar") theme |= parse_section(lines, "menu") theme = resolve_labels(theme) for key, value in theme.items(): print(f"{key}: {value}") return if __name__ == '__main__': main()