feat: Introduce Autocomplete Engine and TUI for enhanced command input and suggestions

- Added `AutocompleteEngine` class for managing command and parameter suggestions with fuzzy matching.
- Implemented TUI components for an interactive command input interface with real-time suggestions.
- Enhanced user experience with a quick action menu for common tasks related to ROM manipulation.
- Established a structured approach for contextual help based on user input, improving command discoverability.
This commit is contained in:
scawful
2025-10-05 01:45:56 -04:00
parent 7712456154
commit 9f119abba7
3 changed files with 268 additions and 0 deletions

View File

@@ -0,0 +1,92 @@
#include "cli/util/autocomplete.h"
#include <algorithm>
#include <cctype>
namespace yaze {
namespace cli {
void AutocompleteEngine::RegisterCommand(const std::string& cmd, const std::string& desc,
const std::vector<std::string>& examples) {
CommandDef def;
def.name = cmd;
def.description = desc;
def.examples = examples;
commands_.push_back(def);
}
void AutocompleteEngine::RegisterParameter(const std::string& param, const std::string& desc,
const std::vector<std::string>& values) {
// TODO: Store parameter definitions
}
int AutocompleteEngine::FuzzyScore(const std::string& text, const std::string& query) {
if (query.empty()) return 0;
std::string t = text, q = query;
std::transform(t.begin(), t.end(), t.begin(), ::tolower);
std::transform(q.begin(), q.end(), q.begin(), ::tolower);
if (t == q) return 1000;
if (t.find(q) == 0) return 500;
if (t.find(q) != std::string::npos) return 250;
// Fuzzy char matching
size_t ti = 0, qi = 0;
int score = 0;
while (ti < t.length() && qi < q.length()) {
if (t[ti] == q[qi]) {
score += 10;
qi++;
}
ti++;
}
return (qi == q.length()) ? score : 0;
}
std::vector<Suggestion> AutocompleteEngine::GetSuggestions(const std::string& input) {
std::vector<Suggestion> results;
for (const auto& cmd : commands_) {
int score = FuzzyScore(cmd.name, input);
if (score > 0) {
Suggestion s;
s.text = cmd.name;
s.description = cmd.description;
s.example = cmd.examples.empty() ? "" : cmd.examples[0];
s.score = score;
results.push_back(s);
}
}
std::sort(results.begin(), results.end(),
[](const Suggestion& a, const Suggestion& b) {
return a.score > b.score;
});
return results;
}
std::vector<Suggestion> AutocompleteEngine::GetContextualHelp(const std::string& partial_cmd) {
std::vector<Suggestion> help;
// Parse command and suggest parameters
if (partial_cmd.find("hex-") == 0) {
help.push_back({"--address=0xXXXXXX", "ROM address in hex", ""});
help.push_back({"--length=16", "Number of bytes", ""});
help.push_back({"--format=both", "Output format (hex/ascii/both)", ""});
} else if (partial_cmd.find("palette-") == 0) {
help.push_back({"--group=0", "Palette group (0-7)", ""});
help.push_back({"--palette=0", "Palette index (0-7)", ""});
help.push_back({"--format=hex", "Color format (snes/rgb/hex)", ""});
} else if (partial_cmd.find("dungeon-") == 0) {
help.push_back({"--room_id=5", "Room ID (0-296)", ""});
help.push_back({"--include_sprites=true", "Include sprite data", ""});
}
return help;
}
} // namespace cli
} // namespace yaze

View File

@@ -0,0 +1,49 @@
#ifndef YAZE_CLI_UTIL_AUTOCOMPLETE_H_
#define YAZE_CLI_UTIL_AUTOCOMPLETE_H_
#include <string>
#include <vector>
#include <functional>
namespace yaze {
namespace cli {
struct Suggestion {
std::string text;
std::string description;
std::string example;
int score;
};
class AutocompleteEngine {
public:
void RegisterCommand(const std::string& cmd, const std::string& desc,
const std::vector<std::string>& examples = {});
void RegisterParameter(const std::string& param, const std::string& desc,
const std::vector<std::string>& values = {});
std::vector<Suggestion> GetSuggestions(const std::string& input);
std::vector<Suggestion> GetContextualHelp(const std::string& partial_cmd);
void SetRomContext(bool has_rom) { has_rom_ = has_rom; }
private:
struct CommandDef {
std::string name;
std::string description;
std::vector<std::string> params;
std::vector<std::string> examples;
};
std::vector<CommandDef> commands_;
bool has_rom_ = false;
int FuzzyScore(const std::string& text, const std::string& query);
};
} // namespace cli
} // namespace yaze
#endif // YAZE_CLI_UTIL_AUTOCOMPLETE_H_