feat(tahuantinsuyu): scaffolding del estudio astrológico (10 crates + ventana 3-panes)
Módulo nuevo `modules/tahuantinsuyu/` con 9 crates reusables + app `apps/tahuantinsuyu` ejecutable que abre la ventana del explorador y coordina los widgets: - tahuantinsuyu-card: Card Brahman + spawn_sidecar (flows chart-request/chart-result). - tahuantinsuyu-model: tipos agnósticos (Group/Contact/Chart, StoredBirthData, StoredChartConfig, ChartKind, TreeSelection). - tahuantinsuyu-store: persistencia SQLite (rusqlite) con migración v1, CRUD por entidad y descenso recursivo `charts_under_group`. - tahuantinsuyu-engine: bridge agnóstico al canvas vía `RenderModel` (Layer/Glyph/Geometry). Feature `eternal-bridge` (off por default) reservada para enchufar eternal-astrology desde ~/eternal. - tahuantinsuyu-modules: registry de módulos pluggables (Module trait + Control schema) con `NatalModule` placeholder. - tahuantinsuyu-theme: AstroPalette (elementos / modos / planetas / aspectos) con variantes dark + light sobre yahweh-theme. - tahuantinsuyu-canvas: widget GPUI con CanvasState (Empty / Wheel / Thumbnails). Render placeholder hasta cablear la rueda real. - tahuantinsuyu-tree: explorador izquierdo sobre yahweh-widget-tree, prefijos g:/c:/h: para Group/Contact/Chart. - tahuantinsuyu-panel: control panel inferior que lee Controls de los módulos del registry y los pinta. - apps/tahuantinsuyu: binario `tahuantinsuyu` (launch_app-style) con Shell coordinador (tree↔canvas↔panel), DB en $XDG_DATA_HOME. Workspace Cargo.toml actualizado con los 10 miembros. `cargo check` verde, tests unitarios verdes (model/store/engine/modules/theme/card). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,295 @@
|
||||
//! `tahuantinsuyu-theme` — paleta simbólica + presets místicos.
|
||||
//!
|
||||
//! Una capa fina sobre [`yahweh_theme::Theme`]: el theme base aporta los
|
||||
//! slots de panel/foreground/accent; nosotros agregamos paletas
|
||||
//! semánticas para los elementos (fuego/tierra/aire/agua), los modos
|
||||
//! (cardinal/fijo/mutable), los planetas y los aspectos.
|
||||
//!
|
||||
//! El canvas pide colores por símbolo (`palette.element(Element::Fire)`),
|
||||
//! nunca hex directos. Así una sola tabla controla tanto el dark como el
|
||||
//! light, y cambiar la paleta no requiere tocar el render.
|
||||
|
||||
#![forbid(unsafe_code)]
|
||||
#![warn(rust_2018_idioms)]
|
||||
|
||||
use gpui::{Hsla, hsla};
|
||||
|
||||
// =====================================================================
|
||||
// Símbolos
|
||||
// =====================================================================
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub enum Element {
|
||||
Fire,
|
||||
Earth,
|
||||
Air,
|
||||
Water,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub enum Modality {
|
||||
Cardinal,
|
||||
Fixed,
|
||||
Mutable,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub enum Planet {
|
||||
Sun,
|
||||
Moon,
|
||||
Mercury,
|
||||
Venus,
|
||||
Mars,
|
||||
Jupiter,
|
||||
Saturn,
|
||||
Uranus,
|
||||
Neptune,
|
||||
Pluto,
|
||||
Chiron,
|
||||
NorthNode,
|
||||
SouthNode,
|
||||
Lilith,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub enum AspectKind {
|
||||
Conjunction,
|
||||
Sextile,
|
||||
Square,
|
||||
Trine,
|
||||
Opposition,
|
||||
Quincunx,
|
||||
Semisextile,
|
||||
Semisquare,
|
||||
Sesquisquare,
|
||||
Quintile,
|
||||
Biquintile,
|
||||
}
|
||||
|
||||
// =====================================================================
|
||||
// Paleta
|
||||
// =====================================================================
|
||||
|
||||
/// Paleta completa de símbolos astrológicos resuelta a colores HSLA. Las
|
||||
/// dos variantes (`dark` / `light`) comparten estructura — el canvas
|
||||
/// elige según `yahweh_theme::Theme::is_dark`.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct AstroPalette {
|
||||
pub is_dark: bool,
|
||||
|
||||
pub fire: Hsla,
|
||||
pub earth: Hsla,
|
||||
pub air: Hsla,
|
||||
pub water: Hsla,
|
||||
|
||||
pub cardinal: Hsla,
|
||||
pub fixed: Hsla,
|
||||
pub mutable: Hsla,
|
||||
|
||||
pub sun: Hsla,
|
||||
pub moon: Hsla,
|
||||
pub mercury: Hsla,
|
||||
pub venus: Hsla,
|
||||
pub mars: Hsla,
|
||||
pub jupiter: Hsla,
|
||||
pub saturn: Hsla,
|
||||
pub uranus: Hsla,
|
||||
pub neptune: Hsla,
|
||||
pub pluto: Hsla,
|
||||
pub chiron: Hsla,
|
||||
pub north_node: Hsla,
|
||||
pub south_node: Hsla,
|
||||
pub lilith: Hsla,
|
||||
|
||||
pub conjunction: Hsla,
|
||||
pub sextile: Hsla,
|
||||
pub square: Hsla,
|
||||
pub trine: Hsla,
|
||||
pub opposition: Hsla,
|
||||
pub minor_aspect: Hsla,
|
||||
|
||||
/// Color del dial zodiacal (anillo exterior).
|
||||
pub dial_ring: Hsla,
|
||||
/// Cusps de casas.
|
||||
pub house_cusp: Hsla,
|
||||
/// Resaltado del ascendente / MC.
|
||||
pub angle_highlight: Hsla,
|
||||
}
|
||||
|
||||
impl AstroPalette {
|
||||
/// Variante oscura — calibrada para sentirse cálida y mística sin
|
||||
/// caer en saturación de carnaval. Las cusps quedan apenas más
|
||||
/// claras que el fondo, los planetas tienen luminancia media-alta
|
||||
/// para destacar sin glow falso.
|
||||
pub fn dark() -> Self {
|
||||
Self {
|
||||
is_dark: true,
|
||||
|
||||
// Elementos — saturación alta + luminancia media. Familiares
|
||||
// al símbolo pero suaves para coexistir.
|
||||
fire: hsla(11.0 / 360.0, 0.78, 0.58, 1.0),
|
||||
earth: hsla(95.0 / 360.0, 0.40, 0.48, 1.0),
|
||||
air: hsla(48.0 / 360.0, 0.72, 0.66, 1.0),
|
||||
water: hsla(210.0 / 360.0, 0.68, 0.58, 1.0),
|
||||
|
||||
cardinal: hsla(340.0 / 360.0, 0.55, 0.62, 1.0),
|
||||
fixed: hsla(258.0 / 360.0, 0.48, 0.58, 1.0),
|
||||
mutable: hsla(170.0 / 360.0, 0.42, 0.55, 1.0),
|
||||
|
||||
sun: hsla(45.0 / 360.0, 0.92, 0.62, 1.0),
|
||||
moon: hsla(220.0 / 360.0, 0.25, 0.85, 1.0),
|
||||
mercury: hsla(140.0 / 360.0, 0.40, 0.62, 1.0),
|
||||
venus: hsla(330.0 / 360.0, 0.55, 0.70, 1.0),
|
||||
mars: hsla(8.0 / 360.0, 0.78, 0.55, 1.0),
|
||||
jupiter: hsla(38.0 / 360.0, 0.72, 0.62, 1.0),
|
||||
saturn: hsla(28.0 / 360.0, 0.20, 0.50, 1.0),
|
||||
uranus: hsla(195.0 / 360.0, 0.65, 0.62, 1.0),
|
||||
neptune: hsla(225.0 / 360.0, 0.55, 0.66, 1.0),
|
||||
pluto: hsla(280.0 / 360.0, 0.40, 0.45, 1.0),
|
||||
chiron: hsla(75.0 / 360.0, 0.30, 0.55, 1.0),
|
||||
north_node: hsla(35.0 / 360.0, 0.35, 0.70, 1.0),
|
||||
south_node: hsla(35.0 / 360.0, 0.20, 0.45, 1.0),
|
||||
lilith: hsla(310.0 / 360.0, 0.45, 0.40, 1.0),
|
||||
|
||||
conjunction: hsla(50.0 / 360.0, 0.65, 0.70, 0.85),
|
||||
sextile: hsla(195.0 / 360.0, 0.60, 0.62, 0.75),
|
||||
square: hsla(8.0 / 360.0, 0.75, 0.58, 0.85),
|
||||
trine: hsla(140.0 / 360.0, 0.55, 0.55, 0.80),
|
||||
opposition: hsla(280.0 / 360.0, 0.55, 0.62, 0.85),
|
||||
minor_aspect: hsla(220.0 / 360.0, 0.20, 0.55, 0.55),
|
||||
|
||||
dial_ring: hsla(40.0 / 360.0, 0.18, 0.78, 0.85),
|
||||
house_cusp: hsla(40.0 / 360.0, 0.12, 0.55, 0.60),
|
||||
angle_highlight: hsla(50.0 / 360.0, 0.95, 0.65, 1.0),
|
||||
}
|
||||
}
|
||||
|
||||
/// Variante clara — desaturada y con luminancias bajas para que los
|
||||
/// símbolos no compitan con el fondo blanco. Pensada para imprimir.
|
||||
pub fn light() -> Self {
|
||||
Self {
|
||||
is_dark: false,
|
||||
|
||||
fire: hsla(11.0 / 360.0, 0.65, 0.42, 1.0),
|
||||
earth: hsla(95.0 / 360.0, 0.45, 0.30, 1.0),
|
||||
air: hsla(48.0 / 360.0, 0.55, 0.42, 1.0),
|
||||
water: hsla(210.0 / 360.0, 0.60, 0.38, 1.0),
|
||||
|
||||
cardinal: hsla(340.0 / 360.0, 0.55, 0.42, 1.0),
|
||||
fixed: hsla(258.0 / 360.0, 0.45, 0.40, 1.0),
|
||||
mutable: hsla(170.0 / 360.0, 0.42, 0.35, 1.0),
|
||||
|
||||
sun: hsla(38.0 / 360.0, 0.85, 0.45, 1.0),
|
||||
moon: hsla(220.0 / 360.0, 0.22, 0.45, 1.0),
|
||||
mercury: hsla(140.0 / 360.0, 0.45, 0.36, 1.0),
|
||||
venus: hsla(330.0 / 360.0, 0.55, 0.45, 1.0),
|
||||
mars: hsla(8.0 / 360.0, 0.75, 0.40, 1.0),
|
||||
jupiter: hsla(38.0 / 360.0, 0.72, 0.42, 1.0),
|
||||
saturn: hsla(28.0 / 360.0, 0.25, 0.30, 1.0),
|
||||
uranus: hsla(195.0 / 360.0, 0.65, 0.40, 1.0),
|
||||
neptune: hsla(225.0 / 360.0, 0.55, 0.42, 1.0),
|
||||
pluto: hsla(280.0 / 360.0, 0.45, 0.30, 1.0),
|
||||
chiron: hsla(75.0 / 360.0, 0.32, 0.35, 1.0),
|
||||
north_node: hsla(35.0 / 360.0, 0.45, 0.45, 1.0),
|
||||
south_node: hsla(35.0 / 360.0, 0.20, 0.30, 1.0),
|
||||
lilith: hsla(310.0 / 360.0, 0.50, 0.30, 1.0),
|
||||
|
||||
conjunction: hsla(45.0 / 360.0, 0.65, 0.40, 0.85),
|
||||
sextile: hsla(195.0 / 360.0, 0.60, 0.38, 0.75),
|
||||
square: hsla(8.0 / 360.0, 0.75, 0.40, 0.85),
|
||||
trine: hsla(140.0 / 360.0, 0.55, 0.35, 0.80),
|
||||
opposition: hsla(280.0 / 360.0, 0.55, 0.42, 0.85),
|
||||
minor_aspect: hsla(220.0 / 360.0, 0.20, 0.45, 0.55),
|
||||
|
||||
dial_ring: hsla(40.0 / 360.0, 0.18, 0.32, 0.90),
|
||||
house_cusp: hsla(40.0 / 360.0, 0.10, 0.45, 0.50),
|
||||
angle_highlight: hsla(45.0 / 360.0, 0.85, 0.40, 1.0),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn for_theme(theme: &yahweh_theme::Theme) -> Self {
|
||||
if theme.is_dark {
|
||||
Self::dark()
|
||||
} else {
|
||||
Self::light()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn element(&self, e: Element) -> Hsla {
|
||||
match e {
|
||||
Element::Fire => self.fire,
|
||||
Element::Earth => self.earth,
|
||||
Element::Air => self.air,
|
||||
Element::Water => self.water,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn modality(&self, m: Modality) -> Hsla {
|
||||
match m {
|
||||
Modality::Cardinal => self.cardinal,
|
||||
Modality::Fixed => self.fixed,
|
||||
Modality::Mutable => self.mutable,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn planet(&self, p: Planet) -> Hsla {
|
||||
match p {
|
||||
Planet::Sun => self.sun,
|
||||
Planet::Moon => self.moon,
|
||||
Planet::Mercury => self.mercury,
|
||||
Planet::Venus => self.venus,
|
||||
Planet::Mars => self.mars,
|
||||
Planet::Jupiter => self.jupiter,
|
||||
Planet::Saturn => self.saturn,
|
||||
Planet::Uranus => self.uranus,
|
||||
Planet::Neptune => self.neptune,
|
||||
Planet::Pluto => self.pluto,
|
||||
Planet::Chiron => self.chiron,
|
||||
Planet::NorthNode => self.north_node,
|
||||
Planet::SouthNode => self.south_node,
|
||||
Planet::Lilith => self.lilith,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn aspect(&self, a: AspectKind) -> Hsla {
|
||||
match a {
|
||||
AspectKind::Conjunction => self.conjunction,
|
||||
AspectKind::Sextile => self.sextile,
|
||||
AspectKind::Square => self.square,
|
||||
AspectKind::Trine => self.trine,
|
||||
AspectKind::Opposition => self.opposition,
|
||||
_ => self.minor_aspect,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Resuelve un símbolo zodiacal (string) a su elemento.
|
||||
/// Ej. `"aries" → Fire`, `"taurus" → Earth`, …
|
||||
pub fn element_for_sign(sign: &str) -> Option<Element> {
|
||||
Some(match sign.to_ascii_lowercase().as_str() {
|
||||
"aries" | "leo" | "sagittarius" => Element::Fire,
|
||||
"taurus" | "virgo" | "capricorn" => Element::Earth,
|
||||
"gemini" | "libra" | "aquarius" => Element::Air,
|
||||
"cancer" | "scorpio" | "pisces" => Element::Water,
|
||||
_ => return None,
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn element_lookup() {
|
||||
assert_eq!(element_for_sign("aries"), Some(Element::Fire));
|
||||
assert_eq!(element_for_sign("CAPRICORN"), Some(Element::Earth));
|
||||
assert_eq!(element_for_sign("zod"), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn palette_indexes() {
|
||||
let p = AstroPalette::dark();
|
||||
assert_eq!(p.planet(Planet::Sun), p.sun);
|
||||
assert_eq!(p.element(Element::Water), p.water);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user