Ir al contenido

Crear temas

Hay cuatro formas de hacer un tema, de la más rápida a la más detallada. Todas devuelven un Theme, que puedes usar directamente (theme = mi_tema) o registrar para usarlo por nombre.

Quieres… Usa Esfuerzo
Cambiar solo el color de marca tema.with_accent("#e11d48") Una línea
Cambiar algunos tokens de un tema existente tema.derive(radius=12, success="#16a34a") Unas líneas
Un tema nuevo a partir de tus colores pz.Theme.generate(nombre, background=, text=, accent=) Tres colores
Control total, o un tema en un archivo pz.Theme.from_dict({...}), Theme.load("tema.json") Cualquier token

Los temas son inmutables: cada método devuelve un tema nuevo y deja el original intacto, así que pz.themes.ONE_DARK siempre es el One Dark de verdad.

El acento es el color de los botones principales, interruptores, sliders, anillos de foco, enlaces y selecciones. with_accent los cambia todos a la vez y elige un on_accent legible (el texto sobre el acento):

class MiApp(pz.App):
theme = pz.themes.ONE_DARK.with_accent("#e11d48") # One Dark, en rojo

derive copia un tema con los tokens que pases. Los diccionarios syntax y ansi se combinan con los del original, así que solo listas lo que cambia:

oceano = pz.themes.ONE_DARK.derive(
name="Océano",
background="#0b1622",
surface="#102131",
radius=10,
radius_sm=8,
syntax={"keyword": "#ff79c6", "comment": ("#5c6f80", "italic")},
).with_accent("#4fb3ff")

Theme.generate construye todos los tokens a partir de un fondo, un color de texto y un acento: superficies, bordes, estados hover, texto atenuado y los colores del editor se mezclan entre el fondo y el texto.

propio = pz.Theme.generate(
"Bosque",
background="#14201a", # donde va el contenido (el token editor); la ventana se mezcla un poco más clara
text="#e3efe6", # el color del texto principal
accent="#4ade80", # botones, foco, enlaces
)

Argumentos opcionales:

Argumento Por defecto Significado
appearance se deduce "dark" o "light"; se deduce de lo claro que es background.
error, warning, success de One Dark / One Light Colores de estado (también colorean los tokens de control de versiones).
syntax los de One Colores de código que cambian (se combinan).
radius 6.0 Radio de las esquinas; radius_sm pasa a ser radius - 2.

Cuando tienes una paleta completa (el marco alrededor del editor y seis tonos para estados y sintaxis), theme_palettes.from_palette usa cada color como lo hacen las familias de temas de Zed. Los temas propios de Pyzed (Midnight, Graphite, Forest, Rosé, Dawn, Glacier) están hechos con ella:

from pyzed import theme_palettes
dusk = theme_palettes.from_palette(
"Dusk", "dark",
editor="#1b1d24", chrome="#23262f", text="#d8dbe2", accent="#7aa2f7",
red="#f7768e", orange="#ff9e64", yellow="#e0af68", green="#9ece6a", cyan="#7dcfff", purple="#bb9af7",
)

4. Cualquier token, desde un diccionario o un archivo

Sección titulada «4. Cualquier token, desde un diccionario o un archivo»

Theme.from_dict toma los tokens que listes y completa el resto con One Dark (o One Light con "appearance": "light"). Los nombres desconocidos lanzan un ValueError, así que las erratas no pasan inadvertidas:

papel = pz.Theme.from_dict({
"name": "Papel",
"appearance": "light",
"background": "#f5f1e8",
"surface": "#fbf8f1",
"editor": "#fffdf8",
"text": "#2b2620",
"text_muted": "#6b6257",
"border": "#d9d0c1",
"accent": "#b45309",
"on_accent": "#ffffff",
})

save escribe un tema en JSON y Theme.load lo vuelve a leer. El archivo tiene las mismas claves que from_dict, así que también puedes escribirlo a mano (solo hacen falta los tokens que cambias):

temas/papel.json
{
"name": "Papel",
"appearance": "light",
"background": "#f5f1e8",
"text": "#2b2620",
"accent": "#b45309",
"on_accent": "#ffffff",
"radius": 2
}
papel = pz.Theme.load("temas/papel.json")
papel.save("temas/papel-completo.json") # todos los tokens, listos para editar

Como los nombres de los tokens siguen el formato de temas del editor Zed, cualquier tema de la galería de temas de Zed funciona en Pyzed. Descarga su .json y:

mocha = pz.Theme.from_zed("catppuccin.json", name="Catppuccin Mocha") # un tema del archivo
pz.themes.load_zed("catppuccin.json") # todos, registrados

pz.themes.register añade un tema a la lista de temas, así que se puede usar por nombre, aparece en pz.themes.names() (y en cualquier selector de temas hecho con ella) y funciona con pz.themes.auto:

  1. Crea los temas, normalmente en su propio módulo:

    mitema.py
    import pyzed as pz
    CLARO = pz.themes.register(pz.Theme.generate("Acme Light", background="#ffffff", text="#1f1b2e", accent="#6d28d9"))
    OSCURO = pz.themes.register(pz.Theme.generate("Acme Dark", background="#16131f", text="#ece9f5", accent="#a78bfa"))
  2. Importa ese módulo antes de que arranque la app y usa los nombres:

    main.py
    import pyzed as pz
    import mitema # noqa: F401 - registra los temas Acme
    class MiApp(pz.App):
    theme = pz.themes.auto("Acme Light", "Acme Dark")
  3. Ejecútala:

    Ventana de terminal
    uv run python main.py

Registrar un tema con el nombre de uno existente lo reemplaza.

pyzed.theme tiene pequeñas funciones de color, útiles al construir temas en código:

Función Devuelve
contrast(a, b) La relación de contraste WCAG de dos colores, de 1 a 21. El texto debería tener al menos 4.5 (AA), idealmente 7 (AAA).
readable_on(fondo) Un color de texto claro u oscuro, el que mejor se lea sobre fondo.
luminance(color) Lo claro que es un color, de 0 a 1.
mix(a, b, cantidad) Un color entre a y b (cantidad 0 es a, 1 es b).
lighten(color, cantidad), darken(color, cantidad) El color mezclado con blanco o con negro.
alpha(color, valor) El color con una opacidad (alpha("#ff0000", 0.5) es #ff000080).
from pyzed.theme import contrast
t = pz.Theme.generate("Bosque", background="#14201a", text="#e3efe6", accent="#4ade80")
print(round(contrast(t.text, t.background), 1)) # 11.2 -> excelente
print(round(contrast(t.text_muted, t.background), 1)) # 6.0 -> sigue por encima de 4.5

El Recetario de temas tiene temas completos para copiar: un tema de marca en claro y oscuro, alto contraste, terminal retro, vidrio oscuro y pastel.