From f5cbfa718e5bb4a284d0c2bfac6b425e4d7a343d Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Tue, 19 Nov 2024 11:20:30 -0500 Subject: [PATCH] assistant: Fix evaluating slash commands in slash command output (like `/default`) (#20864) This PR fixes an issue where slash commands in the output of other slash commands were not being evaluated when configured to do so. Closes https://github.com/zed-industries/zed/issues/20820. Release Notes: - Fixed slash commands from other slash commands (like `/default`) not being evaluated (Preview only). --- crates/assistant/src/assistant_panel.rs | 55 +++++++++++-------- crates/assistant/src/context.rs | 16 ++++-- .../src/slash_command/default_command.rs | 4 ++ 3 files changed, 45 insertions(+), 30 deletions(-) diff --git a/crates/assistant/src/assistant_panel.rs b/crates/assistant/src/assistant_panel.rs index b682bfdcca..c89595c7da 100644 --- a/crates/assistant/src/assistant_panel.rs +++ b/crates/assistant/src/assistant_panel.rs @@ -2050,30 +2050,6 @@ impl ContextEditor { ContextEvent::SlashCommandOutputSectionAdded { section } => { self.insert_slash_command_output_sections([section.clone()], false, cx); } - ContextEvent::SlashCommandFinished { - output_range: _output_range, - run_commands_in_ranges, - } => { - for range in run_commands_in_ranges { - let commands = self.context.update(cx, |context, cx| { - context.reparse(cx); - context - .pending_commands_for_range(range.clone(), cx) - .to_vec() - }); - - for command in commands { - self.run_command( - command.source_range, - &command.name, - &command.arguments, - false, - self.workspace.clone(), - cx, - ); - } - } - } ContextEvent::UsePendingTools => { let pending_tool_uses = self .context @@ -2152,6 +2128,37 @@ impl ContextEditor { command_id: InvokedSlashCommandId, cx: &mut ViewContext, ) { + if let Some(invoked_slash_command) = + self.context.read(cx).invoked_slash_command(&command_id) + { + if let InvokedSlashCommandStatus::Finished = invoked_slash_command.status { + let run_commands_in_ranges = invoked_slash_command + .run_commands_in_ranges + .iter() + .cloned() + .collect::>(); + for range in run_commands_in_ranges { + let commands = self.context.update(cx, |context, cx| { + context.reparse(cx); + context + .pending_commands_for_range(range.clone(), cx) + .to_vec() + }); + + for command in commands { + self.run_command( + command.source_range, + &command.name, + &command.arguments, + false, + self.workspace.clone(), + cx, + ); + } + } + } + } + self.editor.update(cx, |editor, cx| { if let Some(invoked_slash_command) = self.context.read(cx).invoked_slash_command(&command_id) diff --git a/crates/assistant/src/context.rs b/crates/assistant/src/context.rs index d6f0a48868..39c31d7c58 100644 --- a/crates/assistant/src/context.rs +++ b/crates/assistant/src/context.rs @@ -381,10 +381,6 @@ pub enum ContextEvent { SlashCommandOutputSectionAdded { section: SlashCommandOutputSection, }, - SlashCommandFinished { - output_range: Range, - run_commands_in_ranges: Vec>, - }, UsePendingTools, ToolFinished { tool_use_id: Arc, @@ -916,6 +912,7 @@ impl Context { InvokedSlashCommand { name: name.into(), range: output_range, + run_commands_in_ranges: Vec::new(), status: InvokedSlashCommandStatus::Running(Task::ready(())), transaction: None, timestamp: id.0, @@ -1914,7 +1911,6 @@ impl Context { } let mut pending_section_stack: Vec = Vec::new(); - let mut run_commands_in_ranges: Vec> = Vec::new(); let mut last_role: Option = None; let mut last_section_range = None; @@ -1980,7 +1976,13 @@ impl Context { let end = this.buffer.read(cx).anchor_before(insert_position); if run_commands_in_text { - run_commands_in_ranges.push(start..end); + if let Some(invoked_slash_command) = + this.invoked_slash_commands.get_mut(&command_id) + { + invoked_slash_command + .run_commands_in_ranges + .push(start..end); + } } } SlashCommandEvent::EndSection => { @@ -2100,6 +2102,7 @@ impl Context { InvokedSlashCommand { name: name.to_string().into(), range: command_range.clone(), + run_commands_in_ranges: Vec::new(), status: InvokedSlashCommandStatus::Running(insert_output_task), transaction: Some(first_transaction), timestamp: command_id.0, @@ -3176,6 +3179,7 @@ pub struct ParsedSlashCommand { pub struct InvokedSlashCommand { pub name: SharedString, pub range: Range, + pub run_commands_in_ranges: Vec>, pub status: InvokedSlashCommandStatus, pub transaction: Option, timestamp: clock::Lamport, diff --git a/crates/assistant/src/slash_command/default_command.rs b/crates/assistant/src/slash_command/default_command.rs index 4d9c9e2ae4..49a7b244e9 100644 --- a/crates/assistant/src/slash_command/default_command.rs +++ b/crates/assistant/src/slash_command/default_command.rs @@ -69,6 +69,10 @@ impl SlashCommand for DefaultSlashCommand { text.push('\n'); } + if !text.ends_with('\n') { + text.push('\n'); + } + Ok(SlashCommandOutput { sections: vec![SlashCommandOutputSection { range: 0..text.len(),