From e5e67a8c2855d227ab2878ec54d77292efaaa5ac Mon Sep 17 00:00:00 2001 From: Kunall Banerjee Date: Tue, 19 May 2026 06:05:49 -0400 Subject: [PATCH] agent_ui: Trigger @-mention menu after opening brackets (#55504) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Typing `@` immediately after `(`, `[`, or `{` did not open the Agent Panel’s @-mention completion menu, so `(@file)`, `[@file]`, and `{@file}` were unusable. This has been bothering me for quite some time now. Overall, I believe this is a QoL improvement, albeit a small one. Self-Review Checklist: - [x] I've reviewed my own diff for quality, security, and reliability - [ ] Unsafe blocks (if any) have justifying comments - [ ] The content is consistent with the [UI/UX checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist) - [x] Tests cover the new/changed behavior - [ ] Performance impact has been considered and is acceptable Release Notes: - Fixed the Agent Panel’s @-mention menu not appearing when `@` immediately follows `(`, `[`, or `{`. --------- Co-authored-by: Bennet Bo Fenner --- crates/agent_ui/src/completion_provider.rs | 41 +++++++++++++++++++--- 1 file changed, 37 insertions(+), 4 deletions(-) diff --git a/crates/agent_ui/src/completion_provider.rs b/crates/agent_ui/src/completion_provider.rs index 3a4ae6ecc2..acc0854110 100644 --- a/crates/agent_ui/src/completion_provider.rs +++ b/crates/agent_ui/src/completion_provider.rs @@ -1868,10 +1868,11 @@ impl MentionCompletion { offset_to_line: usize, supported_modes: &[PromptContextType], ) -> Option { - // Find the rightmost '@' that has a word boundary before it and no whitespace immediately after + // Find the rightmost '@' that has a boundary before it and no whitespace immediately after. + // A boundary is the start of the line, whitespace, or an opening bracket. let mut last_mention_start = None; for (idx, _) in line.rmatch_indices('@') { - // No whitespace immediately after '@' + // No whitespace immediately after '@'. if line[idx + 1..] .chars() .next() @@ -1880,12 +1881,11 @@ impl MentionCompletion { continue; } - // Must be a word boundary before '@' if idx > 0 && line[..idx] .chars() .last() - .is_some_and(|c| !c.is_whitespace()) + .is_some_and(|c| !c.is_whitespace() && !matches!(c, '(' | '[' | '{')) { continue; } @@ -2960,6 +2960,39 @@ mod tests { }), "Should parse URL ending with @ (even if URL is incomplete)" ); + + // Bracketed mentions: opening brackets count as a boundary before '@' so + // typing `(@`, `[@`, or `{@` still opens the completion menu. + + assert_eq!( + MentionCompletion::try_parse("(@", 0, &supported_modes), + Some(MentionCompletion { + source_range: 1..2, + mode: None, + argument: None, + }), + "Should parse mention immediately after '('" + ); + + assert_eq!( + MentionCompletion::try_parse("[@", 0, &supported_modes), + Some(MentionCompletion { + source_range: 1..2, + mode: None, + argument: None, + }), + "Should parse mention immediately after '['" + ); + + assert_eq!( + MentionCompletion::try_parse("{@", 0, &supported_modes), + Some(MentionCompletion { + source_range: 1..2, + mode: None, + argument: None, + }), + "Should parse mention immediately after '{{'" + ); } #[gpui::test]