Add basic console tab completion

pull/185/head
Jonathan G Rennison 4 years ago
parent 138a7c2d90
commit 37ee095f4a

@ -154,6 +154,7 @@ static inline void IConsoleResetHistoryPos()
static const char *IConsoleHistoryAdd(const char *cmd);
static void IConsoleHistoryNavigate(int direction);
static void IConsoleTabCompletion();
static const struct NWidgetPart _nested_console_window_widgets[] = {
NWidget(WWT_EMPTY, INVALID_COLOUR, WID_C_BACKGROUND), SetResize(1, 1),
@ -299,6 +300,10 @@ struct IConsoleWindow : Window
IConsoleCmdExec("clear");
break;
case WKC_TAB:
IConsoleTabCompletion();
break;
default:
if (_iconsole_cmdline.HandleKeyPress(key, keycode) != HKPR_NOT_HANDLED) {
IConsoleWindow::scroll = 0;
@ -494,6 +499,69 @@ static void IConsoleHistoryNavigate(int direction)
}
}
static void IConsoleTabCompletion()
{
const char *input = _iconsole_cmdline.buf;
/* Strip all spaces at the beginning */
while (IsWhitespace(*input)) input++;
/* Don't do tab completion for no input */
if (StrEmpty(input)) return;
const char *cmdptr = input;
for (; *cmdptr != '\0'; cmdptr++) {
switch (*cmdptr) {
case ' ':
case '"':
case '\\':
// Give up
return;
}
}
size_t length = cmdptr - input;
char *prefix = (char*)alloca(length + 1);
strecpy(prefix, input, prefix + length);
RemoveUnderscores(prefix);
size_t prefix_length = strlen(prefix);
if (prefix_length == 0) return;
char buffer[4096];
char *b = buffer;
uint matches = 0;
std::string common_prefix;
for (const IConsoleCmd *cmd = _iconsole_cmds; cmd != nullptr; cmd = cmd->next) {
if (strncmp(cmd->name, prefix, prefix_length) == 0) {
if ((_settings_client.gui.console_show_unlisted || !cmd->unlisted) && (cmd->hook == nullptr || cmd->hook(false) != CHR_HIDE)) {
if (matches == 0) {
common_prefix = cmd->name;
} else {
const char *cp = common_prefix.c_str();
const char *cmdp = cmd->name;
while (true) {
const char *end = cmdp;
WChar a = Utf8Consume(cp);
WChar b = Utf8Consume(cmdp);
if (a == 0 || b == 0 || a != b) {
common_prefix.resize(end - cmd->name);
break;
}
}
}
matches++;
b += seprintf(b, lastof(buffer), "%s ", cmd->name);
}
}
}
if (matches > 0) {
_iconsole_cmdline.Assign(common_prefix.c_str());
if (matches > 1) {
IConsolePrint(CC_WHITE, buffer);
}
}
}
/**
* Handle the printing of text entered into the console or redirected there
* by any other means. Text can be redirected to other clients in a network game

Loading…
Cancel
Save