aboutsummaryrefslogtreecommitdiff
path: root/src/theme.py
blob: 2144672107dacbf3bc418d2e8c7306896d103686 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
import yaml,re, sys,random

def configure(theme):
    """
    Apply user define colors and apply some correction factors.
    """
    if "colors" in theme:
        colors=theme["colors"]
        window_colors=theme["window_colors"]

        ##### Apply colors to window #####
        for key1,value1 in window_colors.items():
            for key2,value2 in value1.items():
                if re.match("#.*",value2) == None:
                    window_colors[key1][key2]=colors[value2]
        theme["window_colors"]=window_colors
        ##################################
                
        ##### Apply color to bar #####
        bar_colors=theme["bar_colors"]
        for key1,value1 in bar_colors.items():
            if isinstance(value1,dict):
                for key2,value2 in value1.items():
                    if re.match("#.*",value2) == None:
                        bar_colors[key1][key2]=colors[value2]
            else:
                if re.match("#.*",value1) == None:
                    bar_colors[key1]=colors[value1]
        theme["bar_colors"]=bar_colors
        ##############################
        
    ##### I3-style theme do not include child_border by default #####
    window_colors=theme["window_colors"]
    for key,value in window_colors.items():
        if not("child_border" in value):
            newvalue=value
            theme["window_colors"][key]["child_border"]=newvalue["border"] # Set it to border by default
    #################################################################
    return(theme)

def validate(theme):
    """
    Abort if theme is in a wrong format.
    """
    abort=lambda msg: sys.exit("Error while loading theme: "+msg)
    inv_key=lambda key: abort("invalid key \""+key+"\"")
    for key,value in theme.items():
        if not(key in ["meta","colors","window_colors","bar_colors"]):
            inv_key(key)
        if key=="bar_colors":
            for key,value in value.items():
                if not(key in ["separator","background","statusline",
                               "focused_workspace","active_workspace","inactive_workspace","urgent_workspace"]):
                    inv_key(key)
        if key=="window_colors":
            for key,value in value.items():
                if not(key in ["focused","focused_inactive","unfocused","urgent","child_border"]):
                    inv_key(key)
                    
def load(theme_file):
    """
    Load a theme as a dict():
      - Open YAML file
      - Parse it as a dict
      - Configure the parsed dict
      - Validate the configured dict
    """
    f=open(theme_file,mode="r")
    theme=yaml.load(f,Loader=yaml.FullLoader)
    f.close()
    theme=configure(theme)
    validate(theme)
    return(theme)


class ThemeBuilder:
    def __init__(self):
        self.theme={"meta": {"description": "Generated From i3-colors"},
                        "window_colors":dict(),
                        "bar_colors":dict()}
        self.vars=list()
        self.vars_values=dict()
        
    def as_yaml(self):
        return(yaml.dump(self.theme))

    def as_dict(self):
        return(self.theme)

        
    def get(self,key):
        if key in self.vars:
            return(self.vars_values[key])
        else:
            return(key)
        
    def parse(self,line):
        if re.match("client.*",line):
            tokens=line.split()
            key=tokens[0].replace("client.","")
            tokens.pop(0)
            subkeys=["border","background","text","indicator","child_border"]
            self.theme["window_colors"][key]=dict()
            for token in tokens:
                self.theme["window_colors"][key][subkeys[0]]=self.get(token)
                subkeys.pop(0)
        elif re.match(".*background.*",line):
            self.theme["bar_colors"]["background"]=self.get(line.split()[1])
        elif re.match(".*statusline.*",line):
            self.theme["bar_colors"]["statusline"]=self.get(line.split()[1])
        elif re.match(".*separator.*",line):
            self.theme["bar_colors"]["separator"]=self.get(line.split()[1])
        elif re.match(".*_workspace.*",line):
            tokens=line.split()
            key=tokens[0]
            tokens.pop(0)
            subkeys=["border","background","text"]
            self.theme["bar_colors"][key]=dict()
            for token in tokens:
                self.theme["bar_colors"][key][subkeys[0]]=self.get(token)
                subkeys.pop(0)
        elif re.match("(\s)*set\s",line):
            lineList=line.split()
            key=lineList.pop(0)
            name=lineList.pop(0)
            value=" ".join(str(x) for x in lineList)
            self.vars.append(name)
            self.vars_values[name]=value
            
def random_theme():
    r= lambda: "#"+hex(random.randint(0,16777214))[2:]
    t=ThemeBuilder()
    t.parse("client.focused          {} {} {} {} {}".format(r(),r(),r(),r(),r()))
    t.parse("client.unfocused          {} {} {} {} {}".format(r(),r(),r(),r(),r()))
    t.parse("client.urgent          {} {} {} {} {}".format(r(),r(),r(),r(),r()))
    t.parse("background          {}".format(r()))
    t.parse("statusline          {}".format(r()))
    t.parse("separator          {}".format(r()))
    t.parse("focused_workspace          {} {} {}".format(r(),r(),r()))
    t.parse("active_workspace          {} {} {}".format(r(),r(),r()))
    t.parse("inactive_workspace          {} {} {}".format(r(),r(),r()))
    t.parse("urgent_workspace          {} {} {}".format(r(),r(),r()))
    return(t)