assistant: Improve terminal slash command (#16229)

Bennet Bo Fenner created

- Fix terminal slash command not working when terminal tab was placed in
center workspace
- Removed `--line-count` argument, you can now just pass a number to the
slash command
e.g. `/terminal 10` will show the last 10 lines of the active terminal
- Increase default context lines to 50
- We will revisit this once we add support for only including the last n
amount of commands that were run

Release Notes:

- N/A

Change summary

crates/assistant/src/assistant.rs                      |  2 
crates/assistant/src/slash_command/terminal_command.rs | 56 ++++++-----
2 files changed, 30 insertions(+), 28 deletions(-)

Detailed changes

crates/assistant/src/assistant.rs 🔗

@@ -65,7 +65,7 @@ actions!(
     ]
 );
 
-const DEFAULT_CONTEXT_LINES: usize = 20;
+const DEFAULT_CONTEXT_LINES: usize = 50;
 
 #[derive(Clone, Default, Deserialize, PartialEq)]
 pub struct InlineAssist {

crates/assistant/src/slash_command/terminal_command.rs 🔗

@@ -5,7 +5,7 @@ use anyhow::Result;
 use assistant_slash_command::{
     ArgumentCompletion, SlashCommand, SlashCommandOutput, SlashCommandOutputSection,
 };
-use gpui::{AppContext, Task, WeakView};
+use gpui::{AppContext, Task, View, WeakView};
 use language::{CodeLabel, LspAdapterDelegate};
 use terminal_view::{terminal_panel::TerminalPanel, TerminalView};
 use ui::prelude::*;
@@ -42,21 +42,12 @@ impl SlashCommand for TerminalSlashCommand {
 
     fn complete_argument(
         self: Arc<Self>,
-        arguments: &[String],
+        _arguments: &[String],
         _cancel: Arc<AtomicBool>,
         _workspace: Option<WeakView<Workspace>>,
         _cx: &mut WindowContext,
     ) -> Task<Result<Vec<ArgumentCompletion>>> {
-        let completions = if arguments.iter().any(|arg| arg == LINE_COUNT_ARG) {
-            Vec::new()
-        } else {
-            vec![ArgumentCompletion {
-                label: LINE_COUNT_ARG.into(),
-                new_text: LINE_COUNT_ARG.to_string(),
-                run_command: false,
-            }]
-        };
-        Task::ready(Ok(completions))
+        Task::ready(Ok(Vec::new()))
     }
 
     fn run(
@@ -69,24 +60,15 @@ impl SlashCommand for TerminalSlashCommand {
         let Some(workspace) = workspace.upgrade() else {
             return Task::ready(Err(anyhow::anyhow!("workspace was dropped")));
         };
-        let Some(terminal_panel) = workspace.read(cx).panel::<TerminalPanel>(cx) else {
-            return Task::ready(Err(anyhow::anyhow!("no terminal panel open")));
-        };
-        let Some(active_terminal) = terminal_panel.read(cx).pane().and_then(|pane| {
-            pane.read(cx)
-                .active_item()
-                .and_then(|t| t.downcast::<TerminalView>())
-        }) else {
+
+        let Some(active_terminal) = resolve_active_terminal(&workspace, cx) else {
             return Task::ready(Err(anyhow::anyhow!("no active terminal")));
         };
 
-        let mut line_count = DEFAULT_CONTEXT_LINES;
-        if arguments.get(0).map(|s| s.as_str()) == Some(LINE_COUNT_ARG) {
-            if let Some(parsed_line_count) = arguments.get(1).and_then(|s| s.parse::<usize>().ok())
-            {
-                line_count = parsed_line_count;
-            }
-        }
+        let line_count = arguments
+            .get(0)
+            .and_then(|s| s.parse::<usize>().ok())
+            .unwrap_or(DEFAULT_CONTEXT_LINES);
 
         let lines = active_terminal
             .read(cx)
@@ -110,3 +92,23 @@ impl SlashCommand for TerminalSlashCommand {
         }))
     }
 }
+
+fn resolve_active_terminal(
+    workspace: &View<Workspace>,
+    cx: &WindowContext,
+) -> Option<View<TerminalView>> {
+    if let Some(terminal_view) = workspace
+        .read(cx)
+        .active_item(cx)
+        .and_then(|item| item.act_as::<TerminalView>(cx))
+    {
+        return Some(terminal_view);
+    }
+
+    let terminal_panel = workspace.read(cx).panel::<TerminalPanel>(cx)?;
+    terminal_panel.read(cx).pane().and_then(|pane| {
+        pane.read(cx)
+            .active_item()
+            .and_then(|t| t.downcast::<TerminalView>())
+    })
+}