# Autocomplete ## The `Autocomplete` type `src/tools/autocomplete.h` defines an opaque `Autocomplete` (GList-backed sorted set with a stateful "current iterator" for cycling through matches). | Function | Purpose | |---|---| | `autocomplete_new()` | Create empty AC. | | `autocomplete_clear(ac)` | Drop all entries (keep object). | | `autocomplete_free(ac)` | Destroy. | | `autocomplete_add(ac, item)` | Insert sorted. | | `autocomplete_add_unsorted(ac, item, reversed)` | Append, no sort. | | `autocomplete_add_all(ac, items)` | Bulk add from `char**`. | | `autocomplete_update(ac, items)` | Clear + add_all. | | `autocomplete_remove(ac, item)` | Drop one. | | `autocomplete_remove_all(ac, items)` | Drop many. | | `autocomplete_complete(ac, search, quote, previous)` | Cycle to next/previous match. | | `autocomplete_reset(ac)` | Reset cycle position. | | `autocomplete_contains(ac, value)` | Membership. | ## Two completion flavours used in commands In `src/command/cmd_ac.c`: ```c autocomplete_param_with_ac(input, "/cmd sub", static_ac, quote, previous); autocomplete_param_with_func(input, "/cmd sub", callback, previous, ctx); ``` | When to use | Choose | |---|---| | Fixed token set known at startup. | `autocomplete_param_with_ac` + a static `Autocomplete` (allocated in `cmd_ac_init`, freed in `cmd_ac_uninit`). | | Token set is dynamic / queried from state. | `autocomplete_param_with_func` + a callback `char* fn(const char* search, gboolean previous, void* ctx)`. | ## Static Autocompletes Pattern (from `cmd_ac.c`): ```c // File-scope: static Autocomplete account_ac; // In cmd_ac_init(): account_ac = autocomplete_new(); autocomplete_add(account_ac, "list"); autocomplete_add(account_ac, "show"); autocomplete_add(account_ac, "add"); // ... // Registered with: g_hash_table_insert(ac_funcs, "/account", _account_autocomplete); ``` Static `Autocomplete` instances are added to a file-scope free-list array near the top of `cmd_ac.c` so `cmd_ac_uninit` can call `autocomplete_free` on each at shutdown. **Add new static ACs to that free-list.** ## Function-callback completers ```c char* roster_contact_autocomplete(const char* const search_str, gboolean previous, void* context); ``` - Stateless across invocations — no module-level `_last_match` globals. - Returns a freshly-allocated `char*` (caller frees), or `NULL` when no more matches. - `previous` cycles backward (Shift+Tab). - `context` is whatever was passed in `autocomplete_param_with_func`'s last arg (often `NULL`). `roster_contact_autocomplete` (`src/xmpp/roster_list.c`) is a clean canonical example: it delegates straight to `autocomplete_complete` against a roster-owned `Autocomplete` object — no callback-local state. **Avoid the legacy "store previous match in a static" pattern.** Some older completers do it; do not copy them. Keeping callbacks stateless makes shift-tab cycling and concurrent completers safe. ## Per-command dispatcher Every command's autocomplete is a single static function in `cmd_ac.c`: ```c static char* _account_autocomplete(ProfWin* window, const char* const input, gboolean previous); ``` Registered in `cmd_ac_init`: ```c g_hash_table_insert(ac_funcs, "/account", _account_autocomplete); ``` The dispatcher inspects the input prefix and picks the right `autocomplete_param_with_*` call.