Skip to content

feat(cli): implement dynamic runtime completions for plugins - #3876

Merged
ItsLemmy merged 2 commits into
noctalia-dev:mainfrom
oldirtty:feat/dynamic-plugins-completions
Aug 15, 2026
Merged

feat(cli): implement dynamic runtime completions for plugins#3876
ItsLemmy merged 2 commits into
noctalia-dev:mainfrom
oldirtty:feat/dynamic-plugins-completions

Conversation

@oldirtty

Copy link
Copy Markdown
Contributor

Summary

Added a runtimeProvider field to the Positional schema. This allows the completion generators (bash, zsh, fish) to inject shell functions that fetch choices dynamically at runtime.

Implemented this specifically for plugins by adding plugins_enabled and plugins_disabled providers, hooking them into msg plugins enable, msg plugins disable, and msg plugin <entry>.

Motivation

Typing out long author/plugin names by hand is tedious, and it's hard to remember all the exact names off the top of your head. Initially, I just wanted to implement this for the msg plugin command so that hitting <TAB> would only suggest currently enabled plugins. However, I realized the other commands could easily make use of this too, like msg plugins disable (shows only enabled plugins) and msg plugins enable (shows only disabled plugins).

Type of Change

  • Bug fix
  • New feature
  • Breaking change
  • Refactoring
  • Build / packaging

Related Issue

None

Testing

  • Generated and sourced completions for bash, zsh, and fish.
  • Tested noctalia msg plugins disable <TAB> and verified it only lists enabled plugins.
  • Tested noctalia msg plugins enable <TAB> and verified it only lists disabled plugins.
  • Tested noctalia msg plugin <TAB> to ensure the runtime provider triggers correctly on subcommands.
  • ran just format and just test

Manual Coverage

  • Tested on Niri
  • Tested on Hyprland
  • Tested on Sway
  • Tested on another compositor:
  • Tested with different bar positions and density settings
  • Tested at different interface scaling values
  • Tested with multiple monitors

Screenshots / Videos

image

Checklist

  • This PR is ready for review, or it is marked as Draft.
  • I read and followed the relevant guidance in CONTRIBUTING.md.
  • I ran just format with clang-format v22+ installed, or this PR has no code changes.
  • I ran the relevant build or test commands, or explained why they were not run.
  • I self-reviewed the changes.
  • I checked for new warnings or errors.
  • I will update end-user documentation after merge, or this PR does not change user-facing configuration or behavior.
  • I added or updated assets/translations/en.json, or this PR adds no new user-facing strings.
  • I did not edit non-English translation files unless this PR is explicitly for translation tooling, an import/export sync, or a maintainer-requested locale change.
  • I used the existing canonical names for config keys, IPC names, paths, and identifiers.

Additional Notes

The runtimeProvider is can be extensible. If we ever want to add dynamic completions other type of commands in the future, we just need to drop a new provider tag in the schema and add a quick shell function in completions.cpp.

@ItsLemmy

Copy link
Copy Markdown
Collaborator
  1. [P1] msg plugin completes an invalid entry ID — src/cli/schema_msg.h:175-176
    The positional requires author/plugin:entry, but plugins_enabled emits only $1 from
    plugins list, which is author/plugin (src/cli/completions.cpp:214, :361, :503). The IPC
    router performs exact entry-ID matching, so the completed value cannot identify an
    endpoint.

Reproduced with generated Bash and Fish completions:

noctalia msg plugin ali<TAB>
# becomes:
noctalia msg plugin alice/clock 

Both shells append a space, preventing continuation with :entry. Add a provider that
returns concrete enabled entry IDs. If only plugin-prefix completion is intended, emit
author/plugin: and suppress the trailing separator in Bash, Zsh, and Fish.

  1. [P1] Changed file fails required clang-tidy — src/cli/completions.cpp:421-422
std::replace(safeName.begin(), safeName.end(), ':', '-');

This triggers modernize-use-ranges, which is enabled and treated as an error:

error: use a ranges version of this algorithm

Use:

std::ranges::replace(safeName, ':', '-');

This matches the PR’s failed CI state: build and tests passed; lint failed.

@ItsLemmy
ItsLemmy marked this pull request as draft August 15, 2026 04:07
@oldirtty
oldirtty force-pushed the feat/dynamic-plugins-completions branch from 704b7c6 to 6931bef Compare August 15, 2026 05:21
@oldirtty
oldirtty marked this pull request as ready for review August 15, 2026 05:24
@oldirtty

Copy link
Copy Markdown
Contributor Author

Thanks for the thorough review! Just pushed the fixes. Let me know if everything looks good now.

image

@ItsLemmy

Copy link
Copy Markdown
Collaborator

Thanks!

@ItsLemmy
ItsLemmy merged commit ae53665 into noctalia-dev:main Aug 15, 2026
1 of 2 checks passed
@oldirtty
oldirtty deleted the feat/dynamic-plugins-completions branch August 15, 2026 19:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants