Detailed changes
@@ -1,8 +1,10 @@
use dap::{DapRegistry, DebugRequest};
use fuzzy::{StringMatch, StringMatchCandidate};
-use gpui::{AppContext, DismissEvent, Entity, EventEmitter, Focusable, Render};
+use gpui::{AppContext, DismissEvent, Entity, EventEmitter, Focusable, Render, Task};
use gpui::{Subscription, WeakEntity};
use picker::{Picker, PickerDelegate};
+use project::Project;
+use rpc::proto;
use task::ZedDebugConfig;
use util::debug_panic;
@@ -56,29 +58,28 @@ impl AttachModal {
pub fn new(
definition: ZedDebugConfig,
workspace: WeakEntity<Workspace>,
+ project: Entity<Project>,
modal: bool,
window: &mut Window,
cx: &mut Context<Self>,
) -> Self {
- let mut processes: Box<[_]> = System::new_all()
- .processes()
- .values()
- .map(|process| {
- let name = process.name().to_string_lossy().into_owned();
- Candidate {
- name: name.into(),
- pid: process.pid().as_u32(),
- command: process
- .cmd()
- .iter()
- .map(|s| s.to_string_lossy().to_string())
- .collect::<Vec<_>>(),
- }
- })
- .collect();
- processes.sort_by_key(|k| k.name.clone());
- let processes = processes.into_iter().collect();
- Self::with_processes(workspace, definition, processes, modal, window, cx)
+ let processes_task = get_processes_for_project(&project, cx);
+
+ let modal = Self::with_processes(workspace, definition, Arc::new([]), modal, window, cx);
+
+ cx.spawn_in(window, async move |this, cx| {
+ let processes = processes_task.await;
+ this.update_in(cx, |modal, window, cx| {
+ modal.picker.update(cx, |picker, cx| {
+ picker.delegate.candidates = processes;
+ picker.refresh(window, cx);
+ });
+ })?;
+ anyhow::Ok(())
+ })
+ .detach_and_log_err(cx);
+
+ modal
}
pub(super) fn with_processes(
@@ -332,6 +333,57 @@ impl PickerDelegate for AttachModalDelegate {
}
}
+fn get_processes_for_project(project: &Entity<Project>, cx: &mut App) -> Task<Arc<[Candidate]>> {
+ let project = project.read(cx);
+
+ if let Some(remote_client) = project.remote_client() {
+ let proto_client = remote_client.read(cx).proto_client();
+ cx.spawn(async move |_cx| {
+ let response = proto_client
+ .request(proto::GetProcesses {
+ project_id: proto::REMOTE_SERVER_PROJECT_ID,
+ })
+ .await
+ .unwrap_or_else(|_| proto::GetProcessesResponse {
+ processes: Vec::new(),
+ });
+
+ let mut processes: Vec<Candidate> = response
+ .processes
+ .into_iter()
+ .map(|p| Candidate {
+ pid: p.pid,
+ name: p.name.into(),
+ command: p.command,
+ })
+ .collect();
+
+ processes.sort_by_key(|k| k.name.clone());
+ Arc::from(processes.into_boxed_slice())
+ })
+ } else {
+ let mut processes: Box<[_]> = System::new_all()
+ .processes()
+ .values()
+ .map(|process| {
+ let name = process.name().to_string_lossy().into_owned();
+ Candidate {
+ name: name.into(),
+ pid: process.pid().as_u32(),
+ command: process
+ .cmd()
+ .iter()
+ .map(|s| s.to_string_lossy().to_string())
+ .collect::<Vec<_>>(),
+ }
+ })
+ .collect();
+ processes.sort_by_key(|k| k.name.clone());
+ let processes = processes.into_iter().collect();
+ Task::ready(processes)
+ }
+}
+
#[cfg(any(test, feature = "test-support"))]
pub(crate) fn _process_names(modal: &AttachModal, cx: &mut Context<AttachModal>) -> Vec<String> {
modal.picker.read_with(cx, |picker, _| {
@@ -20,7 +20,7 @@ use gpui::{
};
use itertools::Itertools as _;
use picker::{Picker, PickerDelegate, highlighted_match_with_paths::HighlightedMatch};
-use project::{DebugScenarioContext, TaskContexts, TaskSourceKind, task_store::TaskStore};
+use project::{DebugScenarioContext, Project, TaskContexts, TaskSourceKind, task_store::TaskStore};
use settings::Settings;
use task::{DebugScenario, RevealTarget, ZedDebugConfig};
use theme::ThemeSettings;
@@ -88,8 +88,10 @@ impl NewProcessModal {
})?;
workspace.update_in(cx, |workspace, window, cx| {
let workspace_handle = workspace.weak_handle();
+ let project = workspace.project().clone();
workspace.toggle_modal(window, cx, |window, cx| {
- let attach_mode = AttachMode::new(None, workspace_handle.clone(), window, cx);
+ let attach_mode =
+ AttachMode::new(None, workspace_handle.clone(), project, window, cx);
let debug_picker = cx.new(|cx| {
let delegate =
@@ -940,6 +942,7 @@ impl AttachMode {
pub(super) fn new(
debugger: Option<DebugAdapterName>,
workspace: WeakEntity<Workspace>,
+ project: Entity<Project>,
window: &mut Window,
cx: &mut Context<NewProcessModal>,
) -> Entity<Self> {
@@ -950,7 +953,7 @@ impl AttachMode {
stop_on_entry: Some(false),
};
let attach_picker = cx.new(|cx| {
- let modal = AttachModal::new(definition.clone(), workspace, false, window, cx);
+ let modal = AttachModal::new(definition.clone(), workspace, project, false, window, cx);
window.focus(&modal.focus_handle(cx));
modal
@@ -546,3 +546,17 @@ message LogToDebugConsole {
uint64 session_id = 2;
string message = 3;
}
+
+message GetProcesses {
+ uint64 project_id = 1;
+}
+
+message GetProcessesResponse {
+ repeated ProcessInfo processes = 1;
+}
+
+message ProcessInfo {
+ uint32 pid = 1;
+ string name = 2;
+ repeated string command = 3;
+}
@@ -399,7 +399,10 @@ message Envelope {
LspQueryResponse lsp_query_response = 366;
ToggleLspLogs toggle_lsp_logs = 367;
- UpdateUserSettings update_user_settings = 368; // current max
+ UpdateUserSettings update_user_settings = 368;
+
+ GetProcesses get_processes = 369;
+ GetProcessesResponse get_processes_response = 370; // current max
}
reserved 87 to 88;
@@ -102,6 +102,8 @@ messages!(
(GetPathMetadata, Background),
(GetPathMetadataResponse, Background),
(GetPermalinkToLine, Foreground),
+ (GetProcesses, Background),
+ (GetProcessesResponse, Background),
(GetPermalinkToLineResponse, Foreground),
(GetProjectSymbols, Background),
(GetProjectSymbolsResponse, Background),
@@ -485,6 +487,7 @@ request_messages!(
(GetDefaultBranch, GetDefaultBranchResponse),
(GitClone, GitCloneResponse),
(ToggleLspLogs, Ack),
+ (GetProcesses, GetProcessesResponse),
);
lsp_messages!(
@@ -610,6 +613,7 @@ entity_messages!(
ActivateToolchain,
ActiveToolchain,
GetPathMetadata,
+ GetProcesses,
CancelLanguageServerWork,
RegisterBufferWithLanguageServers,
GitShow,
@@ -32,6 +32,7 @@ use std::{
path::{Path, PathBuf},
sync::{Arc, atomic::AtomicUsize},
};
+use sysinfo::System;
use util::ResultExt;
use worktree::Worktree;
@@ -230,6 +231,7 @@ impl HeadlessProject {
session.add_request_handler(cx.weak_entity(), Self::handle_get_path_metadata);
session.add_request_handler(cx.weak_entity(), Self::handle_shutdown_remote_server);
session.add_request_handler(cx.weak_entity(), Self::handle_ping);
+ session.add_request_handler(cx.weak_entity(), Self::handle_get_processes);
session.add_entity_request_handler(Self::handle_add_worktree);
session.add_request_handler(cx.weak_entity(), Self::handle_remove_worktree);
@@ -719,6 +721,34 @@ impl HeadlessProject {
log::debug!("Received ping from client");
Ok(proto::Ack {})
}
+
+ async fn handle_get_processes(
+ _this: Entity<Self>,
+ _envelope: TypedEnvelope<proto::GetProcesses>,
+ _cx: AsyncApp,
+ ) -> Result<proto::GetProcessesResponse> {
+ let mut processes = Vec::new();
+ let system = System::new_all();
+
+ for (_pid, process) in system.processes() {
+ let name = process.name().to_string_lossy().into_owned();
+ let command = process
+ .cmd()
+ .iter()
+ .map(|s| s.to_string_lossy().to_string())
+ .collect::<Vec<_>>();
+
+ processes.push(proto::ProcessInfo {
+ pid: process.pid().as_u32(),
+ name,
+ command,
+ });
+ }
+
+ processes.sort_by_key(|p| p.name.clone());
+
+ Ok(proto::GetProcessesResponse { processes })
+ }
}
fn prompt_to_proto(