hadalized 0.4.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,233 @@
1
+ # This theme is autogenerated by the hadalized theme generation tool
2
+ "$schema" = "https://starship.rs/config-schema.json"
3
+
4
+ scan_timeout = 200
5
+
6
+ format = """
7
+ [](rose)\
8
+ $env_var\
9
+ $os\
10
+ $username\
11
+ $hostname\
12
+ $localip\
13
+ $shlvl\
14
+ [](bg:blue fg:rose)\
15
+ $directory\
16
+ [](bg:magenta fg:blue)\
17
+ $git_branch\
18
+ $git_state\
19
+ $git_metrics\
20
+ $git_status\
21
+ [](fg:magenta bg:green)\
22
+ $c\
23
+ $rust\
24
+ $golang\
25
+ $nodejs\
26
+ $php\
27
+ $java\
28
+ $kotlin\
29
+ $haskell\
30
+ $python\
31
+ $package\
32
+ [](fg:green bg:azure)\
33
+ $conda\
34
+ [](fg:azure bg:violet)\
35
+ $time\
36
+ [ ](fg:violet)\
37
+ $cmd_duration\
38
+ $line_break\
39
+ $character"""
40
+
41
+ palette = "hadalized"
42
+
43
+ [env_var.STARSHIP_SHELL]
44
+ style = "bg:rose fg:bg"
45
+ format = "[ $env_value ]($style)"
46
+
47
+ [os]
48
+ disabled = false
49
+ style = "bg:rose fg:bg"
50
+
51
+ [os.symbols]
52
+ Alpaquita = " "
53
+ Alpine = " "
54
+ AlmaLinux = " "
55
+ Amazon = " "
56
+ Android = " "
57
+ AOSC = " "
58
+ Arch = " "
59
+ Artix = " "
60
+ CachyOS = " "
61
+ CentOS = " "
62
+ Debian = " "
63
+ DragonFly = " "
64
+ Elementary = " "
65
+ Emscripten = " "
66
+ EndeavourOS = " "
67
+ Fedora = " "
68
+ FreeBSD = " "
69
+ Garuda = "󰛓 "
70
+ Gentoo = " "
71
+ HardenedBSD = "󰞌 "
72
+ Illumos = "󰈸 "
73
+ Ios = "󰀷 "
74
+ Kali = " "
75
+ Linux = " "
76
+ Mabox = " "
77
+ Macos = " "
78
+ Manjaro = " "
79
+ Mariner = " "
80
+ MidnightBSD = " "
81
+ Mint = " "
82
+ NetBSD = " "
83
+ NixOS = " "
84
+ Nobara = " "
85
+ OpenBSD = "󰈺 "
86
+ openSUSE = " "
87
+ OracleLinux = "󰌷 "
88
+ Pop = " "
89
+ Raspbian = " "
90
+ Redhat = " "
91
+ RedHatEnterprise = " "
92
+ RockyLinux = " "
93
+ Redox = "󰀘 "
94
+ Solus = "󰠳 "
95
+ SUSE = " "
96
+ Ubuntu = " "
97
+ Unknown = " "
98
+ Void = " "
99
+ Windows = "󰍲 "
100
+ Zorin = " "
101
+
102
+ [username]
103
+ show_always = true
104
+ style_user = "bg:rose fg:bg"
105
+ style_root = "bg:red fg:bg"
106
+ format = "[ $user]($style)"
107
+
108
+ [directory]
109
+ style = "bg:blue fg:bg"
110
+ format = "[ $path ]($style)"
111
+ truncation_length = 3
112
+ truncation_symbol = "…/"
113
+
114
+ [directory.substitutions]
115
+ ".config" = " "
116
+ ".git" = " "
117
+ "Documents" = "󰈙 "
118
+ "Downloads" = " "
119
+ "Music" = "󰝚 "
120
+ "Pictures" = " "
121
+ "Developer" = "󰲋 "
122
+ src = "󰲋 "
123
+
124
+ [git_branch]
125
+ symbol = ""
126
+ style = "bg:magenta"
127
+ format = "[[ $symbol $branch ](fg:bg bg:magenta)]($style)"
128
+
129
+ [git_status]
130
+ style = "bg:magenta"
131
+ format = "[[($all_status$ahead_behind )](fg:bg bg:magenta)]($style)"
132
+
133
+ [nodejs]
134
+ symbol = ""
135
+ style = "bg:green"
136
+ format = "[[ $symbol( $version) ](fg:bg bg:green)]($style)"
137
+
138
+ [package]
139
+ style = "bg:green fg:bg"
140
+ symbol = "󰏗 "
141
+ format = '[$symbol$version]($style)'
142
+
143
+
144
+ [c]
145
+ symbol = " "
146
+ style = "bg:green"
147
+ format = "[[ $symbol( $version) ](fg:bg bg:green)]($style)"
148
+
149
+ [rust]
150
+ symbol = ""
151
+ style = "bg:green"
152
+ format = "[[ $symbol( $version) ](fg:bg bg:green)]($style)"
153
+
154
+ [golang]
155
+ symbol = ""
156
+ style = "bg:green"
157
+ format = "[[ $symbol( $version) ](fg:bg bg:green)]($style)"
158
+
159
+ [php]
160
+ symbol = ""
161
+ style = "bg:green"
162
+ format = "[[ $symbol( $version) ](fg:bg bg:green)]($style)"
163
+
164
+ [java]
165
+ symbol = " "
166
+ style = "bg:green"
167
+ format = "[[ $symbol( $version) ](fg:bg bg:green)]($style)"
168
+
169
+ [kotlin]
170
+ symbol = ""
171
+ style = "bg:green"
172
+ format = "[[ $symbol( $version) ](fg:bg bg:green)]($style)"
173
+
174
+ [haskell]
175
+ symbol = ""
176
+ style = "bg:green"
177
+ format = "[[ $symbol( $version) ](fg:bg bg:green)]($style)"
178
+
179
+ [python]
180
+ symbol = ""
181
+ style = "bg:green"
182
+ format = '[[ $symbol( $version)( \($virtualenv\)) ](fg:bg bg:green)]($style)'
183
+
184
+ [docker_context]
185
+ symbol = ""
186
+ style = "bg:azure"
187
+ format = "[[ $symbol( $context) ](fg:bg bg:azure)]($style)"
188
+
189
+ [conda]
190
+ symbol = "  "
191
+ style = "fg:bg bg:azure"
192
+ format = "[$symbol$environment ]($style)"
193
+ ignore_base = false
194
+
195
+ [time]
196
+ disabled = false
197
+ time_format = "%R"
198
+ style = "bg:violet"
199
+ format = "[[  $time ](fg:bg bg:violet)]($style)"
200
+
201
+ [line_break]
202
+ disabled = false
203
+
204
+ [character]
205
+ disabled = false
206
+ success_symbol = "[❯](bold fg:green)"
207
+ error_symbol = "[❯](bold fg:red)"
208
+ vimcmd_symbol = "[❮](bold fg:green)"
209
+ vimcmd_replace_one_symbol = "[❮](bold fg:violet)"
210
+ vimcmd_replace_symbol = "[❮](bold fg:violet)"
211
+ vimcmd_visual_symbol = "[❮](bold fg:yellow)"
212
+
213
+ [cmd_duration]
214
+ show_milliseconds = true
215
+ format = " $duration "
216
+ style = "bg:violet"
217
+ disabled = false
218
+ show_notifications = true
219
+ min_time_to_notify = 45000
220
+
221
+ {% for palette in context.palettes.values() %}
222
+ [palettes."{{palette.name}}"]
223
+ name = "{{ palette.name }}"
224
+ gamut = "{{ palette.gamut }}"
225
+ mode = "{{ palette.mode }}"
226
+ {% for name, code in palette.hue -%}
227
+ {{name}} = "{{code}}"
228
+ {% endfor -%}
229
+ {% for name, code in palette.base -%}
230
+ {{ name }} = "{{code}}"
231
+ {% endfor -%}
232
+ {% endfor %}
233
+
@@ -0,0 +1,45 @@
1
+ # Autogenerated file defining a wezterm colorscheme.
2
+ # WARNING: Do not edit by hand.
3
+ # Pass in a Palette instance, e.g., palette.hex()
4
+
5
+ [colors]
6
+ ansi = [
7
+ "{{context.base.hidden}}",
8
+ "{{context.hue.red}}",
9
+ "{{context.hue.green}}",
10
+ "{{context.hue.yellow}}",
11
+ "{{context.hue.blue}}",
12
+ "{{context.hue.magenta}}",
13
+ "{{context.hue.cyan}}",
14
+ "{{context.base.fg}}",
15
+ ]
16
+ brights = [
17
+ "{{context.base.subfg}}",
18
+ "{{context.hue.rose}}",
19
+ "{{context.hue.lime}}",
20
+ "{{context.hue.orange}}",
21
+ "{{context.hue.azure}}",
22
+ "{{context.hue.violet}}",
23
+ "{{context.hue.mint}}",
24
+ "{{context.base.op2}}",
25
+ ]
26
+
27
+ background = "{{context.base.bg}}"
28
+ foreground = "{{context.base.fg}}"
29
+ cursor_border = "{{context.base.op}}"
30
+ cursor_bg = "{{context.base.bg6}}"
31
+ cursor_fg = "{{context.base.emph}}"
32
+ selection_bg = "{{context.base.bg3}}"
33
+ selection_fg = "{{context.base.subfg}}"
34
+
35
+ [colors.indexed]
36
+
37
+ [metadata]
38
+ name = "{{context.name}}"
39
+ origin_url = "https://github.com/shawnohare/hadalized.nvim"
40
+
41
+ [metadata.palette]
42
+ name = "{{context.name}}"
43
+ desc = "{{context.desc}}"
44
+ gamut = "{{context.gamut}}"
45
+ mode = "{{context.mode}}"
hadalized/web.py ADDED
@@ -0,0 +1,168 @@
1
+ """Named CSS Colors."""
2
+
3
+ from hadalized.color import ColorField, ColorMap
4
+
5
+
6
+ class CSSNamedColors(ColorMap):
7
+ """Standard CSS named colors as ColorInfo objects.
8
+
9
+ Generally there is only a single instance of this class,
10
+ with the values defined lazily in the `get` method.
11
+ """
12
+
13
+ pink: ColorField = "oklch(0.86774 0.07354 7.0855)"
14
+ lightpink: ColorField = "oklch(0.84739 0.08579 9.0865)"
15
+ snow: ColorField = "oklch(0.98894 0.00534 17.247)"
16
+ rosybrown: ColorField = "oklch(0.69274 0.0548 18.565)"
17
+ crimson: ColorField = "oklch(0.57119 0.22194 20.087)"
18
+ lightcoral: ColorField = "oklch(0.72464 0.13774 21.029)"
19
+ indianred: ColorField = "oklch(0.61544 0.14415 22.228)"
20
+ mistyrose: ColorField = "oklch(0.94001 0.03008 25.281)"
21
+ brown: ColorField = "oklch(0.48061 0.15966 25.562)"
22
+ firebrick: ColorField = "oklch(0.49677 0.17969 26.815)"
23
+ salmon: ColorField = "oklch(0.735 0.15151 28.06)"
24
+ maroon: ColorField = "oklch(0.37669 0.15458 29.234)"
25
+ darkred: ColorField = "oklch(0.39986 0.16408 29.234)"
26
+ red: ColorField = "oklch(0.62796 0.25768 29.234)"
27
+ tomato: ColorField = "oklch(0.69622 0.19552 32.321)"
28
+ orangered: ColorField = "oklch(0.6602 0.22936 35.403)"
29
+ darksalmon: ColorField = "oklch(0.75074 0.10818 39.394)"
30
+ coral: ColorField = "oklch(0.73511 0.16799 40.247)"
31
+ lightsalmon: ColorField = "oklch(0.79376 0.12483 42.425)"
32
+ sienna: ColorField = "oklch(0.52648 0.11512 44.604)"
33
+ chocolate: ColorField = "oklch(0.6344 0.15499 50.266)"
34
+ saddlebrown: ColorField = "oklch(0.47078 0.11214 50.845)"
35
+ seashell: ColorField = "oklch(0.97602 0.01425 57.592)"
36
+ darkorange: ColorField = "oklch(0.75054 0.17911 58.283)"
37
+ sandybrown: ColorField = "oklch(0.784 0.12691 59.71)"
38
+ peru: ColorField = "oklch(0.67819 0.12275 62.182)"
39
+ peachpuff: ColorField = "oklch(0.91125 0.06 63.699)"
40
+ linen: ColorField = "oklch(0.96024 0.01715 67.622)"
41
+ orange: ColorField = "oklch(0.79269 0.17103 70.67)"
42
+ bisque: ColorField = "oklch(0.93286 0.05145 71.849)"
43
+ burlywood: ColorField = "oklch(0.80454 0.07786 73.417)"
44
+ tan: ColorField = "oklch(0.78619 0.06382 74.619)"
45
+ antiquewhite: ColorField = "oklch(0.94669 0.03108 75.219)"
46
+ navajowhite: ColorField = "oklch(0.9164 0.07301 77.436)"
47
+ blanchedalmond: ColorField = "oklch(0.94844 0.04493 78.06)"
48
+ papayawhip: ColorField = "oklch(0.95808 0.03826 80.032)"
49
+ moccasin: ColorField = "oklch(0.92962 0.06754 81.379)"
50
+ darkgoldenrod: ColorField = "oklch(0.65207 0.1322 81.572)"
51
+ wheat: ColorField = "oklch(0.90883 0.0615 83.033)"
52
+ oldlace: ColorField = "oklch(0.97234 0.02156 83.264)"
53
+ goldenrod: ColorField = "oklch(0.75157 0.14693 83.988)"
54
+ floralwhite: ColorField = "oklch(0.98623 0.01422 84.583)"
55
+ gold: ColorField = "oklch(0.88677 0.18219 95.33)"
56
+ cornsilk: ColorField = "oklch(0.9773 0.03726 95.439)"
57
+ lemonchiffon: ColorField = "oklch(0.97781 0.05822 102.16)"
58
+ khaki: ColorField = "oklch(0.91349 0.11192 102.83)"
59
+ palegoldenrod: ColorField = "oklch(0.92105 0.07981 103.18)"
60
+ darkkhaki: ColorField = "oklch(0.76747 0.09804 104.51)"
61
+ ivory: ColorField = "oklch(0.99598 0.01962 106.75)"
62
+ beige: ColorField = "oklch(0.96357 0.03278 107)"
63
+ lightyellow: ColorField = "oklch(0.99201 0.04024 107.11)"
64
+ lightgoldenrodyellow: ColorField = "oklch(0.97501 0.05184 107.32)"
65
+ olive: ColorField = "oklch(0.58066 0.12658 109.77)"
66
+ yellow: ColorField = "oklch(0.96798 0.21101 109.77)"
67
+ darkolivegreen: ColorField = "oklch(0.49552 0.0896 126.19)"
68
+ olivedrab: ColorField = "oklch(0.59948 0.13738 126.32)"
69
+ yellowgreen: ColorField = "oklch(0.78485 0.18374 126.64)"
70
+ greenyellow: ColorField = "oklch(0.91305 0.23346 130.02)"
71
+ chartreuse: ColorField = "oklch(0.89026 0.2648 136.01)"
72
+ lawngreen: ColorField = "oklch(0.88175 0.26307 136.17)"
73
+ darkgreen: ColorField = "oklch(0.43602 0.14837 142.5)"
74
+ green: ColorField = "oklch(0.51975 0.17686 142.5)"
75
+ lime: ColorField = "oklch(0.86644 0.29483 142.5)"
76
+ limegreen: ColorField = "oklch(0.74187 0.22865 142.83)"
77
+ forestgreen: ColorField = "oklch(0.5578 0.16878 142.89)"
78
+ palegreen: ColorField = "oklch(0.90354 0.16242 144.09)"
79
+ lightgreen: ColorField = "oklch(0.868 0.1558 144.09)"
80
+ darkseagreen: ColorField = "oklch(0.75086 0.07971 144.73)"
81
+ honeydew: ColorField = "oklch(0.98484 0.02521 145.38)"
82
+ springgreen: ColorField = "oklch(0.87493 0.23526 151.02)"
83
+ seagreen: ColorField = "oklch(0.56853 0.11871 154.95)"
84
+ mediumseagreen: ColorField = "oklch(0.68404 0.14402 155)"
85
+ mediumspringgreen: ColorField = "oklch(0.86681 0.20674 156.9)"
86
+ mintcream: ColorField = "oklch(0.99117 0.01237 164.81)"
87
+ mediumaquamarine: ColorField = "oklch(0.77669 0.10985 168.82)"
88
+ aquamarine: ColorField = "oklch(0.91499 0.13039 168.99)"
89
+ turquoise: ColorField = "oklch(0.82233 0.13074 185.09)"
90
+ lightseagreen: ColorField = "oklch(0.6912 0.11421 188.96)"
91
+ mediumturquoise: ColorField = "oklch(0.7868 0.11622 191.56)"
92
+ darkcyan: ColorField = "oklch(0.57652 0.09841 194.77)"
93
+ teal: ColorField = "oklch(0.54312 0.09271 194.77)"
94
+ aqua: ColorField = "oklch(0.9054 0.15455 194.77)"
95
+ cyan: ColorField = "oklch(0.9054 0.15455 194.77)"
96
+ darkslategray: ColorField = "oklch(0.40296 0.03772 195.76)"
97
+ darkslategrey: ColorField = "oklch(0.40296 0.03772 195.76)"
98
+ paleturquoise: ColorField = "oklch(0.90691 0.06323 196.09)"
99
+ lightcyan: ColorField = "oklch(0.97786 0.03203 196.64)"
100
+ darkturquoise: ColorField = "oklch(0.77193 0.13144 196.64)"
101
+ azure: ColorField = "oklch(0.98895 0.01572 196.9)"
102
+ cadetblue: ColorField = "oklch(0.65768 0.06501 198.3)"
103
+ powderblue: ColorField = "oklch(0.87508 0.0502 205.73)"
104
+ lightblue: ColorField = "oklch(0.85623 0.04894 219.65)"
105
+ skyblue: ColorField = "oklch(0.81482 0.08192 225.75)"
106
+ deepskyblue: ColorField = "oklch(0.75535 0.15342 231.64)"
107
+ lightskyblue: ColorField = "oklch(0.82062 0.09453 236.75)"
108
+ aliceblue: ColorField = "oklch(0.97514 0.01266 244.25)"
109
+ steelblue: ColorField = "oklch(0.588 0.09934 245.74)"
110
+ slategray: ColorField = "oklch(0.5925 0.03092 248.35)"
111
+ slategrey: ColorField = "oklch(0.5925 0.03092 248.35)"
112
+ lightslategray: ColorField = "oklch(0.61902 0.0325 248.35)"
113
+ lightslategrey: ColorField = "oklch(0.61902 0.0325 248.35)"
114
+ dodgerblue: ColorField = "oklch(0.65201 0.19012 253.21)"
115
+ lightsteelblue: ColorField = "oklch(0.81362 0.04281 255.03)"
116
+ cornflowerblue: ColorField = "oklch(0.67462 0.14136 261.34)"
117
+ blue: ColorField = "oklch(0.45201 0.31321 264.05)"
118
+ darkblue: ColorField = "oklch(0.28782 0.19944 264.05)"
119
+ mediumblue: ColorField = "oklch(0.38345 0.26571 264.05)"
120
+ navy: ColorField = "oklch(0.27115 0.18789 264.05)"
121
+ royalblue: ColorField = "oklch(0.55985 0.18823 266.4)"
122
+ midnightblue: ColorField = "oklch(0.28812 0.14363 272.76)"
123
+ mediumslateblue: ColorField = "oklch(0.60447 0.19389 285.5)"
124
+ slateblue: ColorField = "oklch(0.54357 0.17123 285.54)"
125
+ lavender: ColorField = "oklch(0.9309 0.02694 285.86)"
126
+ darkslateblue: ColorField = "oklch(0.41434 0.12484 286.04)"
127
+ ghostwhite: ColorField = "oklch(0.98112 0.00927 286.23)"
128
+ mediumpurple: ColorField = "oklch(0.62518 0.15415 297.27)"
129
+ blueviolet: ColorField = "oklch(0.53376 0.25031 301.37)"
130
+ indigo: ColorField = "oklch(0.33898 0.17927 301.68)"
131
+ rebeccapurple: ColorField = "oklch(0.44027 0.1603 303.37)"
132
+ darkviolet: ColorField = "oklch(0.51491 0.26067 309.81)"
133
+ darkorchid: ColorField = "oklch(0.54111 0.22724 311.51)"
134
+ mediumorchid: ColorField = "oklch(0.62558 0.20244 319.23)"
135
+ thistle: ColorField = "oklch(0.83329 0.04391 325.96)"
136
+ plum: ColorField = "oklch(0.78328 0.10776 326.54)"
137
+ violet: ColorField = "oklch(0.7619 0.18612 327.21)"
138
+ fuchsia: ColorField = "oklch(0.70167 0.32249 328.36)"
139
+ magenta: ColorField = "oklch(0.70167 0.32249 328.36)"
140
+ darkmagenta: ColorField = "oklch(0.4468 0.20535 328.36)"
141
+ purple: ColorField = "oklch(0.42091 0.19345 328.36)"
142
+ orchid: ColorField = "oklch(0.70213 0.18126 328.71)"
143
+ mediumvioletred: ColorField = "oklch(0.55337 0.22165 349.69)"
144
+ hotpink: ColorField = "oklch(0.7283 0.19708 351.99)"
145
+ lavenderblush: ColorField = "oklch(0.96833 0.01741 355.1)"
146
+ deeppink: ColorField = "oklch(0.65493 0.26134 356.94)"
147
+ palevioletred: ColorField = "oklch(0.67397 0.135 359.97)"
148
+ # Zero Hue
149
+ black: ColorField = "oklch(0 0 0)"
150
+ darkgray: ColorField = "oklch(0.73481 0 0)"
151
+ darkgrey: ColorField = "oklch(0.73481 0 0)"
152
+ dimgray: ColorField = "oklch(0.52081 0 0)"
153
+ dimgrey: ColorField = "oklch(0.52081 0 0)"
154
+ gainsboro: ColorField = "oklch(0.89449 0 0)"
155
+ gray: ColorField = "oklch(0.59987 0 0)"
156
+ grey: ColorField = "oklch(0.59987 0 0)"
157
+ lightgray: ColorField = "oklch(0.86686 0 0)"
158
+ lightgrey: ColorField = "oklch(0.86686 0 0)"
159
+ silver: ColorField = "oklch(0.8078 0 0)"
160
+ white: ColorField = "oklch(1 0 0)"
161
+ whitesmoke: ColorField = "oklch(0.97015 0 0)"
162
+ transparent: ColorField = "oklch(0 0 0 / 0)"
163
+ # Added
164
+ offblack: ColorField = "oklch(0.10 0.01 220)"
165
+ offdarkgray: ColorField = "oklch(0.30 0.01 220)"
166
+ neutralgray: ColorField = "oklch(0.50 0.01 220)"
167
+ offlightgray: ColorField = "oklch(0.70 0.01 220)"
168
+ offwhite: ColorField = "oklch(0.995 0.01 220)"
hadalized/writer.py ADDED
@@ -0,0 +1,243 @@
1
+ """Render templates and write outputs."""
2
+
3
+ from contextlib import suppress
4
+ from functools import cache
5
+ from hashlib import blake2b
6
+ from pathlib import Path
7
+ from typing import TYPE_CHECKING, ClassVar
8
+
9
+ from jinja2 import (
10
+ Environment,
11
+ FileSystemLoader,
12
+ PackageLoader,
13
+ StrictUndefined,
14
+ Template,
15
+ TemplateNotFound,
16
+ select_autoescape,
17
+ )
18
+ from loguru import logger
19
+
20
+ from hadalized import const
21
+ from hadalized.cache import Cache
22
+ from hadalized.config import BuildConfig, Config, ContextType
23
+
24
+ if TYPE_CHECKING:
25
+ from hadalized.base import BaseNode
26
+ from hadalized.palette import Palette
27
+
28
+
29
+ @cache
30
+ def _encode(val: Template | BaseNode) -> bytes:
31
+ if isinstance(val, Template):
32
+ data: bytes = b"null"
33
+ if (fname := val.filename) is not None:
34
+ with suppress(FileNotFoundError):
35
+ data = Path(fname).read_bytes()
36
+ else:
37
+ data = val.model_dump_json().encode()
38
+
39
+ return data
40
+
41
+
42
+ def _hash(template: Template, context: BaseNode) -> str:
43
+ data = _encode(template) + b":::" + _encode(context)
44
+ return blake2b(data, digest_size=32).hexdigest()
45
+
46
+
47
+ class ThemeWriter:
48
+ """Generate application theme files."""
49
+
50
+ _package_template_env: ClassVar[Environment] = Environment(
51
+ loader=PackageLoader(const.APP_NAME),
52
+ undefined=StrictUndefined,
53
+ # autoescape=True,
54
+ autoescape=select_autoescape("html", "xml"),
55
+ )
56
+
57
+ def __init__(self, config: Config):
58
+ """Prepare an instance for writing files.
59
+
60
+ Initializtion does not connect to the cache database or write
61
+ any files.
62
+
63
+ Args:
64
+ config: A configuration instance if customization is required.
65
+
66
+ """
67
+ self.config = config
68
+ self.cache = Cache(config)
69
+ self._fs_template_env = Environment(
70
+ loader=FileSystemLoader(searchpath=config.template_dir),
71
+ undefined=StrictUndefined,
72
+ autoescape=select_autoescape("html", "xml"),
73
+ )
74
+ self._parsed = False
75
+
76
+ def _skip(self, path: Path, digest: str) -> bool:
77
+ return (
78
+ not self.config.force
79
+ and not self.config.no_cache
80
+ and path.exists()
81
+ and self.cache.get(path) == digest
82
+ )
83
+
84
+ def get_template(self, name: str | Path) -> Template:
85
+ """Load theme template.
86
+
87
+ Returns:
88
+ A jinja2.Template instance.
89
+
90
+ """
91
+ tname = str(name)
92
+ if self.config.no_templates or self.config.no_config:
93
+ template = self._package_template_env.get_template(tname)
94
+ else:
95
+ try:
96
+ template = self._fs_template_env.get_template(tname)
97
+ except TemplateNotFound:
98
+ template = self._package_template_env.get_template(tname)
99
+ return template
100
+
101
+ def _parse(self):
102
+ """Parse each palette in the underlying configuration."""
103
+ if not self._parsed:
104
+ self.config = self.config.parse_palettes()
105
+ self._parsed = True
106
+
107
+ def build_file(
108
+ self,
109
+ bconf: BuildConfig,
110
+ data: Palette | Config,
111
+ ) -> tuple[Path, bool]:
112
+ """Build a single color theme file.
113
+
114
+ Returns:
115
+ A path of the built file and whether it was generated.
116
+
117
+ """
118
+ opt = self.config
119
+ template = self.get_template(bconf.template)
120
+ path = self.config.build_dir / bconf.format_path(data)
121
+ context = data.to(bconf.color_type)
122
+ digest = _hash(template, context)
123
+
124
+ if opt.verbose:
125
+ logger.info(f"Checking whether to build {path} with hash {digest}.")
126
+ if self._skip(path, digest):
127
+ return path, False
128
+
129
+ if not opt.quiet:
130
+ logger.info(f"Building {path} {digest}.")
131
+
132
+ text = template.render(context=context)
133
+ if not opt.dry_run:
134
+ path.parent.mkdir(parents=True, exist_ok=True)
135
+ path.write_text(text, encoding="utf-8")
136
+ if opt.use_cache and not opt.dry_run:
137
+ self.cache.add(path, digest)
138
+ return path, True
139
+
140
+ def copy_file(self, build_path: Path) -> Path | None:
141
+ """Copy a built theme file to an output directory.
142
+
143
+ Args:
144
+ build_path: Path to a built theme file, typically saved in
145
+ the applicate state directory.
146
+
147
+ Returns:
148
+ The path of the copied file or None if no copy was performed.
149
+
150
+ """
151
+ opt = self.config
152
+ if opt.output_dir is None:
153
+ return None
154
+
155
+ output_dir = opt.output_dir
156
+ if opt.prefix:
157
+ output_dir /= build_path.parent.name
158
+ copy_path = (output_dir / build_path.name).absolute()
159
+ if not opt.quiet:
160
+ logger.info(f"Copying {build_path} to {output_dir}")
161
+ if not opt.dry_run:
162
+ output_dir.mkdir(parents=True, exist_ok=True)
163
+ build_path.copy(copy_path)
164
+ return copy_path
165
+
166
+ def build(self, bconf: BuildConfig) -> list[Path]:
167
+ """Generate color theme files for a specific app.
168
+
169
+ Args:
170
+ bconf: A configuration specifying how theme files shoud be built.
171
+
172
+ Returns:
173
+ A list of theme file paths that were built.
174
+
175
+ """
176
+ self._parse()
177
+ opt = self.config
178
+ if opt.verbose:
179
+ logger.info(f"Handling themes for {bconf.name}.")
180
+ includes = set(opt.include_palettes)
181
+ filtered_palettes = {
182
+ k: v
183
+ for k, v in opt.palettes.items()
184
+ if not includes
185
+ or k in includes
186
+ or v.name in includes
187
+ or not set(v.aliases).isdisjoint(includes)
188
+ }
189
+
190
+ match bconf.context_type:
191
+ case ContextType.palette:
192
+ contexts = filtered_palettes.values()
193
+ case ContextType.full:
194
+ if not includes:
195
+ contexts = [self.config]
196
+ else:
197
+ contexts = [self.config.replace(palettes=filtered_palettes)]
198
+
199
+ files_built: list[Path] = []
200
+ for item in contexts:
201
+ build_path, is_built = self.build_file(bconf, item)
202
+ if is_built:
203
+ files_built.append(build_path)
204
+ self.copy_file(build_path)
205
+
206
+ return files_built
207
+
208
+ def run(self) -> list[Path]:
209
+ """Generate all relevant app theme files.
210
+
211
+ Returns:
212
+ A list of file paths that were generated.
213
+
214
+ """
215
+ includes = set(self.config.include_builds)
216
+ builds = (
217
+ v
218
+ for k, v in self.config.builds.items()
219
+ if not includes or k in includes or v.name in includes
220
+ )
221
+
222
+ written = []
223
+ for directive in builds:
224
+ written += self.build(directive)
225
+ return written
226
+
227
+ def __enter__(self):
228
+ """Connect to the cache.
229
+
230
+ Returns:
231
+ The instance with a connection to the cache db.
232
+
233
+ """
234
+ if self.config.use_cache:
235
+ self.cache.connect()
236
+ return self
237
+
238
+ def __exit__(self, exc_type, exc_value, traceback):
239
+ """Close cache db connection."""
240
+ if exc_type is not None:
241
+ logger.error((exc_type, exc_value, traceback))
242
+ if self.config.use_cache:
243
+ self.cache.close()