Share completion and add SSH line editing

This commit is contained in:
2026-08-30 22:45:58 +02:00
parent 2f383cd283
commit 21d1b12f31
5 changed files with 180 additions and 60 deletions
+57 -44
View File
@@ -7,7 +7,6 @@
#include <string.h>
#include <unistd.h>
#include "esp_console.h"
#include "linenoise/linenoise.h"
static const char *const s_root_candidates[] = {
@@ -144,6 +143,7 @@ static const char *const s_completion_candidates[] = {
"wifi start",
"wifi stop",
"wifi reconnect",
"wifi next-profile",
"wifi save",
"wifi load",
"wifi defaults",
@@ -202,10 +202,12 @@ static const char *const s_completion_candidates[] = {
"ssh reset --force",
};
bool console_completion_expand(const char *line, char *completed, size_t capacity)
void console_completion_visit(const char *line,
console_completion_visitor_t visitor,
void *context)
{
if (line == NULL || completed == NULL || capacity == 0U) {
return false;
if (line == NULL || visitor == NULL) {
return;
}
size_t line_length = strlen(line);
const char *const *candidates = strchr(line, ' ') == NULL
@@ -215,33 +217,56 @@ bool console_completion_expand(const char *line, char *completed, size_t capacit
? sizeof(s_root_candidates) / sizeof(s_root_candidates[0])
: sizeof(s_completion_candidates) /
sizeof(s_completion_candidates[0]);
const char *first = NULL;
size_t common_length = 0U;
for (size_t index = 0U; index < candidate_count; ++index) {
const char *candidate = candidates[index];
if (strncmp(candidate, line, line_length) != 0) {
continue;
if (strlen(candidate) > line_length &&
strncmp(candidate, line, line_length) == 0 &&
!visitor(candidate, context)) {
return;
}
if (first == NULL) {
first = candidate;
common_length = strlen(candidate);
continue;
}
size_t candidate_length = strlen(candidate);
if (common_length > candidate_length) {
common_length = candidate_length;
}
size_t offset = line_length;
while (offset < common_length && first[offset] == candidate[offset]) {
++offset;
}
common_length = offset;
}
if (first == NULL || common_length <= line_length || common_length >= capacity) {
}
typedef struct {
const char *line;
const char *first;
size_t common_length;
} completion_expand_context_t;
static bool collect_common_prefix(const char *candidate, void *context)
{
completion_expand_context_t *result = context;
if (result->first == NULL) {
result->first = candidate;
result->common_length = strlen(candidate);
return true;
}
size_t candidate_length = strlen(candidate);
if (result->common_length > candidate_length) {
result->common_length = candidate_length;
}
size_t offset = strlen(result->line);
while (offset < result->common_length && result->first[offset] == candidate[offset]) {
++offset;
}
result->common_length = offset;
return true;
}
bool console_completion_expand(const char *line, char *completed, size_t capacity)
{
if (line == NULL || completed == NULL || capacity == 0U) {
return false;
}
memcpy(completed, first, common_length);
completed[common_length] = '\0';
completion_expand_context_t result = {.line = line};
console_completion_visit(line, collect_common_prefix, &result);
size_t line_length = strlen(line);
if (result.first == NULL || result.common_length <= line_length ||
result.common_length >= capacity) {
return false;
}
memcpy(completed, result.first, result.common_length);
completed[result.common_length] = '\0';
return true;
}
@@ -261,27 +286,15 @@ static ssize_t console_read_with_late_terminal_upgrade(int file_descriptor,
return received;
}
static bool add_linenoise_completion(const char *candidate, void *context)
{
linenoiseAddCompletion(context, candidate);
return true;
}
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);
}
}
console_completion_visit(buffer, add_linenoise_completion, completions);
}
void console_completion_install(void)