Replace the single file-structure.md with a stratified layout designed
for AI/agent skill consumption: tables and concrete identifiers over
prose, files loaded on demand, content separated by churn rate.
Layers:
- architecture/ stable structural reference (overview, source-map,
test-map, data-flow)
- patterns/ memory, commands, autocomplete, events, xmpp,
encryption, ui, plugins
- testing/ unit-tests, stubs, functional-tests, bench
- build/ local, docker, ci
- playbooks/ add-command, add-test, add-autocomplete,
add-event-handler, add-encryption
- gotchas.md append-only dated entries (seven seed entries)
- wip/ branch-specific notes; deleted on merge to master
Stable layers describe cproof on master only. In-flight feature
branches (currently feat/ai) get a single file under wip/.
INDEX.md is the entry map with churn labels; SKILL.md is the
always-loaded skill hint pointing to it.
3.8 KiB
3.8 KiB
Commands
Three files, three concerns
| File | Holds |
|---|---|
src/command/cmd_defs.c (cmd_defs.h) |
The big static array of Command records — every /foo is one entry. |
src/command/cmd_funcs.c (cmd_funcs.h) |
Handler implementations: gboolean cmd_<name>(ProfWin*, const char* const, gchar**). |
src/command/cmd_ac.c (cmd_ac.h) |
Per-command autocomplete logic and registration. |
Anatomy of a command record
Defined inline in cmd_defs.c using uppercase macros (declared in cmd_defs.c):
{ CMD_PREAMBLE("/caps",
parse_args, 0, 1, NULL)
CMD_MAINFUNC(cmd_caps)
CMD_TAGS(
CMD_TAG_DISCOVERY,
CMD_TAG_CHAT,
CMD_TAG_GROUPCHAT)
CMD_SYN(
"/caps",
"/caps <fulljid>|<nick>")
CMD_DESC("...")
CMD_ARGS(
{ "<fulljid>", "..." },
{ "<nick>", "..." })
CMD_EXAMPLES(
"/caps user@host/res")
}
| Macro | Role |
|---|---|
CMD_PREAMBLE(name, parse_fn, min, max, pre_hook) |
Command name, parser, arg count bounds, optional pre-hook. |
CMD_MAINFUNC(fn) |
Single handler for the whole command. |
CMD_SUBFUNCS({"sub", fn}, ...) |
Dispatch by first argument. Use instead of CMD_MAINFUNC when the command has subcommands (e.g. /status get, /status set). |
CMD_TAGS(...) |
One or more CMD_TAG_* (UI grouping, search). |
CMD_SYN(...) |
Synopsis lines for /help <cmd>. |
CMD_DESC(...) |
Long description. |
CMD_ARGS({"name", "desc"}, ...) |
Argument table for help. |
CMD_EXAMPLES(...) |
Examples shown in help. |
The full set of CMD_* macro definitions is at the top of cmd_defs.c —
read them when authoring a new command.
Argument parsing
parse_args() lives in src/tools/parser.c:
gchar** parse_args(const char* const inp, int min, int max, gboolean* result);
- Splits on whitespace, honours quoted segments.
- Returns
NULLon parse failure (sets*result = FALSE). - The handler receives the result as
gchar** args— free is owned by the caller incmd_defs.c, the handler does not free.
Parser variants used in CMD_PREAMBLE:
parse_args— standard quoted-aware split.parse_args_with_freetext— last argument is the rest of the line, no splitting (used by/msg,/me, etc.).parse_args_as_one— concatenates remaining tokens into a single string.
Handler signature
gboolean cmd_foo(ProfWin* window, const char* const command, gchar** args);
Return TRUE on success, FALSE to print bad-usage. command is the literal
/foo typed (useful when the same handler is registered under multiple names).
Connection-state gates
Most commands that touch XMPP must verify connection state first:
if (connection_get_status() != JABBER_CONNECTED) {
cons_show("You are not currently connected.");
return TRUE;
}
cons_bad_cmd_usage(cmd) is the canonical "wrong arguments" path; pass the
literal command name.
Adding a new command
See playbooks/add-command.md for the full walkthrough. Short version:
- New entry in
cmd_defs.cwithCMD_PREAMBLE/CMD_MAINFUNC/... - Implement
cmd_<name>()incmd_funcs.c(declare incmd_funcs.h). - (If autocompletion needed) implement
_<name>_autocomplete()incmd_ac.cand register it viag_hash_table_insert(ac_funcs, "/name", ...). - Add a unit test pair
tests/unittests/test_cmd_<name>.{c,h}and register tests intests/unittests/unittests.c.
Conventions
cmd_<name>for handlers;_<name>_autocomplete(file-static) for the autocomplete callback.- Subcommand dispatch via
CMD_SUBFUNCSis preferred overif/elsechains insidecmd_<name>when possible. - Keep handlers in
cmd_funcs.cthin: parse & validate args, then delegate to a domain module (xmpp/,config/,ui/).