debugger: Add an action to rerun the last session (#31442)

Cole Miller created

This works the same as selecting the first history match in the new
session modal.

Release Notes:

- Debugger Beta: Added the `debugger: rerun last session` action, bound
by default to `alt-f4`.

Change summary

assets/keymaps/default-linux.json        |  1 
assets/keymaps/default-macos.json        |  1 
crates/debugger_ui/src/debugger_panel.rs | 39 ++++++++++++++++++++++++++
crates/debugger_ui/src/debugger_ui.rs    | 14 ++++++++
crates/project/src/task_inventory.rs     |  4 ++
5 files changed, 58 insertions(+), 1 deletion(-)

Detailed changes

assets/keymaps/default-linux.json 🔗

@@ -31,6 +31,7 @@
       "ctrl-,": "zed::OpenSettings",
       "ctrl-q": "zed::Quit",
       "f4": "debugger::Start",
+      "alt-f4": "debugger::RerunLastSession",
       "f5": "debugger::Continue",
       "shift-f5": "debugger::Stop",
       "ctrl-shift-f5": "debugger::Restart",

assets/keymaps/default-macos.json 🔗

@@ -4,6 +4,7 @@
     "use_key_equivalents": true,
     "bindings": {
       "f4": "debugger::Start",
+      "alt-f4": "debugger::RerunLastSession",
       "f5": "debugger::Continue",
       "shift-f5": "debugger::Stop",
       "shift-cmd-f5": "debugger::Restart",

crates/debugger_ui/src/debugger_panel.rs 🔗

@@ -322,6 +322,45 @@ impl DebugPanel {
         .detach_and_log_err(cx);
     }
 
+    pub(crate) fn rerun_last_session(
+        &mut self,
+        workspace: &mut Workspace,
+        window: &mut Window,
+        cx: &mut Context<Self>,
+    ) {
+        let task_store = workspace.project().read(cx).task_store().clone();
+        let Some(task_inventory) = task_store.read(cx).task_inventory() else {
+            return;
+        };
+        let Some(scenario) = task_inventory.read(cx).last_scheduled_scenario().cloned() else {
+            return;
+        };
+        let workspace = self.workspace.clone();
+
+        cx.spawn_in(window, async move |this, cx| {
+            let task_contexts = workspace
+                .update_in(cx, |workspace, window, cx| {
+                    tasks_ui::task_contexts(workspace, window, cx)
+                })?
+                .await;
+
+            let task_context = task_contexts.active_context().cloned().unwrap_or_default();
+            let worktree_id = task_contexts.worktree();
+
+            this.update_in(cx, |this, window, cx| {
+                this.start_session(
+                    scenario.clone(),
+                    task_context,
+                    None,
+                    worktree_id,
+                    window,
+                    cx,
+                );
+            })
+        })
+        .detach();
+    }
+
     pub(crate) async fn register_session(
         this: WeakEntity<Self>,
         session: Entity<Session>,

crates/debugger_ui/src/debugger_ui.rs 🔗

@@ -47,6 +47,7 @@ actions!(
         ShowStackTrace,
         ToggleThreadPicker,
         ToggleSessionPicker,
+        RerunLastSession,
     ]
 );
 
@@ -208,7 +209,18 @@ pub fn init(cx: &mut App) {
                 )
                 .register_action(|workspace: &mut Workspace, _: &Start, window, cx| {
                     NewSessionModal::show(workspace, window, cx);
-                });
+                })
+                .register_action(
+                    |workspace: &mut Workspace, _: &RerunLastSession, window, cx| {
+                        let Some(debug_panel) = workspace.panel::<DebugPanel>(cx) else {
+                            return;
+                        };
+
+                        debug_panel.update(cx, |debug_panel, cx| {
+                            debug_panel.rerun_last_session(workspace, window, cx);
+                        })
+                    },
+                );
         })
     })
     .detach();

crates/project/src/task_inventory.rs 🔗

@@ -230,6 +230,10 @@ impl Inventory {
         }
     }
 
+    pub fn last_scheduled_scenario(&self) -> Option<&DebugScenario> {
+        self.last_scheduled_scenarios.back()
+    }
+
     pub fn list_debug_scenarios(
         &self,
         task_contexts: &TaskContexts,