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
144
145
146
147
148
149
150
151
|
import re,tempfile,shutil,theme
config_keys=["client.focused",
"client.focused_inactive",
"client.unfocused",
"client.urgent",
"separator",
"background",
"statusline",
"focused_workspace",
"active_workspace",
"inactive_workspace",
"urgent_workspace"]
##### Parsing Utils #####
def contains(r,line):
"""
Return true if line contains regex r.
"""
return(re.match(r,line)!=None)
def before_token(token, line):
"""
Return what is before token in line.
"""
found=re.search(".*"+token,line)
if found:
return(found.group(0)[:-len(token)])
return("")
def sorted_items(d):
"""
Mainly used for integration testing (to keep having deterministic results).
"""
return(sorted(d.items()))
def no_comment(line):
"""
Remove comment from a line.
"""
newline=""
for ch in line:
if ch=='#':
break
else:
newline+=ch
return(newline)
#########################
def extract(config_file):
"""
Return a temporary file path containing the current user configuration
without any related theme/colors lines.
"""
f=open(config_file,"r")
tmp=tempfile.NamedTemporaryFile(mode="w",delete=False)
in_colors=False
for line_orig in f:
line=no_comment(line_orig)
is_theme_line=False
for key in config_keys:
if contains(".*"+key+"\s",line):
is_theme_line=True
if contains(".*colors",line):
in_colors=True
beforeColor=before_token("colors",line).strip()
if len(beforeColor)>0:
tmp.write(beforeColor+"\n")
if not(is_theme_line) and not(in_colors):
tmp.write(line_orig)
if contains(".*}",line) and in_colors:
in_colors=False
f.close()
tmp.close()
return(tmp.name)
def extract_theme(config_file):
"""
Return a ThemeBuilder object of the config_file file.
"""
f=open(config_file,"r")
build=theme.ThemeBuilder()
in_colors=False
for line_orig in f:
line=no_comment(line_orig)
is_theme_line=False
for key in config_keys:
if contains(".*"+key+"\s",line):
is_theme_line=True
if contains(".*colors",line):
in_colors=True
if contains("(\s)*set",line): # If var definition
build.parse(line_orig)
elif is_theme_line or in_colors:
build.parse(line_orig) # Seems to by strange to have comment here
if contains(".*}",line) and in_colors:
in_colors=False
f.close()
return(build)
def write_theme(tmp_config,theme):
"""
Write the theme in a temporary file
based on tmp_config file.
"""
f=open(tmp_config,mode="r")
tmp=tempfile.NamedTemporaryFile(mode="w",delete=False)
##### Apply bar theme #####
bar_theme=theme["bar_colors"]
in_bar=False
for line_orig in f:
line=no_comment(line_orig)
if contains("(\s)*bar",line):
in_bar=True
if contains(".*}",line) and in_bar:
beforeBrace=before_token("}",line).strip()
if len(beforeBrace)>0:
tmp.write(beforeBrace+"\n")
tmp.write(" colors {\n")
for key,value in sorted_items(bar_theme):
if not(isinstance(value,dict)):
tmp.write(" "+key+" "+value+"\n")
else:
tmp.write(" "+key+" "+value["border"]+" "+value["background"]+" "+value["text"]+"\n")
tmp.write(" }\n}\n")
in_bar=False
else:
tmp.write(line_orig)
tmp.close()
f.close()
shutil.move(tmp.name,tmp_config)
##### Apply client theme #####
client_theme=theme["window_colors"]
f=open(tmp_config,mode="a")
for key,value in sorted_items(client_theme):
f.write("client."+key+" "+value["border"]+" "+value["background"]+" "+value["text"]+" "+value["indicator"]+" "+value["child_border"]+"\n")
f.close()
def apply(config_file,theme,dry=False):
tmp=extract(config_file)
write_theme(tmp,theme)
f=open(tmp,mode="r")
new_config=f.read()
f.close()
if not(dry):
shutil.move(tmp,config_file)
return(new_config)
|