From 45b7a8dda28c448bf52120b01646cc5d90c57dc6 Mon Sep 17 00:00:00 2001 From: Remco Smits Date: Sun, 22 Sep 2024 16:49:22 +0200 Subject: [PATCH] Move all the debug panel actions to the workspace I also had to remove the debug_panel dependency inside the debug_panel_item, because we hit a `"cannot update debug_panel while it is already being updated"` panic. I also move the actions to its own debugger namespace, so its more clear what the actions are for. The new actions can now also be used for key binds: ``` debugger: start debugger: continue debugger: step into debugger: step over debugger: step out debugger: restart debugger: stop debugger: pause ``` --- crates/debugger_ui/src/debugger_panel.rs | 60 +--- crates/debugger_ui/src/debugger_panel_item.rs | 273 +++++++----------- crates/debugger_ui/src/lib.rs | 83 +++++- crates/workspace/src/workspace.rs | 6 +- 4 files changed, 196 insertions(+), 226 deletions(-) diff --git a/crates/debugger_ui/src/debugger_panel.rs b/crates/debugger_ui/src/debugger_panel.rs index 4eecfcd840a0c..5de32ff4682cb 100644 --- a/crates/debugger_ui/src/debugger_panel.rs +++ b/crates/debugger_ui/src/debugger_panel.rs @@ -27,13 +27,15 @@ use workspace::{ dock::{DockPosition, Panel, PanelEvent}, Workspace, }; -use workspace::{pane, Pane, StartDebugger}; +use workspace::{pane, Pane, Start}; enum DebugCurrentRowHighlight {} pub enum DebugPanelEvent { + Exited(DebugAdapterClientId), Stopped((DebugAdapterClientId, StoppedEvent)), Thread((DebugAdapterClientId, ThreadEvent)), + Continued((DebugAdapterClientId, ContinuedEvent)), Output((DebugAdapterClientId, OutputEvent)), ClientStopped(DebugAdapterClientId), } @@ -152,36 +154,14 @@ impl DebugPanel { }) } - pub fn update_thread_state_status( - &mut self, - client_id: &DebugAdapterClientId, - thread_id: Option, - status: ThreadStatus, - all_threads_continued: Option, + pub fn active_debug_panel_item( + &self, cx: &mut ViewContext, - ) { - if all_threads_continued.unwrap_or(false) { - for (_, thread_state) in self - .thread_states - .range_mut((*client_id, u64::MIN)..(*client_id, u64::MAX)) - { - thread_state.update(cx, |thread_state, cx| { - thread_state.status = status; - - cx.notify(); - }); - } - } else if let Some(thread_state) = - thread_id.and_then(|thread_id| self.thread_states.get_mut(&(*client_id, thread_id))) - { - thread_state.update(cx, |thread_state, cx| { - thread_state.status = ThreadStatus::Running; - - cx.notify(); - }); - } - - cx.notify(); + ) -> Option> { + self.pane + .read(cx) + .active_item() + .and_then(|panel| panel.downcast::()) } fn debug_client_by_id( @@ -440,13 +420,7 @@ impl DebugPanel { event: &ContinuedEvent, cx: &mut ViewContext, ) { - self.update_thread_state_status( - client_id, - Some(event.thread_id), - ThreadStatus::Running, - event.all_threads_continued, - cx, - ); + cx.emit(DebugPanelEvent::Continued((*client_id, event.clone()))); } fn handle_stopped_event( @@ -643,14 +617,6 @@ impl DebugPanel { cx.new_model(|_| ThreadState::default()), ); } else { - self.update_thread_state_status( - client_id, - Some(thread_id), - ThreadStatus::Ended, - None, - cx, - ); - // TODO debugger: we want to figure out for witch clients/threads we should remove the highlights // cx.spawn({ // let client = client.clone(); @@ -674,7 +640,7 @@ impl DebugPanel { _: &ExitedEvent, cx: &mut ViewContext, ) { - self.update_thread_state_status(client_id, None, ThreadStatus::Exited, Some(true), cx); + cx.emit(DebugPanelEvent::Exited(*client_id)); } fn handle_terminated_event( @@ -835,7 +801,7 @@ impl Render for DebugPanel { ) .label_size(LabelSize::Small) .on_click(move |_, cx| { - cx.dispatch_action(StartDebugger.boxed_clone()); + cx.dispatch_action(Start.boxed_clone()); }) ), ), diff --git a/crates/debugger_ui/src/debugger_panel_item.rs b/crates/debugger_ui/src/debugger_panel_item.rs index e53983ffdbab5..12b8c8f13846c 100644 --- a/crates/debugger_ui/src/debugger_panel_item.rs +++ b/crates/debugger_ui/src/debugger_panel_item.rs @@ -4,19 +4,20 @@ use crate::variable_list::VariableList; use dap::client::{DebugAdapterClientId, ThreadStatus}; use dap::debugger_settings::DebuggerSettings; -use dap::{Capabilities, OutputEvent, OutputEventCategory, StackFrame, StoppedEvent, ThreadEvent}; +use dap::{ + Capabilities, ContinuedEvent, OutputEvent, OutputEventCategory, StackFrame, StoppedEvent, + ThreadEvent, +}; use editor::Editor; use gpui::{ - impl_actions, list, AnyElement, AppContext, EventEmitter, FocusHandle, FocusableView, - ListState, Model, Subscription, View, WeakView, + list, AnyElement, AppContext, EventEmitter, FocusHandle, FocusableView, ListState, Model, + Subscription, View, WeakView, }; use project::dap_store::DapStore; -use serde::Deserialize; use settings::Settings; use task::DebugAdapterKind; use ui::WindowContext; use ui::{prelude::*, Tooltip}; -use workspace::dock::Panel; use workspace::item::{Item, ItemEvent}; use workspace::Workspace; @@ -40,7 +41,6 @@ pub struct DebugPanelItem { output_editor: View, current_stack_frame_id: u64, client_kind: DebugAdapterKind, - debug_panel: View, active_thread_item: ThreadItem, workspace: WeakView, client_id: DebugAdapterClientId, @@ -49,30 +49,6 @@ pub struct DebugPanelItem { _subscriptions: Vec, } -impl_actions!(debug_panel_item, [DebugItemAction]); - -/// This struct is for actions that should be triggered even when -/// the debug pane is not in focus. This is done by setting workspace -/// as the action listener then having workspace call `handle_workspace_action` -#[derive(Clone, Deserialize, PartialEq)] -pub struct DebugItemAction { - kind: DebugPanelItemActionKind, -} - -/// Actions that can be sent to workspace -/// currently all of these are button toggles -#[derive(Deserialize, PartialEq, Clone, Debug)] -enum DebugPanelItemActionKind { - Continue, - StepOver, - StepIn, - StepOut, - Restart, - Pause, - Stop, - Disconnect, -} - impl DebugPanelItem { #[allow(clippy::too_many_arguments)] pub fn new( @@ -118,16 +94,22 @@ impl DebugPanelItem { move |this: &mut Self, _, event: &DebugPanelEvent, cx| { match event { DebugPanelEvent::Stopped((client_id, event)) => { - Self::handle_stopped_event(this, client_id, event, cx) + this.handle_stopped_event(client_id, event, cx) } DebugPanelEvent::Thread((client_id, event)) => { - Self::handle_thread_event(this, client_id, event, cx) + this.handle_thread_event(client_id, event, cx) } DebugPanelEvent::Output((client_id, event)) => { - Self::handle_output_event(this, client_id, event, cx) + this.handle_output_event(client_id, event, cx) } DebugPanelEvent::ClientStopped(client_id) => { - Self::handle_client_stopped_event(this, client_id, cx) + this.handle_client_stopped_event(client_id, cx) + } + DebugPanelEvent::Continued((client_id, event)) => { + this.handle_thread_continued_event(client_id, event, cx); + } + DebugPanelEvent::Exited(client_id) => { + this.handle_client_exited_event(client_id, cx); } }; } @@ -152,7 +134,6 @@ impl DebugPanelItem { thread_id, dap_store, workspace, - debug_panel, thread_state, focus_handle, output_editor, @@ -166,54 +147,73 @@ impl DebugPanelItem { } } - fn should_skip_event( - this: &mut Self, + pub fn update_thread_state_status(&mut self, status: ThreadStatus, cx: &mut ViewContext) { + self.thread_state.update(cx, |thread_state, cx| { + thread_state.status = status; + + cx.notify(); + }); + + cx.notify(); + } + + fn should_skip_event(&self, client_id: &DebugAdapterClientId, thread_id: u64) -> bool { + thread_id != self.thread_id || *client_id != self.client_id + } + + fn handle_thread_continued_event( + &mut self, client_id: &DebugAdapterClientId, - thread_id: u64, - ) -> bool { - thread_id != this.thread_id || *client_id != this.client_id + event: &ContinuedEvent, + cx: &mut ViewContext, + ) { + if self.should_skip_event(client_id, event.thread_id) { + return; + } + + self.update_thread_state_status(ThreadStatus::Running, cx); } fn handle_stopped_event( - this: &mut Self, + &mut self, client_id: &DebugAdapterClientId, event: &StoppedEvent, cx: &mut ViewContext, ) { - if Self::should_skip_event(this, client_id, event.thread_id.unwrap_or(this.thread_id)) { + if self.should_skip_event(client_id, event.thread_id.unwrap_or(self.thread_id)) { return; } - let thread_state = this.thread_state.read(cx); + let thread_state = self.thread_state.read(cx); - this.stack_frame_list.reset(thread_state.stack_frames.len()); + self.stack_frame_list.reset(thread_state.stack_frames.len()); if let Some(stack_frame) = thread_state.stack_frames.first() { - this.update_stack_frame_id(stack_frame.id, cx); + self.update_stack_frame_id(stack_frame.id, cx); }; cx.notify(); } fn handle_thread_event( - this: &mut Self, + &mut self, client_id: &DebugAdapterClientId, event: &ThreadEvent, - _: &mut ViewContext, + cx: &mut ViewContext, ) { - if Self::should_skip_event(this, client_id, event.thread_id) { + if self.should_skip_event(client_id, event.thread_id) { return; } - // TODO debugger: handle thread event + self.update_thread_state_status(ThreadStatus::Ended, cx); } fn handle_output_event( - this: &mut Self, + &mut self, client_id: &DebugAdapterClientId, event: &OutputEvent, cx: &mut ViewContext, ) { - if Self::should_skip_event(this, client_id, this.thread_id) { + if self.should_skip_event(client_id, self.thread_id) { return; } @@ -226,13 +226,13 @@ impl DebugPanelItem { match output_category { OutputEventCategory::Console => { - this.console.update(cx, |console, cx| { + self.console.update(cx, |console, cx| { console.add_message(&event.output, cx); }); } // OutputEventCategory::Stderr => {} OutputEventCategory::Stdout => { - this.output_editor.update(cx, |editor, cx| { + self.output_editor.update(cx, |editor, cx| { editor.set_read_only(false); editor.move_to_end(&editor::actions::MoveToEnd, cx); editor.insert(format!("{}\n", &event.output.trim_end()).as_str(), cx); @@ -245,7 +245,7 @@ impl DebugPanelItem { // OutputEventCategory::Important => {} OutputEventCategory::Telemetry => {} _ => { - this.output_editor.update(cx, |editor, cx| { + self.output_editor.update(cx, |editor, cx| { editor.set_read_only(false); editor.move_to_end(&editor::actions::MoveToEnd, cx); editor.insert(format!("{}\n", &event.output.trim_end()).as_str(), cx); @@ -258,17 +258,29 @@ impl DebugPanelItem { } fn handle_client_stopped_event( - this: &mut Self, + &mut self, client_id: &DebugAdapterClientId, cx: &mut ViewContext, ) { - if Self::should_skip_event(this, client_id, this.thread_id) { + if self.should_skip_event(client_id, self.thread_id) { return; } - this.stack_frame_list.reset(0); + self.update_thread_state_status(ThreadStatus::Stopped, cx); - cx.notify(); + cx.emit(Event::Close); + } + + fn handle_client_exited_event( + &mut self, + client_id: &DebugAdapterClientId, + cx: &mut ViewContext, + ) { + if Self::should_skip_event(self, client_id, self.thread_id) { + return; + } + + self.update_thread_state_status(ThreadStatus::Exited, cx); cx.emit(Event::Close); } @@ -371,55 +383,8 @@ impl DebugPanelItem { .into_any() } - /// Actions that should be handled even when Debug Panel is not in focus - pub fn workspace_action_handler( - workspace: &mut Workspace, - action: &DebugItemAction, - cx: &mut ViewContext, - ) { - let Some(pane) = workspace - .panel::(cx) - .and_then(|panel| panel.read(cx).pane()) - else { - log::error!( - "Can't get Debug panel to handle Debug action: {:?} - This shouldn't happen because there has to be an Debug panel to click a button and trigger this action", - action.kind - ); - return; - }; - - pane.update(cx, |this, cx| { - let Some(active_item) = this - .active_item() - .and_then(|item| item.downcast::()) - else { - return; - }; - - active_item.update(cx, |item, cx| match action.kind { - DebugPanelItemActionKind::Stop => item.handle_stop_action(cx), - DebugPanelItemActionKind::Continue => item.handle_continue_action(cx), - DebugPanelItemActionKind::StepIn => item.handle_step_in_action(cx), - DebugPanelItemActionKind::StepOut => item.handle_step_out_action(cx), - DebugPanelItemActionKind::StepOver => item.handle_step_over_action(cx), - DebugPanelItemActionKind::Pause => item.handle_pause_action(cx), - DebugPanelItemActionKind::Disconnect => item.handle_disconnect_action(cx), - DebugPanelItemActionKind::Restart => item.handle_restart_action(cx), - }); - }); - } - - fn handle_continue_action(&mut self, cx: &mut ViewContext) { - self.debug_panel.update(cx, |panel, cx| { - panel.update_thread_state_status( - &self.client_id, - Some(self.thread_id), - ThreadStatus::Running, - None, - cx, - ); - }); + pub fn continue_thread(&mut self, cx: &mut ViewContext) { + self.update_thread_state_status(ThreadStatus::Running, cx); self.dap_store.update(cx, |store, cx| { store @@ -428,16 +393,8 @@ impl DebugPanelItem { }); } - fn handle_step_over_action(&mut self, cx: &mut ViewContext) { - self.debug_panel.update(cx, |panel, cx| { - panel.update_thread_state_status( - &self.client_id, - Some(self.thread_id), - ThreadStatus::Running, - None, - cx, - ); - }); + pub fn step_over(&mut self, cx: &mut ViewContext) { + self.update_thread_state_status(ThreadStatus::Running, cx); let granularity = DebuggerSettings::get_global(cx).stepping_granularity(); @@ -448,16 +405,8 @@ impl DebugPanelItem { }); } - fn handle_step_in_action(&mut self, cx: &mut ViewContext) { - self.debug_panel.update(cx, |panel, cx| { - panel.update_thread_state_status( - &self.client_id, - Some(self.thread_id), - ThreadStatus::Running, - None, - cx, - ); - }); + pub fn step_in(&mut self, cx: &mut ViewContext) { + self.update_thread_state_status(ThreadStatus::Running, cx); let granularity = DebuggerSettings::get_global(cx).stepping_granularity(); @@ -468,16 +417,8 @@ impl DebugPanelItem { }); } - fn handle_step_out_action(&mut self, cx: &mut ViewContext) { - self.debug_panel.update(cx, |panel, cx| { - panel.update_thread_state_status( - &self.client_id, - Some(self.thread_id), - ThreadStatus::Running, - None, - cx, - ); - }); + pub fn step_out(&mut self, cx: &mut ViewContext) { + self.update_thread_state_status(ThreadStatus::Running, cx); let granularity = DebuggerSettings::get_global(cx).stepping_granularity(); @@ -488,7 +429,7 @@ impl DebugPanelItem { }); } - fn handle_restart_action(&mut self, cx: &mut ViewContext) { + pub fn restart_client(&self, cx: &mut ViewContext) { self.dap_store.update(cx, |store, cx| { store .restart(&self.client_id, None, cx) @@ -496,7 +437,7 @@ impl DebugPanelItem { }); } - fn handle_pause_action(&mut self, cx: &mut ViewContext) { + pub fn pause_thread(&self, cx: &mut ViewContext) { self.dap_store.update(cx, |store, cx| { store .pause_thread(&self.client_id, self.thread_id, cx) @@ -504,7 +445,7 @@ impl DebugPanelItem { }); } - fn handle_stop_action(&mut self, cx: &mut ViewContext) { + pub fn stop_thread(&self, cx: &mut ViewContext) { self.dap_store.update(cx, |store, cx| { store .terminate_threads(&self.client_id, Some(vec![self.thread_id; 1]), cx) @@ -512,7 +453,7 @@ impl DebugPanelItem { }); } - fn handle_disconnect_action(&mut self, cx: &mut ViewContext) { + pub fn disconnect_client(&self, cx: &mut ViewContext) { self.dap_store.update(cx, |store, cx| { store .disconnect_client(&self.client_id, cx) @@ -593,10 +534,8 @@ impl Render for DebugPanelItem { this.child( IconButton::new("debug-pause", IconName::DebugPause) .icon_size(IconSize::Small) - .on_click(cx.listener(|_, _, cx| { - cx.dispatch_action(Box::new(DebugItemAction { - kind: DebugPanelItemActionKind::Pause, - })) + .on_click(cx.listener(|this, _, cx| { + this.pause_thread(cx); })) .tooltip(move |cx| Tooltip::text("Pause program", cx)), ) @@ -604,11 +543,9 @@ impl Render for DebugPanelItem { this.child( IconButton::new("debug-continue", IconName::DebugContinue) .icon_size(IconSize::Small) - .on_click(cx.listener(|_, _, cx| { - cx.dispatch_action(Box::new(DebugItemAction { - kind: DebugPanelItemActionKind::Continue, - })) - })) + .on_click( + cx.listener(|this, _, cx| this.continue_thread(cx)), + ) .disabled(thread_status != ThreadStatus::Stopped) .tooltip(move |cx| { Tooltip::text("Continue program", cx) @@ -619,10 +556,8 @@ impl Render for DebugPanelItem { .child( IconButton::new("debug-step-over", IconName::DebugStepOver) .icon_size(IconSize::Small) - .on_click(cx.listener(|_, _, cx| { - cx.dispatch_action(Box::new(DebugItemAction { - kind: DebugPanelItemActionKind::StepOver, - })) + .on_click(cx.listener(|this, _, cx| { + this.step_over(cx); })) .disabled(thread_status != ThreadStatus::Stopped) .tooltip(move |cx| Tooltip::text("Step over", cx)), @@ -630,10 +565,8 @@ impl Render for DebugPanelItem { .child( IconButton::new("debug-step-in", IconName::DebugStepInto) .icon_size(IconSize::Small) - .on_click(cx.listener(|_, _, cx| { - cx.dispatch_action(Box::new(DebugItemAction { - kind: DebugPanelItemActionKind::StepIn, - })) + .on_click(cx.listener(|this, _, cx| { + this.step_over(cx); })) .disabled(thread_status != ThreadStatus::Stopped) .tooltip(move |cx| Tooltip::text("Step in", cx)), @@ -641,10 +574,8 @@ impl Render for DebugPanelItem { .child( IconButton::new("debug-step-out", IconName::DebugStepOut) .icon_size(IconSize::Small) - .on_click(cx.listener(|_, _, cx| { - cx.dispatch_action(Box::new(DebugItemAction { - kind: DebugPanelItemActionKind::StepOut, - })) + .on_click(cx.listener(|this, _, cx| { + this.step_out(cx); })) .disabled(thread_status != ThreadStatus::Stopped) .tooltip(move |cx| Tooltip::text("Step out", cx)), @@ -652,10 +583,8 @@ impl Render for DebugPanelItem { .child( IconButton::new("debug-restart", IconName::DebugRestart) .icon_size(IconSize::Small) - .on_click(cx.listener(|_, _, cx| { - cx.dispatch_action(Box::new(DebugItemAction { - kind: DebugPanelItemActionKind::Restart, - })) + .on_click(cx.listener(|this, _, cx| { + this.restart_client(cx); })) .disabled( !capabilities.supports_restart_request.unwrap_or_default(), @@ -665,10 +594,8 @@ impl Render for DebugPanelItem { .child( IconButton::new("debug-stop", IconName::DebugStop) .icon_size(IconSize::Small) - .on_click(cx.listener(|_, _, cx| { - cx.dispatch_action(Box::new(DebugItemAction { - kind: DebugPanelItemActionKind::Stop, - })) + .on_click(cx.listener(|this, _, cx| { + this.stop_thread(cx); })) .disabled( thread_status != ThreadStatus::Stopped @@ -679,10 +606,8 @@ impl Render for DebugPanelItem { .child( IconButton::new("debug-disconnect", IconName::DebugDisconnect) .icon_size(IconSize::Small) - .on_click(cx.listener(|_, _, cx| { - cx.dispatch_action(Box::new(DebugItemAction { - kind: DebugPanelItemActionKind::Disconnect, - })) + .on_click(cx.listener(|this, _, cx| { + this.disconnect_client(cx); })) .disabled( thread_status == ThreadStatus::Exited diff --git a/crates/debugger_ui/src/lib.rs b/crates/debugger_ui/src/lib.rs index b35bdf0d64005..28048d0eb3b5f 100644 --- a/crates/debugger_ui/src/lib.rs +++ b/crates/debugger_ui/src/lib.rs @@ -1,10 +1,9 @@ use dap::debugger_settings::DebuggerSettings; use debugger_panel::{DebugPanel, ToggleFocus}; -use debugger_panel_item::DebugPanelItem; use gpui::AppContext; use settings::Settings; use ui::ViewContext; -use workspace::{StartDebugger, Workspace}; +use workspace::{Continue, Pause, Restart, Start, StepInto, StepOut, StepOver, Stop, Workspace}; mod console; pub mod debugger_panel; @@ -20,10 +19,86 @@ pub fn init(cx: &mut AppContext) { .register_action(|workspace, _: &ToggleFocus, cx| { workspace.toggle_panel_focus::(cx); }) - .register_action(|workspace: &mut Workspace, _: &StartDebugger, cx| { + .register_action(|workspace: &mut Workspace, _: &Start, cx| { tasks_ui::toggle_modal(workspace, cx, task::TaskModal::DebugModal).detach(); }) - .register_action(DebugPanelItem::workspace_action_handler); + .register_action(|workspace: &mut Workspace, _: &Stop, cx| { + let debug_panel = workspace.panel::(cx).unwrap(); + + debug_panel.update(cx, |panel, cx| { + let Some(active_item) = panel.active_debug_panel_item(cx) else { + return; + }; + + active_item.update(cx, |item, cx| item.stop_thread(cx)) + }); + }) + .register_action(|workspace: &mut Workspace, _: &Continue, cx| { + let debug_panel = workspace.panel::(cx).unwrap(); + + debug_panel.update(cx, |panel, cx| { + let Some(active_item) = panel.active_debug_panel_item(cx) else { + return; + }; + + active_item.update(cx, |item, cx| item.continue_thread(cx)) + }); + }) + .register_action(|workspace: &mut Workspace, _: &StepInto, cx| { + let debug_panel = workspace.panel::(cx).unwrap(); + + debug_panel.update(cx, |panel, cx| { + let Some(active_item) = panel.active_debug_panel_item(cx) else { + return; + }; + + active_item.update(cx, |item, cx| item.step_in(cx)) + }); + }) + .register_action(|workspace: &mut Workspace, _: &StepOut, cx| { + let debug_panel = workspace.panel::(cx).unwrap(); + + debug_panel.update(cx, |panel, cx| { + let Some(active_item) = panel.active_debug_panel_item(cx) else { + return; + }; + + active_item.update(cx, |item, cx| item.step_out(cx)) + }); + }) + .register_action(|workspace: &mut Workspace, _: &StepOver, cx| { + let debug_panel = workspace.panel::(cx).unwrap(); + + debug_panel.update(cx, |panel, cx| { + let Some(active_item) = panel.active_debug_panel_item(cx) else { + return; + }; + + active_item.update(cx, |item, cx| item.step_over(cx)) + }); + }) + .register_action(|workspace: &mut Workspace, _: &Restart, cx| { + let debug_panel = workspace.panel::(cx).unwrap(); + + debug_panel.update(cx, |panel, cx| { + let Some(active_item) = panel.active_debug_panel_item(cx) else { + return; + }; + + active_item.update(cx, |item, cx| item.restart_client(cx)) + }); + }) + .register_action(|workspace: &mut Workspace, _: &Pause, cx| { + let debug_panel = workspace.panel::(cx).unwrap(); + + debug_panel.update(cx, |panel, cx| { + let Some(active_item) = panel.active_debug_panel_item(cx) else { + return; + }; + + active_item.update(cx, |item, cx| item.pause_thread(cx)) + }); + }); }, ) .detach(); diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index 8273444b618d0..f1aba57c3ca7c 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -125,6 +125,11 @@ pub struct RemoveWorktreeFromProject(pub WorktreeId); actions!(assistant, [ShowConfiguration]); +actions!( + debugger, + [Start, Continue, Disconnect, Pause, Restart, StepInto, StepOver, StepOut, Stop] +); + actions!( workspace, [ @@ -150,7 +155,6 @@ actions!( ReloadActiveItem, SaveAs, SaveWithoutFormat, - StartDebugger, ToggleBottomDock, ToggleCenteredLayout, ToggleLeftDock,