Files
ESP32_Serial_Swiss_Army_Knife/src/console_completion.c
T

245 lines
6.8 KiB
C

/* SPDX-License-Identifier: GPL-3.0-only */
/* Full-line linenoise completion for nested project console commands. */
#include "console_completion.h"
#include <stddef.h>
#include <string.h>
#include <unistd.h>
#include "esp_console.h"
#include "linenoise/linenoise.h"
/* Keep full-line candidate strings grouped by their registered root command. */
static const char *const s_completion_candidates[] = {
/* Hardware debug commands and safe fixed arguments. */
"debug transceiver",
"debug transceiver enable",
"debug transceiver disable",
"debug drivers",
"debug loopback-a",
"debug loopback-b",
"debug valid-test",
"debug uart-loopback",
"debug uart-suite",
"debug cts-flow-test",
"debug rts-flow-test",
"debug display",
"debug display status",
"debug display probe",
"debug display scan",
"debug display scan --force",
"debug display init",
"debug display init 0x3c",
"debug display init 0x78",
"debug display init 0x79",
"debug display init 0x3d",
"debug display init 0x7a",
"debug display init 0x7b",
"debug display off",
"debug display pattern",
"debug display pattern clear",
"debug display pattern fill",
"debug display pattern checker",
"debug display pattern grid",
"debug display pattern corners",
"debug display pattern layout",
"debug display row",
"debug display contrast",
"debug display invert",
"debug display invert on",
"debug display invert off",
"debug buttons",
"debug buttons status",
"debug buttons test",
/* Persistent local OLED aging settings. */
"display status",
"display set",
"display set dim-seconds",
"display set off-seconds",
"display save",
"display load",
"display defaults",
"display reset",
/* Serial service lifecycle, persistence, counters, and settings. */
"serial status",
"serial start",
"serial stop",
"serial set",
"serial set baud",
"serial set data-bits",
"serial set data-bits 7",
"serial set data-bits 8",
"serial set parity",
"serial set parity none",
"serial set parity even",
"serial set parity odd",
"serial set stop-bits",
"serial set stop-bits 1",
"serial set stop-bits 2",
"serial set flow",
"serial set flow none",
"serial set flow rts-cts",
"serial set dtr",
"serial set dtr inactive",
"serial set dtr active",
"serial set dtr on-connect",
"serial set rts-threshold",
"serial save",
"serial load",
"serial defaults",
"serial reset",
"serial counters",
"serial clear-counters",
/* Session broker inspection, ownership, and data operations. */
"broker status",
"broker clients",
"broker counters",
"broker clear-counters",
"broker connect",
"broker disconnect",
"broker request-writer",
"broker release-writer",
"broker force-writer",
"broker send-hex",
"broker read",
"broker events",
/* Native USB CDC status and writer ownership. */
"usb help",
"usb status",
"usb counters",
"usb clear-counters",
"usb request-writer",
"usb release-writer",
/* Physical role-based user, password, and SSH-key administration. */
"user status",
"user list",
"user show",
"user bootstrap",
"user bootstrap --generate",
"user recover --force",
"user add",
"user delete",
"user role",
"user password",
"user key add",
"user key delete",
"user key clear",
/* Wi-Fi lifecycle, persistence, profiles, AP policy, and diagnostics. */
"wifi status",
"wifi profiles",
"wifi counters",
"wifi clear-counters",
"wifi start",
"wifi stop",
"wifi reconnect",
"wifi save",
"wifi load",
"wifi defaults",
"wifi reset",
"wifi profile",
"wifi profile set",
"wifi profile secret",
"wifi profile enable",
"wifi profile disable",
"wifi profile delete",
"wifi ap",
"wifi ap policy",
"wifi ap policy off",
"wifi ap policy fallback",
"wifi ap policy always",
"wifi ap ssid",
"wifi ap channel",
"wifi ap secret",
"wifi ap show-secret",
"wifi ping",
"wifi nslookup",
"wifi traceroute",
/* Authenticated HTTPS lifecycle and physical-admin recovery operations. */
"web help",
"web status",
"web start",
"web stop",
"web counters",
"web clear-counters",
"web credentials",
"web credentials show",
"web credentials rotate",
"web credentials rotate --force",
"web certificate",
"web certificate info",
"web certificate rotate",
"web certificate rotate --force",
"web reset",
"web reset --force",
/* Authenticated SSH serial transport and independent host identity. */
"ssh help",
"ssh status",
"ssh start",
"ssh stop",
"ssh sessions",
"ssh disconnect",
"ssh counters",
"ssh clear-counters",
"ssh host-key",
"ssh host-key info",
"ssh host-key rotate",
"ssh host-key rotate --force",
"ssh reset",
"ssh reset --force",
};
static ssize_t console_read_with_late_terminal_upgrade(int file_descriptor,
void *buffer,
size_t size)
{
ssize_t received = read(file_descriptor, buffer, size);
if (received > 0 && linenoiseIsDumbMode()) {
/*
* The current line remains in the safe dumb reader. The next call to
* linenoise() starts enhanced mode only after a terminal has proven it
* can send data, so its cursor-position query cannot block unattended.
*/
linenoiseSetDumbMode(0);
}
return received;
}
static void console_completion_callback(const char *buffer, linenoiseCompletions *completions)
{
/* Preserve ESP-IDF completion for registered root command names. */
if (strchr(buffer, ' ') == NULL) {
esp_console_get_completion(buffer, completions);
return;
}
const size_t buffer_length = strlen(buffer);
for (size_t index = 0;
index < sizeof(s_completion_candidates) / sizeof(s_completion_candidates[0]);
++index) {
const char *const candidate = s_completion_candidates[index];
const size_t candidate_length = strlen(candidate);
/* linenoise expects the complete replacement line, not only its suffix. */
if (candidate_length > buffer_length &&
strncmp(candidate, buffer, buffer_length) == 0) {
linenoiseAddCompletion(completions, candidate);
}
}
}
void console_completion_install(void)
{
/* Preserve ESP-IDF's safe boot-time mode until actual UART input arrives. */
linenoiseSetReadFunction(&console_read_with_late_terminal_upgrade);
linenoiseSetCompletionCallback(&console_completion_callback);
}