Detailed changes
@@ -4001,7 +4001,6 @@ dependencies = [
"node_runtime",
"parking_lot",
"paths",
- "regex",
"schemars",
"serde",
"serde_json",
@@ -4033,7 +4032,6 @@ dependencies = [
"gpui",
"language",
"paths",
- "regex",
"serde",
"serde_json",
"task",
@@ -39,7 +39,6 @@ log.workspace = true
node_runtime.workspace = true
parking_lot.workspace = true
paths.workspace = true
-regex.workspace = true
schemars.workspace = true
serde.workspace = true
serde_json.workspace = true
@@ -20,7 +20,7 @@ use std::{
net::Ipv4Addr,
ops::Deref,
path::PathBuf,
- sync::{Arc, LazyLock},
+ sync::Arc,
};
use task::{DebugAdapterConfig, DebugTaskDefinition};
use util::ResultExt;
@@ -291,14 +291,7 @@ pub trait DebugAdapter: 'static + Send + Sync {
/// Should return base configuration to make the debug adapter work
fn request_args(&self, config: &DebugTaskDefinition) -> Value;
-
- fn attach_processes_filter(&self) -> regex::Regex {
- EMPTY_REGEX.clone()
- }
}
-
-static EMPTY_REGEX: LazyLock<regex::Regex> =
- LazyLock::new(|| regex::Regex::new("").expect("Regex compilation to succeed"));
#[cfg(any(test, feature = "test-support"))]
pub struct FakeAdapter {}
@@ -375,10 +368,4 @@ impl DebugAdapter for FakeAdapter {
},
})
}
-
- fn attach_processes_filter(&self) -> regex::Regex {
- static REGEX: LazyLock<regex::Regex> =
- LazyLock::new(|| regex::Regex::new("^fake-binary").unwrap());
- REGEX.clone()
- }
}
@@ -8,7 +8,7 @@ struct DapRegistryState {
adapters: BTreeMap<DebugAdapterName, Arc<dyn DebugAdapter>>,
}
-#[derive(Default)]
+#[derive(Clone, Default)]
/// Stores available debug adapters.
pub struct DapRegistry(Arc<RwLock<DapRegistryState>>);
@@ -27,7 +27,6 @@ dap.workspace = true
gpui.workspace = true
language.workspace = true
paths.workspace = true
-regex.workspace = true
serde.workspace = true
serde_json.workspace = true
task.workspace = true
@@ -31,7 +31,7 @@ pub fn init(registry: Arc<DapRegistry>) {
registry.add_adapter(Arc::from(CodeLldbDebugAdapter::default()));
registry.add_adapter(Arc::from(PythonDebugAdapter));
registry.add_adapter(Arc::from(PhpDebugAdapter));
- registry.add_adapter(Arc::from(JsDebugAdapter::default()));
+ registry.add_adapter(Arc::from(JsDebugAdapter));
registry.add_adapter(Arc::from(LldbDebugAdapter));
registry.add_adapter(Arc::from(GoDebugAdapter));
registry.add_adapter(Arc::from(GdbDebugAdapter));
@@ -1,24 +1,13 @@
use adapters::latest_github_release;
use gpui::AsyncApp;
-use regex::Regex;
use std::path::PathBuf;
use task::{DebugRequestType, DebugTaskDefinition};
use crate::*;
#[derive(Debug)]
-pub(crate) struct JsDebugAdapter {
- attach_processes: Regex,
-}
+pub(crate) struct JsDebugAdapter;
-impl Default for JsDebugAdapter {
- fn default() -> Self {
- Self {
- attach_processes: Regex::new(r"(?i)^(?:node|bun|iojs)(?:$|\b)")
- .expect("Regex compilation to succeed"),
- }
- }
-}
impl JsDebugAdapter {
const ADAPTER_NAME: &'static str = "JavaScript";
const ADAPTER_NPM_NAME: &'static str = "vscode-js-debug";
@@ -149,8 +138,4 @@ impl DebugAdapter for JsDebugAdapter {
}
args
}
-
- fn attach_processes_filter(&self) -> Regex {
- self.attach_processes.clone()
- }
}
@@ -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);