@saulwade/swl-ses 2.3.0 → 2.4.1
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.
- package/CLAUDE.md +241 -199
- package/README.md +597 -597
- package/agentes/_intent-spec.md +73 -73
- package/agentes/_propose-step.md +90 -90
- package/agentes/accesibilidad-wcag-swl.md +2 -2
- package/agentes/arquitecto-swl.md +2 -2
- package/agentes/auto-evolucion-swl.md +2 -2
- package/agentes/backend-api-swl.md +2 -2
- package/agentes/backend-csharp-swl.md +2 -2
- package/agentes/backend-go-swl.md +2 -2
- package/agentes/backend-java-swl.md +2 -2
- package/agentes/backend-node-swl.md +2 -2
- package/agentes/backend-python-swl.md +2 -2
- package/agentes/backend-rust-swl.md +2 -2
- package/agentes/backend-workers-swl.md +2 -2
- package/agentes/cloud-infra-swl.md +2 -2
- package/agentes/consolidador-swl.md +2 -2
- package/agentes/datos-swl.md +2 -2
- package/agentes/depurador-swl.md +2 -2
- package/agentes/devops-ci-swl.md +2 -2
- package/agentes/disenador-ui-swl.md +2 -2
- package/agentes/documentador-swl.md +2 -2
- package/agentes/frontend-angular-swl.md +2 -2
- package/agentes/frontend-css-swl.md +2 -2
- package/agentes/frontend-react-swl.md +2 -2
- package/agentes/frontend-swl.md +2 -2
- package/agentes/frontend-tailwind-swl.md +2 -2
- package/agentes/gh-fix-ci-swl.md +275 -275
- package/agentes/implementador-swl.md +2 -2
- package/agentes/investigador-swl.md +2 -2
- package/agentes/investigador-ux-swl.md +2 -2
- package/agentes/llm-apps-swl.md +2 -2
- package/agentes/migrador-swl.md +2 -2
- package/agentes/mobile-android-swl.md +2 -2
- package/agentes/mobile-cross-swl.md +2 -2
- package/agentes/mobile-ios-swl.md +2 -2
- package/agentes/mobile-testing-swl.md +2 -2
- package/agentes/nemesis-auditor-swl.md +1 -1
- package/agentes/notificador-swl.md +2 -2
- package/agentes/observabilidad-swl.md +2 -2
- package/agentes/orquestador-swl.md +41 -14
- package/agentes/pagos-swl.md +2 -2
- package/agentes/perfilador-usuario-swl.md +2 -2
- package/agentes/planificador-swl.md +2 -2
- package/agentes/producto-prd-swl.md +2 -2
- package/agentes/red-team-swl.md +218 -218
- package/agentes/release-manager-swl.md +2 -2
- package/agentes/rendimiento-swl.md +2 -2
- package/agentes/resolutor-build-swl.md +2 -2
- package/agentes/revisor-angular-swl.md +2 -2
- package/agentes/revisor-codigo-swl.md +36 -3
- package/agentes/revisor-csharp-swl.md +2 -2
- package/agentes/revisor-go-swl.md +2 -2
- package/agentes/revisor-java-swl.md +2 -2
- package/agentes/revisor-kotlin-swl.md +2 -2
- package/agentes/revisor-nextjs-swl.md +2 -2
- package/agentes/revisor-php-swl.md +2 -2
- package/agentes/revisor-react-swl.md +2 -2
- package/agentes/revisor-rust-swl.md +2 -2
- package/agentes/revisor-seguridad-swl.md +2 -2
- package/agentes/revisor-swift-swl.md +2 -2
- package/agentes/revisor-typescript-swl.md +2 -2
- package/agentes/sre-swl.md +2 -2
- package/agentes/tdd-qa-swl.md +2 -2
- package/comandos/swl/briefing.md +119 -119
- package/comandos/swl/contexto.md +0 -2
- package/comandos/swl/contribuir.md +233 -233
- package/comandos/swl/deuda-codigo.md +97 -0
- package/comandos/swl/predecir.md +139 -139
- package/comandos/swl/sesiones.md +1 -1
- package/gateway/agent-executor.js +1 -1
- package/gateway/lib/event-channel.js +191 -191
- package/habilidades/agent-deep-links/SKILL.md +148 -148
- package/habilidades/agentes-como-servicio/SKILL.md +2 -2
- package/habilidades/angular-moderno/SKILL.md +24 -1
- package/habilidades/auto-evolucion-protocolo/SKILL.md +276 -276
- package/habilidades/backend-async-postgres-testing/SKILL.md +215 -215
- package/habilidades/backend-error-design/SKILL.md +221 -221
- package/habilidades/backend-production-resilience/SKILL.md +288 -288
- package/habilidades/benchmark-memoria/SKILL.md +186 -186
- package/habilidades/calidad-anti-patrones-universales/SKILL.md +368 -368
- package/habilidades/calidad-contract-testing/SKILL.md +165 -165
- package/habilidades/calidad-mutation-testing/SKILL.md +170 -170
- package/habilidades/changelog-generator/scripts/parse-commits.js +367 -367
- package/habilidades/checklist-seguridad/recursos/stride-cobertura.md +60 -60
- package/habilidades/contenedores-docker/SKILL.md +3 -1
- package/habilidades/diagrama-arquitectura/assets/template.html +276 -276
- package/habilidades/doubt-driven-review/recursos/EXAMPLES.md +130 -130
- package/habilidades/drift-detection/SKILL.md +179 -179
- package/habilidades/estructura-proyecto-claude/recursos/frontmatter-y-hooks-referencia.md +1 -1
- package/habilidades/estructura-proyecto-claude/recursos/mcp-json-template.json +57 -57
- package/habilidades/eval-framework/SKILL.md +212 -212
- package/habilidades/feynman-auditor-swl/recursos/preguntas-language-agnostic.md +108 -108
- package/habilidades/harness-claude-code/SKILL.md +4 -4
- package/habilidades/harness-claude-code/recursos/disciplina-harness-regla.md +253 -252
- package/habilidades/legacy-code-rescue/SKILL.md +268 -267
- package/habilidades/meta-skills-estandar/SKILL.md +1 -1
- package/habilidades/meta-skills-estandar/recursos/convencion-examples.md +93 -93
- package/habilidades/meta-skills-estandar/recursos/skills-as-agents.md +2 -2
- package/habilidades/patrones-python/recursos/patrones-avanzados.md +469 -469
- package/habilidades/perfil-usuario/SKILL.md +200 -200
- package/habilidades/postgresql-experto/SKILL.md +3 -1
- package/habilidades/prevencion-sobreingenieria/SKILL.md +70 -92
- package/habilidades/prevencion-sobreingenieria/recursos/EXAMPLES.md +580 -580
- package/habilidades/prevencion-sobreingenieria/recursos/soluciones-nativas.md +166 -0
- package/habilidades/prevencion-sobreingenieria/recursos/variables-residuales-post-refactor.md +85 -0
- package/habilidades/proceso-ddia-fundamentos/SKILL.md +255 -255
- package/habilidades/proceso-ddia-streaming/SKILL.md +231 -231
- package/habilidades/proceso-debate-adversarial/recursos/personas.md +105 -105
- package/habilidades/proceso-discovery-machote/SKILL.md +157 -157
- package/habilidades/proceso-dynamic-workflows/SKILL.md +138 -138
- package/habilidades/proceso-dynamic-workflows/recursos/template-adversarial-verify.js +65 -65
- package/habilidades/proceso-dynamic-workflows/recursos/template-triage.js +65 -65
- package/habilidades/proceso-intent-engineering/SKILL.md +269 -269
- package/habilidades/proceso-modular-split/SKILL.md +256 -256
- package/habilidades/prompt-engineering/recursos/patrones-avanzados.md +2 -2
- package/habilidades/state-inconsistency-auditor-swl/recursos/coupled-state-patterns.md +147 -147
- package/habilidades/structured-outputs/SKILL.md +2 -2
- package/habilidades/swl-claudemd/recursos/contrato-aprender.md +83 -83
- package/habilidades/swl-claudemd/recursos/duplicacion-reglas-globales.md +85 -85
- package/habilidades/swl-claudemd/recursos/plantillas-init.md +94 -94
- package/habilidades/swl-dashboard/SKILL.md +2 -2
- package/habilidades/tdd-workflow/recursos/gherkin-bdd.md +111 -111
- package/habilidades/validacion-ci-sistema/recursos/validadores-completos.md +1 -1
- package/habilidades/validacion-ci-sistema/scripts/validar-sistema.sh +1 -1
- package/hooks/audit-trail.js +4 -4
- package/hooks/calidad-pre-commit.js +15 -11
- package/hooks/captura-acciones-post.js +3 -2
- package/hooks/captura-acciones-session.js +3 -2
- package/hooks/ciclo-evolucion-subagente.js +26 -26
- package/hooks/ciclo-evolucion.js +26 -26
- package/hooks/claudemd-bloat-detector.js +161 -161
- package/hooks/claudemd-duplicacion-detector.js +170 -170
- package/hooks/contexto-iteracion.js +145 -144
- package/hooks/contexto-subagente.js +68 -0
- package/hooks/guardrail-modelo.js +14 -4
- package/hooks/inyeccion-contexto.js +12 -12
- package/hooks/lib/agent-routing.js +107 -107
- package/hooks/lib/auto-consolidator.js +335 -335
- package/hooks/lib/autonomia.js +208 -208
- package/hooks/lib/ciclo-evolucion.js +47 -47
- package/hooks/lib/deep-links.js +185 -185
- package/hooks/lib/error-classifier.js +308 -308
- package/hooks/lib/etapa-auto-evolucion.js +701 -701
- package/hooks/lib/etapa-metricas.js +388 -388
- package/hooks/lib/etapa-perfil-usuario.js +376 -376
- package/hooks/lib/loop-telemetry.js +321 -321
- package/hooks/lib/merkle-audit.js +96 -96
- package/hooks/lib/model-router.js +2 -2
- package/hooks/lib/propose-step.js +358 -358
- package/hooks/lib/provenance-tracker.js +191 -191
- package/hooks/lib/rate-limit-tracker.js +253 -253
- package/hooks/lib/resource-quota.js +122 -122
- package/hooks/lib/retry-jitter.js +165 -165
- package/hooks/lib/security-net.js +201 -201
- package/hooks/lib/skill-auditor.js +588 -588
- package/hooks/lib/sync-status.js +228 -228
- package/hooks/lib/taint-tracker.js +107 -107
- package/hooks/lib/text-similarity.js +241 -241
- package/hooks/lib/token-estimator.js +1 -0
- package/hooks/lib/toon-compressor.js +245 -245
- package/hooks/lib/usage-model.js +1 -1
- package/hooks/registro-turnos.js +210 -209
- package/hooks/session-briefing.js +98 -98
- package/hooks/spec-gate.js +212 -211
- package/hooks/sugerir-contribuir.js +2 -1
- package/hooks/sugerir-regenerar-inventario.js +171 -170
- package/hooks/tdd-gate.js +242 -241
- package/hooks/telemetria-skill-routing.js +100 -100
- package/hooks/validar-formato-post-subagente.js +140 -140
- package/hooks/validar-intent-spec.js +242 -242
- package/hooks/validar-memoria-hook.js +218 -218
- package/hooks/validar-planning-paths.js +134 -134
- package/instintos/autonomia.yaml +27 -27
- package/instintos/prompt-appendices.yaml +57 -57
- package/llms.txt +29 -29
- package/manifiestos/agent-output-schemas.json +57 -57
- package/manifiestos/canonical-hashes.json +2948 -1964
- package/manifiestos/hook-profiles.json +0 -2
- package/manifiestos/hooks-config.json +469 -477
- package/manifiestos/invariantes-criticos.json +30 -0
- package/manifiestos/modulos.json +1390 -1390
- package/manifiestos/planning-paths.json +44 -44
- package/manifiestos/skills-lock.json +1282 -1282
- package/package.json +93 -93
- package/plantillas/auditor-veto-template.md +105 -105
- package/plantillas/github-workflows/README.md +47 -47
- package/plantillas/github-workflows/release-please.yml +44 -44
- package/plantillas/github-workflows/swl-ci.yml +107 -107
- package/plantillas/github-workflows/swl-security.yml +51 -51
- package/plugin.json +369 -371
- package/reglas/accesibilidad.md +10 -10
- package/reglas/analisis-previo-tareas-grandes.md +172 -172
- package/reglas/api-diseno.md +9 -9
- package/reglas/arreglar-al-detectar.md +240 -240
- package/reglas/auditorias-documentales-estructurales.md +7 -7
- package/reglas/cloud-infra.md +8 -8
- package/reglas/consultar-vault-primero.md +195 -195
- package/reglas/debatir-antes-de-aceptar.md +158 -158
- package/reglas/fragmentos-compartidos.md +183 -183
- package/reglas/hooks.md +6 -6
- package/reglas/intent-engineering.md +218 -218
- package/reglas/markitdown.md +8 -8
- package/reglas/monitor-ci.md +309 -309
- package/reglas/patrones.md +6 -6
- package/reglas/sesiones-paralelas.md +180 -180
- package/reglas/sin-duplicacion-reglas-globales.md +182 -182
- package/reglas/skills-estandar.md +6 -6
- package/reglas/testing.md +7 -7
- package/reglas/tests-cleanup.md +224 -224
- package/reglas/usar-code-review-graph.md +155 -155
- package/reglas/usar-context7.md +226 -226
- package/reglas/verificar-citas-normativas.md +548 -548
- package/schemas/agent-frontmatter.schema.json +5 -3
- package/schemas/agent-message.schema.json +73 -73
- package/schemas/agent-output-implementacion.schema.json +114 -114
- package/schemas/agent-output-planificacion.schema.json +150 -150
- package/schemas/agent-output-review.schema.json +98 -98
- package/schemas/diary-entry.schema.json +112 -112
- package/schemas/hook-profiles.schema.json +54 -54
- package/schemas/hooks-config.schema.json +89 -89
- package/schemas/modulos.schema.json +38 -38
- package/schemas/perfiles.schema.json +36 -36
- package/schemas/plugin.schema.json +77 -77
- package/schemas/skill-evals.schema.json +119 -119
- package/schemas/skill-frontmatter.schema.json +245 -245
- package/scripts/audit-tools/audit-history.js +330 -330
- package/scripts/audit-tools/bundle-tracker.js +290 -290
- package/scripts/audit-tools/canary-monitor.js +352 -352
- package/scripts/audit-tools/code-profiler.js +605 -605
- package/scripts/audit-tools/dep-doctor.js +320 -320
- package/scripts/audit-tools/env-validator.js +206 -206
- package/scripts/audit-tools/lib/fs-walk.js +48 -48
- package/scripts/audit-tools/lib/output.js +23 -23
- package/scripts/audit-tools/migration-checker.js +392 -392
- package/scripts/audit-tools/pentest-scanner.js +1436 -1436
- package/scripts/benchmark-memoria.js +167 -167
- package/scripts/cli/aprobar-plan.js +73 -73
- package/scripts/cli/briefing.js +23 -23
- package/scripts/cli/ciclo-evolucion.js +26 -26
- package/scripts/cli/configurar-ci.js +40 -40
- package/scripts/cli/derivar-feature-list.js +25 -25
- package/scripts/cli/detectar-host.js +27 -27
- package/scripts/cli/diary-entry.js +69 -69
- package/scripts/cli/execution-state.js +18 -18
- package/scripts/cli/gateway-notify.js +41 -41
- package/scripts/cli/liberar-fase.js +42 -42
- package/scripts/cli/loop-telemetry.js +125 -125
- package/scripts/cli/mark-evolved.js +56 -56
- package/scripts/cli/metricas-dora.js +26 -26
- package/scripts/cli/near-duplicate.js +55 -55
- package/scripts/cli/notificaciones.js +123 -123
- package/scripts/cli/propose-step.js +29 -29
- package/scripts/cli/schedule-parse.js +19 -19
- package/scripts/cli/sugerir-modelo.js +20 -20
- package/scripts/cli/verificar-plan.js +36 -36
- package/scripts/cli/verificar-trazabilidad.js +35 -35
- package/scripts/configurar-branch-protection.js +418 -418
- package/scripts/detectar-aprendizajes-duplicados.js +151 -151
- package/scripts/field-report.js +199 -199
- package/scripts/generar-checklists-consolidados.js +273 -273
- package/scripts/generar-matriz-lenguajes.js +271 -271
- package/scripts/instalador.js +4 -1
- package/scripts/lib/artefactos-python.js +43 -43
- package/scripts/lib/auditar-invocaciones-comandos.js +104 -104
- package/scripts/lib/benchmark-metrics.js +160 -160
- package/scripts/lib/budget-enforcer.js +252 -252
- package/scripts/lib/ci-reader.js +193 -193
- package/scripts/lib/claude-sessions.js +1 -0
- package/scripts/lib/configurar-ci.js +380 -380
- package/scripts/lib/contadores-inventario.js +217 -217
- package/scripts/lib/detectar-host-swl.js +175 -175
- package/scripts/lib/detectar-stack-detallado.js +307 -307
- package/scripts/lib/detector-autoduplicacion-intra-archivo.js +234 -234
- package/scripts/lib/detector-reglas-duplicadas.js +220 -220
- package/scripts/lib/diary-entry.js +234 -234
- package/scripts/lib/eval-metrics-store.js +218 -218
- package/scripts/lib/eval-quality.js +171 -171
- package/scripts/lib/eval-schemas.js +144 -144
- package/scripts/lib/eval-self-correct.js +106 -106
- package/scripts/lib/eval-validator.js +185 -185
- package/scripts/lib/evidencia-release.js +322 -322
- package/scripts/lib/gate-hooks-requires.js +249 -249
- package/scripts/lib/gate-licencias.js +212 -212
- package/scripts/lib/git-metricas.js +257 -257
- package/scripts/lib/jaccard-similarity.js +98 -98
- package/scripts/lib/longmemeval-runner.js +125 -125
- package/scripts/lib/metricas-dora.js +204 -204
- package/scripts/lib/npm-version.js +261 -261
- package/scripts/lib/paquetes-conocidos.js +50 -50
- package/scripts/lib/plan-lock.js +275 -275
- package/scripts/lib/pr-analyzer.js +399 -399
- package/scripts/lib/preservar-usuario.js +39 -5
- package/scripts/lib/prompt-builder.js +264 -264
- package/scripts/lib/reglas-globales-conocidas.json +180 -180
- package/scripts/lib/resolver-plan-fase.js +37 -37
- package/scripts/lib/rrf-fusion.js +175 -175
- package/scripts/lib/schema-version.js +164 -164
- package/scripts/lib/scoring-instintos.js +277 -277
- package/scripts/lib/semantic-search.js +252 -252
- package/scripts/lib/tool-cost-analyzer.js +1 -0
- package/scripts/limpiar-artefactos-python.js +131 -131
- package/scripts/migrar-csv-a-array.js +168 -168
- package/scripts/migrar-fase-dominio.js +200 -200
- package/scripts/publicar.js +497 -497
- package/scripts/run-eval.js +141 -141
- package/scripts/tui/componentes/selector-multi.js +189 -189
- package/scripts/tui/componentes/selector-unico.js +158 -158
- package/scripts/tui/ejecutores.js +375 -375
- package/scripts/tui/index.js +162 -162
- package/scripts/tui/lib/colores.js +129 -129
- package/scripts/tui/lib/render.js +264 -264
- package/scripts/tui/lib/teclas.js +113 -113
- package/scripts/tui/pantallas/inspect.js +173 -173
- package/scripts/tui/pantallas/install-wizard.js +334 -334
- package/scripts/tui/pantallas/menu-principal.js +52 -52
- package/scripts/tui/pantallas/progreso.js +274 -274
- package/scripts/tui/pantallas/resumen.js +132 -132
- package/scripts/tui/pantallas/uninstall-wizard.js +208 -208
- package/scripts/tui/pantallas/update-wizard.js +232 -232
- package/scripts/tui/pantallas/welcome.js +187 -187
- package/scripts/validar-userland-vacio.js +110 -110
- package/scripts/validar.js +1 -1
- package/scripts/verificar-release.js +51 -0
- package/hooks/lib/context-compressor.js +0 -657
- package/hooks/linea-estado.js +0 -326
- package/hooks/monitor-contexto.js +0 -373
|
@@ -1,264 +1,264 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Primitivas de render para la TUI custom de swl-ses.
|
|
5
|
-
* Zero-deps. Solo escape codes ANSI estándar + readline para keypress.
|
|
6
|
-
*
|
|
7
|
-
* Modelo:
|
|
8
|
-
* - `iniciarModoTui()` entra al alternate screen buffer, oculta cursor.
|
|
9
|
-
* - `salirModoTui()` restaura el buffer principal y muestra el cursor.
|
|
10
|
-
* - Cada pantalla llama `limpiarPantalla()` y dibuja desde (1,1).
|
|
11
|
-
* - Las coordenadas son 1-based (compatibilidad con escape codes ANSI).
|
|
12
|
-
*
|
|
13
|
-
* Diseño defensivo:
|
|
14
|
-
* - Si stdout no es TTY (CI, pipe), todas las funciones de cursor son no-op
|
|
15
|
-
* y los dibujos se reducen a console.log lineal.
|
|
16
|
-
* - Capturar SIGINT y exit para garantizar salirModoTui() siempre.
|
|
17
|
-
*/
|
|
18
|
-
|
|
19
|
-
const { colores, borde, iconos } = require('./colores');
|
|
20
|
-
|
|
21
|
-
const ES_TTY = !!process.stdout.isTTY;
|
|
22
|
-
|
|
23
|
-
// ---------------------------------------------------------------------------
|
|
24
|
-
// Control del terminal
|
|
25
|
-
// ---------------------------------------------------------------------------
|
|
26
|
-
|
|
27
|
-
let modoTuiActivo = false;
|
|
28
|
-
let limpiezaRegistrada = false;
|
|
29
|
-
|
|
30
|
-
function iniciarModoTui() {
|
|
31
|
-
if (modoTuiActivo || !ES_TTY) return;
|
|
32
|
-
modoTuiActivo = true;
|
|
33
|
-
|
|
34
|
-
// Alternate screen buffer: preserva el contenido del terminal pre-TUI
|
|
35
|
-
process.stdout.write('\x1b[?1049h');
|
|
36
|
-
// Ocultar cursor
|
|
37
|
-
process.stdout.write('\x1b[?25l');
|
|
38
|
-
// Limpiar
|
|
39
|
-
process.stdout.write('\x1b[2J\x1b[H');
|
|
40
|
-
|
|
41
|
-
// Registrar limpieza al salir (idempotente)
|
|
42
|
-
if (!limpiezaRegistrada) {
|
|
43
|
-
limpiezaRegistrada = true;
|
|
44
|
-
const limpieza = () => salirModoTui();
|
|
45
|
-
process.once('exit', limpieza);
|
|
46
|
-
process.once('SIGINT', () => { salirModoTui(); process.exit(130); });
|
|
47
|
-
process.once('SIGTERM', () => { salirModoTui(); process.exit(143); });
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
function salirModoTui() {
|
|
52
|
-
if (!modoTuiActivo || !ES_TTY) return;
|
|
53
|
-
modoTuiActivo = false;
|
|
54
|
-
|
|
55
|
-
// Mostrar cursor
|
|
56
|
-
process.stdout.write('\x1b[?25h');
|
|
57
|
-
// Salir del alternate screen buffer (restaura contenido pre-TUI)
|
|
58
|
-
process.stdout.write('\x1b[?1049l');
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
function estaActivo() {
|
|
62
|
-
return modoTuiActivo;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
// ---------------------------------------------------------------------------
|
|
66
|
-
// Movimiento de cursor
|
|
67
|
-
// ---------------------------------------------------------------------------
|
|
68
|
-
|
|
69
|
-
function moverCursor(fila, col) {
|
|
70
|
-
if (!ES_TTY) return;
|
|
71
|
-
process.stdout.write(`\x1b[${fila};${col}H`);
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
function limpiarPantalla() {
|
|
75
|
-
if (!ES_TTY) return;
|
|
76
|
-
process.stdout.write('\x1b[2J\x1b[H');
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
function limpiarLinea() {
|
|
80
|
-
if (!ES_TTY) return;
|
|
81
|
-
process.stdout.write('\x1b[2K\r');
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
function obtenerDimensiones() {
|
|
85
|
-
return {
|
|
86
|
-
cols: process.stdout.columns || 80,
|
|
87
|
-
rows: process.stdout.rows || 24,
|
|
88
|
-
};
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
// ---------------------------------------------------------------------------
|
|
92
|
-
// Escritura posicionada
|
|
93
|
-
// ---------------------------------------------------------------------------
|
|
94
|
-
|
|
95
|
-
/**
|
|
96
|
-
* Escribe texto en una posición específica de la pantalla. El texto
|
|
97
|
-
* puede contener escape codes ANSI (colores) — no se cuentan en la longitud.
|
|
98
|
-
*/
|
|
99
|
-
function escribirEn(fila, col, texto) {
|
|
100
|
-
moverCursor(fila, col);
|
|
101
|
-
process.stdout.write(texto);
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
/**
|
|
105
|
-
* Cuenta la longitud visual de un string ignorando códigos ANSI.
|
|
106
|
-
* Útil para centrar/alinear texto con color sin distorsionar el cálculo.
|
|
107
|
-
*/
|
|
108
|
-
function anchoVisual(texto) {
|
|
109
|
-
return String(texto).replace(/\x1b\[[0-9;]*m/g, '').length;
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
/**
|
|
113
|
-
* Recorta un string a `maxAncho` caracteres visuales preservando códigos ANSI.
|
|
114
|
-
* Si excede, agrega '…' al final.
|
|
115
|
-
*/
|
|
116
|
-
function recortar(texto, maxAncho) {
|
|
117
|
-
const s = String(texto);
|
|
118
|
-
if (anchoVisual(s) <= maxAncho) return s;
|
|
119
|
-
|
|
120
|
-
// Conservar códigos ANSI mientras se cuentan solo caracteres visibles
|
|
121
|
-
let resultado = '';
|
|
122
|
-
let ancho = 0;
|
|
123
|
-
let i = 0;
|
|
124
|
-
while (i < s.length && ancho < maxAncho - 1) {
|
|
125
|
-
if (s[i] === '\x1b' && s[i + 1] === '[') {
|
|
126
|
-
// copiar el escape code completo sin contar
|
|
127
|
-
const finCode = s.indexOf('m', i);
|
|
128
|
-
if (finCode === -1) break;
|
|
129
|
-
resultado += s.slice(i, finCode + 1);
|
|
130
|
-
i = finCode + 1;
|
|
131
|
-
} else {
|
|
132
|
-
resultado += s[i];
|
|
133
|
-
ancho++;
|
|
134
|
-
i++;
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
return resultado + '…\x1b[0m';
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
/**
|
|
141
|
-
* Rellena un string a `ancho` caracteres visuales con espacios a la derecha.
|
|
142
|
-
*/
|
|
143
|
-
function rellenarDer(texto, ancho) {
|
|
144
|
-
const diff = ancho - anchoVisual(texto);
|
|
145
|
-
return diff > 0 ? String(texto) + ' '.repeat(diff) : recortar(texto, ancho);
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
/**
|
|
149
|
-
* Centra un string en `ancho` caracteres visuales.
|
|
150
|
-
*/
|
|
151
|
-
function centrar(texto, ancho) {
|
|
152
|
-
const sobra = ancho - anchoVisual(texto);
|
|
153
|
-
if (sobra <= 0) return recortar(texto, ancho);
|
|
154
|
-
const izq = Math.floor(sobra / 2);
|
|
155
|
-
const der = sobra - izq;
|
|
156
|
-
return ' '.repeat(izq) + texto + ' '.repeat(der);
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
// ---------------------------------------------------------------------------
|
|
160
|
-
// Cajas y paneles
|
|
161
|
-
// ---------------------------------------------------------------------------
|
|
162
|
-
|
|
163
|
-
/**
|
|
164
|
-
* Dibuja una caja con borde rounded en (fila, col) con ancho y alto dados.
|
|
165
|
-
* Opciones:
|
|
166
|
-
* - titulo: string opcional centrado en la línea superior
|
|
167
|
-
* - color: función de color a aplicar al borde
|
|
168
|
-
* - doble: usar borde doble (═║) en lugar de rounded (─│)
|
|
169
|
-
* - resaltado: invertir colores del borde (para indicar foco)
|
|
170
|
-
*/
|
|
171
|
-
function dibujarCaja(fila, col, ancho, alto, opts = {}) {
|
|
172
|
-
if (!ES_TTY) return;
|
|
173
|
-
if (ancho < 2 || alto < 2) return;
|
|
174
|
-
|
|
175
|
-
const c = opts.color || colores.gris;
|
|
176
|
-
const b = opts.doble ? {
|
|
177
|
-
esqSI: borde.dbEsqSupIzq, esqSD: borde.dbEsqSupDer,
|
|
178
|
-
esqII: borde.dbEsqInfIzq, esqID: borde.dbEsqInfDer,
|
|
179
|
-
h: borde.dbHorizontal, v: borde.dbVertical,
|
|
180
|
-
} : {
|
|
181
|
-
esqSI: borde.esquinaSupIzq, esqSD: borde.esquinaSupDer,
|
|
182
|
-
esqII: borde.esquinaInfIzq, esqID: borde.esquinaInfDer,
|
|
183
|
-
h: borde.horizontal, v: borde.vertical,
|
|
184
|
-
};
|
|
185
|
-
|
|
186
|
-
// Línea superior con título opcional
|
|
187
|
-
let lineaSup;
|
|
188
|
-
if (opts.titulo) {
|
|
189
|
-
const tituloRecortado = recortar(opts.titulo, ancho - 4);
|
|
190
|
-
const anchoTitulo = anchoVisual(tituloRecortado);
|
|
191
|
-
const izq = b.h.repeat(2);
|
|
192
|
-
const der = b.h.repeat(Math.max(0, ancho - 4 - anchoTitulo));
|
|
193
|
-
lineaSup = c(b.esqSI + izq) + ' ' + tituloRecortado + ' ' + c(der + b.esqSD);
|
|
194
|
-
} else {
|
|
195
|
-
lineaSup = c(b.esqSI + b.h.repeat(ancho - 2) + b.esqSD);
|
|
196
|
-
}
|
|
197
|
-
escribirEn(fila, col, lineaSup);
|
|
198
|
-
|
|
199
|
-
// Laterales
|
|
200
|
-
for (let f = fila + 1; f < fila + alto - 1; f++) {
|
|
201
|
-
escribirEn(f, col, c(b.v));
|
|
202
|
-
escribirEn(f, col + ancho - 1, c(b.v));
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
// Línea inferior
|
|
206
|
-
escribirEn(fila + alto - 1, col, c(b.esqII + b.h.repeat(ancho - 2) + b.esqID));
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
/**
|
|
210
|
-
* Dibuja una barra horizontal de progreso en (fila, col) con ancho dado.
|
|
211
|
-
* Porcentaje entre 0 y 1. Estilo: [████░░░░░░] 42%
|
|
212
|
-
*/
|
|
213
|
-
function dibujarBarra(fila, col, ancho, porcentaje, opts = {}) {
|
|
214
|
-
const pct = Math.max(0, Math.min(1, porcentaje));
|
|
215
|
-
const lleno = opts.charLleno || '█';
|
|
216
|
-
const vacio = opts.charVacio || '░';
|
|
217
|
-
const colorLleno = opts.colorLleno || colores.verde;
|
|
218
|
-
const colorVacio = opts.colorVacio || colores.dim;
|
|
219
|
-
|
|
220
|
-
const anchoBarra = ancho - 7; // reservar espacio para " 100%"
|
|
221
|
-
const llenoN = Math.round(pct * anchoBarra);
|
|
222
|
-
const vacioN = anchoBarra - llenoN;
|
|
223
|
-
|
|
224
|
-
const barra = colorLleno(lleno.repeat(llenoN)) + colorVacio(vacio.repeat(vacioN));
|
|
225
|
-
const pctStr = String(Math.round(pct * 100)).padStart(3) + '%';
|
|
226
|
-
|
|
227
|
-
escribirEn(fila, col, barra + ' ' + colores.dim(pctStr));
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
/**
|
|
231
|
-
* Dibuja una línea de pie (footer hint) con atajos de teclado.
|
|
232
|
-
* Ejemplo: "↑↓ navegar · Enter elegir · Esc salir"
|
|
233
|
-
*/
|
|
234
|
-
function dibujarPiePagina(atajos) {
|
|
235
|
-
const { rows, cols } = obtenerDimensiones();
|
|
236
|
-
const sep = colores.dim(' · ');
|
|
237
|
-
const linea = atajos
|
|
238
|
-
.map(([tecla, accion]) => `${colores.cyan(tecla)} ${colores.dim(accion)}`)
|
|
239
|
-
.join(sep);
|
|
240
|
-
escribirEn(rows, 1, ' ' + recortar(linea, cols - 2));
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
// ---------------------------------------------------------------------------
|
|
244
|
-
// Exports
|
|
245
|
-
// ---------------------------------------------------------------------------
|
|
246
|
-
|
|
247
|
-
module.exports = {
|
|
248
|
-
ES_TTY,
|
|
249
|
-
iniciarModoTui,
|
|
250
|
-
salirModoTui,
|
|
251
|
-
estaActivo,
|
|
252
|
-
moverCursor,
|
|
253
|
-
limpiarPantalla,
|
|
254
|
-
limpiarLinea,
|
|
255
|
-
obtenerDimensiones,
|
|
256
|
-
escribirEn,
|
|
257
|
-
anchoVisual,
|
|
258
|
-
recortar,
|
|
259
|
-
rellenarDer,
|
|
260
|
-
centrar,
|
|
261
|
-
dibujarCaja,
|
|
262
|
-
dibujarBarra,
|
|
263
|
-
dibujarPiePagina,
|
|
264
|
-
};
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Primitivas de render para la TUI custom de swl-ses.
|
|
5
|
+
* Zero-deps. Solo escape codes ANSI estándar + readline para keypress.
|
|
6
|
+
*
|
|
7
|
+
* Modelo:
|
|
8
|
+
* - `iniciarModoTui()` entra al alternate screen buffer, oculta cursor.
|
|
9
|
+
* - `salirModoTui()` restaura el buffer principal y muestra el cursor.
|
|
10
|
+
* - Cada pantalla llama `limpiarPantalla()` y dibuja desde (1,1).
|
|
11
|
+
* - Las coordenadas son 1-based (compatibilidad con escape codes ANSI).
|
|
12
|
+
*
|
|
13
|
+
* Diseño defensivo:
|
|
14
|
+
* - Si stdout no es TTY (CI, pipe), todas las funciones de cursor son no-op
|
|
15
|
+
* y los dibujos se reducen a console.log lineal.
|
|
16
|
+
* - Capturar SIGINT y exit para garantizar salirModoTui() siempre.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
const { colores, borde, iconos } = require('./colores');
|
|
20
|
+
|
|
21
|
+
const ES_TTY = !!process.stdout.isTTY;
|
|
22
|
+
|
|
23
|
+
// ---------------------------------------------------------------------------
|
|
24
|
+
// Control del terminal
|
|
25
|
+
// ---------------------------------------------------------------------------
|
|
26
|
+
|
|
27
|
+
let modoTuiActivo = false;
|
|
28
|
+
let limpiezaRegistrada = false;
|
|
29
|
+
|
|
30
|
+
function iniciarModoTui() {
|
|
31
|
+
if (modoTuiActivo || !ES_TTY) return;
|
|
32
|
+
modoTuiActivo = true;
|
|
33
|
+
|
|
34
|
+
// Alternate screen buffer: preserva el contenido del terminal pre-TUI
|
|
35
|
+
process.stdout.write('\x1b[?1049h');
|
|
36
|
+
// Ocultar cursor
|
|
37
|
+
process.stdout.write('\x1b[?25l');
|
|
38
|
+
// Limpiar
|
|
39
|
+
process.stdout.write('\x1b[2J\x1b[H');
|
|
40
|
+
|
|
41
|
+
// Registrar limpieza al salir (idempotente)
|
|
42
|
+
if (!limpiezaRegistrada) {
|
|
43
|
+
limpiezaRegistrada = true;
|
|
44
|
+
const limpieza = () => salirModoTui();
|
|
45
|
+
process.once('exit', limpieza);
|
|
46
|
+
process.once('SIGINT', () => { salirModoTui(); process.exit(130); });
|
|
47
|
+
process.once('SIGTERM', () => { salirModoTui(); process.exit(143); });
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function salirModoTui() {
|
|
52
|
+
if (!modoTuiActivo || !ES_TTY) return;
|
|
53
|
+
modoTuiActivo = false;
|
|
54
|
+
|
|
55
|
+
// Mostrar cursor
|
|
56
|
+
process.stdout.write('\x1b[?25h');
|
|
57
|
+
// Salir del alternate screen buffer (restaura contenido pre-TUI)
|
|
58
|
+
process.stdout.write('\x1b[?1049l');
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function estaActivo() {
|
|
62
|
+
return modoTuiActivo;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// ---------------------------------------------------------------------------
|
|
66
|
+
// Movimiento de cursor
|
|
67
|
+
// ---------------------------------------------------------------------------
|
|
68
|
+
|
|
69
|
+
function moverCursor(fila, col) {
|
|
70
|
+
if (!ES_TTY) return;
|
|
71
|
+
process.stdout.write(`\x1b[${fila};${col}H`);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function limpiarPantalla() {
|
|
75
|
+
if (!ES_TTY) return;
|
|
76
|
+
process.stdout.write('\x1b[2J\x1b[H');
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function limpiarLinea() {
|
|
80
|
+
if (!ES_TTY) return;
|
|
81
|
+
process.stdout.write('\x1b[2K\r');
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function obtenerDimensiones() {
|
|
85
|
+
return {
|
|
86
|
+
cols: process.stdout.columns || 80,
|
|
87
|
+
rows: process.stdout.rows || 24,
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// ---------------------------------------------------------------------------
|
|
92
|
+
// Escritura posicionada
|
|
93
|
+
// ---------------------------------------------------------------------------
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Escribe texto en una posición específica de la pantalla. El texto
|
|
97
|
+
* puede contener escape codes ANSI (colores) — no se cuentan en la longitud.
|
|
98
|
+
*/
|
|
99
|
+
function escribirEn(fila, col, texto) {
|
|
100
|
+
moverCursor(fila, col);
|
|
101
|
+
process.stdout.write(texto);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Cuenta la longitud visual de un string ignorando códigos ANSI.
|
|
106
|
+
* Útil para centrar/alinear texto con color sin distorsionar el cálculo.
|
|
107
|
+
*/
|
|
108
|
+
function anchoVisual(texto) {
|
|
109
|
+
return String(texto).replace(/\x1b\[[0-9;]*m/g, '').length;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Recorta un string a `maxAncho` caracteres visuales preservando códigos ANSI.
|
|
114
|
+
* Si excede, agrega '…' al final.
|
|
115
|
+
*/
|
|
116
|
+
function recortar(texto, maxAncho) {
|
|
117
|
+
const s = String(texto);
|
|
118
|
+
if (anchoVisual(s) <= maxAncho) return s;
|
|
119
|
+
|
|
120
|
+
// Conservar códigos ANSI mientras se cuentan solo caracteres visibles
|
|
121
|
+
let resultado = '';
|
|
122
|
+
let ancho = 0;
|
|
123
|
+
let i = 0;
|
|
124
|
+
while (i < s.length && ancho < maxAncho - 1) {
|
|
125
|
+
if (s[i] === '\x1b' && s[i + 1] === '[') {
|
|
126
|
+
// copiar el escape code completo sin contar
|
|
127
|
+
const finCode = s.indexOf('m', i);
|
|
128
|
+
if (finCode === -1) break;
|
|
129
|
+
resultado += s.slice(i, finCode + 1);
|
|
130
|
+
i = finCode + 1;
|
|
131
|
+
} else {
|
|
132
|
+
resultado += s[i];
|
|
133
|
+
ancho++;
|
|
134
|
+
i++;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
return resultado + '…\x1b[0m';
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Rellena un string a `ancho` caracteres visuales con espacios a la derecha.
|
|
142
|
+
*/
|
|
143
|
+
function rellenarDer(texto, ancho) {
|
|
144
|
+
const diff = ancho - anchoVisual(texto);
|
|
145
|
+
return diff > 0 ? String(texto) + ' '.repeat(diff) : recortar(texto, ancho);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Centra un string en `ancho` caracteres visuales.
|
|
150
|
+
*/
|
|
151
|
+
function centrar(texto, ancho) {
|
|
152
|
+
const sobra = ancho - anchoVisual(texto);
|
|
153
|
+
if (sobra <= 0) return recortar(texto, ancho);
|
|
154
|
+
const izq = Math.floor(sobra / 2);
|
|
155
|
+
const der = sobra - izq;
|
|
156
|
+
return ' '.repeat(izq) + texto + ' '.repeat(der);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// ---------------------------------------------------------------------------
|
|
160
|
+
// Cajas y paneles
|
|
161
|
+
// ---------------------------------------------------------------------------
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Dibuja una caja con borde rounded en (fila, col) con ancho y alto dados.
|
|
165
|
+
* Opciones:
|
|
166
|
+
* - titulo: string opcional centrado en la línea superior
|
|
167
|
+
* - color: función de color a aplicar al borde
|
|
168
|
+
* - doble: usar borde doble (═║) en lugar de rounded (─│)
|
|
169
|
+
* - resaltado: invertir colores del borde (para indicar foco)
|
|
170
|
+
*/
|
|
171
|
+
function dibujarCaja(fila, col, ancho, alto, opts = {}) {
|
|
172
|
+
if (!ES_TTY) return;
|
|
173
|
+
if (ancho < 2 || alto < 2) return;
|
|
174
|
+
|
|
175
|
+
const c = opts.color || colores.gris;
|
|
176
|
+
const b = opts.doble ? {
|
|
177
|
+
esqSI: borde.dbEsqSupIzq, esqSD: borde.dbEsqSupDer,
|
|
178
|
+
esqII: borde.dbEsqInfIzq, esqID: borde.dbEsqInfDer,
|
|
179
|
+
h: borde.dbHorizontal, v: borde.dbVertical,
|
|
180
|
+
} : {
|
|
181
|
+
esqSI: borde.esquinaSupIzq, esqSD: borde.esquinaSupDer,
|
|
182
|
+
esqII: borde.esquinaInfIzq, esqID: borde.esquinaInfDer,
|
|
183
|
+
h: borde.horizontal, v: borde.vertical,
|
|
184
|
+
};
|
|
185
|
+
|
|
186
|
+
// Línea superior con título opcional
|
|
187
|
+
let lineaSup;
|
|
188
|
+
if (opts.titulo) {
|
|
189
|
+
const tituloRecortado = recortar(opts.titulo, ancho - 4);
|
|
190
|
+
const anchoTitulo = anchoVisual(tituloRecortado);
|
|
191
|
+
const izq = b.h.repeat(2);
|
|
192
|
+
const der = b.h.repeat(Math.max(0, ancho - 4 - anchoTitulo));
|
|
193
|
+
lineaSup = c(b.esqSI + izq) + ' ' + tituloRecortado + ' ' + c(der + b.esqSD);
|
|
194
|
+
} else {
|
|
195
|
+
lineaSup = c(b.esqSI + b.h.repeat(ancho - 2) + b.esqSD);
|
|
196
|
+
}
|
|
197
|
+
escribirEn(fila, col, lineaSup);
|
|
198
|
+
|
|
199
|
+
// Laterales
|
|
200
|
+
for (let f = fila + 1; f < fila + alto - 1; f++) {
|
|
201
|
+
escribirEn(f, col, c(b.v));
|
|
202
|
+
escribirEn(f, col + ancho - 1, c(b.v));
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// Línea inferior
|
|
206
|
+
escribirEn(fila + alto - 1, col, c(b.esqII + b.h.repeat(ancho - 2) + b.esqID));
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Dibuja una barra horizontal de progreso en (fila, col) con ancho dado.
|
|
211
|
+
* Porcentaje entre 0 y 1. Estilo: [████░░░░░░] 42%
|
|
212
|
+
*/
|
|
213
|
+
function dibujarBarra(fila, col, ancho, porcentaje, opts = {}) {
|
|
214
|
+
const pct = Math.max(0, Math.min(1, porcentaje));
|
|
215
|
+
const lleno = opts.charLleno || '█';
|
|
216
|
+
const vacio = opts.charVacio || '░';
|
|
217
|
+
const colorLleno = opts.colorLleno || colores.verde;
|
|
218
|
+
const colorVacio = opts.colorVacio || colores.dim;
|
|
219
|
+
|
|
220
|
+
const anchoBarra = ancho - 7; // reservar espacio para " 100%"
|
|
221
|
+
const llenoN = Math.round(pct * anchoBarra);
|
|
222
|
+
const vacioN = anchoBarra - llenoN;
|
|
223
|
+
|
|
224
|
+
const barra = colorLleno(lleno.repeat(llenoN)) + colorVacio(vacio.repeat(vacioN));
|
|
225
|
+
const pctStr = String(Math.round(pct * 100)).padStart(3) + '%';
|
|
226
|
+
|
|
227
|
+
escribirEn(fila, col, barra + ' ' + colores.dim(pctStr));
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* Dibuja una línea de pie (footer hint) con atajos de teclado.
|
|
232
|
+
* Ejemplo: "↑↓ navegar · Enter elegir · Esc salir"
|
|
233
|
+
*/
|
|
234
|
+
function dibujarPiePagina(atajos) {
|
|
235
|
+
const { rows, cols } = obtenerDimensiones();
|
|
236
|
+
const sep = colores.dim(' · ');
|
|
237
|
+
const linea = atajos
|
|
238
|
+
.map(([tecla, accion]) => `${colores.cyan(tecla)} ${colores.dim(accion)}`)
|
|
239
|
+
.join(sep);
|
|
240
|
+
escribirEn(rows, 1, ' ' + recortar(linea, cols - 2));
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
// ---------------------------------------------------------------------------
|
|
244
|
+
// Exports
|
|
245
|
+
// ---------------------------------------------------------------------------
|
|
246
|
+
|
|
247
|
+
module.exports = {
|
|
248
|
+
ES_TTY,
|
|
249
|
+
iniciarModoTui,
|
|
250
|
+
salirModoTui,
|
|
251
|
+
estaActivo,
|
|
252
|
+
moverCursor,
|
|
253
|
+
limpiarPantalla,
|
|
254
|
+
limpiarLinea,
|
|
255
|
+
obtenerDimensiones,
|
|
256
|
+
escribirEn,
|
|
257
|
+
anchoVisual,
|
|
258
|
+
recortar,
|
|
259
|
+
rellenarDer,
|
|
260
|
+
centrar,
|
|
261
|
+
dibujarCaja,
|
|
262
|
+
dibujarBarra,
|
|
263
|
+
dibujarPiePagina,
|
|
264
|
+
};
|