Colores de Consola estilo Colorama (Python) y Logs estilo Gin (Go) en DMVCFramework
El regreso de la consola
Las aplicaciones de consola están viviendo una segunda juventud. No es nostalgia: es una tendencia concreta impulsada por algunas de las corrientes tecnológicas más relevantes de los últimos años.
Los agentes de IA viven en la consola. Claude Code, GitHub Copilot CLI, Aider, Cursor Agent - las herramientas de desarrollo asistidas por IA son aplicaciones de línea de comandos. No tienen GUI: leen, escriben código y se comunican con el desarrollador a través del terminal. Y lo hacen con una salida rica, coloreada y estructurada, porque cuando la interacción es textual, cada detalle visual cuenta.
Los servidores MCP (Model Context Protocol) son procesos de consola. El protocolo MCP de Anthropic, que se está convirtiendo en el estándar para conectar agentes de IA con herramientas externas, se basa en servidores que se comunican vía stdin/stdout. Cada servidor MCP es una aplicación de consola. Y con Delphi se pueden escribir servidores MCP nativos, rápidos y con un único ejecutable - una ventaja enorme frente a los equivalentes en Python o TypeScript que requieren runtime y dependencias.
Los microservicios son (a menudo) aplicaciones de consola. Contenedores Docker, servicios systemd, demonios Windows: el patrón dominante en el backend moderno es un ejecutable sin GUI que registra logs en la consola. Los frameworks web modernos - desde Go con Gin hasta Python con FastAPI y uvicorn - todos han invertido en logs de consola coloreados y estructurados porque es ahí donde el desarrollador pasa su tiempo durante el desarrollo.
Las herramientas CLI están en todas partes. gh, docker, kubectl, terraform, npm - las herramientas que usamos cada día son aplicaciones de consola con salida cuidada. Una herramienta de línea de comandos con salida monocromática y no estructurada parece inmediatamente anticuada.
En este contexto, disponer de un soporte de primera clase para la salida de consola coloreada no es un lujo: es una necesidad. Por eso he introducido en DelphiMVCFramework un sistema de colores ANSI en dos niveles:
- Primitivas estilo colorama (
Fore,Back,Style) - constantes de cadena componibles para colorear cualquier salida de consola, inspiradas en colorama para Python - Renderer estilo Gin - logs HTTP estructurados y coloreados, inspirados en el logger de Gin para Go, activados automáticamente en cada aplicación DMVC
Los colores de consola son solo una de las muchas novedades que trae DMVCFramework 3.5.0 “Silicon”:
- JWT asimetrico (RS256, PS256, ES256, EdDSA)
- Verificacion JWKS e integracion OIDC
- Streaming SSE y JSONL
- Middleware RangeMedia (RFC 7233)
- Soporte Oracle 12c+ en ActiveRecord
- Wizard IDE completamente rediseñado
- Console spinner y colores ANSI
- …y mucho más
Presentaré todo en primicia en ITDevCon 2026 Spring Edition. Como todas las ediciones de primavera, la conferencia será íntegramente en italiano - una ocasión perfecta para profundizar cada detalle con la comunidad. Para quienes prefieran la edición internacional en inglés, la cita es en noviembre con la conferencia de dos días. ¡Inscríbete ahora!
La API estilo Colorama: Fore, Back, Style
La unit MVCFramework.Console.pas forma parte del repositorio de DMVCFramework, pero no tiene ninguna dependencia del framework. Puedes copiarla y usarla en cualquier proyecto Delphi de consola - un servidor, una herramienta de línea de comandos, un servidor MCP - sin necesidad de incluir otras dependencias de DMVCFramework.
“La simplicidad es la suprema sofisticación” - esta frase, atribuida a Leonardo da Vinci, es el principio que ha guiado el diseño de esta API. Sin clases, sin objetos, sin métodos, sin interfaces. Solo tres records con constantes de cadena: Fore (color de texto), Back (color de fondo) y Style (estilo). Cada constante es una secuencia de escape ANSI que se compone por simple concatenación - exactamente como colorama en Python.
Podríamos haber creado un builder pattern con method chaining, un sistema de temas con herencia, un color manager thread-safe con dependency injection. Pero, ¿para qué?
“La complejidad se añade con bisturí, no con pala.” — Daniele Teti
Este es un principio que repito a menudo durante mis cursos y que guía cada decisión de diseño en DMVCFramework. Cuando el problema es simple - colorear texto en la consola - la solución debe ser igualmente simple. Si se necesita toda una jerarquía de clases para escribir una línea verde, algo ha salido mal.
Colores básicos
program ColorBasics;
{$APPTYPE CONSOLE}
uses
System.SysUtils, MVCFramework.Console;
begin
EnableANSIColorConsole;
WriteLn(Fore.Red + 'This is red text' + Style.ResetAll);
WriteLn(Fore.Green + 'This is green text' + Style.ResetAll);
WriteLn(Fore.Yellow + 'This is yellow text' + Style.ResetAll);
WriteLn(Fore.Blue + 'This is blue text' + Style.ResetAll);
WriteLn(Fore.Cyan + 'This is cyan text' + Style.ResetAll);
WriteLn(Fore.Magenta + 'This is magenta text' + Style.ResetAll);
WriteLn(Fore.White + 'This is white text' + Style.ResetAll);
WriteLn(Fore.DarkGray + 'This is dark gray text' + Style.ResetAll);
ReadLn;
end.
La función EnableANSIColorConsole habilita el soporte ANSI en Windows 10+ (mediante ENABLE_VIRTUAL_TERMINAL_PROCESSING). En Linux no es necesario, los terminales soportan ANSI de forma nativa. La llamada es idempotente: se puede invocar cuantas veces se quiera sin efectos secundarios.
Style.ResetAll restablece todos los atributos (color de texto, fondo y estilo) a los valores predeterminados del terminal. Debe usarse siempre al final de cada línea coloreada para evitar que el color “se propague” a las líneas siguientes.
Cada record ofrece 16 colores, tanto en las variantes “dark” (códigos ANSI 30-37 / 40-47) como en las variantes bright (90-97 / 100-107):
| Fore/Back | Dark | Bright |
|---|---|---|
| Red | DarkRed (31/41) |
Red (91/101) |
| Green | DarkGreen (32/42) |
Green (92/102) |
| Yellow | DarkYellow (33/43) |
Yellow (93/103) |
| Blue | DarkBlue (34/44) |
Blue (94/104) |
| Magenta | DarkMagenta (35/45) |
Magenta (95/105) |
| Cyan | DarkCyan (36/46) |
Cyan (96/106) |
| Gray | Gray (37/47) |
White (97/107) |
| Black/Gray | Black (30/40) |
DarkGray (90/100) |

Composición de colores
La verdadera potencia de la API está en la composición. Al ser simples cadenas, los colores se combinan con el operador +:
// Foreground + Background
WriteLn(Fore.White + Back.DarkBlue + ' White on Blue ' + Style.ResetAll);
WriteLn(Fore.Black + Back.Yellow + ' Black on Yellow ' + Style.ResetAll);
WriteLn(Fore.White + Back.DarkRed + ' CRITICAL ERROR ' + Style.ResetAll);
// Style + Foreground
WriteLn(Style.Bright + Fore.Green + 'Bold green text' + Style.ResetAll);
WriteLn(Style.Dim + Fore.Cyan + 'Dimmed cyan text' + Style.ResetAll);
// Colores inline en el texto
WriteLn(
'Status: ' + Fore.Green + 'OK' + Style.ResetAll +
' | Items: ' + Fore.Cyan + '42' + Style.ResetAll +
' | Errors: ' + Fore.Red + '0' + Style.ResetAll
);
No hay ninguna clase, ningún objeto, ningún método. Solo constantes de cadena y concatenación. El compilador resuelve todo en tiempo de compilación: cero overhead en tiempo de ejecución.

Badges prácticos
Con Fore + Back se pueden crear badges coloreados para cualquier tipo de salida estructurada:
// Test result badges
WriteLn(Back.DarkGreen + Fore.White + ' PASS ' + Style.ResetAll + ' TestUserAuth');
WriteLn(Back.DarkRed + Fore.White + ' FAIL ' + Style.ResetAll + ' TestPaymentTimeout');
WriteLn(Back.DarkYellow + Fore.White + ' SKIP ' + Style.ResetAll + ' TestExternalAPI');
// HTTP status badges
WriteLn(Fore.White + Back.DarkGreen + ' 200 ' + Style.ResetAll + ' GET /api/people');
WriteLn(Fore.White + Back.DarkYellow + ' 404 ' + Style.ResetAll + ' GET /api/unknown');
WriteLn(Fore.White + Back.DarkRed + ' 500 ' + Style.ResetAll + ' GET /api/crash');

Definir estilos reutilizables (como un CSS para la consola)
Repetir Fore.White + Back.DarkGreen cada vez que se quiere un badge verde es verboso y frágil: si mañana se decide cambiar el verde por cian, hay que modificar cada punto. La solución es simple pero eficaz: basta con definir constantes.
const
STYLE_SUCCESS = Fore.White + Back.DarkGreen;
STYLE_ERROR = Fore.White + Back.DarkRed;
STYLE_WARNING = Fore.White + Back.DarkYellow;
STYLE_INFO = Fore.White + Back.DarkBlue;
STYLE_MUTED = Fore.DarkGray;
STYLE_RESET = Style.ResetAll;
A partir de aquí el código se vuelve limpio y legible, exactamente como aplicar clases CSS a elementos HTML:
WriteLn(STYLE_SUCCESS + ' DONE ' + STYLE_RESET + ' Database migration completed');
WriteLn(STYLE_WARNING + ' SLOW ' + STYLE_RESET + ' Query took 3.2s on table Orders');
WriteLn(STYLE_ERROR + ' FAIL ' + STYLE_RESET + ' Connection refused on port 5432');
WriteLn(STYLE_INFO + ' NOTE ' + STYLE_RESET + ' Using fallback configuration');
WriteLn(STYLE_MUTED + '--- end of report ---' + STYLE_RESET);
Al ser constantes de cadena resueltas en tiempo de compilación, no hay ningún overhead: el compilador las expande inline. Se obtiene la comodidad de un estilo centralizado con el rendimiento de cadenas hard-coded.
Logs HTTP estilo Gin en DMVCFramework
La verdadera killer feature es el renderer TMVCColorConsoleRenderer, inspirado en el logger HTTP de Gin (el popular web framework de Go). Este renderer está activo por defecto en todas las aplicaciones DMVCFramework de consola - no es necesario configurar nada.
Cómo funciona
Cada petición HTTP se registra en formato estructurado con colores:
TIME | TID | STATUS | DURATION | IP | METHOD "path"
Los badges usan los mismos códigos ANSI idénticos del código fuente de Gin:
| Elemento | Color | Código ANSI |
|---|---|---|
| Status 2xx | White sobre DarkGreen | 97;42 |
| Status 3xx | DarkGray sobre Gray | 90;47 |
| Status 4xx | White sobre DarkYellow | 97;43 |
| Status 5xx | White sobre DarkRed | 97;41 |
| GET | White sobre DarkBlue | 97;44 |
| POST | White sobre DarkCyan | 97;46 |
| PUT | White sobre DarkYellow | 97;43 |
| DELETE | White sobre DarkRed | 97;41 |
| PATCH | White sobre DarkGreen | 97;42 |
| HEAD | White sobre DarkMagenta | 97;45 |

Niveles de log de aplicación
Los logs no-HTTP (mensajes de aplicación) usan colores distintos que no se solapan con los badges HTTP:
| Nivel | Estilo | Lógica |
|---|---|---|
| DEBUG | Gris oscuro | Bajo ruido visual |
| INFO | Azul | Neutro, informativo |
| WARN | Amarillo | Atención |
| ERROR | Rojo bold | Problema |
| FATAL | Badge blanco sobre rojo | Imposible de ignorar |
FATAL es el único nivel de aplicación con fondo coloreado: al ser el más crítico, debe destacar inmediatamente incluso en un log muy denso.
LogD('Processing request...'); // DEBUG - gris, casi invisible
LogI('Server started on port 8080'); // INFO - azul, informativo
LogW('Cache miss rate above 50%'); // WARN - amarillo, atención
LogE('Connection to database lost'); // ERROR - rojo bold, problema
Log.Fatal('Out of memory', LOGGERPRO_TAG); // FATAL - badge rojo, crítico

Consola coloreada, archivos limpios
Una pregunta legítima: si los logs de consola contienen secuencias de escape ANSI, ¿qué pasa con los logs en archivo? La respuesta es: nada. El sistema de logging de DMVCFramework está basado en LoggerPro, que soporta appenders múltiples. Cada appender tiene su propio renderer: el appender de consola usa TMVCColorConsoleRenderer que produce salida coloreada, mientras que el appender de archivo usa un renderer de texto estándar. Los códigos ANSI nunca terminan en los archivos de log - cada destino recibe exactamente el formato apropiado.
Fallback automático
El renderer de consola detecta automáticamente si el terminal soporta colores ANSI. Si no los soporta (por ejemplo en versiones de Windows anteriores a la 10), produce salida en texto plano sin secuencias de escape, idéntica al formato anterior de DMVCFramework. No se necesita ningún {$IFDEF} en el código.
Duración de las peticiones
Cada petición HTTP incluye automáticamente el tiempo de ejecución, medido con TStopWatch de System.Diagnostics. El overhead es insignificante (20-50 nanosegundos por llamada) y la información es valiosa para identificar endpoints lentos.
Compatibilidad
| Plataforma | Soporte |
|---|---|
| Windows 10+ | Completo (ANSI via SetConsoleMode) |
| Windows < 10 | Fallback a texto plano |
| Linux | Nativo (ANSI soportado por todos los terminales) |
Pruébalo ahora
El código fuente de los ejemplos está disponible en la carpeta samples/console_colors* del repositorio GitHub:
samples/console_colors_basics/- Colores básicossamples/console_colors_composition/- Composición y estilossamples/console_colors_badges/- Badges prácticos
Para los logs estilo Gin no hay que hacer nada: basta con crear una aplicación DMVCFramework de consola y los logs coloreados aparecerán automáticamente.
// Eso es todo. Los colores ya están activos.
program MyServer;
{$APPTYPE CONSOLE}
uses
MVCFramework, MVCFramework.Console, MVCFramework.Logger;
begin
// EnableANSIColorConsole es llamada automáticamente por el renderer
// ... tu servidor DMVC
end.
Preguntas frecuentes
¿Cómo se añaden colores a la consola en Delphi?
Usa la unit MVCFramework.Console y los records Fore, Back, Style. Llama a EnableANSIColorConsole al inicio del programa, luego compone los colores con concatenación: WriteLn(Fore.Red + 'texto rojo' + Style.ResetAll).
¿Funciona en Windows?
Sí, en Windows 10 y posteriores. La función EnableANSIColorConsole activa el soporte ANSI mediante SetConsoleMode. En versiones anteriores, el renderer produce automáticamente salida en texto plano.
¿Se pueden usar los colores sin DMVCFramework?
Sí. La unit MVCFramework.Console.pas no tiene dependencias del framework. Puedes copiarla en cualquier proyecto Delphi de consola.
¿Los códigos ANSI terminan en los archivos de log? No. DMVCFramework usa LoggerPro con appenders múltiples: el appender de consola usa el renderer coloreado, el appender de archivo usa un renderer de texto estándar. Cada destino recibe el formato apropiado.
¿Cuál es el overhead del timing de las peticiones?
Insignificante. TStopWatch emplea 20-50 nanosegundos por llamada, irrelevante comparado con el tiempo de procesamiento de cualquier petición HTTP.
Comments
comments powered by Disqus