README.md

# Aurora 🎨

> _"Porque la vida es muy corta para terminales en blanco y negro"_

🌈 **La biblioteca más simpática para hacer que tu terminal se vea increíble**

¿Cansado de ver texto aburrido en tu terminal? ¿Quieres que tus logs tengan más estilo que un influencer en Instagram? **Aurora** es tu nuevo mejor amigo. Convierte tu terminal del equivalente digital de una pared gris en un festival de colores y efectos que hasta tu gato querrá ver.

## ✨ Filosofía de Aurora

Aurora está diseñado con **simplicidad en mente**:

- 🚀 **Uso básico ultra-simple** - `Aurora.format/2` con opciones básicas para el 90% de casos
- 🔧 **Módulos especializados** - Para casos avanzados que requieren control total
- 📚 **Documentación clara** - Con ejemplos que hasta tu abuela entendería

## 🚀 Instalación (más fácil que hacer café)

```elixir
# En tu mix.exs, agrega esta línea mágica:
def deps do
  [
    {:aurora, "~> 1.0"}
  ]
end
```

```bash
mix deps.get  # ¡Y ya está! 🎉
```

### 🎨 Configuración Opcional

Si quieres personalizar los colores, crea un archivo `config/config.exs` en tu proyecto:

```elixir
# config/config.exs
import Config

config :aurora, :colors,
  colors: %{
    primary: %{hex: "#0066CC"},     # Tu color principal
    error: %{hex: "#DC3545"},       # Tu color de error
    # ... más colores personalizados
  }
```

Ver [configuración completa](#-configuración-personalizada-de-colores) más abajo.

## 📋 Funciones Disponibles - Referencia Rápida

### 🎯 Funciones Básicas (en Aurora.ex)

| Función             | Descripción                            | Ejemplo                                   |
| ------------------- | -------------------------------------- | ----------------------------------------- |
| `Aurora.format/2`   | Formateo básico con color, align, bold | `Aurora.format("texto", color: :primary)` |
| `Aurora.colorize/2` | Solo aplicar color                     | `Aurora.colorize("texto", :error)`        |
| `Aurora.stylize/2`  | Solo aplicar efectos                   | `Aurora.stylize("texto", :bold)`          |

### 📊 Datos Estructurados (en Aurora.ex)

| Función                  | Descripción               | Ejemplo                              |
| ------------------------ | ------------------------- | ------------------------------------ |
| `Aurora.json/2`          | JSON formateado           | `Aurora.json(data, color: :info)`    |
| `Aurora.chunks/1`        | Crear múltiples chunks    | `Aurora.chunks([{"Error", :error}])` |
| `Aurora.format_chunks/2` | Formatear lista de chunks | `Aurora.format_chunks(chunks)`       |

### 🔧 Utilidades (en Aurora.ex)

| Función                | Descripción         | Ejemplo                                   |
| ---------------------- | ------------------- | ----------------------------------------- |
| `Aurora.clean/1`       | Quitar códigos ANSI | `Aurora.clean("\\e[31mTexto\\e[0m")`      |
| `Aurora.text_length/1` | Longitud sin ANSI   | `Aurora.text_length("\\e[31mHola\\e[0m")` |
| `Aurora.colors/0`      | Listar colores      | `Aurora.colors()`                         |
| `Aurora.effects/0`     | Listar efectos      | `Aurora.effects()`                        |

**💡 Para funciones avanzadas** (tablas, badges, divisores, encabezados, efectos específicos, etc.) usar directamente los módulos especializados: `Aurora.Format`, `Aurora.Color`, `Aurora.Effects`, `Aurora.Convert`, `Aurora.Ensure`, `Aurora.Normalize`.

## 🎯 Uso Básico (para el 90% de casos)

### La función mágica: `Aurora.format/2`

```elixir
# Texto simple con color
Aurora.format("¡Hola mundo!", color: :primary) |> IO.puts()

# Texto con error (rojo y negrita)
Aurora.format("Error crítico", color: :error, bold: true) |> IO.puts()

# Texto centrado
Aurora.format("Título centrado", color: :info, align: :center) |> IO.puts()

# Múltiples líneas con el mismo formato |> IO.puts()
Aurora.format(["Línea 1", "Línea 2", "Línea 3"], color: :success) |> IO.puts()

# Color personalizado con hex
Aurora.format("Color custom", color: "#FF6B35") |> IO.puts()
```

### Opciones básicas de `Aurora.format/2`

| Opción   | Valores                                              | Descripción          |
| -------- | ---------------------------------------------------- | -------------------- |
| `:color` | `:primary`, `:error`, `:success`, etc. o `"#FF0000"` | Color del texto      |
| `:align` | `:left`, `:right`, `:center`                         | Alineación del texto |
| `:bold`  | `true`/`false`                                       | Texto en negrita     |

## 🔧 Funciones Especializadas (para casos avanzados)

### Colorizar texto directamente

```elixir
# Solo aplicar color
Aurora.colorize("texto", :primary) |> IO.puts()
Aurora.colorize("error", "#FF0000") |> IO.puts()
```

### Efectos de texto

```elixir
# Un solo efecto
Aurora.stylize("texto", :bold) |> IO.puts()

# Múltiples efectos
Aurora.stylize("texto", [:bold, :underline, :italic]) |> IO.puts()
```

### Gradientes de color

```elixir
# Generar gradiente de 6 colores
colors = Aurora.gradient("#FF0000", "#00FF00")  # Rojo a verde

# Gradiente personalizado
colors = Aurora.gradient("#FF0000", "#0000FF", 10)  # 10 colores
```

### Trabajar con chunks (piezas de texto)

```elixir
# Crear chunk individual
chunk = Aurora.chunk("texto", :primary)

# Crear múltiples chunks
chunks = Aurora.chunks([
  {"Error:", :error},
  {" Archivo no encontrado", :warning}
])

# Formatear lista de chunks
Aurora.format_chunks(chunks)
```

### Utilidades básicas

```elixir
# Limpiar códigos ANSI de texto formateado
text_limpio = Aurora.clean("\\e[31mTexto\\e[0m")

# Obtener longitud real del texto (sin códigos ANSI)
longitud = Aurora.text_length("\\e[31mHola\\e[0m")  # => 4
```

### Formateo de datos estructurados

```elixir
# JSON (acepta maps, strings, listas)
data = %{name: "Juan", age: 25, active: true}
Aurora.json(data) |> IO.puts()                            # Pretty print con colores
Aurora.json(data, color: :success) |> IO.puts()           # JSON en verde
Aurora.json(data, compact: true) |> IO.puts()             # Formato compacto
Aurora.json(data, indent: true) |> IO.puts()              # Con indentación extra

# Para funciones más avanzadas (tablas, badges, etc.) usar los módulos especializados
# Ver sección "Uso Avanzado con Módulos" más abajo
```

## 📋 Colores Disponibles

### Colores Principales

| Color         | Nombre        | Hex     | Uso típico              |
| ------------- | ------------- | ------- | ----------------------- |
| `:primary`    | Azul claro    | #A1E7FA | Información principal   |
| `:secondary`  | Verde azulado | #3AABA3 | Información secundaria  |
| `:ternary`    | Naranja       | #FF8000 | Información terciaria   |
| `:quaternary` | Púrpura       | #9B42E2 | Información cuaternaria |

### Colores de Estado

| Color      | Nombre     | Hex     | Uso típico           |
| ---------- | ---------- | ------- | -------------------- |
| `:success` | Verde lima | #97C53C | Operaciones exitosas |
| `:warning` | Amarillo   | #FFCC00 | Advertencias         |
| `:error`   | Rojo coral | #FF5B5B | Errores              |
| `:info`    | Cyan       | #00FFFF | Información general  |
| `:debug`   | Gris       | #B0B0B0 | Información de debug |

### Colores Especiales

| Color        | Nombre     | Hex     | Especial             |
| ------------ | ---------- | ------- | -------------------- |
| `:critical`  | Amarillo   | #FBFF00 | ⚠️ Invertido (fondo) |
| `:alert`     | Amarillo   | #FBFF00 | ⚠️ Invertido (fondo) |
| `:emergency` | Rojo       | #FF0000 | ⚠️ Invertido (fondo) |
| `:happy`     | Rosa       | #EE80C3 | Mensajes positivos   |
| `:notice`    | Azul claro | #5FD7FF | Notificaciones       |
| `:menu`      | Azul suave | #ABCDF1 | Elementos de menú    |
| `:no_color`  | Blanco     | #F8F8F2 | Sin color específico |

### 🎨 Configuración Personalizada de Colores

Puedes personalizar los colores predefinidos creando tu propia configuración en `config/config.exs`:

```elixir
# config/config.exs
config :aurora, :colors,
  colors: %{
    no_color: %{name: :no_color, hex: "#F8F8F2"},
    debug: %{name: :debug, hex: "#B0B0B0"},
    primary: %{name: :primary, hex: "#A1E7FA"},
    secondary: %{name: :secondary, hex: "#3AABA3"},
    ternary: %{name: :ternary, hex: "#FF8000"},
    quaternary: %{name: :quaternary, hex: "#9B42E2"},
    success: %{name: :success, hex: "#97C53C"},
    warning: %{name: :warning, hex: "#FFCC00"},
    warn: %{name: :warning, hex: "#FFCC00"},
    error: %{name: :error, hex: "#FF5B5B"},
    info: %{name: :info, hex: "#00ffff"},
    happy: %{name: :happy, hex: "#EE80C3"},
    background: %{name: :background, hex: "#32302f"},
    menu: %{name: :menu, hex: "#abcdf1"},
    notice: %{name: :notice, hex: "#5FD7FF"},
    critical: %{name: :critical, hex: "#fbff00", inverted: true},
    alert: %{name: :alert, hex: "#fbff00", inverted: true},
    emergency: %{name: :emergency, hex: "#FF0000", inverted: true}
  },
  gradients: %{
    gradient_1: %{name: :gradient_1, hex: "#ff8000"},
    gradient_2: %{name: :gradient_2, hex: "#ff9429"},
    gradient_3: %{name: :gradient_3, hex: "#ffa952"},
    gradient_4: %{name: :gradient_4, hex: "#ffbd7a"},
    gradient_5: %{name: :gradient_5, hex: "#ffd2a3"},
    gradient_6: %{name: :gradient_6, hex: "#ffe6cc"}
  }
```

**Uso con colores personalizados:**

```elixir
# Usar colores personalizados
Aurora.format("Mensaje de marca", color: :brand)
Aurora.format("Texto resaltado", color: :highlight)
Aurora.format("Información secundaria", color: :muted)

# Los colores se aplican automáticamente
Aurora.colorize("Gradiente fuego", :fire)
```

**Ejemplos de configuración:** Consulta el archivo [`config/config.exs.example`](config/config.exs.example) para ver un ejemplo completo de configuración con muchos colores personalizados.

**Nota:** Si no se proporciona configuración, Aurora usará los colores predeterminados mostrados en la tabla.

### 🔍 Consultar Colores Disponibles

Puedes obtener dinámicamente todos los colores configurados:

```elixir
# Obtener todos los colores disponibles
colores_disponibles = Aurora.colors()
IO.inspect(colores_disponibles)

# Verificar si un color específico existe
color_existe = Map.has_key?(Aurora.colors(), :brand)

# Obtener información detallada de un color
info_color = Aurora.Color.get_color_info(:primary)
IO.inspect(info_color)
# => %Aurora.Structs.ColorInfo{name: :primary, hex: "#00FFFF", inverted: false}
```

## 🎨 Efectos Disponibles

| Efecto           | Descripción        |
| ---------------- | ------------------ |
| `:bold`          | Texto en negrita   |
| `:italic`        | Texto en cursiva   |
| `:underline`     | Texto subrayado    |
| `:dim`           | Texto atenuado     |
| `:blink`         | Texto parpadeante  |
| `:reverse`       | Colores invertidos |
| `:strikethrough` | Texto tachado      |

## 🏗️ Uso Avanzado con Módulos

Para casos donde necesitas control total, usa los módulos especializados:

### Tabla de Referencia Rápida - Módulos Especializados

| Módulo             | Funciones principales                                | Uso principal                         |
| ------------------ | ---------------------------------------------------- | ------------------------------------- |
| `Aurora.Format`    | `format/1`, `clean_ansi/1`, `pretty_json/1`          | Formateo de texto y estructuras       |
| `Aurora.Color`     | `get_color_info/1`, `apply_to_chunk/1`, `gradient/3` | Manejo de colores y gradientes        |
| `Aurora.Effects`   | `apply_effect/2`, `apply_multiple_effects/2`         | Aplicación de efectos ANSI            |
| `Aurora.Convert`   | `to_chunk/1`, `table?/1`, `normalize_table/1`        | Conversión y transformación de datos  |
| `Aurora.Ensure`    | `string/1`, `integer/1`, `list/1`                    | Garantía de tipos con valores seguros |
| `Aurora.Normalize` | `normalize_text/2`, `normalize_messages/1`           | Normalización de texto y estructuras  |

### `Aurora.Format` - Control total del formateo

```elixir
# Crear estructura FormatInfo completa
format_info = %Aurora.Structs.FormatInfo{
  chunks: [
    %Aurora.Structs.ChunkText{
      text: "Título importante",
      color: Aurora.Color.get_color_info(:primary),
      effects: %Aurora.Structs.EffectInfo{bold: true, underline: true}
    }
  ],
  align: :center,
  manual_tabs: 2,
  add_line: :both
}

resultado = Aurora.Format.format(format_info)
```

### `Aurora.Color` - Manejo avanzado de colores

```elixir
# Obtener información de color
color_info = Aurora.Color.get_color_info(:primary)

# Trabajar con colores hex
color_custom = Aurora.Color.get_color_info("#FF6B35")

# Generar gradientes entre colores
gradiente = Aurora.Color.generate_gradient_between("#FF0000", "#00FF00")

# Obtener todos los colores disponibles
colores = Aurora.Color.get_all_colors()
```

### `Aurora.Effects` - Control de efectos

```elixir
# Aplicar efecto individual
texto = Aurora.Effects.apply_effect("texto", :bold)

# Aplicar múltiples efectos
texto = Aurora.Effects.apply_multiple_effects("texto", [:bold, :italic])

# Aplicar efectos desde lista de opciones
texto = Aurora.Effects.apply_effects("texto", [bold: true, italic: true])

# Aplicar efectos desde EffectInfo
effect_info = %Aurora.Structs.EffectInfo{bold: true, italic: true}
texto = Aurora.Effects.apply_effect_info("texto", effect_info)

# Aplicar efectos a ChunkText
chunk = %Aurora.Structs.ChunkText{
  text: "texto",
  effects: %Aurora.Structs.EffectInfo{bold: true, underline: true}
}
chunk_con_efectos = Aurora.Effects.apply_chunk_effects(chunk)
```

### `Aurora.Convert` - Utilidades de conversión

```elixir
# Convertir datos a chunks
chunk = Aurora.Convert.to_chunk("texto")
chunk = Aurora.Convert.to_chunk({"texto", :primary})

# Verificar si datos forman tabla
es_tabla = Aurora.Convert.table?([[1, 2], [3, 4]])

# Normalizar tabla con alineación automática
table_data = [["ID", "Nombre"], ["1", "Juan"], ["2", "María"]]
normalized = Aurora.Convert.normalize_table(table_data)

# Manipulación de claves en mapas
data = %{"firstName" => "Juan", "lastName" => "Pérez"}
atom_keys = Aurora.Convert.atomize_keys(data)  # %{firstName: "Juan", lastName: "Pérez"}
string_keys = Aurora.Convert.stringify_keys(atom_keys)  # Vuelta a strings

# Conversión de tipos con validación
Aurora.Convert.cast("123", :integer)  # 123
Aurora.Convert.cast("true", :boolean)  # true
Aurora.Convert.cast("texto", :atom)    # :texto
```

### `Aurora.Ensure` - Garantía de tipos

```elixir
# Asegurar tipos específicos con valores por defecto seguros
Aurora.Ensure.string(nil)        # ""
Aurora.Ensure.string(123)        # "123"
Aurora.Ensure.integer("42")      # 42
Aurora.Ensure.integer("invalid") # 0

# Asegurar listas y estructuras
Aurora.Ensure.list(nil)          # []
Aurora.Ensure.list("texto")      # ["texto"]
Aurora.Ensure.map([a: 1, b: 2])  # %{a: 1, b: 2}

# Asegurar chunks de texto válidos
chunk = Aurora.Ensure.chunk_text("texto")
chunk = Aurora.Ensure.chunk_text({"texto", :primary})

# Conversión de listas con función de transformación
Aurora.Ensure.list_of(["1", "2", "3"], :integer)  # [1, 2, 3]
```

### `Aurora.Normalize` - Normalización de datos

```elixir
# Normalización de texto
Aurora.Normalize.normalize_text("ÑOÑO", :lower)  # "nono" (sin diacríticos)
Aurora.Normalize.normalize_text("café", :upper)  # "CAFE"

# Normalización de mensajes a chunks
messages = [{"Error", :error}, {"Info", :info}, "Texto simple"]
chunks = Aurora.Normalize.normalize_messages(messages)
# => [%ChunkText{text: "Error", color: %ColorInfo{...}}, ...]

# Normalización de tablas con padding automático
table = [["ID", "Name"], ["1", "John"], ["2", "Jane"]]
normalized_table = Aurora.Normalize.normalize_table(table)
# Asegura que todas las filas tengan el mismo número de columnas
# y aplica padding para alineación uniforme
```

## 🧪 Estructuras de Datos

### `ChunkText` - Fragmento de texto formateado

```elixir
%Aurora.Structs.ChunkText{
  text: "Mi texto",                    # Texto (requerido)
  color: %ColorInfo{},                 # Color opcional
  effects: %EffectInfo{}               # Efectos opcionales (integrado con Aurora.Effects)
}
```

### `ColorInfo` - Información de color

```elixir
%Aurora.Structs.ColorInfo{
  name: :primary,                      # Nombre del color
  hex: "#00FFFF",                      # Código hexadecimal
  inverted: false                      # Si está invertido
}
```

### `FormatInfo` - Configuración completa de formato

```elixir
%Aurora.Structs.FormatInfo{
  chunks: [%ChunkText{}],              # Lista de chunks (requerido)
  default_color: %ColorInfo{},         # Color por defecto
  align: :left,                        # Alineación
  manual_tabs: -1,                     # Indentación manual (-1 = automática)
  add_line: :none,                     # Saltos de línea (:before, :after, :both, :none)
  animation: ""                        # Prefijo de animación
}
```

### `EffectInfo` - Efectos de texto

```elixir
%Aurora.Structs.EffectInfo{
  bold: false,                         # Negrita
  italic: false,                       # Cursiva
  underline: false,                    # Subrayado
  dim: false,                          # Atenuado
  blink: false,                        # Parpadeante
  reverse: false,                      # Invertido
  hidden: false,                       # Oculto
  strikethrough: false                 # Tachado
}
```

## 🧪 Testing

```bash
# Ejecutar todos los tests
mix test

# Ejecutar solo doctests
mix test --only doctest

# Ejecutar tests con cobertura
mix test --cover
```

## 📦 Dependencias

- `:jason` - Para formateo de JSON (incluida automáticamente)

## 📄 Licencia

MIT License - ¡Úsalo, mejóralo, compártelo!

---

## 🤝 Contribuir

¿Tienes ideas para hacer Aurora aún más genial? ¡Los PRs son bienvenidos! Asegúrate de:

1. Mantener la filosofía simple
2. Agregar tests para nuevas funcionalidades
3. Actualizar la documentación
4. Hacer que todo sea súper fácil de usar

---

**¡Disfruta haciendo tu terminal hermoso! 🎨✨**