DAP log view improvements (#34311)
Now DAP logs show the label of each session which makes it much easier to pick out the right one. Also "initialization sequence" now shows up correctly when that view is selected. Release Notes: - N/A --------- Co-authored-by: Cole Miller <cole@zed.dev>
This commit is contained in:
parent
625a4b90a5
commit
c3edc2cfc1
2 changed files with 56 additions and 30 deletions
|
@ -32,12 +32,19 @@ use workspace::{
|
||||||
ui::{Button, Clickable, ContextMenu, Label, LabelCommon, PopoverMenu, h_flex},
|
ui::{Button, Clickable, ContextMenu, Label, LabelCommon, PopoverMenu, h_flex},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||||
|
enum View {
|
||||||
|
AdapterLogs,
|
||||||
|
RpcMessages,
|
||||||
|
InitializationSequence,
|
||||||
|
}
|
||||||
|
|
||||||
struct DapLogView {
|
struct DapLogView {
|
||||||
editor: Entity<Editor>,
|
editor: Entity<Editor>,
|
||||||
focus_handle: FocusHandle,
|
focus_handle: FocusHandle,
|
||||||
log_store: Entity<LogStore>,
|
log_store: Entity<LogStore>,
|
||||||
editor_subscriptions: Vec<Subscription>,
|
editor_subscriptions: Vec<Subscription>,
|
||||||
current_view: Option<(SessionId, LogKind)>,
|
current_view: Option<(SessionId, View)>,
|
||||||
project: Entity<Project>,
|
project: Entity<Project>,
|
||||||
_subscriptions: Vec<Subscription>,
|
_subscriptions: Vec<Subscription>,
|
||||||
}
|
}
|
||||||
|
@ -77,6 +84,7 @@ struct DebugAdapterState {
|
||||||
id: SessionId,
|
id: SessionId,
|
||||||
log_messages: VecDeque<SharedString>,
|
log_messages: VecDeque<SharedString>,
|
||||||
rpc_messages: RpcMessages,
|
rpc_messages: RpcMessages,
|
||||||
|
session_label: SharedString,
|
||||||
adapter_name: DebugAdapterName,
|
adapter_name: DebugAdapterName,
|
||||||
has_adapter_logs: bool,
|
has_adapter_logs: bool,
|
||||||
is_terminated: bool,
|
is_terminated: bool,
|
||||||
|
@ -121,12 +129,18 @@ impl MessageKind {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DebugAdapterState {
|
impl DebugAdapterState {
|
||||||
fn new(id: SessionId, adapter_name: DebugAdapterName, has_adapter_logs: bool) -> Self {
|
fn new(
|
||||||
|
id: SessionId,
|
||||||
|
adapter_name: DebugAdapterName,
|
||||||
|
session_label: SharedString,
|
||||||
|
has_adapter_logs: bool,
|
||||||
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
id,
|
id,
|
||||||
log_messages: VecDeque::new(),
|
log_messages: VecDeque::new(),
|
||||||
rpc_messages: RpcMessages::new(),
|
rpc_messages: RpcMessages::new(),
|
||||||
adapter_name,
|
adapter_name,
|
||||||
|
session_label,
|
||||||
has_adapter_logs,
|
has_adapter_logs,
|
||||||
is_terminated: false,
|
is_terminated: false,
|
||||||
}
|
}
|
||||||
|
@ -371,18 +385,21 @@ impl LogStore {
|
||||||
return None;
|
return None;
|
||||||
};
|
};
|
||||||
|
|
||||||
let (adapter_name, has_adapter_logs) = session.read_with(cx, |session, _| {
|
let (adapter_name, session_label, has_adapter_logs) =
|
||||||
(
|
session.read_with(cx, |session, _| {
|
||||||
session.adapter(),
|
(
|
||||||
session
|
session.adapter(),
|
||||||
.adapter_client()
|
session.label(),
|
||||||
.map_or(false, |client| client.has_adapter_logs()),
|
session
|
||||||
)
|
.adapter_client()
|
||||||
});
|
.map_or(false, |client| client.has_adapter_logs()),
|
||||||
|
)
|
||||||
|
});
|
||||||
|
|
||||||
state.insert(DebugAdapterState::new(
|
state.insert(DebugAdapterState::new(
|
||||||
id.session_id,
|
id.session_id,
|
||||||
adapter_name,
|
adapter_name,
|
||||||
|
session_label,
|
||||||
has_adapter_logs,
|
has_adapter_logs,
|
||||||
));
|
));
|
||||||
|
|
||||||
|
@ -506,12 +523,13 @@ impl Render for DapLogToolbarItemView {
|
||||||
current_client
|
current_client
|
||||||
.map(|sub_item| {
|
.map(|sub_item| {
|
||||||
Cow::Owned(format!(
|
Cow::Owned(format!(
|
||||||
"{} ({}) - {}",
|
"{} - {} - {}",
|
||||||
sub_item.adapter_name,
|
sub_item.adapter_name,
|
||||||
sub_item.session_id.0,
|
sub_item.session_label,
|
||||||
match sub_item.selected_entry {
|
match sub_item.selected_entry {
|
||||||
LogKind::Adapter => ADAPTER_LOGS,
|
View::AdapterLogs => ADAPTER_LOGS,
|
||||||
LogKind::Rpc => RPC_MESSAGES,
|
View::RpcMessages => RPC_MESSAGES,
|
||||||
|
View::InitializationSequence => INITIALIZATION_SEQUENCE,
|
||||||
}
|
}
|
||||||
))
|
))
|
||||||
})
|
})
|
||||||
|
@ -529,8 +547,8 @@ impl Render for DapLogToolbarItemView {
|
||||||
.pl_2()
|
.pl_2()
|
||||||
.child(
|
.child(
|
||||||
Label::new(format!(
|
Label::new(format!(
|
||||||
"{}. {}",
|
"{} - {}",
|
||||||
row.session_id.0, row.adapter_name,
|
row.adapter_name, row.session_label
|
||||||
))
|
))
|
||||||
.color(workspace::ui::Color::Muted),
|
.color(workspace::ui::Color::Muted),
|
||||||
)
|
)
|
||||||
|
@ -669,9 +687,16 @@ impl DapLogView {
|
||||||
|
|
||||||
let events_subscriptions = cx.subscribe(&log_store, |log_view, _, event, cx| match event {
|
let events_subscriptions = cx.subscribe(&log_store, |log_view, _, event, cx| match event {
|
||||||
Event::NewLogEntry { id, entry, kind } => {
|
Event::NewLogEntry { id, entry, kind } => {
|
||||||
if log_view.current_view == Some((id.session_id, *kind))
|
let is_current_view = match (log_view.current_view, *kind) {
|
||||||
&& log_view.project == *id.project
|
(Some((i, View::AdapterLogs)), LogKind::Adapter)
|
||||||
{
|
| (Some((i, View::RpcMessages)), LogKind::Rpc)
|
||||||
|
if i == id.session_id =>
|
||||||
|
{
|
||||||
|
log_view.project == *id.project
|
||||||
|
}
|
||||||
|
_ => false,
|
||||||
|
};
|
||||||
|
if is_current_view {
|
||||||
log_view.editor.update(cx, |editor, cx| {
|
log_view.editor.update(cx, |editor, cx| {
|
||||||
editor.set_read_only(false);
|
editor.set_read_only(false);
|
||||||
let last_point = editor.buffer().read(cx).len(cx);
|
let last_point = editor.buffer().read(cx).len(cx);
|
||||||
|
@ -768,10 +793,11 @@ impl DapLogView {
|
||||||
.map(|state| DapMenuItem {
|
.map(|state| DapMenuItem {
|
||||||
session_id: state.id,
|
session_id: state.id,
|
||||||
adapter_name: state.adapter_name.clone(),
|
adapter_name: state.adapter_name.clone(),
|
||||||
|
session_label: state.session_label.clone(),
|
||||||
has_adapter_logs: state.has_adapter_logs,
|
has_adapter_logs: state.has_adapter_logs,
|
||||||
selected_entry: self
|
selected_entry: self
|
||||||
.current_view
|
.current_view
|
||||||
.map_or(LogKind::Adapter, |(_, kind)| kind),
|
.map_or(View::AdapterLogs, |(_, kind)| kind),
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
})
|
})
|
||||||
|
@ -789,7 +815,7 @@ impl DapLogView {
|
||||||
.map(|state| log_contents(state.iter().cloned()))
|
.map(|state| log_contents(state.iter().cloned()))
|
||||||
});
|
});
|
||||||
if let Some(rpc_log) = rpc_log {
|
if let Some(rpc_log) = rpc_log {
|
||||||
self.current_view = Some((id.session_id, LogKind::Rpc));
|
self.current_view = Some((id.session_id, View::RpcMessages));
|
||||||
let (editor, editor_subscriptions) = Self::editor_for_logs(rpc_log, window, cx);
|
let (editor, editor_subscriptions) = Self::editor_for_logs(rpc_log, window, cx);
|
||||||
let language = self.project.read(cx).languages().language_for_name("JSON");
|
let language = self.project.read(cx).languages().language_for_name("JSON");
|
||||||
editor
|
editor
|
||||||
|
@ -830,7 +856,7 @@ impl DapLogView {
|
||||||
.map(|state| log_contents(state.iter().cloned()))
|
.map(|state| log_contents(state.iter().cloned()))
|
||||||
});
|
});
|
||||||
if let Some(message_log) = message_log {
|
if let Some(message_log) = message_log {
|
||||||
self.current_view = Some((id.session_id, LogKind::Adapter));
|
self.current_view = Some((id.session_id, View::AdapterLogs));
|
||||||
let (editor, editor_subscriptions) = Self::editor_for_logs(message_log, window, cx);
|
let (editor, editor_subscriptions) = Self::editor_for_logs(message_log, window, cx);
|
||||||
editor
|
editor
|
||||||
.read(cx)
|
.read(cx)
|
||||||
|
@ -859,7 +885,7 @@ impl DapLogView {
|
||||||
.map(|state| log_contents(state.iter().cloned()))
|
.map(|state| log_contents(state.iter().cloned()))
|
||||||
});
|
});
|
||||||
if let Some(rpc_log) = rpc_log {
|
if let Some(rpc_log) = rpc_log {
|
||||||
self.current_view = Some((id.session_id, LogKind::Rpc));
|
self.current_view = Some((id.session_id, View::InitializationSequence));
|
||||||
let (editor, editor_subscriptions) = Self::editor_for_logs(rpc_log, window, cx);
|
let (editor, editor_subscriptions) = Self::editor_for_logs(rpc_log, window, cx);
|
||||||
let language = self.project.read(cx).languages().language_for_name("JSON");
|
let language = self.project.read(cx).languages().language_for_name("JSON");
|
||||||
editor
|
editor
|
||||||
|
@ -899,11 +925,12 @@ fn log_contents(lines: impl Iterator<Item = SharedString>) -> String {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, PartialEq)]
|
#[derive(Clone, PartialEq)]
|
||||||
pub(crate) struct DapMenuItem {
|
struct DapMenuItem {
|
||||||
pub session_id: SessionId,
|
session_id: SessionId,
|
||||||
pub adapter_name: DebugAdapterName,
|
session_label: SharedString,
|
||||||
pub has_adapter_logs: bool,
|
adapter_name: DebugAdapterName,
|
||||||
pub selected_entry: LogKind,
|
has_adapter_logs: bool,
|
||||||
|
selected_entry: View,
|
||||||
}
|
}
|
||||||
|
|
||||||
const ADAPTER_LOGS: &str = "Adapter Logs";
|
const ADAPTER_LOGS: &str = "Adapter Logs";
|
||||||
|
|
|
@ -11,7 +11,7 @@ use project::worktree_store::WorktreeStore;
|
||||||
use rpc::proto;
|
use rpc::proto;
|
||||||
use running::RunningState;
|
use running::RunningState;
|
||||||
use std::{cell::OnceCell, sync::OnceLock};
|
use std::{cell::OnceCell, sync::OnceLock};
|
||||||
use ui::{Indicator, Tooltip, prelude::*};
|
use ui::{Indicator, prelude::*};
|
||||||
use util::truncate_and_trailoff;
|
use util::truncate_and_trailoff;
|
||||||
use workspace::{
|
use workspace::{
|
||||||
CollaboratorId, FollowableItem, ViewId, Workspace,
|
CollaboratorId, FollowableItem, ViewId, Workspace,
|
||||||
|
@ -158,7 +158,6 @@ impl DebugSession {
|
||||||
|
|
||||||
h_flex()
|
h_flex()
|
||||||
.id("session-label")
|
.id("session-label")
|
||||||
.tooltip(Tooltip::text(format!("Session {}", self.session_id(cx).0,)))
|
|
||||||
.ml(depth * px(16.0))
|
.ml(depth * px(16.0))
|
||||||
.gap_2()
|
.gap_2()
|
||||||
.when_some(icon, |this, indicator| this.child(indicator))
|
.when_some(icon, |this, indicator| this.child(indicator))
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue