Skip to content

Commit 168e868

Browse files
committed
fix(tui): unshare EventLine from multiple event lists
1 parent bbb20c0 commit 168e868

File tree

4 files changed

+67
-29
lines changed

4 files changed

+67
-29
lines changed

src/tui/app.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -687,6 +687,15 @@ impl App {
687687
})
688688
.unwrap_or(&mut self.event_list)
689689
}
690+
691+
pub fn inspect_all_event_list_mut(&mut self, mut f: impl FnMut(&mut EventList)) {
692+
f(&mut self.event_list);
693+
for popup in self.popup.iter_mut() {
694+
if let ActivePopup::Backtrace(b) = popup {
695+
f(&mut b.list);
696+
}
697+
}
698+
}
690699
}
691700

692701
trait OptionalAccessMut<T> {

src/tui/backtrace_popup.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ impl BacktracePopupState {
3636
false,
3737
old_list.has_clipboard,
3838
);
39+
list.rt_modifier = old_list.rt_modifier;
3940
for e in trace {
4041
list.dumb_push(e);
4142
}

src/tui/event_list.rs

Lines changed: 52 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,6 @@ pub struct Event {
4444
pub status: Option<EventStatus>,
4545
/// The elapsed time between event start and process exit/detach.
4646
pub elapsed: Option<TimeDelta>,
47-
/// The string representation of the events, used for searching
48-
pub event_line: EventLine,
4947
pub id: EventId,
5048
}
5149

@@ -59,7 +57,8 @@ pub struct EventList {
5957
state: ListState,
6058
// TODO: move the event id out of RwLock
6159
events: VecDeque<Rc<RefCell<Event>>>,
62-
event_map: HashMap<EventId, Rc<RefCell<Event>>>,
60+
/// 0. The string representation of the events, used for searching
61+
event_map: HashMap<EventId, (EventLine, Rc<RefCell<Event>>)>,
6362
/// Current window of the event list, [start, end)
6463
window: (usize, usize),
6564
/// Cache of the list items in the view
@@ -77,7 +76,7 @@ pub struct EventList {
7776
pub baseline: Arc<BaselineInfo>,
7877
follow: bool,
7978
pub modifier_args: ModifierArgs,
80-
rt_modifier: RuntimeModifier,
79+
pub(super) rt_modifier: RuntimeModifier,
8180
query: Option<Query>,
8281
query_result: Option<QueryResult>,
8382
is_ptrace: bool,
@@ -144,7 +143,12 @@ impl EventList {
144143
pub fn toggle_env_display(&mut self) {
145144
self.rt_modifier.show_env = !self.rt_modifier.show_env;
146145
for event in &self.events {
147-
event.borrow_mut().event_line.toggle_env_mask();
146+
self
147+
.event_map
148+
.get_mut(&event.borrow().id)
149+
.unwrap()
150+
.0
151+
.toggle_env_mask();
148152
}
149153
self.should_refresh_list_cache = true;
150154
self.search();
@@ -153,7 +157,12 @@ impl EventList {
153157
pub fn toggle_cwd_display(&mut self) {
154158
self.rt_modifier.show_cwd = !self.rt_modifier.show_cwd;
155159
for event in &mut self.events {
156-
event.borrow_mut().event_line.toggle_cwd_mask();
160+
self
161+
.event_map
162+
.get_mut(&event.borrow().id)
163+
.unwrap()
164+
.0
165+
.toggle_cwd_mask();
157166
}
158167
self.should_refresh_list_cache = true;
159168
self.search();
@@ -211,12 +220,12 @@ impl EventList {
211220
}
212221

213222
pub(super) fn get(&self, id: EventId) -> Option<Rc<RefCell<Event>>> {
214-
self.event_map.get(&id).map(Rc::clone)
223+
self.event_map.get(&id).map(|(_, x)| Rc::clone(x))
215224
}
216225

217226
pub fn get_map<T>(&self, id: EventId, f: impl FnOnce(&Event) -> T) -> Option<T> {
218227
self.event_map.get(&id).map(|e| {
219-
let e = e.borrow();
228+
let e = e.1.borrow();
220229
f(&e)
221230
})
222231
}
@@ -246,9 +255,9 @@ impl EventList {
246255
// Events won't change during the search because this is Rust and we already have a reference to it.
247256
// Rust really makes the code more easier to reason about.
248257
for evt in self.events.iter() {
249-
let evt = evt.borrow();
250-
if query.matches(&evt.event_line) {
251-
indices.insert(evt.id);
258+
let id = evt.borrow().id;
259+
if query.matches(&self.event_map[&id].0) {
260+
indices.insert(id);
252261
}
253262
}
254263
let mut result = QueryResult {
@@ -284,9 +293,9 @@ impl EventList {
284293
.into_inner()
285294
.saturating_sub(offset) as usize;
286295
for evt in self.events.iter().skip(start_search_index) {
287-
let evt = evt.borrow();
288-
if query.matches(&evt.event_line) {
289-
existing_result.indices.insert(evt.id);
296+
let id = evt.borrow().id;
297+
if query.matches(&self.event_map[&id].0) {
298+
existing_result.indices.insert(id);
290299
modified = true;
291300
}
292301
}
@@ -338,8 +347,8 @@ impl EventList {
338347
}
339348
_ => None,
340349
};
350+
let event_line = Event::to_event_line(&details, status, &self.baseline, &self.event_modifier());
341351
let event = Event {
342-
event_line: Event::to_event_line(&details, status, &self.baseline, &self.event_modifier()),
343352
elapsed: None,
344353
details,
345354
status,
@@ -360,15 +369,23 @@ impl EventList {
360369
// # SAFETY
361370
//
362371
// The event ids are guaranteed to be unique
363-
unsafe { self.event_map.insert_unique_unchecked(id, event) };
372+
unsafe {
373+
self
374+
.event_map
375+
.insert_unique_unchecked(id, (event_line, event))
376+
};
364377
self.incremental_search();
365378
if (self.window.0..self.window.1).contains(&(self.events.len() - 1)) {
366379
self.should_refresh_list_cache = true;
367380
}
368381
}
369382

370383
pub fn set_status(&mut self, id: EventId, status: Option<EventStatus>) -> Option<()> {
371-
self.event_map.get_mut(&id).map(|v| v.borrow_mut())?.status = status;
384+
self
385+
.event_map
386+
.get_mut(&id)
387+
.map(|v| v.1.borrow_mut())?
388+
.status = status;
372389
Some(())
373390
}
374391

@@ -378,16 +395,28 @@ impl EventList {
378395
pub(super) fn dumb_push(&mut self, event: Rc<RefCell<Event>>) {
379396
let id = event.borrow().id;
380397
self.events.push_back(event.clone());
398+
let evt = event.borrow();
399+
let event_line = Event::to_event_line(
400+
&evt.details,
401+
evt.status,
402+
&self.baseline,
403+
&self.event_modifier(),
404+
);
405+
drop(evt);
381406
// # SAFETY
382407
//
383408
// The event ids are guaranteed to be unique
384-
unsafe { self.event_map.insert_unique_unchecked(id, event) };
409+
unsafe {
410+
self
411+
.event_map
412+
.insert_unique_unchecked(id, (event_line, event))
413+
};
385414
}
386415

387416
pub fn update(&mut self, update: ProcessStateUpdateEvent) {
388417
let modifier = self.event_modifier();
389418
for i in update.ids {
390-
if let Some(e) = self.event_map.get(&i) {
419+
if let Some((line, e)) = self.event_map.get_mut(&i) {
391420
let mut e = e.borrow_mut();
392421
if let TracerEventDetails::Exec(exec) = e.details.as_ref() {
393422
if exec.result != 0 {
@@ -399,7 +428,7 @@ impl EventList {
399428
if let Some(ts) = update.update.termination_timestamp() {
400429
e.elapsed = Some(ts - e.details.timestamp().unwrap())
401430
}
402-
e.event_line = Event::to_event_line(&e.details, e.status, &self.baseline, &modifier);
431+
*line = Event::to_event_line(&e.details, e.status, &self.baseline, &modifier);
403432
}
404433
let i = i.into_inner() as usize;
405434
if self.window.0 <= i && i < self.window.1 {
@@ -411,9 +440,9 @@ impl EventList {
411440
pub fn rebuild_lines(&mut self) {
412441
// TODO: only update spans that are affected by the change
413442
let modifier = self.event_modifier();
414-
for e in self.events.iter_mut() {
415-
let mut e = e.borrow_mut();
416-
e.event_line = Event::to_event_line(&e.details, e.status, &self.baseline, &modifier);
443+
for (_, (line, e)) in self.event_map.iter_mut() {
444+
let e = e.borrow();
445+
*line = Event::to_event_line(&e.details, e.status, &self.baseline, &modifier);
417446
}
418447
self.should_refresh_list_cache = true;
419448
}

src/tui/event_list/ui.rs

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -61,18 +61,17 @@ impl Widget for &mut EventList {
6161
.skip(self.window.0)
6262
.take(self.window.1 - self.window.0)
6363
.map(|event| {
64-
let event = event.borrow();
65-
max_len = max_len.max(event.event_line.line.width());
64+
let id = event.borrow().id;
65+
let line = &self.event_map[&id].0;
66+
max_len = max_len.max(line.line.width());
6667
let highlighted = self
6768
.query_result
6869
.as_ref()
69-
.is_some_and(|query_result| query_result.indices.contains(&event.id));
70-
let mut base = event
71-
.event_line
70+
.is_some_and(|query_result| query_result.indices.contains(&id));
71+
let mut base = line
7272
.line
7373
.clone()
7474
.substring(self.horizontal_offset, area.width);
75-
drop(event);
7675
if highlighted {
7776
base = base.style(THEME.search_match);
7877
}

0 commit comments

Comments
 (0)