From b92c501fde4eb89ca8566e529fa95d36ba2c6b98 Mon Sep 17 00:00:00 2001 From: "s0wlz (Matthias Puchstein)" Date: Tue, 30 Dec 2025 06:12:20 +0100 Subject: [PATCH] refactor: restructure dist/ and implement aggregated Zed theme - Updated build.py to support app-centric directory structure (dist//). - Modified build.py to allow aggregated multi-scheme rendering (for Zed). - Refactored Zed template to include both Neon and Aeon variants in a single JSON. - Standardized theme file naming in dist/. --- build.py | 87 ++++++---- templates/zed/apex.json.j2 | 321 +++++++++++++++++++++++++++++++++++++ 2 files changed, 377 insertions(+), 31 deletions(-) create mode 100644 templates/zed/apex.json.j2 diff --git a/build.py b/build.py index 4ee08a1..9e5444f 100644 --- a/build.py +++ b/build.py @@ -6,7 +6,7 @@ from jinja2 import Environment, FileSystemLoader SRC_DIR = 'src' TEMPLATES_DIR = 'templates' DIST_DIR = 'dist' -SCHEMES = ['neon.yaml', 'aeon.yaml'] +SCHEME_FILES = ['neon.yaml', 'aeon.yaml'] def load_scheme(filename): with open(os.path.join(SRC_DIR, filename), 'r') as f: @@ -18,47 +18,72 @@ def render_template(template_path, context): return template.render(context) def build(): + # Load all schemes first + schemes = [] + for f in SCHEME_FILES: + schemes.append(load_scheme(f)) + # Ensure dist directory exists if not os.path.exists(DIST_DIR): os.makedirs(DIST_DIR) - for scheme_file in SCHEMES: - scheme_data = load_scheme(scheme_file) - scheme_name_slug = scheme_data['scheme'].lower().replace(' ', '-') - print(f"Building {scheme_data['scheme']}...") + # Walk through templates + for root, dirs, files in os.walk(TEMPLATES_DIR): + for file in files: + if not file.endswith('.j2'): + continue - # Find all templates - for root, dirs, files in os.walk(TEMPLATES_DIR): - for file in files: - if file.endswith('.j2'): - # Calculate relative path to mirror structure in dist - rel_path = os.path.relpath(root, TEMPLATES_DIR) - template_rel_path = os.path.join(rel_path, file) + rel_path = os.path.relpath(root, TEMPLATES_DIR) + app_name = rel_path # e.g., 'nvim', 'zed', 'kitty' + + template_rel_path = os.path.join(rel_path, file) + output_filename_base = file.replace('.j2', '') + + # Create app directory in dist + app_dist_dir = os.path.join(DIST_DIR, app_name) + if not os.path.exists(app_dist_dir): + os.makedirs(app_dist_dir) + + print(f"Processing template: {template_rel_path}") + + # Special case for Zed: Aggregated output (single JSON for all themes) + if app_name == 'zed': + context = {'schemes': schemes} + rendered_content = render_template(template_rel_path, context) + + # Output file: dist/zed/apex.json (matches base name) + output_path = os.path.join(app_dist_dir, output_filename_base) + + with open(output_path, 'w') as f: + f.write(rendered_content) + print(f" -> {output_path} (Aggregated)") + + # Default behavior: Per-scheme output + else: + for scheme in schemes: + scheme_slug = scheme['scheme'].lower().replace(' ', '-') - # Prepare output path - output_filename = file.replace('.j2', '') - # If the template is generic (apex.lua), rename it to the scheme name (apex-neon.lua) - if 'apex' in output_filename: - output_filename = output_filename.replace('apex', scheme_name_slug) + # Rename output file: e.g., apex.conf -> apex-neon.conf + # or apex.lua -> apex-neon.lua + # If filename is generic 'apex', replace with slug. + # If filename is 'apex.lua', result 'apex-neon.lua' - output_dir = os.path.join(DIST_DIR, scheme_name_slug, rel_path) - if not os.path.exists(output_dir): - os.makedirs(output_dir) + if 'apex' in output_filename_base: + final_filename = output_filename_base.replace('apex', f"apex-{scheme_slug.replace('apex-', '')}") + else: + final_filename = f"{scheme_slug}-{output_filename_base}" + + # Clean up double prefixes if any (e.g. apex-apex-neon) + final_filename = final_filename.replace('apex-apex-', 'apex-') + + output_path = os.path.join(app_dist_dir, final_filename) - output_path = os.path.join(output_dir, output_filename) - - # Render and write - # We pass template_rel_path because jinja loader is rooted at TEMPLATES_DIR - # But os.walk returns paths relative to CWD usually, but we constructed it. - # Actually Environment loader is correct. We just need the path relative to templates dir. - template_name_for_jinja = template_rel_path - - rendered_content = render_template(template_name_for_jinja, scheme_data) + rendered_content = render_template(template_rel_path, scheme) with open(output_path, 'w') as f: f.write(rendered_content) - - print(f" -> {output_path}") + print(f" -> {output_path} ({scheme['scheme']})") if __name__ == '__main__': build() + diff --git a/templates/zed/apex.json.j2 b/templates/zed/apex.json.j2 new file mode 100644 index 0000000..64644dc --- /dev/null +++ b/templates/zed/apex.json.j2 @@ -0,0 +1,321 @@ +{ + "$schema": "https://zed.dev/schema/themes/v0.2.0.json", + "name": "Apex", + "author": "S0wlz (Owlibou)", + "themes": [ + {% for s in schemes %} + { + "name": "{{ s.scheme }}", + "appearance": "{{ s.type }}", + "style": { + "background": "{{ s.palette.background }}", + "background.appearance": "opaque", + "surface.background": "{{ s.ui.panel }}", + "elevated_surface.background": "{% if s.type == 'dark' %}{{ s.ui.panel }}{% else %}#ffffff{% endif %}", + "panel.background": "{{ s.ui.panel }}", + "panel.focused_border": "{{ s.palette.cursor }}", + "panel.indent_guide": "{{ s.ui.border }}66", + "panel.indent_guide_active": "{{ s.ui.dim }}aa", + "panel.indent_guide_hover": "{{ s.ui.dim }}cc", + "tab_bar.background": "{% if s.type == 'dark' %}{{ s.ui.panel }}{% else %}{{ s.ui.panel }}{% endif %}", + "tab.inactive_background": "{{ s.ui.panel }}", + "tab.active_background": "{{ s.palette.background }}", + "title_bar.background": "{{ s.palette.background }}", + "title_bar.inactive_background": "{{ s.ui.panel }}", + "toolbar.background": "{{ s.ui.panel }}", + "status_bar.background": "{{ s.ui.panel }}", + "border": "{{ s.ui.border }}", + "border.variant": "{% if s.type == 'dark' %}{{ s.ui.panel }}{% else %}{{ s.ui.stealth }}{% endif %}", + "border.focused": "{{ s.palette.cursor }}", + "border.selected": "{{ s.palette.cursor }}", + "border.disabled": "{% if s.type == 'dark' %}{{ s.ui.panel }}{% else %}{{ s.ui.stealth }}{% endif %}", + "border.transparent": "transparent", + "text": "{{ s.palette.foreground }}", + "text.muted": "{{ s.ui.dim }}", + "text.placeholder": "{{ s.ui.dim }}", + "text.disabled": "{% if s.type == 'dark' %}{{ s.ui.dim }}{% else %}{{ s.ui.stealth }}{% endif %}", + "text.accent": "{{ s.palette.info }}", + "icon": "{{ s.palette.foreground }}", + "icon.muted": "{{ s.ui.dim }}", + "icon.placeholder": "{{ s.ui.dim }}", + "icon.disabled": "{% if s.type == 'dark' %}{{ s.ui.dim }}{% else %}{{ s.ui.stealth }}{% endif %}", + "icon.accent": "{{ s.palette.info }}", + "accents": [ + "{{ s.palette.cursor }}", + "{{ s.palette.info }}", + "{{ s.palette.special }}", + "{{ s.palette.success }}", + "{{ s.palette.warning }}" + ], + "element.background": "{% if s.type == 'dark' %}{{ s.ui.panel }}{% else %}#ffffff{% endif %}", + "element.hover": "{{ s.ui.border }}", + "element.active": "{{ s.ui.border }}", + "element.selected": "{{ s.ui.border }}", + "element.disabled": "{{ s.ui.panel }}", + "ghost_element.background": null, + "ghost_element.hover": "{{ s.ui.border }}66", + "ghost_element.active": "{{ s.ui.border }}88", + "ghost_element.selected": "{{ s.ui.border }}66", + "ghost_element.disabled": null, + "drop_target.background": "{% if s.type == 'dark' %}{{ s.palette.info }}22{% else %}{{ s.ansi.bright.cyan }}22{% endif %}", + "editor.background": "{{ s.palette.background }}", + "editor.foreground": "{{ s.palette.foreground }}", + "editor.gutter.background": "{{ s.palette.background }}", + "editor.subheader.background": "{{ s.ui.panel }}", + "editor.active_line.background": "{{ s.ui.panel }}", + "editor.highlighted_line.background": "{{ s.ui.panel }}", + "editor.line_number": "{{ s.ui.dim }}", + "editor.active_line_number": "{{ s.palette.cursor }}", + "editor.wrap_guide": "{{ s.ui.border }}", + "editor.active_wrap_guide": "{{ s.ui.dim }}", + "editor.indent_guide": "{{ s.ui.border }}66", + "editor.indent_guide_active": "{{ s.ui.dim }}aa", + "editor.invisible": "{{ s.ui.border }}88", + "editor.document_highlight.read_background": "{{ s.palette.info }}{% if s.type == 'dark' %}22{% else %}1a{% endif %}", + "editor.document_highlight.write_background": "{{ s.palette.cursor }}{% if s.type == 'dark' %}22{% else %}1a{% endif %}", + "editor.document_highlight.bracket_background": "{{ s.ui.border }}66", + "search.match_background": "{% if s.type == 'dark' %}{{ s.palette.info }}33{% else %}{{ s.ansi.bright.cyan }}44{% endif %}", + "scrollbar.track.background": "{{ s.palette.background }}", + "scrollbar.track.border": "{{ s.palette.background }}", + "scrollbar.thumb.background": "{% if s.type == 'dark' %}{{ s.ui.border }}aa{% else %}{{ s.ui.stealth }}aa{% endif %}", + "scrollbar.thumb.hover_background": "{% if s.type == 'dark' %}{{ s.ui.stealth }}{% else %}{{ s.ui.dim }}{% endif %}", + "scrollbar.thumb.border": "transparent", + "pane.focused_border": "{{ s.palette.cursor }}", + "pane_group.border": "{% if s.type == 'dark' %}{{ s.ui.border }}{% else %}{{ s.ui.stealth }}{% endif %}", + "link_text.hover": "{% if s.type == 'dark' %}{{ s.ansi.bright.blue }}{% else %}{{ s.ansi.bright.blue }}{% endif %}", + "success": "{{ s.palette.success }}", + "success.background": "{{ s.palette.success }}1a", + "success.border": "{{ s.palette.success }}", + "warning": "{{ s.palette.warning }}", + "warning.background": "{{ s.palette.warning }}1a", + "warning.border": "{{ s.palette.warning }}", + "error": "{{ s.ansi.bright.red }}", + "error.background": "{{ s.ansi.bright.red }}1a", + "error.border": "{{ s.ansi.bright.red }}", + "info": "{{ s.palette.info }}", + "info.background": "{{ s.palette.info }}1a", + "info.border": "{{ s.palette.info }}", + "hint": "{{ s.palette.azure }}", + "hint.background": "{{ s.palette.azure }}1a", + "hint.border": "{{ s.palette.azure }}", + "predictive": "{% if s.type == 'dark' %}{{ s.palette.azure }}{% else %}{{ s.palette.azure }}{% endif %}", + "predictive.background": "{{ s.palette.azure }}1a", + "predictive.border": "{{ s.palette.azure }}", + "unreachable": "{{ s.palette.special }}", + "unreachable.background": "{{ s.palette.special }}1a", + "unreachable.border": "{{ s.palette.special }}", + "created": "{{ s.palette.success }}", + "created.background": "{{ s.palette.success }}1a", + "created.border": "{{ s.palette.success }}", + "modified": "{{ s.palette.warning }}", + "modified.background": "{{ s.palette.warning }}1a", + "modified.border": "{{ s.palette.warning }}", + "deleted": "{{ s.ansi.bright.red }}", + "deleted.background": "{{ s.ansi.bright.red }}1a", + "deleted.border": "{{ s.ansi.bright.red }}", + "renamed": "{{ s.palette.info }}", + "renamed.background": "{{ s.palette.info }}1a", + "renamed.border": "{{ s.palette.info }}", + "conflict": "{{ s.ansi.bright.red }}", + "conflict.background": "{{ s.ansi.bright.red }}1a", + "conflict.border": "{{ s.ansi.bright.red }}", + "ignored": "{{ s.ui.dim }}", + "ignored.background": "{{ s.ui.dim }}1a", + "ignored.border": "{{ s.ui.border }}", + "hidden": "{{ s.ui.dim }}", + "hidden.background": "{{ s.ui.dim }}1a", + "hidden.border": "{{ s.ui.border }}", + "terminal.background": "{{ s.palette.background }}", + "terminal.foreground": "{{ s.palette.foreground }}", + "terminal.bright_foreground": "{% if s.type == 'dark' %}#ffffff{% else %}{{ s.palette.foreground }}{% endif %}", + "terminal.dim_foreground": "{{ s.ui.dim }}", + "terminal.ansi.background": "{{ s.palette.background }}", + "terminal.ansi.black": "{{ s.ansi.normal.black }}", + "terminal.ansi.red": "{{ s.ansi.normal.red }}", + "terminal.ansi.green": "{{ s.ansi.normal.green }}", + "terminal.ansi.yellow": "{{ s.ansi.normal.yellow }}", + "terminal.ansi.blue": "{{ s.ansi.normal.blue }}", + "terminal.ansi.magenta": "{{ s.ansi.normal.magenta }}", + "terminal.ansi.cyan": "{{ s.ansi.normal.cyan }}", + "terminal.ansi.white": "{{ s.ansi.normal.white }}", + "terminal.ansi.bright_black": "{{ s.ansi.bright.black }}", + "terminal.ansi.bright_red": "{{ s.ansi.bright.red }}", + "terminal.ansi.bright_green": "{{ s.ansi.bright.green }}", + "terminal.ansi.bright_yellow": "{{ s.ansi.bright.yellow }}", + "terminal.ansi.bright_blue": "{{ s.ansi.bright.blue }}", + "terminal.ansi.bright_magenta": "{{ s.ansi.bright.magenta }}", + "terminal.ansi.bright_cyan": "{{ s.ansi.bright.cyan }}", + "terminal.ansi.bright_white": "{{ s.ansi.bright.white }}", + "terminal.ansi.dim_black": "{{ s.ansi.normal.black }}", + "terminal.ansi.dim_red": "{{ s.ansi.normal.red }}", + "terminal.ansi.dim_green": "{{ s.ansi.normal.green }}", + "terminal.ansi.dim_yellow": "{{ s.ansi.normal.yellow }}", + "terminal.ansi.dim_blue": "{{ s.ansi.normal.blue }}", + "terminal.ansi.dim_magenta": "{{ s.ansi.normal.magenta }}", + "terminal.ansi.dim_cyan": "{{ s.ansi.normal.cyan }}", + "terminal.ansi.dim_white": "{{ s.ansi.normal.white }}", + "players": [ + { + "cursor": "{{ s.palette.cursor }}", + "background": "{{ s.palette.cursor }}", + "selection": "{{ s.palette.cursor }}33" + }, + { + "cursor": "{{ s.palette.info }}", + "background": "{{ s.palette.info }}", + "selection": "{{ s.palette.info }}33" + }, + { + "cursor": "{{ s.palette.special }}", + "background": "{{ s.palette.special }}", + "selection": "{{ s.palette.special }}33" + }, + { + "cursor": "{{ s.palette.success }}", + "background": "{{ s.palette.success }}", + "selection": "{{ s.palette.success }}33" + }, + { + "cursor": "{{ s.palette.warning }}", + "background": "{{ s.palette.warning }}", + "selection": "{{ s.palette.warning }}33" + } + ], + "version_control.added": "{{ s.palette.success }}", + "version_control.modified": "{{ s.palette.warning }}", + "version_control.deleted": "{{ s.ansi.bright.red }}", + "version_control.conflict": "{{ s.ansi.bright.red }}", + "version_control.renamed": "{{ s.palette.info }}", + "version_control.ignored": "{{ s.ui.dim }}", + "syntax": { + "comment": { + "color": "{{ s.ui.dim }}", + "font_style": "italic" + }, + "comment.doc": { + "color": "{{ s.ui.dim }}", + "font_style": "italic" + }, + "keyword": { + "color": "{{ s.palette.info }}" + }, + "keyword.import": { + "color": "{{ s.palette.info }}" + }, + "keyword.storage": { + "color": "{{ s.palette.info }}" + }, + "function": { + "color": "{{ s.palette.azure }}" + }, + "function.method": { + "color": "{{ s.palette.azure }}" + }, + "function.special.definition": { + "color": "{{ s.palette.azure }}" + }, + "type": { + "color": "{{ s.palette.special }}" + }, + "type.builtin": { + "color": "{{ s.palette.special }}" + }, + "string": { + "color": "{{ s.palette.success }}" + }, + "string.escape": { + "color": "{{ s.ansi.bright.green }}" + }, + "string.regex": { + "color": "{{ s.palette.warning }}" + }, + "number": { + "color": "{{ s.palette.warning }}" + }, + "boolean": { + "color": "{{ s.palette.warning }}" + }, + "constant": { + "color": "{{ s.palette.foreground }}" + }, + "constant.builtin": { + "color": "{{ s.palette.special }}" + }, + "variable": { + "color": "{{ s.palette.foreground }}" + }, + "variable.special": { + "color": "{{ s.palette.special }}" + }, + "property": { + "color": "{{ s.palette.foreground }}" + }, + "attribute": { + "color": "{{ s.palette.azure }}" + }, + "tag": { + "color": "{{ s.palette.info }}" + }, + "label": { + "color": "{{ s.palette.azure }}" + }, + "operator": { + "color": "{{ s.palette.foreground }}" + }, + "punctuation": { + "color": "{{ s.ui.dim }}" + }, + "punctuation.bracket": { + "color": "{{ s.ui.dim }}" + }, + "punctuation.delimiter": { + "color": "{{ s.ui.dim }}" + }, + "punctuation.list_marker": { + "color": "{{ s.ui.dim }}", + "font_weight": 700 + }, + "link_text": { + "color": "{{ s.palette.info }}" + }, + "link_uri": { + "color": "{{ s.palette.azure }}" + }, + "emphasis": { + "font_style": "italic" + }, + "emphasis.strong": { + "font_weight": 700 + }, + "title": { + "color": "{{ s.palette.foreground }}", + "font_weight": 700 + }, + "text.literal": { + "color": "{{ s.palette.success }}" + }, + "preproc": { + "color": "{{ s.palette.azure }}" + }, + "constructor": { + "color": "{{ s.palette.azure }}" + }, + "enum": { + "color": "{{ s.palette.special }}" + }, + "variant": { + "color": "{{ s.palette.special }}" + }, + "hint": { + "color": "{{ s.palette.azure }}" + }, + "predictive": { + "color": "{{ s.ui.dim }}" + } + } + } + }{% if not loop.last %},{% endif %} + {% endfor %} + ] +} +