debugger: Always show process list in attach (#28685)
Closes #ISSUE Release Notes: - N/A
This commit is contained in:
parent
d4a985a6e3
commit
98d001bad5
10 changed files with 78 additions and 112 deletions
|
@ -4,7 +4,6 @@ use gpui::Subscription;
|
|||
use gpui::{DismissEvent, Entity, EventEmitter, Focusable, Render};
|
||||
use picker::{Picker, PickerDelegate};
|
||||
|
||||
use std::cell::LazyCell;
|
||||
use std::sync::Arc;
|
||||
use sysinfo::System;
|
||||
use ui::{Context, Tooltip, prelude::*};
|
||||
|
@ -24,7 +23,7 @@ pub(crate) struct AttachModalDelegate {
|
|||
matches: Vec<StringMatch>,
|
||||
placeholder_text: Arc<str>,
|
||||
project: Entity<project::Project>,
|
||||
debug_config: task::DebugTaskDefinition,
|
||||
pub(crate) debug_config: task::DebugTaskDefinition,
|
||||
candidates: Arc<[Candidate]>,
|
||||
}
|
||||
|
||||
|
@ -58,7 +57,7 @@ impl AttachModal {
|
|||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) -> Self {
|
||||
let mut processes: Vec<_> = System::new_all()
|
||||
let mut processes: Box<[_]> = System::new_all()
|
||||
.processes()
|
||||
.values()
|
||||
.map(|process| {
|
||||
|
@ -75,30 +74,18 @@ impl AttachModal {
|
|||
})
|
||||
.collect();
|
||||
processes.sort_by_key(|k| k.name.clone());
|
||||
let processes = processes.into_iter().collect();
|
||||
Self::with_processes(project, debug_config, processes, modal, window, cx)
|
||||
}
|
||||
|
||||
pub(super) fn with_processes(
|
||||
project: Entity<project::Project>,
|
||||
debug_config: task::DebugTaskDefinition,
|
||||
processes: Vec<Candidate>,
|
||||
processes: Arc<[Candidate]>,
|
||||
modal: bool,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) -> Self {
|
||||
let adapter = project
|
||||
.read(cx)
|
||||
.debug_adapters()
|
||||
.adapter(&debug_config.adapter);
|
||||
let filter = LazyCell::new(|| adapter.map(|adapter| adapter.attach_processes_filter()));
|
||||
let processes = processes
|
||||
.into_iter()
|
||||
.filter(|process| {
|
||||
filter
|
||||
.as_ref()
|
||||
.map_or(false, |filter| filter.is_match(&process.name))
|
||||
})
|
||||
.collect();
|
||||
let picker = cx.new(|cx| {
|
||||
Picker::uniform_list(
|
||||
AttachModalDelegate::new(project, debug_config, processes),
|
||||
|
@ -117,9 +104,10 @@ impl AttachModal {
|
|||
}
|
||||
|
||||
impl Render for AttachModal {
|
||||
fn render(&mut self, _window: &mut Window, _: &mut Context<Self>) -> impl ui::IntoElement {
|
||||
fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl ui::IntoElement {
|
||||
v_flex()
|
||||
.key_context("AttachModal")
|
||||
.track_focus(&self.focus_handle(cx))
|
||||
.w(rems(34.))
|
||||
.child(self.picker.clone())
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ use gpui::{
|
|||
App, AppContext, DismissEvent, Entity, EventEmitter, FocusHandle, Focusable, Render, TextStyle,
|
||||
WeakEntity,
|
||||
};
|
||||
use project::Project;
|
||||
use settings::Settings;
|
||||
use task::{DebugTaskDefinition, LaunchConfig};
|
||||
use theme::ThemeSettings;
|
||||
|
@ -59,7 +60,7 @@ impl NewSessionModal {
|
|||
debug_panel: WeakEntity<DebugPanel>,
|
||||
workspace: WeakEntity<Workspace>,
|
||||
window: &mut Window,
|
||||
cx: &mut App,
|
||||
cx: &mut Context<Self>,
|
||||
) -> Self {
|
||||
let debugger = past_debug_definition
|
||||
.as_ref()
|
||||
|
@ -171,25 +172,13 @@ impl NewSessionModal {
|
|||
attach.update(cx, |this, cx| {
|
||||
if selected_debugger != this.debug_definition.adapter {
|
||||
this.debug_definition.adapter = selected_debugger.into();
|
||||
if let Some(project) = this
|
||||
.workspace
|
||||
.read_with(cx, |workspace, _| workspace.project().clone())
|
||||
.ok()
|
||||
{
|
||||
this.attach_picker = Some(cx.new(|cx| {
|
||||
let modal = AttachModal::new(
|
||||
project,
|
||||
this.debug_definition.clone(),
|
||||
false,
|
||||
window,
|
||||
cx,
|
||||
);
|
||||
|
||||
window.focus(&modal.focus_handle(cx));
|
||||
|
||||
modal
|
||||
}));
|
||||
}
|
||||
this.attach_picker.update(cx, |this, cx| {
|
||||
this.picker.update(cx, |this, cx| {
|
||||
this.delegate.debug_config.adapter = selected_debugger.into();
|
||||
this.focus(window, cx);
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
cx.notify();
|
||||
|
@ -256,7 +245,6 @@ impl NewSessionModal {
|
|||
ContextMenu::build(window, cx, move |mut menu, _, cx| {
|
||||
let setter_for_name = |task: DebugTaskDefinition| {
|
||||
let weak = weak.clone();
|
||||
let workspace = workspace.clone();
|
||||
move |window: &mut Window, cx: &mut App| {
|
||||
weak.update(cx, |this, cx| {
|
||||
this.last_selected_profile_name = Some(SharedString::from(&task.label));
|
||||
|
@ -271,12 +259,19 @@ impl NewSessionModal {
|
|||
);
|
||||
}
|
||||
DebugRequestType::Attach(_) => {
|
||||
let Ok(project) = this
|
||||
.workspace
|
||||
.read_with(cx, |this, _| this.project().clone())
|
||||
else {
|
||||
return;
|
||||
};
|
||||
this.mode = NewSessionMode::attach(
|
||||
this.debugger.clone(),
|
||||
workspace.clone(),
|
||||
project,
|
||||
window,
|
||||
cx,
|
||||
);
|
||||
this.mode.focus_handle(cx).focus(window);
|
||||
if let Some((debugger, attach)) =
|
||||
this.debugger.as_ref().zip(this.mode.as_attach())
|
||||
{
|
||||
|
@ -365,18 +360,16 @@ impl LaunchMode {
|
|||
|
||||
#[derive(Clone)]
|
||||
struct AttachMode {
|
||||
workspace: WeakEntity<Workspace>,
|
||||
debug_definition: DebugTaskDefinition,
|
||||
attach_picker: Option<Entity<AttachModal>>,
|
||||
focus_handle: FocusHandle,
|
||||
attach_picker: Entity<AttachModal>,
|
||||
}
|
||||
|
||||
impl AttachMode {
|
||||
fn new(
|
||||
debugger: Option<SharedString>,
|
||||
workspace: WeakEntity<Workspace>,
|
||||
project: Entity<Project>,
|
||||
window: &mut Window,
|
||||
cx: &mut App,
|
||||
cx: &mut Context<NewSessionModal>,
|
||||
) -> Entity<Self> {
|
||||
let debug_definition = DebugTaskDefinition {
|
||||
label: "Attach New Session Setup".into(),
|
||||
|
@ -387,27 +380,15 @@ impl AttachMode {
|
|||
initialize_args: None,
|
||||
stop_on_entry: Some(false),
|
||||
};
|
||||
let attach_picker = cx.new(|cx| {
|
||||
let modal = AttachModal::new(project, debug_definition.clone(), false, window, cx);
|
||||
window.focus(&modal.focus_handle(cx));
|
||||
|
||||
let attach_picker = if let Some(project) = debugger.and(
|
||||
workspace
|
||||
.read_with(cx, |workspace, _| workspace.project().clone())
|
||||
.ok(),
|
||||
) {
|
||||
Some(cx.new(|cx| {
|
||||
let modal = AttachModal::new(project, debug_definition.clone(), false, window, cx);
|
||||
window.focus(&modal.focus_handle(cx));
|
||||
|
||||
modal
|
||||
}))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
cx.new(|cx| Self {
|
||||
workspace,
|
||||
modal
|
||||
});
|
||||
cx.new(|_| Self {
|
||||
debug_definition,
|
||||
attach_picker,
|
||||
focus_handle: cx.focus_handle(),
|
||||
})
|
||||
}
|
||||
fn debug_task(&self) -> task::AttachConfig {
|
||||
|
@ -444,7 +425,7 @@ impl Focusable for NewSessionMode {
|
|||
fn focus_handle(&self, cx: &App) -> FocusHandle {
|
||||
match &self {
|
||||
NewSessionMode::Launch(entity) => entity.read(cx).program.focus_handle(cx),
|
||||
NewSessionMode::Attach(entity) => entity.read(cx).focus_handle.clone(),
|
||||
NewSessionMode::Attach(entity) => entity.read(cx).attach_picker.focus_handle(cx),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -476,8 +457,11 @@ impl RenderOnce for LaunchMode {
|
|||
}
|
||||
|
||||
impl RenderOnce for AttachMode {
|
||||
fn render(self, _: &mut Window, _: &mut App) -> impl IntoElement {
|
||||
v_flex().w_full().children(self.attach_picker.clone())
|
||||
fn render(self, _: &mut Window, cx: &mut App) -> impl IntoElement {
|
||||
v_flex()
|
||||
.w_full()
|
||||
.track_focus(&self.attach_picker.focus_handle(cx))
|
||||
.child(self.attach_picker.clone())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -497,13 +481,17 @@ impl RenderOnce for NewSessionMode {
|
|||
impl NewSessionMode {
|
||||
fn attach(
|
||||
debugger: Option<SharedString>,
|
||||
workspace: WeakEntity<Workspace>,
|
||||
project: Entity<Project>,
|
||||
window: &mut Window,
|
||||
cx: &mut App,
|
||||
cx: &mut Context<NewSessionModal>,
|
||||
) -> Self {
|
||||
Self::Attach(AttachMode::new(debugger, workspace, window, cx))
|
||||
Self::Attach(AttachMode::new(debugger, project, window, cx))
|
||||
}
|
||||
fn launch(past_launch_config: Option<LaunchConfig>, window: &mut Window, cx: &mut App) -> Self {
|
||||
fn launch(
|
||||
past_launch_config: Option<LaunchConfig>,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<NewSessionModal>,
|
||||
) -> Self {
|
||||
Self::Launch(LaunchMode::new(past_launch_config, window, cx))
|
||||
}
|
||||
}
|
||||
|
@ -592,18 +580,25 @@ impl Render for NewSessionModal {
|
|||
.toggle_state(matches!(self.mode, NewSessionMode::Attach(_)))
|
||||
.style(ui::ButtonStyle::Subtle)
|
||||
.on_click(cx.listener(|this, _, window, cx| {
|
||||
let Ok(project) = this
|
||||
.workspace
|
||||
.read_with(cx, |this, _| this.project().clone())
|
||||
else {
|
||||
return;
|
||||
};
|
||||
this.mode = NewSessionMode::attach(
|
||||
this.debugger.clone(),
|
||||
this.workspace.clone(),
|
||||
project,
|
||||
window,
|
||||
cx,
|
||||
);
|
||||
this.mode.focus_handle(cx).focus(window);
|
||||
if let Some((debugger, attach)) =
|
||||
this.debugger.as_ref().zip(this.mode.as_attach())
|
||||
{
|
||||
Self::update_attach_picker(&attach, &debugger, window, cx);
|
||||
}
|
||||
this.mode.focus_handle(cx).focus(window);
|
||||
|
||||
cx.notify();
|
||||
}))
|
||||
.last(),
|
||||
|
|
|
@ -100,7 +100,7 @@ async fn test_show_attach_modal_and_select_process(
|
|||
},
|
||||
Candidate {
|
||||
pid: 3,
|
||||
name: "non-fake-binary-1".into(),
|
||||
name: "real-binary-1".into(),
|
||||
command: vec![],
|
||||
},
|
||||
Candidate {
|
||||
|
@ -108,7 +108,9 @@ async fn test_show_attach_modal_and_select_process(
|
|||
name: "fake-binary-2".into(),
|
||||
command: vec![],
|
||||
},
|
||||
],
|
||||
]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
true,
|
||||
window,
|
||||
cx,
|
||||
|
@ -121,17 +123,30 @@ async fn test_show_attach_modal_and_select_process(
|
|||
|
||||
cx.run_until_parked();
|
||||
|
||||
// assert we got the expected processes
|
||||
workspace
|
||||
.update(cx, |_, window, cx| {
|
||||
let names =
|
||||
attach_modal.update(cx, |modal, cx| attach_modal::_process_names(&modal, cx));
|
||||
// Initially all processes are visible.
|
||||
assert_eq!(3, names.len());
|
||||
attach_modal.update(cx, |this, cx| {
|
||||
this.picker.update(cx, |this, cx| {
|
||||
this.set_query("fakb", window, cx);
|
||||
})
|
||||
})
|
||||
})
|
||||
.unwrap();
|
||||
cx.run_until_parked();
|
||||
// assert we got the expected processes
|
||||
workspace
|
||||
.update(cx, |_, _, cx| {
|
||||
let names =
|
||||
attach_modal.update(cx, |modal, cx| attach_modal::_process_names(&modal, cx));
|
||||
|
||||
// we filtered out all processes that are not starting with `fake-binary`
|
||||
// Initially all processes are visible.
|
||||
assert_eq!(2, names.len());
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
// select the only existing process
|
||||
cx.dispatch_action(Confirm);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue