feat: improve autocomplete for JIDs #167

Open
jabber.developer wants to merge 2 commits from feat/disco-ac into master

Resolves #164

Resolves #164
jabber.developer added 2 commits 2026-07-11 17:19:17 +00:00
Introduce _resolve_contact_jid helper to convert contact names to JIDs.
Apply this helper to /caps, /software, /disco, /lastactivity, and /ping
commands, allowing users to specify contacts by name instead of full JIDs.

Enhance command-line autocomplete by adding _disco_autocomplete and
_roster_jid_autocomplete functions. Update /caps autocomplete to utilize
the new roster resolution logic and ensure it only returns results when
connected.
fix(autocomplete): guard history completion safely
All checks were successful
CI Code / Check spelling (pull_request) Successful in 12s
CI Code / Check coding style (pull_request) Successful in 23s
CI Code / Code Coverage (pull_request) Successful in 3m40s
CI Code / Linux (debian) (pull_request) Successful in 5m14s
CI Code / Linux (ubuntu) (pull_request) Successful in 5m20s
CI Code / Linux (arch) (pull_request) Successful in 7m23s
b7dec705c3
Prevent autocomplete crashes on asset failures when executing history subcommands without an active connection by validating the session state beforehand. Standardize JID resolution across command handlers to ensure consistent contact lookup behavior.

Use auto_gchar gchar instead of GString for performance and readability purposes.
Collaborator

Nice cleanup — folding the scattered contact/barejid/fulljid completion into _roster_jid_autocomplete, and the nickname→JID conversion into _resolve_contact_jid, reads well and seems to cover what #164 asks for. The _resolve_contact_jid ownership looks fine too: roster_barejid_from_name() returns a borrowed pointer into the roster table (and the fallback returns the caller's name), so nothing there needs freeing.

One thing that might be worth a second look: _roster_jid_autocomplete seems to be called with the raw input, whereas the /msg path that #164 points at as the reference strips quotes first and passes unquoted:

// /msg in _cmd_ac_complete_params
char* unquoted = strip_arg_quotes(input);
result = autocomplete_param_with_func(unquoted, contact_choices[i], roster_contact_autocomplete, ...);
result = autocomplete_param_with_func(unquoted, contact_choices[i], roster_barejid_autocomplete, ...);

The new helper, as used in _win_autocomplete, _vcard_autocomplete (roster branch) and _status_autocomplete (/status get), gets input instead:

char* unquoted = strip_arg_quotes(input);
result = _roster_jid_autocomplete(input, "/win", previous);   // input, not unquoted
free(unquoted);

If that reading is right, a couple of things seem to follow:

  • Those sites previously stripped quotes before matching, so contact names entered with quotes (names containing spaces) might no longer complete against the roster — a small behavior change versus before, and also a divergence from the /msg pattern #164 holds up as the standard.
  • In _win_autocomplete and the _vcard_autocomplete roster branch, unquoted now appears to be computed and freed without being used anywhere — harmless at runtime, but a bit misleading (and it wouldn't trip -Wunused, since it's still passed to free()).

Perhaps the cleanest option would be to strip quotes once inside _roster_jid_autocomplete and drop the now-redundant local unquoted at the call sites that only kept it for that. That would line the helper up with /msg and remove the dead locals in one go, which seems in keeping with the "standardize" goal of the issue.

A few smaller things, likely intentional but maybe worth confirming:

  • /history verify|export|import <jid> completion now sits behind a JABBER_CONNECTED check. Since /history works against the local DB offline, tab-completing a past contact's JID while disconnected wouldn't work anymore. The roster is empty offline anyway, so the practical effect may be nil — just flagging in case offline completion was expected.
  • _invite_autocomplete seems to now run the /invite decline (muc_invites_find) completion unconditionally, where it used to be inside the connected branch. That looks harmless for local invite state, possibly even more correct, but it is a change in when it fires.
  • Very minor: _resolve_contact_jid returns const gchar* after a (char*)name cast, which can read as if it owns something. A one-line note that it returns a borrowed roster/arg pointer (not to be freed) might save a future reader a double-take.

Overall the core of #164 looks handled; the input vs `unquo

Nice cleanup — folding the scattered contact/barejid/fulljid completion into `_roster_jid_autocomplete`, and the nickname→JID conversion into `_resolve_contact_jid`, reads well and seems to cover what #164 asks for. The `_resolve_contact_jid` ownership looks fine too: `roster_barejid_from_name()` returns a borrowed pointer into the roster table (and the fallback returns the caller's `name`), so nothing there needs freeing. One thing that might be worth a second look: `_roster_jid_autocomplete` seems to be called with the raw `input`, whereas the `/msg` path that #164 points at as the reference strips quotes first and passes `unquoted`: ```c // /msg in _cmd_ac_complete_params char* unquoted = strip_arg_quotes(input); result = autocomplete_param_with_func(unquoted, contact_choices[i], roster_contact_autocomplete, ...); result = autocomplete_param_with_func(unquoted, contact_choices[i], roster_barejid_autocomplete, ...); ``` The new helper, as used in `_win_autocomplete`, `_vcard_autocomplete` (roster branch) and `_status_autocomplete` (`/status get`), gets `input` instead: ```c char* unquoted = strip_arg_quotes(input); result = _roster_jid_autocomplete(input, "/win", previous); // input, not unquoted free(unquoted); ``` If that reading is right, a couple of things seem to follow: - Those sites previously stripped quotes before matching, so contact names entered with quotes (names containing spaces) might no longer complete against the roster — a small behavior change versus before, and also a divergence from the `/msg` pattern #164 holds up as the standard. - In `_win_autocomplete` and the `_vcard_autocomplete` roster branch, `unquoted` now appears to be computed and freed without being used anywhere — harmless at runtime, but a bit misleading (and it wouldn't trip `-Wunused`, since it's still passed to `free()`). Perhaps the cleanest option would be to strip quotes once *inside* `_roster_jid_autocomplete` and drop the now-redundant local `unquoted` at the call sites that only kept it for that. That would line the helper up with `/msg` and remove the dead locals in one go, which seems in keeping with the "standardize" goal of the issue. A few smaller things, likely intentional but maybe worth confirming: - `/history verify|export|import <jid>` completion now sits behind a `JABBER_CONNECTED` check. Since `/history` works against the local DB offline, tab-completing a past contact's JID while disconnected wouldn't work anymore. The roster is empty offline anyway, so the practical effect may be nil — just flagging in case offline completion was expected. - `_invite_autocomplete` seems to now run the `/invite decline` (`muc_invites_find`) completion unconditionally, where it used to be inside the connected branch. That looks harmless for local invite state, possibly even more correct, but it is a change in when it fires. - Very minor: `_resolve_contact_jid` returns `const gchar*` after a `(char*)name` cast, which can read as if it owns something. A one-line note that it returns a borrowed roster/arg pointer (not to be freed) might save a future reader a double-take. Overall the core of #164 looks handled; the `input` vs `unquo
All checks were successful
CI Code / Check spelling (pull_request) Successful in 12s
Required
Details
CI Code / Check coding style (pull_request) Successful in 23s
Required
Details
CI Code / Code Coverage (pull_request) Successful in 3m40s
Required
Details
CI Code / Linux (debian) (pull_request) Successful in 5m14s
Required
Details
CI Code / Linux (ubuntu) (pull_request) Successful in 5m20s
Required
Details
CI Code / Linux (arch) (pull_request) Successful in 7m23s
Required
Details
This pull request is blocked because it's outdated.
This branch is out-of-date with the base branch
You are not authorized to merge this pull request.
View command line instructions

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u origin feat/disco-ac:feat/disco-ac
git checkout feat/disco-ac
Sign in to join this conversation.
No description provided.