grmenu 2.0.0 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/GRmenu.rb +1570 -319
- data/README.md +425 -264
- data/data/help.txt +304 -0
- metadata +7 -3
data/README.md
CHANGED
|
@@ -1,381 +1,542 @@
|
|
|
1
|
-
|
|
1
|
+
# GRmenu (Ruby) v3.0
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
**Suite TUI Profesional y Ligera para la Creacion de Interfaces de Linea de Comandos en Terminales TTY.**
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
Flechas arriba/abajo para moverte · `Enter` para elegir · `q` para salir
|
|
5
|
+
Menus interactivos por teclado, seleccion multiple con casillas de verificacion, controles deslizantes en tiempo real, renderizado de imagenes ANSI TrueColor de 24 bits, modo cromatico RGB animado a 30 FPS, modales nativos de confirmacion y texto, buscador instantaneo en vivo, cuadriculas bidimensionales, barras de progreso y banners 3D sin dependencias externas.
|
|
8
6
|
|
|
9
7
|
[](https://badge.fury.io/rb/grmenu)
|
|
10
8
|
[](LICENSE)
|
|
11
9
|
[](https://github.com/JoseEduardoGR/GRmenu)
|
|
10
|
+
[](https://www.ruby-lang.org)
|
|
11
|
+
|
|
12
|
+
---
|
|
12
13
|
|
|
13
|
-
|
|
14
|
+
## Tabla de Contenidos
|
|
15
|
+
|
|
16
|
+
1. [Por que elegir GRmenu?](#-por-que-elegir-grmenu)
|
|
17
|
+
2. [Instalacion y Requisitos](#-instalacion-y-requisitos)
|
|
18
|
+
3. [Inicio Rapido en 10 Segundos](#-inicio-rapido-en-10-segundos)
|
|
19
|
+
4. [Guia de Componentes y Caracteristicas](#-guia-de-componentes-y-caracteristicas)
|
|
20
|
+
- [1. Menu Interactivo Principal (Buscador, Grid 2D y Paginacion)](#1-menu-interactivo-principal)
|
|
21
|
+
- [2. Seleccion Multiple con Checkboxes (GRmenu.checkbox)](#2-seleccion-multiple-con-checkboxes)
|
|
22
|
+
- [3. Control Deslizante Interactivo (GRmenu.slider)](#3-control-deslizante-interactivo)
|
|
23
|
+
- [4. Renderizado Universal de Imagenes (GRmenu.image)](#4-renderizado-universal-de-imagenes)
|
|
24
|
+
- [5. Modales Nativos de Confirmacion y Entrada (confirm e input)](#5-modales-nativos-de-confirmacion-y-entrada)
|
|
25
|
+
- [6. Modo RGB Chroma Wave Animado a 30 FPS](#6-modo-rgb-chroma-wave-animado)
|
|
26
|
+
- [7. Barra de Progreso y Spinner de Carga](#7-barra-de-progreso-y-spinner-de-carga)
|
|
27
|
+
- [8. Banners 3D y Lineas Divisorias](#8-banners-3d-y-lineas-divisorias)
|
|
28
|
+
- [9. Modulo Independiente de Color (Color / C)](#9-modulo-independiente-de-color)
|
|
29
|
+
5. [Catalogo Visual de Fuentes 3D (1 al 10)](#-catalogo-visual-de-fuentes-3d)
|
|
30
|
+
6. [Catalogo Visual de Marcos y Bordes (1 al 20)](#-catalogo-visual-de-marcos-y-bordes)
|
|
31
|
+
7. [Referencia Exhaustiva de la API](#-referencia-exhaustiva-de-la-api)
|
|
32
|
+
8. [Mapa de Controles y Teclado](#-mapa-de-controles-y-teclado)
|
|
33
|
+
9. [Recetas y Casos de Uso del Mundo Real](#-recetas-y-casos-de-uso-del-mundo-real)
|
|
34
|
+
10. [Licencia](#-licencia)
|
|
14
35
|
|
|
15
36
|
---
|
|
16
37
|
|
|
17
|
-
##
|
|
38
|
+
## Por que elegir GRmenu?
|
|
18
39
|
|
|
19
|
-
-
|
|
20
|
-
-
|
|
21
|
-
-
|
|
22
|
-
-
|
|
23
|
-
-
|
|
24
|
-
- 🎨 **20 estilos de borde** — desde ASCII clásico hasta caracteres Unicode dobles, curvas redondeadas y bloques outline.
|
|
25
|
-
- 🌈 **Paleta de colores completa** — personalización individual de marco, título, banner, subtítulo, divisores, opciones y foco activo con 2 niveles de brillo.
|
|
26
|
-
- 📐 **Centrado simétrico automático** — alinea y centra automáticamente subtítulos y menús de opciones respecto al ancho de banners grandes.
|
|
27
|
-
- 🛠️ **Helpers nativos en modo crudo** — `clear_screen`, `continue`, `banner`, `spinner`, `progress`, `div` y `help`.
|
|
28
|
-
- 💻 **100% Multiplataforma** — compatible con Linux, macOS y Windows (PowerShell, CMD, Windows Terminal, VS Code).
|
|
29
|
-
- 📦 **Cero dependencias externas** — utiliza únicamente la librería estándar `io/console` y `json`.
|
|
40
|
+
- **Cero Dependencias Externas:** Funciona exclusivamente con la libreria estandar de Ruby (`io/console`, `json`, `zlib`), sin gemas pesadas ni binarios nativos requeridos.
|
|
41
|
+
- **Modo TTY Crudo Instantaneo:** Control milimetrico de la consola sin parpadeo de pantalla y con captura instantanea de eventos de teclado (0 ms de latencia).
|
|
42
|
+
- **Animaciones Sin Lag a 30 FPS:** Motor de renderizado reactivo no bloqueante basado en `IO.select` que permite efectos visuales dinamicos continuos sin saturar la CPU ni bloquear la entrada del usuario.
|
|
43
|
+
- **Multiplataforma Real:** Totalmente compatible con Linux, macOS y Windows (Windows Terminal, PowerShell, CMD y VS Code Terminal).
|
|
44
|
+
- **Diseno Modular y Expresivo:** Desde un simple menu de 3 lineas hasta complejas suites de instalacion, paneles DevOps o herramientas de configuracion.
|
|
30
45
|
|
|
31
46
|
---
|
|
32
47
|
|
|
33
|
-
##
|
|
48
|
+
## Instalacion y Requisitos
|
|
49
|
+
|
|
50
|
+
Requiere **Ruby >= 2.6.0**.
|
|
51
|
+
|
|
52
|
+
### Via RubyGems
|
|
34
53
|
|
|
35
54
|
```bash
|
|
36
55
|
gem install grmenu
|
|
37
56
|
```
|
|
38
57
|
|
|
39
|
-
|
|
58
|
+
### Via Gemfile
|
|
40
59
|
|
|
41
60
|
```ruby
|
|
42
|
-
|
|
61
|
+
gem 'grmenu', '~> 3.0'
|
|
43
62
|
```
|
|
44
63
|
|
|
45
|
-
|
|
64
|
+
### Requerimiento directo en scripts
|
|
65
|
+
|
|
66
|
+
```ruby
|
|
67
|
+
require 'GRmenu'
|
|
68
|
+
```
|
|
46
69
|
|
|
47
70
|
---
|
|
48
71
|
|
|
49
|
-
##
|
|
72
|
+
## Inicio Rapido en 10 Segundos
|
|
50
73
|
|
|
51
|
-
|
|
74
|
+
Crea un archivo llamado `app.rb` y ejecuta `ruby app.rb`:
|
|
52
75
|
|
|
53
76
|
```ruby
|
|
77
|
+
require 'GRmenu'
|
|
78
|
+
|
|
79
|
+
def iniciar_servicio
|
|
80
|
+
GRmenu.clear_screen
|
|
81
|
+
puts Color.bright_green("-> Servicio iniciado exitosamente en http://localhost:3000")
|
|
82
|
+
GRmenu.continue
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def ver_estado
|
|
86
|
+
GRmenu.clear_screen
|
|
87
|
+
puts Color.bright_cyan("-> Estado: Servidor Operativo | Memoria: 45 MB | Conexiones: 12")
|
|
88
|
+
GRmenu.continue
|
|
89
|
+
end
|
|
90
|
+
|
|
54
91
|
menu = GRmenu.new(
|
|
55
92
|
[
|
|
56
|
-
method(:
|
|
57
|
-
|
|
58
|
-
["
|
|
59
|
-
["Crear Backup", method(:respaldo), "Genera dump SQL de la BD"], # 4. Con Tooltip descriptivo al pie del marco
|
|
60
|
-
["Ejecutar Lambda", -> { puts Color.pink("Lambda!"); GRmenu.continue }, "Bloque anónimo Proc/Lambda"],
|
|
61
|
-
["Probar Banner Helper", method(:prueba_banner_rapido)], # 5. Helper GRmenu.banner
|
|
62
|
-
["Ver Ayuda y Referencia", method(:ver_ayuda_completa)], # 6. Helper GRmenu.help
|
|
63
|
-
method(:salir) # 7. Salir
|
|
93
|
+
["Iniciar Servicio", method(:iniciar_servicio), "Lanza el worker en segundo plano"],
|
|
94
|
+
["Ver Estado", method(:ver_estado), "Muestra metricas de memoria y conexion"],
|
|
95
|
+
["Salir", -> { exit(0) }, "Finaliza la ejecucion"]
|
|
64
96
|
],
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
font: 1, # Fuente del banner (1 al 10, default 1: ANSI Shadow 3D)
|
|
69
|
-
style: 7, # Estilo de marco de opciones (1 al 20, ej: 7=redondeado, 3=doble)
|
|
70
|
-
banner_style: 3, # Estilo de marco del banner (1 al 20, ej: 3=doble línea)
|
|
71
|
-
divider: true, # Líneas divisorias a la par del banner (true, false o número)
|
|
72
|
-
center: true, # Centrado automático del menú y subtítulo respecto al banner
|
|
73
|
-
page_size: 8 # (Opcional) Límite visible para auto-scroll y paginación
|
|
97
|
+
title: "Panel de Control",
|
|
98
|
+
banner: "MI APP",
|
|
99
|
+
style: 3
|
|
74
100
|
)
|
|
101
|
+
|
|
102
|
+
menu.draw
|
|
75
103
|
```
|
|
76
104
|
|
|
77
105
|
---
|
|
78
106
|
|
|
79
|
-
##
|
|
107
|
+
## Guia de Componentes y Caracteristicas
|
|
108
|
+
|
|
109
|
+
### 1. Menu Interactivo Principal
|
|
110
|
+
|
|
111
|
+
El constructor `GRmenu.new` proporciona una experiencia interactiva completa con navegacion continua, paginacion automatica, buscador en vivo y organizacion en cuadricula 2D.
|
|
80
112
|
|
|
81
|
-
|
|
113
|
+
```text
|
|
114
|
+
╔═══════════════════════════════════════════╗
|
|
115
|
+
║ Panel de Control ║
|
|
116
|
+
║═══════════════════════════════════════════║
|
|
117
|
+
║ Buscar: serv█ ║
|
|
118
|
+
║═══════════════════════════════════════════║
|
|
119
|
+
║ > [X] Servidor Web Nginx ║
|
|
120
|
+
║ [ ] Servidor Base de Datos Postgres ║
|
|
121
|
+
║───────────────────────────────────────────║
|
|
122
|
+
║ * Proxy inverso HTTP de alto rendimiento ║
|
|
123
|
+
╚═══════════════════════════════════════════╝
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
#### Formatos de Opciones Aceptados
|
|
127
|
+
|
|
128
|
+
Puedes combinar cualquiera de los siguientes formatos en el array de opciones:
|
|
82
129
|
|
|
83
130
|
```ruby
|
|
84
|
-
|
|
131
|
+
menu = GRmenu.new(
|
|
132
|
+
[
|
|
133
|
+
# 1. Method directo (auto-formatea y capitaliza el nombre)
|
|
134
|
+
method(:iniciar_servidor),
|
|
85
135
|
|
|
86
|
-
|
|
136
|
+
# 2. Symbol (invoca el metodo global o del contexto)
|
|
137
|
+
:crear_respaldo,
|
|
87
138
|
|
|
88
|
-
#
|
|
89
|
-
|
|
90
|
-
GRmenu.clear_screen
|
|
91
|
-
puts Color.bright_green("-> Servidor iniciado correctamente en el puerto 3000.")
|
|
92
|
-
GRmenu.continue
|
|
93
|
-
end
|
|
139
|
+
# 3. Arreglo [Etiqueta, Accion]
|
|
140
|
+
["Lanzar Proceso", method(:lanzar)],
|
|
94
141
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
puts Color.bright_cyan("-> Creando respaldo de la base de datos...")
|
|
98
|
-
GRmenu.continue
|
|
99
|
-
end
|
|
142
|
+
# 4. Arreglo con Tooltip [Etiqueta, Accion, Descripcion]
|
|
143
|
+
["Limpieza de Cache", method(:limpiar), "Vacia los temporales en disco"],
|
|
100
144
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
puts Color.bright_magenta("-> CPU: 12% | RAM: 4.2 GB | Estado: Operativo")
|
|
104
|
-
GRmenu.continue
|
|
105
|
-
end
|
|
145
|
+
# 5. Bloque anonimo Proc o Lambda
|
|
146
|
+
["Accion Rapida", -> { puts "Ejecutado!"; GRmenu.continue }, "Ejecuta bloque inline"],
|
|
106
147
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
148
|
+
# 6. Hash explicito
|
|
149
|
+
{ name: "Configuracion", action: method(:config), desc: "Ajustes del sistema" }
|
|
150
|
+
],
|
|
151
|
+
title: "Consola de Administracion",
|
|
152
|
+
banner: "SISTEMA",
|
|
153
|
+
search: true, # Activa buscador interactivo en vivo
|
|
154
|
+
columns: 2, # Cuadricula de 2 columnas con flechas izquierda/derecha
|
|
155
|
+
page_size: 6, # Paginacion con auto-scroll
|
|
156
|
+
style: 3
|
|
157
|
+
)
|
|
115
158
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
GRmenu.help
|
|
119
|
-
GRmenu.continue
|
|
120
|
-
end
|
|
159
|
+
menu.draw(size_max: 44)
|
|
160
|
+
```
|
|
121
161
|
|
|
122
|
-
|
|
123
|
-
GRmenu.clear_screen
|
|
124
|
-
puts Color.bright_yellow("¡Sesión finalizada con éxito!")
|
|
125
|
-
exit(0)
|
|
126
|
-
end
|
|
162
|
+
---
|
|
127
163
|
|
|
128
|
-
|
|
129
|
-
def demo_barra_progreso
|
|
130
|
-
GRmenu.clear_screen
|
|
131
|
-
# Fácil y rápido: pasas el total y bar.advance(1) en tu bucle
|
|
132
|
-
GRmenu.progress(10, title: "Descargando Paquetes", color: "cyan", style: 3) do |bar|
|
|
133
|
-
10.times do |i|
|
|
134
|
-
sleep 0.1
|
|
135
|
-
bar.advance(1, status: "Paso #{i + 1} de 10 completado")
|
|
136
|
-
end
|
|
137
|
-
end
|
|
138
|
-
puts Color.bright_green("\n-> ¡Barra completada al 100%!")
|
|
139
|
-
GRmenu.continue
|
|
140
|
-
end
|
|
164
|
+
### 2. Seleccion Multiple con Checkboxes
|
|
141
165
|
|
|
142
|
-
|
|
143
|
-
GRmenu.clear_screen
|
|
144
|
-
GRmenu.spinner("Conectando a la base de datos...", color: "green") do
|
|
145
|
-
sleep 1.2
|
|
146
|
-
end
|
|
147
|
-
puts Color.bright_green("\n-> Conexión establecida con éxito.")
|
|
148
|
-
GRmenu.continue
|
|
149
|
-
end
|
|
166
|
+
Permite al usuario seleccionar multiples elementos simultaneamente mediante casillas de verificacion interactivas `[X]` / `[ ]`.
|
|
150
167
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
168
|
+
```text
|
|
169
|
+
╔══════════════════ Instalador de Paquetes ══════════════════╗
|
|
170
|
+
║ [X] Servidor Nginx Web ║
|
|
171
|
+
║ [X] Base de Datos PostgreSQL 16 ║
|
|
172
|
+
║ [ ] Almacen de Cache Redis 7.2 ║
|
|
173
|
+
║ [X] Monitor Prometheus ║
|
|
174
|
+
║────────────────────────────────────────────────────────────║
|
|
175
|
+
║ Espacio: Marcar | a: Todos | n: Ninguno | Enter: Confirmar ║
|
|
176
|
+
╚════════════════════════════════════════════════════════════╝
|
|
177
|
+
```
|
|
160
178
|
|
|
161
|
-
|
|
162
|
-
opciones_largas,
|
|
163
|
-
title: "Submenú Paginado",
|
|
164
|
-
subtitle: "Usa ↑ / ↓ para ver el auto-scroll",
|
|
165
|
-
style: 7,
|
|
166
|
-
page_size: 6
|
|
167
|
-
)
|
|
168
|
-
sub.draw(size_max: 38)
|
|
169
|
-
end
|
|
179
|
+
#### Codigo de Ejemplo:
|
|
170
180
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
],
|
|
186
|
-
banner: " gr codE ",
|
|
187
|
-
title: "Panel de Control",
|
|
188
|
-
subtitle: "Consola de Administración TTY\nUsa ↑ / ↓ para navegar y Enter para seleccionar",
|
|
189
|
-
style: 3,
|
|
190
|
-
banner_style: 3,
|
|
191
|
-
divider: true,
|
|
192
|
-
center: true
|
|
193
|
-
)
|
|
194
|
-
|
|
195
|
-
# 4. Configuración completa de colores y estilos
|
|
196
|
-
menu.set_style.font(1) # 1 = ANSI Shadow 3D
|
|
197
|
-
menu.set_style.banner("cyan", 2) # Color del banner ASCII
|
|
198
|
-
menu.set_style.title("yellow", 2) # Color del título del recuadro
|
|
199
|
-
menu.set_style.subtitle("white", 1)# Color del subtítulo
|
|
200
|
-
menu.set_style.divider("blue", 1) # Color de las líneas divisorias
|
|
201
|
-
menu.set_style.border("yellow", 1) # Color del borde del marco de opciones
|
|
202
|
-
menu.set_style.options("white", 1) # Color de opciones no seleccionadas
|
|
203
|
-
menu.set_style.focus("green", 2) # Color y brillo de la opción resaltada
|
|
204
|
-
|
|
205
|
-
# 5. Dibujar y lanzar el menú interactivo
|
|
206
|
-
menu.draw(size_max: 38)
|
|
207
|
-
end
|
|
181
|
+
```ruby
|
|
182
|
+
paquetes = [
|
|
183
|
+
["Servidor Nginx Web", true, "Proxy inverso de alta velocidad"],
|
|
184
|
+
["Base de Datos PostgreSQL 16", true, "Motor de datos principal"],
|
|
185
|
+
["Almacen de Cache Redis 7.2", false, "Cache en memoria RAM"],
|
|
186
|
+
["Monitor Prometheus", true, "Metricas y alertas"]
|
|
187
|
+
]
|
|
188
|
+
|
|
189
|
+
seleccionados = GRmenu.checkbox(
|
|
190
|
+
paquetes,
|
|
191
|
+
title: "Instalador de Paquetes",
|
|
192
|
+
color: "rgb",
|
|
193
|
+
style: 3
|
|
194
|
+
)
|
|
208
195
|
|
|
209
|
-
|
|
196
|
+
puts "Elementos seleccionados: #{seleccionados.length}"
|
|
197
|
+
seleccionados.each do |elem|
|
|
198
|
+
nombre = elem.is_a?(Array) ? elem[0] : elem
|
|
199
|
+
puts " - [X] #{nombre}"
|
|
200
|
+
end
|
|
210
201
|
```
|
|
211
202
|
|
|
203
|
+
**Teclas de Control en Checkbox:**
|
|
204
|
+
- `Espacio`: Alterna entre marcado `[X]` y desmarcado `[ ]`.
|
|
205
|
+
- `a` / `A`: Marca todos los elementos (*Select All*).
|
|
206
|
+
- `n` / `N`: Desmarca todos los elementos (*Deselect All*).
|
|
207
|
+
- `i` / `I`: Invierte la seleccion actual.
|
|
208
|
+
- `Enter`: Confirma y devuelve el arreglo de elementos seleccionados.
|
|
209
|
+
- `q` / `Esc`: Cancela y devuelve un arreglo vacio `[]`.
|
|
210
|
+
|
|
212
211
|
---
|
|
213
212
|
|
|
214
|
-
|
|
213
|
+
### 3. Control Deslizante Interactivo
|
|
215
214
|
|
|
216
|
-
|
|
215
|
+
Permite seleccionar numericamente un valor o porcentaje dentro de un rango mediante una barra horizontal en tiempo real.
|
|
217
216
|
|
|
218
|
-
```
|
|
219
|
-
|
|
217
|
+
```text
|
|
218
|
+
╔══════════════ Asignar Memoria RAM ══════════════╗
|
|
219
|
+
║ [████████████████████░░░░░░░░░░] 16 GB ║
|
|
220
|
+
║ ║
|
|
221
|
+
║ ← / → Ajustar paso | ↑ / ↓ Salto x5 | Enter OK ║
|
|
222
|
+
╚═════════════════════════════════════════════════╝
|
|
220
223
|
```
|
|
221
224
|
|
|
222
|
-
|
|
225
|
+
#### Codigo de Ejemplo:
|
|
223
226
|
|
|
224
227
|
```ruby
|
|
225
|
-
|
|
228
|
+
ram = GRmenu.slider(
|
|
229
|
+
"Asignar Memoria RAM",
|
|
230
|
+
min: 1,
|
|
231
|
+
max: 64,
|
|
232
|
+
step: 1,
|
|
233
|
+
default: 16,
|
|
234
|
+
unit: "GB",
|
|
235
|
+
color: "rgb",
|
|
236
|
+
style: 3
|
|
237
|
+
)
|
|
238
|
+
|
|
239
|
+
puts "Memoria configurada: #{ram} GB"
|
|
226
240
|
```
|
|
227
241
|
|
|
242
|
+
**Teclas de Control en Slider:**
|
|
243
|
+
- `←` / `→` o `h` / `l`: Ajusta el valor paso a paso (`step`).
|
|
244
|
+
- `↑` / `↓` o `k` / `j`: Salto rapido de 5 pasos.
|
|
245
|
+
- `Enter`: Guarda y retorna el numero exacto (`Integer` o `Float`).
|
|
246
|
+
- `q` / `Esc`: Cancela y retorna el valor por defecto.
|
|
247
|
+
|
|
228
248
|
---
|
|
229
249
|
|
|
230
|
-
|
|
250
|
+
### 4. Renderizado Universal de Imagenes
|
|
231
251
|
|
|
232
|
-
|
|
233
|
-
|-------------|---------------------------|
|
|
234
|
-
| `↑` | Mover selección arriba |
|
|
235
|
-
| `↓` | Mover selección abajo |
|
|
236
|
-
| `Enter` | Ejecutar opción seleccionada |
|
|
237
|
-
| `q` | Salir del menú |
|
|
252
|
+
Decodifica y renderiza cualquier formato de imagen (PNG, JPEG, JPG, WEBP, GIF, BMP) con micro-pixeles ANSI TrueColor de 24 bits y escalado proporcional exacto.
|
|
238
253
|
|
|
239
|
-
|
|
254
|
+
#### Renderizado Directo en Consola:
|
|
240
255
|
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
| **`1`** | **ANSI Shadow 3D (Default)** | `██████╗ ██╗ ██╗ ██████╗ ██╗ ██╗` |
|
|
246
|
-
| **`2`** | **Slant 3D (FIGlet)** | ` ____ __ __ ____ __ __` |
|
|
247
|
-
| **`3`** | **Doom / Standard 3D** | ` ____ _ _ ____ __ __` |
|
|
248
|
-
| **`4`** | **Graffiti Shadow 3D** | ` ,---. ,--. ,--. ,---. ,--. ,--.` |
|
|
249
|
-
| **`5`** | **Small Slant / Mini 3D**| ` ___ _ _ ___ _ _` |
|
|
250
|
-
| **`6`** | **Modular Pipe 3D** | ` _____ _____ _____ _____` |
|
|
251
|
-
| **`7`** | **Bubble / Round Gothic**| ` ____ _ _ ____ _ _` |
|
|
252
|
-
| **`8`** | **Double-Line Wire 3D** | ` ╔═════╗ ║ ║ ╔════╗ ║ ║` |
|
|
253
|
-
| **`9`** | **Solid Fat 3D Block** | ` ██████▄ ██ ██ ██████▄ ██ ██` |
|
|
254
|
-
| **`10`**| **Arcade Stars Matrix** | ` ★★★★ ★ ★ ★★★★ ★ ★` |
|
|
256
|
+
```ruby
|
|
257
|
+
# Renderiza una imagen centrada dentro de un marco estilizado
|
|
258
|
+
GRmenu.image("fondo.jpg", width: 60, color: "rgb", style: 3)
|
|
259
|
+
```
|
|
255
260
|
|
|
256
|
-
|
|
261
|
+
#### Como Cabecera Superior en un Menu:
|
|
257
262
|
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
263
|
+
```ruby
|
|
264
|
+
menu = GRmenu.new(
|
|
265
|
+
[
|
|
266
|
+
["Escanear Red", method(:escanear)],
|
|
267
|
+
["Ver Reporte", method(:reporte)],
|
|
268
|
+
["Salir", -> { exit(0) }]
|
|
269
|
+
],
|
|
270
|
+
image: "logo.png",
|
|
271
|
+
image_width: 44,
|
|
272
|
+
title: "Security Toolset",
|
|
273
|
+
style: 3
|
|
274
|
+
)
|
|
275
|
+
|
|
276
|
+
menu.draw
|
|
277
|
+
```
|
|
272
278
|
|
|
273
279
|
---
|
|
274
280
|
|
|
275
|
-
|
|
281
|
+
### 5. Modales Nativos de Confirmacion y Entrada
|
|
282
|
+
|
|
283
|
+
Cuadros de dialogo emergentes bloqueantes que capturan respuestas del usuario de forma directa y visual.
|
|
284
|
+
|
|
285
|
+
#### Modal de Confirmacion (`GRmenu.confirm`):
|
|
276
286
|
|
|
277
287
|
```ruby
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
puts Color.
|
|
281
|
-
|
|
282
|
-
puts Color.
|
|
283
|
-
|
|
284
|
-
puts Color.pink("Texto en rosa")
|
|
285
|
-
puts Color.gray("Texto en gris")
|
|
288
|
+
# Dialogo interactivo Si / No con seleccion por flechas y teclado
|
|
289
|
+
if GRmenu.confirm("Deseas aplicar los cambios en produccion?", default: true, color: "rgb", style: 3)
|
|
290
|
+
puts Color.bright_green("-> Cambios aplicados con exito.")
|
|
291
|
+
else
|
|
292
|
+
puts Color.bright_red("-> Operacion cancelada.")
|
|
293
|
+
end
|
|
286
294
|
```
|
|
287
295
|
|
|
288
|
-
|
|
296
|
+
#### Cuadro de Entrada de Texto (`GRmenu.input`):
|
|
297
|
+
|
|
298
|
+
```ruby
|
|
299
|
+
# Entrada interactiva con cursor en vivo
|
|
300
|
+
nombre = GRmenu.input("Ingresa tu nombre de usuario:", default: "admin", color: "rgb", style: 3)
|
|
301
|
+
|
|
302
|
+
# Modo password para claves secretas (oculta caracteres con asteriscos)
|
|
303
|
+
token = GRmenu.input("Ingresa tu API Token:", password: true, color: "magenta", style: 7)
|
|
304
|
+
```
|
|
289
305
|
|
|
290
306
|
---
|
|
291
307
|
|
|
292
|
-
|
|
308
|
+
### 6. Modo RGB Chroma Wave Animado
|
|
309
|
+
|
|
310
|
+
Puedes activar el modo de color animado pasando `"rgb"`, `"rainbow"` o `"chroma"` a cualquier componente visual. El motor genera una onda sinusoidal horizontal que fluye suavemente a 30 FPS en segundo plano sin producir retraso en el teclado.
|
|
293
311
|
|
|
294
312
|
```ruby
|
|
295
|
-
|
|
296
|
-
|
|
313
|
+
menu = GRmenu.new(opciones, banner: "CHROMA", title: "RGB Wave Panel")
|
|
314
|
+
|
|
315
|
+
menu.set_style.banner("rgb") # Letras 3D en degradado continuo
|
|
316
|
+
menu.set_style.title("rgb") # Titulo de cabecera en RGB
|
|
317
|
+
menu.set_style.border("rgb") # Marco exterior multicolor
|
|
318
|
+
menu.set_style.divider("rgb") # Lineas divisorias animadas
|
|
319
|
+
menu.set_style.focus("rgb") # Cursor enfocado pulsando en RGB
|
|
320
|
+
menu.set_style.options("rgb") # Texto de opciones en tono suave
|
|
297
321
|
|
|
298
|
-
|
|
299
|
-
|
|
322
|
+
menu.draw
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
---
|
|
300
326
|
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
327
|
+
### 7. Barra de Progreso y Spinner de Carga
|
|
328
|
+
|
|
329
|
+
#### Barra de Progreso (`GRmenu.progress`):
|
|
330
|
+
|
|
331
|
+
```ruby
|
|
332
|
+
GRmenu.progress(100, title: "Descargando Actualizacion", color: "rgb", style: 3) do |bar|
|
|
333
|
+
10.times do |i|
|
|
334
|
+
sleep 0.1
|
|
335
|
+
bar.advance(10, status: "Procesando bloque #{i + 1} de 10...")
|
|
336
|
+
end
|
|
304
337
|
end
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
#### Spinner Animado (`GRmenu.spinner`):
|
|
305
341
|
|
|
306
|
-
|
|
307
|
-
GRmenu.
|
|
308
|
-
|
|
342
|
+
```ruby
|
|
343
|
+
resultado = GRmenu.spinner("Conectando con el cluster remoto...", color: "rgb") do
|
|
344
|
+
# Simula tarea pesada
|
|
345
|
+
sleep 1.5
|
|
346
|
+
"Conexion Establecida"
|
|
309
347
|
end
|
|
310
348
|
|
|
311
|
-
|
|
312
|
-
|
|
349
|
+
puts Color.bright_green("-> #{resultado}")
|
|
350
|
+
```
|
|
313
351
|
|
|
314
|
-
|
|
315
|
-
|
|
352
|
+
---
|
|
353
|
+
|
|
354
|
+
### 8. Banners 3D y Lineas Divisorias
|
|
355
|
+
|
|
356
|
+
```ruby
|
|
357
|
+
# Imprime un banner en arte ASCII 3D con retardo opcional de animacion
|
|
358
|
+
GRmenu.banner("ADMIN", 0, color: "rgb", style: 3, font: 1)
|
|
316
359
|
|
|
317
|
-
#
|
|
318
|
-
GRmenu.
|
|
360
|
+
# Imprime una linea divisoria horizontal con ajuste automatico al ancho de terminal
|
|
361
|
+
GRmenu.div(60, "rgb", 1, "═")
|
|
319
362
|
```
|
|
320
363
|
|
|
321
364
|
---
|
|
322
365
|
|
|
323
|
-
|
|
366
|
+
### 9. Modulo Independiente de Color
|
|
324
367
|
|
|
325
|
-
|
|
368
|
+
El modulo `Color` (o su alias `C`) permite pintar cadenas de texto directamente con secuencias ANSI y TrueColor:
|
|
326
369
|
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
370
|
+
```ruby
|
|
371
|
+
# Modo Arcoiris RGB Dinamico
|
|
372
|
+
puts Color.rgb("Texto degradado en onda horizontal multicolor")
|
|
373
|
+
|
|
374
|
+
# Metodos directos por color (Nivel 1 Normal / Nivel 2 Brillante)
|
|
375
|
+
puts Color.bright_green("Verde brillante")
|
|
376
|
+
puts Color.bright_cyan("Cian brillante")
|
|
377
|
+
puts Color.bright_magenta("Magenta brillante")
|
|
378
|
+
puts Color.bright_yellow("Amarillo brillante")
|
|
379
|
+
puts Color.bright_red("Rojo brillante")
|
|
380
|
+
puts Color.orange("Naranja")
|
|
381
|
+
puts Color.purple("Morado")
|
|
382
|
+
puts Color.pink("Rosa")
|
|
383
|
+
puts Color.gray("Gris")
|
|
384
|
+
puts Color.white("Blanco")
|
|
385
|
+
|
|
386
|
+
# Atajos ultra-cortos de 1 o 2 letras
|
|
387
|
+
puts Color.g("Verde")
|
|
388
|
+
puts Color.cy("Cian")
|
|
389
|
+
puts Color.r("Rojo")
|
|
390
|
+
puts Color.y("Amarillo")
|
|
391
|
+
puts Color.w("Blanco")
|
|
392
|
+
puts Color.gr("Gris")
|
|
393
|
+
```
|
|
339
394
|
|
|
340
|
-
|
|
395
|
+
---
|
|
341
396
|
|
|
342
|
-
|
|
397
|
+
## Catalogo Visual de Fuentes 3D
|
|
343
398
|
|
|
344
|
-
|
|
399
|
+
Configura la tipografia mediante el parametro `font: 1..10`:
|
|
345
400
|
|
|
346
|
-
|
|
401
|
+
| ID | Nombre de Fuente | Muestra Visual |
|
|
402
|
+
|:--:|:-----------------|:---------------|
|
|
403
|
+
| `1` | **ANSI Shadow 3D** *(Default)* | `██████╗ ██╗ ██╗` |
|
|
404
|
+
| `2` | **Slant 3D** | ` ____ __ __` |
|
|
405
|
+
| `3` | **Doom / Standard 3D** | ` ____ _ _` |
|
|
406
|
+
| `4` | **Graffiti Shadow 3D** | ` ,---. ,--. ,--.` |
|
|
407
|
+
| `5` | **Small Slant / Mini 3D** | ` ___ _ _` |
|
|
408
|
+
| `6` | **Modular Pipe 3D** | ` _____ _____` |
|
|
409
|
+
| `7` | **Bubble / Round Gothic** | ` ____ _ _` |
|
|
410
|
+
| `8` | **Double-Line Wire 3D** | ` ╔═════╗ ║ ║` |
|
|
411
|
+
| `9` | **Solid Fat 3D Block** | ` ██████▄ ██ ██` |
|
|
412
|
+
| `10`| **Arcade Stars Matrix** | ` ★★★★ ★ ★` |
|
|
347
413
|
|
|
348
|
-
|
|
414
|
+
---
|
|
349
415
|
|
|
350
|
-
|
|
351
|
-
|-------------------------------------|-------------------------------------------|
|
|
352
|
-
| `set_style.font(id)` | Cambia el tipo de fuente ASCII 3D (1..10). |
|
|
353
|
-
| `set_style.banner(color, level=2)` | Color y brillo del banner ASCII 3D. |
|
|
354
|
-
| `set_style.title(color, level=2)` | Color y brillo del título del marco. |
|
|
355
|
-
| `set_style.subtitle(color, level=1)`| Color y brillo del subtítulo. |
|
|
356
|
-
| `set_style.divider(color, level=1)` | Color y brillo de las líneas divisorias. |
|
|
357
|
-
| `set_style.border(color, level=1)` | Color y brillo del marco de opciones. |
|
|
358
|
-
| `set_style.options(color, level=1)` | Color y brillo de opciones no activas. |
|
|
359
|
-
| `set_style.focus(color, level=2)` | Color y brillo de la opción resaltada. |
|
|
416
|
+
## Catalogo Visual de Marcos y Bordes
|
|
360
417
|
|
|
361
|
-
|
|
418
|
+
Configura el diseno del marco mediante el parametro `style: 1..20`:
|
|
362
419
|
|
|
363
|
-
|
|
420
|
+
| ID | Muestra | ID | Muestra | ID | Muestra | ID | Muestra |
|
|
421
|
+
|:--:|:--------|:--:|:--------|:--:|:--------|:--:|:--------|
|
|
422
|
+
| `1` | `#####` (Hash) | `6` | `╓───╖` (Mixto) | `11`| `░░░░░` (Sombra suave) | `16`| `~~~~~` (Ondas) |
|
|
423
|
+
| `2` | `┌───┐` (Simple) | `7` | `╭───╮` (Curvas) | `12`| `█████` (Bloque) | `17`| `-----` (Guion) |
|
|
424
|
+
| `3` | `╔═══╗` (Doble) | `8` | `▛▀▀▀▜` (Outline) | `13`| `*****` (Asterisco) | `18`| `◆◆◆◆◆` (Rombos) |
|
|
425
|
+
| `4` | `┏━━━┓` (Gruesa) | `9` | `▓▓▓▓▓` (Sombra oscura) | `14`| `+++++` (Cruces) | `19`| `●○○○●` (Circulos) |
|
|
426
|
+
| `5` | `╒═══╕` (Mixto) | `10`| `▒▒▒▒▒` (Sombra media) | `15`| `=====` (Doble simple) | `20`| `★☆☆☆★` (Estrellas) |
|
|
364
427
|
|
|
365
428
|
---
|
|
366
429
|
|
|
367
|
-
##
|
|
430
|
+
## Referencia Exhaustiva de la API
|
|
431
|
+
|
|
432
|
+
### Constructor `GRmenu.new(functions, **opciones)`
|
|
433
|
+
|
|
434
|
+
| Parametro | Tipo | Valor por Defecto | Descripcion |
|
|
435
|
+
|:----------|:-----|:------------------|:------------|
|
|
436
|
+
| `functions` | `Array` | *Obligatorio* | Lista de metodos, simbolos, arrays `[nombre, accion, tooltip]`, procs o hashes. |
|
|
437
|
+
| `title:` | `String` | `""` | Titulo centrado en la cabecera del marco de opciones. |
|
|
438
|
+
| `banner:` | `String` | `""` | Texto convertido a arte ASCII 3D superior. |
|
|
439
|
+
| `subtitle:` | `String` | `""` | Descripcion o subtitulo (soporta saltos de linea `\n`). |
|
|
440
|
+
| `search:` | `Boolean` | `false` | Activa el buscador instantaneo mientras se escribe. |
|
|
441
|
+
| `columns:` | `Integer` | `1` | Cantidad de columnas para distribucion en cuadricula 2D. |
|
|
442
|
+
| `page_size:` | `Integer` | `auto` | Maximo de filas visibles antes de activar desplazamiento con scroll. |
|
|
443
|
+
| `style:` | `Integer` | `19` | Estilo de marco para las opciones (1 al 20). |
|
|
444
|
+
| `banner_style:` | `Integer` | `3` | Estilo de marco para el banner 3D (1 al 20). |
|
|
445
|
+
| `font:` | `Integer` | `1` | Fuente tipografica del banner ASCII (1 al 10). |
|
|
446
|
+
| `image:` | `String` | `nil` | Ruta al archivo de imagen de cabecera (PNG/JPG/WEBP/GIF/BMP). |
|
|
447
|
+
| `image_width:` | `Integer` | `40` | Ancho en columnas para el renderizado de la imagen. |
|
|
448
|
+
| `divider:` | `Boolean/Int` | `true` | Lineas divisorias horizontales ajustadas al marco. |
|
|
449
|
+
| `center:` | `Boolean` | `true` | Centrado horizontal simetrico automatico. |
|
|
450
|
+
|
|
451
|
+
### Metodos de Estilo `menu.set_style`
|
|
452
|
+
|
|
453
|
+
| Metodo | Argumentos | Descripcion |
|
|
454
|
+
|:-------|:-----------|:------------|
|
|
455
|
+
| `banner(color, level=2)` | `(String, Integer)` | Color del banner ASCII (soporta `"rgb"`). |
|
|
456
|
+
| `title(color, level=2)` | `(String, Integer)` | Color del titulo del recuadro (soporta `"rgb"`). |
|
|
457
|
+
| `subtitle(color, level=1)` | `(String, Integer)` | Color del texto del subtitulo (soporta `"rgb"`). |
|
|
458
|
+
| `divider(color, level=1)` | `(String, Integer)` | Color de las lineas divisorias (soporta `"rgb"`). |
|
|
459
|
+
| `border(color, level=1)` | `(String, Integer)` | Color del marco de opciones (soporta `"rgb"`). |
|
|
460
|
+
| `options(color, level=1)` | `(String, Integer)` | Color de las opciones inactivas (soporta `"rgb"`). |
|
|
461
|
+
| `focus(color, level=2)` | `(String, Integer)` | Color del cursor y opcion activa (soporta `"rgb"`). |
|
|
462
|
+
| `font(font_id)` | `(Integer 1..10)` | Cambia la fuente tipografica del banner. |
|
|
463
|
+
|
|
464
|
+
### Metodos Estaticos y Modales
|
|
465
|
+
|
|
466
|
+
| Metodo | Firma | Retorno |
|
|
467
|
+
|:-------|:------|:--------|
|
|
468
|
+
| `GRmenu.checkbox` | `(items, title:, color:, style:, page_size:, preselected:)` | `Array` con los elementos marcados. |
|
|
469
|
+
| `GRmenu.slider` | `(prompt, min:, max:, step:, default:, unit:, color:, style:)` | `Numeric` con el valor seleccionado. |
|
|
470
|
+
| `GRmenu.confirm` | `(pregunta, default: true, color: "cyan", style: 3)` | `Boolean` (`true` para Si, `false` para No). |
|
|
471
|
+
| `GRmenu.input` | `(prompt, default: "", password: false, color: "cyan", style: 3)` | `String` ingresado por el usuario. |
|
|
472
|
+
| `GRmenu.image` | `(filepath, width: 40, height: nil, style: 3, color: "cyan")` | Dibuja la imagen en la terminal. |
|
|
473
|
+
| `GRmenu.progress` | `(total = 100, title: nil, color: "cyan", style: 3, &bloque)` | Ejecuta el bloque con la barra de progreso. |
|
|
474
|
+
| `GRmenu.spinner` | `(mensaje = "...", color: "cyan", delay: 0.08, &bloque)` | Ejecuta el bloque mostrando un spinner animado. |
|
|
475
|
+
| `GRmenu.banner` | `(texto, delay = 0, color: "magenta", style: 3, font: 1)` | Imprime texto en arte ASCII 3D. |
|
|
476
|
+
| `GRmenu.div` | `(long = nil, color = "blue", level = 1, char = "─")` | Imprime una linea divisoria en la consola. |
|
|
477
|
+
| `GRmenu.clear_screen`| `()` (Alias: `GRmenu.clr`) | Limpia la pantalla y el scrollback al instante. |
|
|
478
|
+
| `GRmenu.continue` | `(texto = "Presiona cualquier tecla...")` | Pausa la ejecucion hasta presionar una tecla. |
|
|
479
|
+
| `GRmenu.help` | `()` | Muestra la guia interactiva de documentacion en consola. |
|
|
368
480
|
|
|
369
|
-
|
|
481
|
+
---
|
|
482
|
+
|
|
483
|
+
## Mapa de Controles y Teclado
|
|
484
|
+
|
|
485
|
+
| Tecla / Combinacion | Contexto | Accion Realizada |
|
|
486
|
+
|:--------------------|:---------|:-----------------|
|
|
487
|
+
| `↑` (Arriba) / `k` | Menus / Checkbox | Mueve el foco hacia arriba (con salto continuo *Snake* en extremos). |
|
|
488
|
+
| `↓` (Abajo) / `j` | Menus / Checkbox | Mueve el foco hacia abajo. |
|
|
489
|
+
| `←` / `→` | Grid 2D | Salta de columna a la izquierda o derecha. |
|
|
490
|
+
| `Espacio` | Checkbox | Marca o desmarca la casilla del elemento actual `[X]` / `[ ]`. |
|
|
491
|
+
| `a` / `A` | Checkbox | Marca todos los elementos (*Select All*). |
|
|
492
|
+
| `n` / `N` | Checkbox | Desmarca todos los elementos (*Deselect All*). |
|
|
493
|
+
| `i` / `I` | Checkbox | Invierte la seleccion de todos los elementos. |
|
|
494
|
+
| `←` / `→` o `h` / `l`| Slider | Ajusta el valor numerico en un incremento (`step`). |
|
|
495
|
+
| `↑` / `↓` o `k` / `j`| Slider | Salto rapido de 5 pasos en el valor numerico. |
|
|
496
|
+
| `Enter` | Global | Ejecuta la accion seleccionada o confirma el formulario. |
|
|
497
|
+
| `q` / `Esc` | Global | Sale del menu o cancela la operacion actual. |
|
|
498
|
+
| `Backspace` | Buscador / Input | Borra el ultimo caracter ingresado. |
|
|
499
|
+
| `Ctrl+U` | Buscador / Input | Limpia todo el texto ingresado. |
|
|
370
500
|
|
|
371
501
|
---
|
|
372
502
|
|
|
373
|
-
##
|
|
503
|
+
## Recetas y Casos de Uso del Mundo Real
|
|
504
|
+
|
|
505
|
+
### Asistente de Instalacion de Servidores
|
|
506
|
+
|
|
507
|
+
```ruby
|
|
508
|
+
require 'GRmenu'
|
|
509
|
+
|
|
510
|
+
GRmenu.clear_screen
|
|
511
|
+
GRmenu.banner("SETUP", 0, color: "rgb", style: 3, font: 1)
|
|
512
|
+
|
|
513
|
+
nombre = GRmenu.input("Nombre del proyecto:", default: "mi-app", color: "rgb")
|
|
514
|
+
puerto = GRmenu.slider("Puerto HTTP:", min: 3000, max: 9000, step: 100, default: 8080, color: "rgb")
|
|
515
|
+
|
|
516
|
+
modulos = [
|
|
517
|
+
["Proxy Nginx", true, "Servidor web frontal"],
|
|
518
|
+
["Base PostgreSQL", true, "Base de datos relacional"],
|
|
519
|
+
["Redis Cache", false, "Acelerador de sesiones"]
|
|
520
|
+
]
|
|
521
|
+
seleccion = GRmenu.checkbox(modulos, title: "Selecciona Modulos", color: "rgb")
|
|
522
|
+
|
|
523
|
+
if GRmenu.confirm("Deseas comenzar la instalacion ahora?", default: true, color: "rgb")
|
|
524
|
+
GRmenu.progress(100, title: "Instalando Componentes", color: "rgb") do |bar|
|
|
525
|
+
seleccion.each_with_index do |item, idx|
|
|
526
|
+
sleep 0.4
|
|
527
|
+
bar.advance(100 / seleccion.length, status: "Configurando #{item[0]}...")
|
|
528
|
+
end
|
|
529
|
+
end
|
|
530
|
+
puts Color.bright_green("\n-> Instalacion de '#{nombre}' completada en el puerto #{puerto}!")
|
|
531
|
+
end
|
|
532
|
+
GRmenu.continue
|
|
533
|
+
```
|
|
534
|
+
|
|
535
|
+
---
|
|
374
536
|
|
|
375
|
-
|
|
537
|
+
## Licencia
|
|
376
538
|
|
|
377
|
-
|
|
539
|
+
Distribuido bajo licencia **MIT**. Consulta [`LICENSE`](LICENSE) para mas detalles.
|
|
378
540
|
|
|
379
|
-
|
|
541
|
+
Desarrollado con precision por **[grcode](https://github.com/JoseEduardoGR)**
|
|
380
542
|
|
|
381
|
-
</div>
|