debugger: Update the default layout (#31057)

- Remove the modules list and loaded sources list from the default
layout
- Move the console to the center pane so it's visible initially

Release Notes:

- Debugger Beta: changed the default layout of the debugger panel,
hiding the modules list and loaded sources list by default and making
the console more prominent.

---------

Co-authored-by: Remco Smits <djsmits12@gmail.com>
This commit is contained in:
Cole Miller 2025-05-22 00:32:44 -04:00 committed by GitHub
parent 97e437c632
commit 71fb17c507
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 85 additions and 77 deletions

View file

@ -628,10 +628,9 @@ impl RunningState {
&workspace,
&stack_frame_list,
&variable_list,
&module_list,
&loaded_source_list,
&console,
&breakpoint_list,
&debug_terminal,
dock_axis,
&mut pane_close_subscriptions,
window,
@ -1468,10 +1467,9 @@ impl RunningState {
workspace: &WeakEntity<Workspace>,
stack_frame_list: &Entity<StackFrameList>,
variable_list: &Entity<VariableList>,
module_list: &Entity<ModuleList>,
loaded_source_list: &Entity<LoadedSourceList>,
console: &Entity<Console>,
breakpoints: &Entity<BreakpointList>,
debug_terminal: &Entity<DebugTerminal>,
dock_axis: Axis,
subscriptions: &mut HashMap<EntityId, Subscription>,
window: &mut Window,
@ -1512,6 +1510,26 @@ impl RunningState {
let center_pane = new_debugger_pane(workspace.clone(), project.clone(), window, cx);
center_pane.update(cx, |this, cx| {
let weak_console = console.downgrade();
this.add_item(
Box::new(SubView::new(
console.focus_handle(cx),
console.clone().into(),
DebuggerPaneItem::Console,
Some(Box::new(move |cx| {
weak_console
.read_with(cx, |console, cx| console.show_indicator(cx))
.unwrap_or_default()
})),
cx,
)),
true,
false,
None,
window,
cx,
);
this.add_item(
Box::new(SubView::new(
variable_list.focus_handle(cx),
@ -1526,54 +1544,20 @@ impl RunningState {
window,
cx,
);
this.add_item(
Box::new(SubView::new(
module_list.focus_handle(cx),
module_list.clone().into(),
DebuggerPaneItem::Modules,
None,
cx,
)),
false,
false,
None,
window,
cx,
);
this.add_item(
Box::new(SubView::new(
loaded_source_list.focus_handle(cx),
loaded_source_list.clone().into(),
DebuggerPaneItem::LoadedSources,
None,
cx,
)),
false,
false,
None,
window,
cx,
);
this.activate_item(0, false, false, window, cx);
});
let rightmost_pane = new_debugger_pane(workspace.clone(), project.clone(), window, cx);
rightmost_pane.update(cx, |this, cx| {
let weak_console = console.downgrade();
this.add_item(
Box::new(SubView::new(
this.focus_handle(cx),
console.clone().into(),
DebuggerPaneItem::Console,
Some(Box::new(move |cx| {
weak_console
.read_with(cx, |console, cx| console.show_indicator(cx))
.unwrap_or_default()
})),
debug_terminal.focus_handle(cx),
debug_terminal.clone().into(),
DebuggerPaneItem::Terminal,
None,
cx,
)),
true,
false,
false,
None,
window,

View file

@ -14,7 +14,7 @@ use language::{Buffer, CodeLabel, ToOffset};
use menu::Confirm;
use project::{
Completion,
debugger::session::{CompletionsQuery, OutputToken, Session},
debugger::session::{CompletionsQuery, OutputToken, Session, SessionEvent},
};
use settings::Settings;
use std::{cell::RefCell, rc::Rc, usize};
@ -79,6 +79,11 @@ impl Console {
let _subscriptions = vec![
cx.subscribe(&stack_frame_list, Self::handle_stack_frame_list_events),
cx.subscribe_in(&session, window, |this, _, event, window, cx| {
if let SessionEvent::ConsoleOutput = event {
this.update_output(window, cx)
}
}),
cx.on_focus_in(&focus_handle, window, |console, window, cx| {
if console.is_running(cx) {
console.query_bar.focus_handle(cx).focus(window);
@ -200,12 +205,11 @@ impl Console {
fn render_query_bar(&self, cx: &Context<Self>) -> impl IntoElement {
EditorElement::new(&self.query_bar, self.editor_style(cx))
}
}
impl Render for Console {
fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
fn update_output(&mut self, window: &mut Window, cx: &mut Context<Self>) {
let session = self.session.clone();
let token = self.last_token;
self.update_output_task = cx.spawn_in(window, async move |this, cx| {
_ = session.update_in(cx, move |session, window, cx| {
let (output, last_processed_token) = session.output(token);
@ -220,7 +224,11 @@ impl Render for Console {
});
});
});
}
}
impl Render for Console {
fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
v_flex()
.track_focus(&self.focus_handle)
.key_context("DebugConsole")

View file

@ -154,12 +154,15 @@ impl VariableList {
let _subscriptions = vec![
cx.subscribe(&stack_frame_list, Self::handle_stack_frame_list_events),
cx.subscribe(&session, |this, _, event, _| match event {
cx.subscribe(&session, |this, _, event, cx| match event {
SessionEvent::Stopped(_) => {
this.selection.take();
this.edited_path.take();
this.selected_stack_frame_id.take();
}
SessionEvent::Variables => {
this.build_entries(cx);
}
_ => {}
}),
cx.on_focus_out(&focus_handle, window, |this, _, _, cx| {
@ -300,7 +303,7 @@ impl VariableList {
match event {
StackFrameListEvent::SelectedStackFrameChanged(stack_frame_id) => {
self.selected_stack_frame_id = Some(*stack_frame_id);
cx.notify();
self.build_entries(cx);
}
StackFrameListEvent::BuiltEntries => {}
}
@ -344,14 +347,14 @@ impl VariableList {
};
entry.is_expanded = !entry.is_expanded;
cx.notify();
self.build_entries(cx);
}
fn select_first(&mut self, _: &SelectFirst, window: &mut Window, cx: &mut Context<Self>) {
self.cancel_variable_edit(&Default::default(), window, cx);
if let Some(variable) = self.entries.first() {
self.selection = Some(variable.path.clone());
cx.notify();
self.build_entries(cx);
}
}
@ -359,7 +362,7 @@ impl VariableList {
self.cancel_variable_edit(&Default::default(), window, cx);
if let Some(variable) = self.entries.last() {
self.selection = Some(variable.path.clone());
cx.notify();
self.build_entries(cx);
}
}
@ -378,7 +381,7 @@ impl VariableList {
index.and_then(|ix| self.entries.get(ix).map(|var| var.path.clone()))
{
self.selection = Some(new_selection);
cx.notify();
self.build_entries(cx);
} else {
self.select_last(&SelectLast, window, cx);
}
@ -402,7 +405,7 @@ impl VariableList {
index.and_then(|ix| self.entries.get(ix).map(|var| var.path.clone()))
{
self.selection = Some(new_selection);
cx.notify();
self.build_entries(cx);
} else {
self.select_first(&SelectFirst, window, cx);
}
@ -464,7 +467,7 @@ impl VariableList {
self.select_prev(&SelectPrevious, window, cx);
} else {
entry_state.is_expanded = false;
cx.notify();
self.build_entries(cx);
}
}
}
@ -485,7 +488,7 @@ impl VariableList {
self.select_next(&SelectNext, window, cx);
} else {
entry_state.is_expanded = true;
cx.notify();
self.build_entries(cx);
}
}
}
@ -929,8 +932,6 @@ impl Focusable for VariableList {
impl Render for VariableList {
fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
self.build_entries(cx);
v_flex()
.track_focus(&self.focus_handle)
.key_context("VariableList")
@ -946,7 +947,6 @@ impl Render for VariableList {
.on_action(cx.listener(Self::collapse_selected_entry))
.on_action(cx.listener(Self::cancel_variable_edit))
.on_action(cx.listener(Self::confirm_variable_edit))
//
.child(
uniform_list(
cx.entity().clone(),

View file

@ -1,5 +1,6 @@
use crate::{
debugger_panel::DebugPanel,
persistence::DebuggerPaneItem,
tests::{active_debug_session_panel, init_test, init_test_workspace, start_debug_session},
};
use dap::{
@ -110,7 +111,8 @@ async fn test_module_list(executor: BackgroundExecutor, cx: &mut TestAppContext)
});
running_state.update_in(cx, |this, window, cx| {
this.activate_item(crate::persistence::DebuggerPaneItem::Modules, window, cx);
this.ensure_pane_item(DebuggerPaneItem::Modules, window, cx);
this.activate_item(DebuggerPaneItem::Modules, window, cx);
cx.refresh_windows();
});

View file

@ -5,6 +5,7 @@ use std::sync::{
use crate::{
DebugPanel,
persistence::DebuggerPaneItem,
session::running::variable_list::{CollapseSelectedEntry, ExpandSelectedEntry},
tests::{active_debug_session_panel, init_test, init_test_workspace, start_debug_session},
};
@ -706,7 +707,13 @@ async fn test_keyboard_navigation(executor: BackgroundExecutor, cx: &mut TestApp
cx.focus_self(window);
let running = item.running_state().clone();
let variable_list = running.read_with(cx, |state, _| state.variable_list().clone());
let variable_list = running.update(cx, |state, cx| {
// have to do this because the variable list pane should be shown/active
// for testing keyboard navigation
state.activate_item(DebuggerPaneItem::Variables, window, cx);
state.variable_list().clone()
});
variable_list.update(cx, |_, cx| cx.focus_self(window));
running
});