refactor(ai): flatten autocomplete into sequential prefix-matching chain
Some checks failed
CI Code / Check spelling (pull_request) Successful in 1m5s
CI Code / Check coding style (pull_request) Successful in 2m7s
CI Code / Linux (arch) (pull_request) Failing after 3m9s
CI Code / Code Coverage (pull_request) Successful in 2m54s
CI Code / Linux (debian) (pull_request) Successful in 4m28s
CI Code / Linux (ubuntu) (pull_request) Successful in 4m41s
Some checks failed
CI Code / Check spelling (pull_request) Successful in 1m5s
CI Code / Check coding style (pull_request) Successful in 2m7s
CI Code / Linux (arch) (pull_request) Failing after 3m9s
CI Code / Code Coverage (pull_request) Successful in 2m54s
CI Code / Linux (debian) (pull_request) Successful in 4m28s
CI Code / Linux (ubuntu) (pull_request) Successful in 4m41s
Replace the deeply nested conditional tree in _ai_autocomplete() with a flat sequential chain of autocomplete_param_with_*() calls. Each call tries a specific command prefix (e.g., "/ai set provider", "/ai start") and returns immediately on match — a common, reliable pattern for command-line tab completion. The previous design nested provider-name autocomplete inside g_strv_length() and g_strcmp0() checks, meaning /ai<tab> and /ai <tab> would never reach the subcommand matcher. The new flat structure ensures every prefix is tried in order, with the most specific prefixes first and the generic /ai subcommand fallback last. This pattern — sequential prefix matching with early return — is the standard approach for autocomplete dispatch: each handler owns its prefix, no shared state or argument parsing is needed, and adding a new subcommand is a single append to the chain.
This commit is contained in:
@@ -4445,84 +4445,61 @@ static char*
|
||||
_ai_autocomplete(ProfWin* window, const char* const input, gboolean previous)
|
||||
{
|
||||
char* result = NULL;
|
||||
gboolean parsed = FALSE;
|
||||
|
||||
auto_gcharv gchar** args = parse_args(input, 0, 3, &parsed);
|
||||
|
||||
if (parsed) {
|
||||
int num_args = g_strv_length(args);
|
||||
|
||||
/* Top-level /ai <subcommand> autocomplete (e.g., /ai s<tab> -> /ai set) */
|
||||
if (num_args >= 1) {
|
||||
if (g_strcmp0(args[0], "set") == 0) {
|
||||
if (num_args >= 2) {
|
||||
if (g_strcmp0(args[1], "provider") == 0) {
|
||||
// /ai set provider <name> <url> - autocomplete provider names
|
||||
result = autocomplete_param_with_func(input, "/ai set provider", ai_providers_find, previous, NULL);
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
} else if (g_strcmp0(args[1], "token") == 0) {
|
||||
// /ai set token <provider> <token> - autocomplete provider names
|
||||
result = autocomplete_param_with_func(input, "/ai set token", ai_providers_find, previous, NULL);
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
} else if (g_strcmp0(args[1], "org") == 0) {
|
||||
// /ai set org <provider> <org_id> - autocomplete provider names
|
||||
result = autocomplete_param_with_func(input, "/ai set org", ai_providers_find, previous, NULL);
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
// /ai set <subcommand> - autocomplete subcommands
|
||||
result = autocomplete_param_with_ac(input, "/ai set", ai_set_subcommands_ac, TRUE, previous);
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
} else if (g_strcmp0(args[0], "remove") == 0) {
|
||||
if (num_args >= 2 && g_strcmp0(args[1], "provider") == 0) {
|
||||
// /ai remove provider <name> - autocomplete provider names
|
||||
result = autocomplete_param_with_func(input, "/ai remove provider", ai_providers_find, previous, NULL);
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
} else {
|
||||
result = autocomplete_param_with_ac(input, "/ai remove", ai_remove_subcommands_ac, TRUE, previous);
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
} else if (g_strcmp0(args[0], "start") == 0) {
|
||||
// /ai start [<provider>/<model>] - autocomplete provider names
|
||||
result = autocomplete_param_with_func(input, "/ai start", ai_providers_find, previous, NULL);
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
} else if (g_strcmp0(args[0], "clear") == 0) {
|
||||
// /ai clear [<provider>] - autocomplete provider names
|
||||
result = autocomplete_param_with_func(input, "/ai clear", ai_providers_find, previous, NULL);
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
} else if (g_strcmp0(args[0], "correct") == 0) {
|
||||
// /ai correct <provider> <text>
|
||||
result = autocomplete_param_with_func(input, "/ai correct", ai_providers_find, previous, NULL);
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
} else if (g_strcmp0(args[0], "providers") == 0) {
|
||||
// /ai providers - no subcommands
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
result = autocomplete_param_with_ac(input, "/ai", ai_subcommands_ac, FALSE, previous);
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
/* Top-level /ai <subcommand> autocomplete (e.g., /ai s<tab> -> /ai set) */
|
||||
result = autocomplete_param_with_func(input, "/ai set provider", ai_providers_find, previous, NULL);
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
|
||||
// /ai set token <provider> <token> - autocomplete provider names
|
||||
result = autocomplete_param_with_func(input, "/ai set token", ai_providers_find, previous, NULL);
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
|
||||
// /ai set org <provider> <org_id> - autocomplete provider names
|
||||
result = autocomplete_param_with_func(input, "/ai set org", ai_providers_find, previous, NULL);
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
|
||||
// /ai set <subcommand> - autocomplete subcommands
|
||||
result = autocomplete_param_with_ac(input, "/ai set", ai_set_subcommands_ac, TRUE, previous);
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
|
||||
// /ai remove provider <name> - autocomplete provider names
|
||||
result = autocomplete_param_with_func(input, "/ai remove provider", ai_providers_find, previous, NULL);
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
|
||||
result = autocomplete_param_with_ac(input, "/ai remove", ai_remove_subcommands_ac, TRUE, previous);
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
|
||||
// /ai start [<provider>/<model>] - autocomplete provider names
|
||||
result = autocomplete_param_with_func(input, "/ai start", ai_providers_find, previous, NULL);
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
|
||||
// /ai clear [<provider>] - autocomplete provider names
|
||||
result = autocomplete_param_with_func(input, "/ai clear", ai_providers_find, previous, NULL);
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
|
||||
// /ai correct <provider> <text>
|
||||
result = autocomplete_param_with_func(input, "/ai correct", ai_providers_find, previous, NULL);
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
|
||||
result = autocomplete_param_with_ac(input, "/ai", ai_subcommands_ac, FALSE, previous);
|
||||
|
||||
return result;
|
||||
}
|
||||
Reference in New Issue
Block a user