forked from jaildesigner-jailgames/jaildoctors_dilemma
console crea la tabla tab_completions automaticament
This commit is contained in:
@@ -28,11 +28,16 @@
|
|||||||
|
|
||||||
// ── Sistema de comandos ────────────────────────────────────────────────────────
|
// ── Sistema de comandos ────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
// Mapa de completions: {ruta_completa_en_mayúsculas, {opciones}}
|
||||||
|
// Ej: {"CHEAT OPEN THE", {"JAIL"}}
|
||||||
|
using CompletionMap = std::vector<std::pair<std::string_view, std::vector<std::string_view>>>;
|
||||||
|
|
||||||
struct ConsoleCommand {
|
struct ConsoleCommand {
|
||||||
std::string_view keyword;
|
std::string_view keyword;
|
||||||
std::function<std::string(const std::vector<std::string>& args)> execute;
|
std::function<std::string(const std::vector<std::string>& args)> execute;
|
||||||
bool instant{false}; // Si true, muestra la respuesta sin efecto typewriter
|
bool instant{false}; // Si true, muestra la respuesta sin efecto typewriter
|
||||||
bool hidden{false}; // Si true, no aparece en el autocompletado (TAB)
|
bool hidden{false}; // Si true, no aparece en el autocompletado (TAB)
|
||||||
|
CompletionMap completions{}; // Árbol de sub-argumentos para TAB; cargado en el constructor de Console
|
||||||
};
|
};
|
||||||
|
|
||||||
// Convierte la entrada a uppercase y la divide en tokens por espacios
|
// Convierte la entrada a uppercase y la divide en tokens por espacios
|
||||||
@@ -196,6 +201,11 @@ static const std::vector<ConsoleCommand> COMMANDS = {
|
|||||||
return "PostFX Supersampling OFF";
|
return "PostFX Supersampling OFF";
|
||||||
}
|
}
|
||||||
return "usage: ss [on|off|size|upscale [nearest|linear]|downscale [bilinear|lanczos2|lanczos3]]";
|
return "usage: ss [on|off|size|upscale [nearest|linear]|downscale [bilinear|lanczos2|lanczos3]]";
|
||||||
|
},
|
||||||
|
.completions = {
|
||||||
|
{"SS", {"ON", "OFF", "SIZE", "UPSCALE", "DOWNSCALE"}},
|
||||||
|
{"SS UPSCALE", {"NEAREST", "LINEAR"}},
|
||||||
|
{"SS DOWNSCALE", {"BILINEAR", "LANCZOS2", "LANCZOS3"}},
|
||||||
}},
|
}},
|
||||||
|
|
||||||
// SHADER [ON|OFF|NEXT [PRESET]|POSTFX|CRTPI] — Toggle/cicla/selecciona shader (F4 / Shift+F4)
|
// SHADER [ON|OFF|NEXT [PRESET]|POSTFX|CRTPI] — Toggle/cicla/selecciona shader (F4 / Shift+F4)
|
||||||
@@ -248,10 +258,15 @@ static const std::vector<ConsoleCommand> COMMANDS = {
|
|||||||
(Options::current_shader == Rendering::ShaderType::CRTPI ? "CRTPI" : "POSTFX");
|
(Options::current_shader == Rendering::ShaderType::CRTPI ? "CRTPI" : "POSTFX");
|
||||||
}
|
}
|
||||||
return "usage: shader [on|off|next [preset]|postfx|crtpi]";
|
return "usage: shader [on|off|next [preset]|postfx|crtpi]";
|
||||||
|
},
|
||||||
|
.completions = {
|
||||||
|
{"SHADER", {"ON", "OFF", "NEXT", "POSTFX", "CRTPI"}},
|
||||||
|
{"SHADER NEXT", {"PRESET"}},
|
||||||
}},
|
}},
|
||||||
|
|
||||||
// BORDER [ON|OFF] — Borde decorativo (B)
|
// BORDER [ON|OFF] — Borde decorativo (B)
|
||||||
{.keyword = "BORDER", .execute = BOOL_TOGGLE_CMD("Border", Options::video.border.enabled, Screen::get()->toggleBorder())},
|
{.keyword = "BORDER", .execute = BOOL_TOGGLE_CMD("Border", Options::video.border.enabled, Screen::get()->toggleBorder()),
|
||||||
|
.completions = {{"BORDER", {"ON", "OFF"}}}},
|
||||||
|
|
||||||
// FULLSCREEN [ON|OFF [PLEASE]] — Pantalla completa (F3); OFF bloqueado en kiosk sin PLEASE
|
// FULLSCREEN [ON|OFF [PLEASE]] — Pantalla completa (F3); OFF bloqueado en kiosk sin PLEASE
|
||||||
{.keyword = "FULLSCREEN", .execute = [](const std::vector<std::string>& args) -> std::string {
|
{.keyword = "FULLSCREEN", .execute = [](const std::vector<std::string>& args) -> std::string {
|
||||||
@@ -279,7 +294,8 @@ static const std::vector<ConsoleCommand> COMMANDS = {
|
|||||||
return std::string("Fullscreen ") + (Options::video.fullscreen ? "ON" : "OFF");
|
return std::string("Fullscreen ") + (Options::video.fullscreen ? "ON" : "OFF");
|
||||||
}
|
}
|
||||||
return "usage: fullscreen [on|off]";
|
return "usage: fullscreen [on|off]";
|
||||||
}},
|
},
|
||||||
|
.completions = {{"FULLSCREEN", {"ON", "OFF"}}}},
|
||||||
|
|
||||||
// ZOOM UP/DOWN — Zoom de ventana (F1/F2)
|
// ZOOM UP/DOWN — Zoom de ventana (F1/F2)
|
||||||
{.keyword = "ZOOM", .execute = [](const std::vector<std::string>& args) -> std::string {
|
{.keyword = "ZOOM", .execute = [](const std::vector<std::string>& args) -> std::string {
|
||||||
@@ -293,7 +309,8 @@ static const std::vector<ConsoleCommand> COMMANDS = {
|
|||||||
return "Zoom " + std::to_string(Options::window.zoom);
|
return "Zoom " + std::to_string(Options::window.zoom);
|
||||||
}
|
}
|
||||||
return "usage: zoom [up|down]";
|
return "usage: zoom [up|down]";
|
||||||
}},
|
},
|
||||||
|
.completions = {{"ZOOM", {"UP", "DOWN"}}}},
|
||||||
|
|
||||||
// INTSCALE [ON|OFF] — Escalado entero (F7)
|
// INTSCALE [ON|OFF] — Escalado entero (F7)
|
||||||
{.keyword = "INTSCALE", .execute = [](const std::vector<std::string>& args) -> std::string {
|
{.keyword = "INTSCALE", .execute = [](const std::vector<std::string>& args) -> std::string {
|
||||||
@@ -308,10 +325,12 @@ static const std::vector<ConsoleCommand> COMMANDS = {
|
|||||||
Screen::get()->toggleIntegerScale();
|
Screen::get()->toggleIntegerScale();
|
||||||
Screen::get()->setVideoMode(Options::video.fullscreen);
|
Screen::get()->setVideoMode(Options::video.fullscreen);
|
||||||
return std::string("IntScale ") + (Options::video.integer_scale ? "ON" : "OFF");
|
return std::string("IntScale ") + (Options::video.integer_scale ? "ON" : "OFF");
|
||||||
}},
|
},
|
||||||
|
.completions = {{"INTSCALE", {"ON", "OFF"}}}},
|
||||||
|
|
||||||
// VSYNC [ON|OFF] — Sincronización vertical
|
// VSYNC [ON|OFF] — Sincronización vertical
|
||||||
{.keyword = "VSYNC", .execute = BOOL_TOGGLE_CMD("VSync", Options::video.vertical_sync, Screen::get()->toggleVSync())},
|
{.keyword = "VSYNC", .execute = BOOL_TOGGLE_CMD("VSync", Options::video.vertical_sync, Screen::get()->toggleVSync()),
|
||||||
|
.completions = {{"VSYNC", {"ON", "OFF"}}}},
|
||||||
|
|
||||||
// DRIVER [LIST|AUTO|<nombre>] — Driver GPU (aplica en el próximo arranque)
|
// DRIVER [LIST|AUTO|<nombre>] — Driver GPU (aplica en el próximo arranque)
|
||||||
{.keyword = "DRIVER", .execute = [](const std::vector<std::string>& args) -> std::string {
|
{.keyword = "DRIVER", .execute = [](const std::vector<std::string>& args) -> std::string {
|
||||||
@@ -367,7 +386,8 @@ static const std::vector<ConsoleCommand> COMMANDS = {
|
|||||||
Options::video.gpu_preferred_driver = driver_lower;
|
Options::video.gpu_preferred_driver = driver_lower;
|
||||||
Options::saveToFile();
|
Options::saveToFile();
|
||||||
return "Driver: " + driver_lower + " (restart)";
|
return "Driver: " + driver_lower + " (restart)";
|
||||||
}},
|
},
|
||||||
|
.completions = {{"DRIVER", {"LIST", "AUTO", "NONE"}}}},
|
||||||
|
|
||||||
// PALETTE NEXT/PREV/<nombre> — Paleta de colores (F5/F6 o por nombre)
|
// PALETTE NEXT/PREV/<nombre> — Paleta de colores (F5/F6 o por nombre)
|
||||||
{.keyword = "PALETTE", .execute = [](const std::vector<std::string>& args) -> std::string {
|
{.keyword = "PALETTE", .execute = [](const std::vector<std::string>& args) -> std::string {
|
||||||
@@ -405,7 +425,8 @@ static const std::vector<ConsoleCommand> COMMANDS = {
|
|||||||
if (!args.empty()) { return "usage: debug [on|off]"; }
|
if (!args.empty()) { return "usage: debug [on|off]"; }
|
||||||
GameControl::toggle_debug_mode();
|
GameControl::toggle_debug_mode();
|
||||||
return std::string("Debug mode ") + (Debug::get()->isEnabled() ? "ON" : "OFF");
|
return std::string("Debug mode ") + (Debug::get()->isEnabled() ? "ON" : "OFF");
|
||||||
}},
|
},
|
||||||
|
.completions = {{"DEBUG", {"ON", "OFF"}}}},
|
||||||
|
|
||||||
// ROOM <num>|NEXT|PREV — Cambia a la habitación indicada (1-60); solo en escena GAME
|
// ROOM <num>|NEXT|PREV — Cambia a la habitación indicada (1-60); solo en escena GAME
|
||||||
{.keyword = "ROOM", .execute = [](const std::vector<std::string>& args) -> std::string {
|
{.keyword = "ROOM", .execute = [](const std::vector<std::string>& args) -> std::string {
|
||||||
@@ -431,7 +452,8 @@ static const std::vector<ConsoleCommand> COMMANDS = {
|
|||||||
return std::string("Room: ") + buf;
|
return std::string("Room: ") + buf;
|
||||||
}
|
}
|
||||||
return std::string("Room not found: ") + buf;
|
return std::string("Room not found: ") + buf;
|
||||||
}},
|
},
|
||||||
|
.completions = {{"ROOM", {"NEXT", "PREV"}}}},
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -453,6 +475,13 @@ static const std::vector<ConsoleCommand> COMMANDS = {
|
|||||||
if (RenderInfo::get()->isActive()) { return "Info overlay already ON"; }
|
if (RenderInfo::get()->isActive()) { return "Info overlay already ON"; }
|
||||||
RenderInfo::get()->toggle();
|
RenderInfo::get()->toggle();
|
||||||
return "Info overlay ON";
|
return "Info overlay ON";
|
||||||
|
},
|
||||||
|
.completions = {
|
||||||
|
#ifdef _DEBUG
|
||||||
|
{"SHOW", {"INFO", "NOTIFICATION", "CHEEVO"}},
|
||||||
|
#else
|
||||||
|
{"SHOW", {"INFO"}},
|
||||||
|
#endif
|
||||||
}},
|
}},
|
||||||
|
|
||||||
// HIDE INFO — disponible en Release
|
// HIDE INFO — disponible en Release
|
||||||
@@ -461,7 +490,8 @@ static const std::vector<ConsoleCommand> COMMANDS = {
|
|||||||
if (!RenderInfo::get()->isActive()) { return "Info overlay already OFF"; }
|
if (!RenderInfo::get()->isActive()) { return "Info overlay already OFF"; }
|
||||||
RenderInfo::get()->toggle();
|
RenderInfo::get()->toggle();
|
||||||
return "Info overlay OFF";
|
return "Info overlay OFF";
|
||||||
}},
|
},
|
||||||
|
.completions = {{"HIDE", {"INFO"}}}},
|
||||||
|
|
||||||
// CHEAT <subcomando> — Trucos de juego; solo en escena GAME; no aparece en ayuda en builds Release
|
// CHEAT <subcomando> — Trucos de juego; solo en escena GAME; no aparece en ayuda en builds Release
|
||||||
{.keyword = "CHEAT", .execute = [](const std::vector<std::string>& args) -> std::string {
|
{.keyword = "CHEAT", .execute = [](const std::vector<std::string>& args) -> std::string {
|
||||||
@@ -526,7 +556,17 @@ static const std::vector<ConsoleCommand> COMMANDS = {
|
|||||||
|
|
||||||
return "usage: cheat [infinite lives|invincibility|open the jail|close the jail]";
|
return "usage: cheat [infinite lives|invincibility|open the jail|close the jail]";
|
||||||
},
|
},
|
||||||
.hidden = CHEAT_HIDDEN},
|
.hidden = CHEAT_HIDDEN,
|
||||||
|
.completions = {
|
||||||
|
{"CHEAT", {"INFINITE", "INVINCIBILITY", "OPEN", "CLOSE"}},
|
||||||
|
{"CHEAT INFINITE", {"LIVES"}},
|
||||||
|
{"CHEAT INFINITE LIVES", {"ON", "OFF"}},
|
||||||
|
{"CHEAT INVINCIBILITY", {"ON", "OFF"}},
|
||||||
|
{"CHEAT OPEN", {"THE"}},
|
||||||
|
{"CHEAT OPEN THE", {"JAIL"}},
|
||||||
|
{"CHEAT CLOSE", {"THE"}},
|
||||||
|
{"CHEAT CLOSE THE", {"JAIL"}},
|
||||||
|
}},
|
||||||
|
|
||||||
// SET PLAYER SKIN <1|2> — Cambia la skin del jugador (disponible en todos los builds, GAME)
|
// SET PLAYER SKIN <1|2> — Cambia la skin del jugador (disponible en todos los builds, GAME)
|
||||||
// SET INITIAL [ROOM|POS] — Guarda habitación/posición actual como inicio (solo _DEBUG, GAME)
|
// SET INITIAL [ROOM|POS] — Guarda habitación/posición actual como inicio (solo _DEBUG, GAME)
|
||||||
@@ -612,6 +652,17 @@ static const std::vector<ConsoleCommand> COMMANDS = {
|
|||||||
return result;
|
return result;
|
||||||
#else
|
#else
|
||||||
return "usage: set player skin <1|2>";
|
return "usage: set player skin <1|2>";
|
||||||
|
#endif
|
||||||
|
},
|
||||||
|
.completions = {
|
||||||
|
#ifdef _DEBUG
|
||||||
|
{"SET", {"PLAYER", "INITIAL", "ITEMS"}},
|
||||||
|
{"SET PLAYER", {"SKIN"}},
|
||||||
|
{"SET INITIAL", {"ROOM", "POS", "SCENE"}},
|
||||||
|
{"SET INITIAL SCENE", {"LOGO", "LOADING", "TITLE", "CREDITS", "GAME", "ENDING", "ENDING2"}},
|
||||||
|
#else
|
||||||
|
{"SET", {"PLAYER"}},
|
||||||
|
{"SET PLAYER", {"SKIN"}},
|
||||||
#endif
|
#endif
|
||||||
}},
|
}},
|
||||||
|
|
||||||
@@ -647,7 +698,8 @@ static const std::vector<ConsoleCommand> COMMANDS = {
|
|||||||
if (args[0] == "ENDING") { return GO_TO(SceneManager::Scene::ENDING, "Ending"); }
|
if (args[0] == "ENDING") { return GO_TO(SceneManager::Scene::ENDING, "Ending"); }
|
||||||
if (args[0] == "ENDING2") { return GO_TO(SceneManager::Scene::ENDING2, "Ending 2"); }
|
if (args[0] == "ENDING2") { return GO_TO(SceneManager::Scene::ENDING2, "Ending 2"); }
|
||||||
return "Unknown scene: " + args[0];
|
return "Unknown scene: " + args[0];
|
||||||
}},
|
},
|
||||||
|
.completions = {{"SCENE", {"LOGO", "LOADING", "TITLE", "CREDITS", "GAME", "ENDING", "ENDING2", "RESTART"}}}},
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// RESTART — Reiniciar desde el principio (equivale a SCENE LOGO)
|
// RESTART — Reiniciar desde el principio (equivale a SCENE LOGO)
|
||||||
@@ -676,7 +728,8 @@ static const std::vector<ConsoleCommand> COMMANDS = {
|
|||||||
return "Kiosk mode ON";
|
return "Kiosk mode ON";
|
||||||
}
|
}
|
||||||
return "usage: kiosk [on]";
|
return "usage: kiosk [on]";
|
||||||
}},
|
},
|
||||||
|
.completions = {{"KIOSK", {"ON"}}}},
|
||||||
|
|
||||||
// AUDIO [ON|OFF|VOL <0-100>] — Audio maestro (estado + volumen)
|
// AUDIO [ON|OFF|VOL <0-100>] — Audio maestro (estado + volumen)
|
||||||
{.keyword = "AUDIO", .execute = [](const std::vector<std::string>& args) -> std::string {
|
{.keyword = "AUDIO", .execute = [](const std::vector<std::string>& args) -> std::string {
|
||||||
@@ -707,7 +760,8 @@ static const std::vector<ConsoleCommand> COMMANDS = {
|
|||||||
} catch (...) { return "usage: audio vol <0-100>"; }
|
} catch (...) { return "usage: audio vol <0-100>"; }
|
||||||
}
|
}
|
||||||
return "usage: audio [on|off|vol n]";
|
return "usage: audio [on|off|vol n]";
|
||||||
}},
|
},
|
||||||
|
.completions = {{"AUDIO", {"ON", "OFF", "VOL"}}}},
|
||||||
|
|
||||||
// MUSIC [ON|OFF|VOL <0-100>] — Volumen e interruptor de música
|
// MUSIC [ON|OFF|VOL <0-100>] — Volumen e interruptor de música
|
||||||
{.keyword = "MUSIC", .execute = [](const std::vector<std::string>& args) -> std::string {
|
{.keyword = "MUSIC", .execute = [](const std::vector<std::string>& args) -> std::string {
|
||||||
@@ -742,7 +796,8 @@ static const std::vector<ConsoleCommand> COMMANDS = {
|
|||||||
} catch (...) { return "usage: music vol <0-100>"; }
|
} catch (...) { return "usage: music vol <0-100>"; }
|
||||||
}
|
}
|
||||||
return "usage: music [on|off|vol n]";
|
return "usage: music [on|off|vol n]";
|
||||||
}},
|
},
|
||||||
|
.completions = {{"MUSIC", {"ON", "OFF", "VOL"}}}},
|
||||||
|
|
||||||
// SOUND [ON|OFF|VOL <0-100>] — Volumen e interruptor de efectos de sonido
|
// SOUND [ON|OFF|VOL <0-100>] — Volumen e interruptor de efectos de sonido
|
||||||
{.keyword = "SOUND", .execute = [](const std::vector<std::string>& args) -> std::string {
|
{.keyword = "SOUND", .execute = [](const std::vector<std::string>& args) -> std::string {
|
||||||
@@ -777,7 +832,8 @@ static const std::vector<ConsoleCommand> COMMANDS = {
|
|||||||
} catch (...) { return "usage: sound vol <0-100>"; }
|
} catch (...) { return "usage: sound vol <0-100>"; }
|
||||||
}
|
}
|
||||||
return "usage: sound [on|off|vol n]";
|
return "usage: sound [on|off|vol n]";
|
||||||
}},
|
},
|
||||||
|
.completions = {{"SOUND", {"ON", "OFF", "VOL"}}}},
|
||||||
|
|
||||||
// EXIT / QUIT — Cerrar la aplicacion (bloqueado en kiosk)
|
// EXIT / QUIT — Cerrar la aplicacion (bloqueado en kiosk)
|
||||||
{.keyword = "EXIT", .execute = [](const std::vector<std::string>& args) -> std::string {
|
{.keyword = "EXIT", .execute = [](const std::vector<std::string>& args) -> std::string {
|
||||||
@@ -905,6 +961,14 @@ Console::Console(const std::string& font_name)
|
|||||||
target_height_ = height_;
|
target_height_ = height_;
|
||||||
y_ = -height_;
|
y_ = -height_;
|
||||||
|
|
||||||
|
// Construir mapa de autocompletado a partir de COMMANDS
|
||||||
|
for (const auto& cmd : COMMANDS) {
|
||||||
|
for (const auto& [path, opts] : cmd.completions) {
|
||||||
|
auto& vec = tab_completions_[std::string(path)];
|
||||||
|
for (const auto& opt : opts) { vec.emplace_back(opt); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
buildSurface();
|
buildSurface();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1151,40 +1215,11 @@ void Console::handleEvent(const SDL_Event& event) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Modo sub-argumento: completar primer arg del comando base
|
const std::string base_cmd = upper.substr(0, space_pos);
|
||||||
using SubArgs = std::vector<std::string_view>;
|
|
||||||
using Entry = std::pair<std::string_view, SubArgs>;
|
|
||||||
static const std::vector<Entry> SUB_ARGS = {
|
|
||||||
{"SS", {"ON", "OFF", "SIZE", "UPSCALE", "DOWNSCALE"}},
|
|
||||||
{"SHADER", {"ON", "OFF", "NEXT", "POSTFX", "CRTPI"}},
|
|
||||||
{"BORDER", {"ON", "OFF"}},
|
|
||||||
{"FULLSCREEN", {"ON", "OFF"}},
|
|
||||||
{"ZOOM", {"UP", "DOWN"}},
|
|
||||||
{"INTSCALE", {"ON", "OFF"}},
|
|
||||||
{"VSYNC", {"ON", "OFF"}},
|
|
||||||
{"DRIVER", {"LIST", "AUTO", "NONE"}},
|
|
||||||
{"AUDIO", {"ON", "OFF", "VOL"}},
|
|
||||||
{"MUSIC", {"ON", "OFF", "VOL"}},
|
|
||||||
{"SOUND", {"ON", "OFF", "VOL"}},
|
|
||||||
#ifdef _DEBUG
|
|
||||||
{"SHOW", {"INFO", "NOTIFICATION", "CHEEVO"}},
|
|
||||||
{"SET", {"PLAYER", "INITIAL", "ITEMS"}},
|
|
||||||
{"DEBUG", {"ON", "OFF"}},
|
|
||||||
{"ROOM", {"NEXT", "PREV"}},
|
|
||||||
{"SCENE", {"LOGO", "LOADING", "TITLE", "CREDITS", "GAME", "ENDING", "ENDING2", "RESTART"}},
|
|
||||||
#else
|
|
||||||
{"SHOW", {"INFO"}},
|
|
||||||
{"SET", {"PLAYER"}},
|
|
||||||
#endif
|
|
||||||
{"HIDE", {"INFO"}},
|
|
||||||
{"KIOSK", {"ON"}},
|
|
||||||
{"CHEAT", {"INFINITE", "INVINCIBILITY", "OPEN", "CLOSE"}},
|
|
||||||
};
|
|
||||||
const std::string base_cmd = upper.substr(0, space_pos);
|
|
||||||
const std::string sub_prefix = upper.substr(space_pos + 1);
|
const std::string sub_prefix = upper.substr(space_pos + 1);
|
||||||
if (base_cmd == "PALETTE" && Screen::get() != nullptr) {
|
if (base_cmd == "PALETTE" && Screen::get() != nullptr) {
|
||||||
// NEXT/PREV primero, luego todos los nombres de paleta disponibles
|
// NEXT/PREV primero, luego todos los nombres de paleta disponibles
|
||||||
for (const auto sv : {"NEXT", "PREV"}) {
|
for (const auto* sv : {"NEXT", "PREV"}) {
|
||||||
if (sub_prefix.empty() || std::string_view{sv}.starts_with(sub_prefix)) {
|
if (sub_prefix.empty() || std::string_view{sv}.starts_with(sub_prefix)) {
|
||||||
tab_matches_.emplace_back("PALETTE " + std::string(sv));
|
tab_matches_.emplace_back("PALETTE " + std::string(sv));
|
||||||
}
|
}
|
||||||
@@ -1195,14 +1230,12 @@ void Console::handleEvent(const SDL_Event& event) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (const auto& [keyword, args] : SUB_ARGS) {
|
const auto it = tab_completions_.find(base_cmd);
|
||||||
if (keyword == base_cmd) {
|
if (it != tab_completions_.end()) {
|
||||||
for (const auto& arg : args) {
|
for (const auto& arg : it->second) {
|
||||||
if (sub_prefix.empty() || std::string_view{arg}.starts_with(sub_prefix)) {
|
if (sub_prefix.empty() || std::string_view{arg}.starts_with(sub_prefix)) {
|
||||||
tab_matches_.emplace_back(std::string(base_cmd) + " " + std::string(arg));
|
tab_matches_.emplace_back(base_cmd + " " + arg);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,11 +2,12 @@
|
|||||||
|
|
||||||
#include <SDL3/SDL.h>
|
#include <SDL3/SDL.h>
|
||||||
|
|
||||||
#include <deque> // Para deque (historial)
|
#include <deque> // Para deque (historial)
|
||||||
#include <functional> // Para function
|
#include <functional> // Para function
|
||||||
#include <memory> // Para shared_ptr
|
#include <memory> // Para shared_ptr
|
||||||
#include <string> // Para string
|
#include <string> // Para string
|
||||||
#include <vector> // Para vector
|
#include <unordered_map> // Para unordered_map (tab_completions_)
|
||||||
|
#include <vector> // Para vector
|
||||||
|
|
||||||
class Surface;
|
class Surface;
|
||||||
class Sprite;
|
class Sprite;
|
||||||
@@ -101,4 +102,5 @@ class Console {
|
|||||||
// Estado de autocompletado (TAB)
|
// Estado de autocompletado (TAB)
|
||||||
std::vector<std::string> tab_matches_; // Comandos que coinciden con el prefijo actual
|
std::vector<std::string> tab_matches_; // Comandos que coinciden con el prefijo actual
|
||||||
int tab_index_{-1}; // Índice actual en tab_matches_
|
int tab_index_{-1}; // Índice actual en tab_matches_
|
||||||
|
std::unordered_map<std::string, std::vector<std::string>> tab_completions_; // Mapa pre-calculado en constructor
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user