debugger: Update New Session Modal (#30018)
This PR simplifies the new session modal by flattening its three modes and updating the UI to be less noisy. The new UI also defaults to the Debug Scenario Picker, and allows users to save debug scenarios created in the UI to the active worktree's .zed/debug.json file. Release Notes: - N/A
This commit is contained in:
parent
e9a756b5fc
commit
dc01aef0cf
12 changed files with 460 additions and 527 deletions
|
@ -43,6 +43,7 @@ language.workspace = true
|
|||
log.workspace = true
|
||||
menu.workspace = true
|
||||
parking_lot.workspace = true
|
||||
paths.workspace = true
|
||||
picker.workspace = true
|
||||
pretty_assertions.workspace = true
|
||||
project.workspace = true
|
||||
|
|
|
@ -32,12 +32,12 @@ pub(crate) struct AttachModalDelegate {
|
|||
|
||||
impl AttachModalDelegate {
|
||||
fn new(
|
||||
workspace: Entity<Workspace>,
|
||||
workspace: WeakEntity<Workspace>,
|
||||
definition: DebugTaskDefinition,
|
||||
candidates: Arc<[Candidate]>,
|
||||
) -> Self {
|
||||
Self {
|
||||
workspace: workspace.downgrade(),
|
||||
workspace,
|
||||
definition,
|
||||
candidates,
|
||||
selected_index: 0,
|
||||
|
@ -55,7 +55,7 @@ pub struct AttachModal {
|
|||
impl AttachModal {
|
||||
pub fn new(
|
||||
definition: DebugTaskDefinition,
|
||||
workspace: Entity<Workspace>,
|
||||
workspace: WeakEntity<Workspace>,
|
||||
modal: bool,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
|
@ -82,7 +82,7 @@ impl AttachModal {
|
|||
}
|
||||
|
||||
pub(super) fn with_processes(
|
||||
workspace: Entity<Workspace>,
|
||||
workspace: WeakEntity<Workspace>,
|
||||
definition: DebugTaskDefinition,
|
||||
processes: Arc<[Candidate]>,
|
||||
modal: bool,
|
||||
|
|
|
@ -5,15 +5,15 @@ use crate::{
|
|||
FocusLoadedSources, FocusModules, FocusTerminal, FocusVariables, Pause, Restart, StepBack,
|
||||
StepInto, StepOut, StepOver, Stop, ToggleIgnoreBreakpoints, persistence,
|
||||
};
|
||||
use anyhow::Result;
|
||||
use anyhow::{Result, anyhow};
|
||||
use command_palette_hooks::CommandPaletteFilter;
|
||||
use dap::StartDebuggingRequestArguments;
|
||||
use dap::adapters::DebugAdapterName;
|
||||
use dap::debugger_settings::DebugPanelDockPosition;
|
||||
use dap::{
|
||||
ContinuedEvent, LoadedSourceEvent, ModuleEvent, OutputEvent, StoppedEvent, ThreadEvent,
|
||||
client::SessionId, debugger_settings::DebuggerSettings,
|
||||
};
|
||||
use dap::{StartDebuggingRequestArguments, adapters::DebugTaskDefinition};
|
||||
use gpui::{
|
||||
Action, App, AsyncWindowContext, Context, DismissEvent, Entity, EntityId, EventEmitter,
|
||||
FocusHandle, Focusable, MouseButton, MouseDownEvent, Point, Subscription, Task, WeakEntity,
|
||||
|
@ -54,12 +54,11 @@ pub enum DebugPanelEvent {
|
|||
}
|
||||
|
||||
actions!(debug_panel, [ToggleFocus]);
|
||||
|
||||
pub struct DebugPanel {
|
||||
size: Pixels,
|
||||
sessions: Vec<Entity<DebugSession>>,
|
||||
active_session: Option<Entity<DebugSession>>,
|
||||
/// This represents the last debug definition that was created in the new session modal
|
||||
pub(crate) past_debug_definition: Option<DebugTaskDefinition>,
|
||||
project: Entity<Project>,
|
||||
workspace: WeakEntity<Workspace>,
|
||||
focus_handle: FocusHandle,
|
||||
|
@ -80,7 +79,6 @@ impl DebugPanel {
|
|||
size: px(300.),
|
||||
sessions: vec![],
|
||||
active_session: None,
|
||||
past_debug_definition: None,
|
||||
focus_handle: cx.focus_handle(),
|
||||
project,
|
||||
workspace: workspace.weak_handle(),
|
||||
|
@ -992,6 +990,69 @@ impl DebugPanel {
|
|||
self.active_session = Some(session_item);
|
||||
cx.notify();
|
||||
}
|
||||
|
||||
pub(crate) fn save_scenario(
|
||||
&self,
|
||||
scenario: &DebugScenario,
|
||||
worktree_id: WorktreeId,
|
||||
window: &mut Window,
|
||||
cx: &mut App,
|
||||
) -> Task<Result<()>> {
|
||||
self.workspace
|
||||
.update(cx, |workspace, cx| {
|
||||
let Some(mut path) = workspace.absolute_path_of_worktree(worktree_id, cx) else {
|
||||
return Task::ready(Err(anyhow!("Couldn't get worktree path")));
|
||||
};
|
||||
|
||||
let serialized_scenario = serde_json::to_value(scenario);
|
||||
|
||||
path.push(paths::local_debug_file_relative_path());
|
||||
|
||||
cx.spawn_in(window, async move |workspace, cx| {
|
||||
let serialized_scenario = serialized_scenario?;
|
||||
let path = path.as_path();
|
||||
let fs =
|
||||
workspace.update(cx, |workspace, _| workspace.app_state().fs.clone())?;
|
||||
|
||||
if !fs.is_file(path).await {
|
||||
let content =
|
||||
serde_json::to_string_pretty(&serde_json::Value::Array(vec![
|
||||
serialized_scenario,
|
||||
]))?;
|
||||
|
||||
fs.create_file(path, Default::default()).await?;
|
||||
fs.save(path, &content.into(), Default::default()).await?;
|
||||
} else {
|
||||
let content = fs.load(path).await?;
|
||||
let mut values = serde_json::from_str::<Vec<serde_json::Value>>(&content)?;
|
||||
values.push(serialized_scenario);
|
||||
fs.save(
|
||||
path,
|
||||
&serde_json::to_string_pretty(&values).map(Into::into)?,
|
||||
Default::default(),
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
|
||||
workspace.update_in(cx, |workspace, window, cx| {
|
||||
if let Some(project_path) = workspace
|
||||
.project()
|
||||
.read(cx)
|
||||
.project_path_for_absolute_path(&path, cx)
|
||||
{
|
||||
workspace.open_path(project_path, None, true, window, cx)
|
||||
} else {
|
||||
Task::ready(Err(anyhow!(
|
||||
"Couldn't get project path for .zed/debug.json in active worktree"
|
||||
)))
|
||||
}
|
||||
})?.await?;
|
||||
|
||||
anyhow::Ok(())
|
||||
})
|
||||
})
|
||||
.unwrap_or_else(|err| Task::ready(Err(err)))
|
||||
}
|
||||
}
|
||||
|
||||
impl EventEmitter<PanelEvent> for DebugPanel {}
|
||||
|
|
|
@ -147,36 +147,7 @@ pub fn init(cx: &mut App) {
|
|||
},
|
||||
)
|
||||
.register_action(|workspace: &mut Workspace, _: &Start, window, cx| {
|
||||
if let Some(debug_panel) = workspace.panel::<DebugPanel>(cx) {
|
||||
let weak_panel = debug_panel.downgrade();
|
||||
let weak_workspace = cx.weak_entity();
|
||||
let task_store = workspace.project().read(cx).task_store().clone();
|
||||
|
||||
cx.spawn_in(window, async move |this, cx| {
|
||||
let task_contexts = this
|
||||
.update_in(cx, |workspace, window, cx| {
|
||||
tasks_ui::task_contexts(workspace, window, cx)
|
||||
})?
|
||||
.await;
|
||||
|
||||
this.update_in(cx, |workspace, window, cx| {
|
||||
workspace.toggle_modal(window, cx, |window, cx| {
|
||||
NewSessionModal::new(
|
||||
debug_panel.read(cx).past_debug_definition.clone(),
|
||||
weak_panel,
|
||||
weak_workspace,
|
||||
Some(task_store),
|
||||
task_contexts,
|
||||
window,
|
||||
cx,
|
||||
)
|
||||
});
|
||||
})?;
|
||||
|
||||
anyhow::Ok(())
|
||||
})
|
||||
.detach()
|
||||
}
|
||||
NewSessionModal::show(workspace, window, cx);
|
||||
});
|
||||
})
|
||||
})
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -864,7 +864,7 @@ impl RunningState {
|
|||
|
||||
dap::DebugRequest::Launch(new_launch_request)
|
||||
}
|
||||
request @ dap::DebugRequest::Attach(_) => request,
|
||||
request @ dap::DebugRequest::Attach(_) => request, // todo(debugger): We should check that process_id is valid and if not show the modal
|
||||
};
|
||||
Ok(DebugTaskDefinition {
|
||||
label,
|
||||
|
|
|
@ -103,7 +103,7 @@ async fn test_show_attach_modal_and_select_process(
|
|||
});
|
||||
let attach_modal = workspace
|
||||
.update(cx, |workspace, window, cx| {
|
||||
let workspace_handle = cx.entity();
|
||||
let workspace_handle = cx.weak_entity();
|
||||
workspace.toggle_modal(window, cx, |window, cx| {
|
||||
AttachModal::with_processes(
|
||||
workspace_handle,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue