Skip to content

Commit 5857ea9

Browse files
authored
Merge pull request #509 from Bluemangoo/feature/top-tui-l4
top: tui implement `4`, `l`
2 parents fe47393 + 364c2ba commit 5857ea9

File tree

3 files changed

+108
-36
lines changed

3 files changed

+108
-36
lines changed

src/uu/top/src/top.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,14 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
157157
uucore::error::set_exit_code(0);
158158
break;
159159
}
160+
event::Event::Key(KeyEvent {
161+
code: KeyCode::Char('l'),
162+
..
163+
}) => {
164+
let mut stat = tui_stat.write().unwrap();
165+
stat.show_load_avg = !stat.show_load_avg;
166+
should_update.store(true, Ordering::Relaxed);
167+
}
160168
event::Event::Key(KeyEvent {
161169
code: KeyCode::Char('t'),
162170
..
@@ -175,6 +183,14 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
175183
should_update.store(true, Ordering::Relaxed);
176184
data.write().unwrap().0.update_cpu(&stat);
177185
}
186+
event::Event::Key(KeyEvent {
187+
code: KeyCode::Char('4'),
188+
..
189+
}) => {
190+
let mut stat = tui_stat.write().unwrap();
191+
stat.cpu_column = stat.cpu_column % 8 + 1;
192+
should_update.store(true, Ordering::Relaxed);
193+
}
178194
event::Event::Key(KeyEvent {
179195
code: KeyCode::Char('m'),
180196
..

src/uu/top/src/tui/mod.rs

Lines changed: 88 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -34,50 +34,88 @@ impl<'a> Tui<'a> {
3434
}
3535

3636
fn calc_header_height(&self) -> u16 {
37-
let mut height = 1;
37+
let mut height = u16::from(self.stat.show_load_avg);
3838

39+
let mut columns = 0;
3940
if self.stat.cpu_graph_mode != CpuGraphMode::Hide {
40-
height += 1;
41-
height += self.header.cpu.len() as u16;
41+
height += 1; // task line
42+
if self.stat.cpu_graph_mode == CpuGraphMode::Sum {
43+
height += self.header.cpu.len() as u16;
44+
} else {
45+
columns += self.header.cpu.len() as u16;
46+
}
4247
}
4348
if self.stat.memory_graph_mode != MemoryGraphMode::Hide {
44-
height += 2;
49+
if self.stat.memory_graph_mode == MemoryGraphMode::Sum {
50+
height += 2;
51+
} else {
52+
columns += 2;
53+
}
54+
}
55+
height += columns / self.stat.cpu_column;
56+
if columns % self.stat.cpu_column != 0 {
57+
height += 1;
4558
}
4659

4760
height
4861
}
4962

5063
fn render_header(&self, area: Rect, buf: &mut Buffer) {
51-
let mut constraints = vec![Constraint::Length(1)];
64+
let constraints = vec![Constraint::Length(1); self.calc_header_height() as usize];
5265

5366
let cpu = &self.header.cpu;
5467

55-
if self.stat.cpu_graph_mode != CpuGraphMode::Hide {
56-
constraints.extend(vec![Constraint::Length(1); cpu.len() + 1]);
57-
}
58-
if self.stat.memory_graph_mode != MemoryGraphMode::Hide {
59-
constraints.extend(vec![Constraint::Length(1); 2]);
60-
}
6168
let header_layout = Layout::new(Direction::Vertical, constraints).split(area);
6269
let mut i = 0;
6370

64-
let render_bars = |bars_to_render: Vec<(String, f64, f64, f64, f64, char, bool)>,
65-
buf: &mut Buffer,
66-
i: usize| {
71+
let mut i_columns = 0;
72+
let mut cpu_column = None;
73+
let mut render_bars = |bars_to_render: Vec<(String, f64, f64, f64, f64, char, bool)>,
74+
buf: &mut Buffer,
75+
i: usize| {
6776
let mut i = i;
6877
for (tag, l, r, red, yellow, content, print_percentage) in bars_to_render {
78+
if cpu_column.is_none() || i_columns >= self.stat.cpu_column as usize {
79+
let mut constraints = vec![Constraint::Min(25)];
80+
let mut width_left = header_layout[i].width - 25;
81+
for _ in 0..self.stat.cpu_column {
82+
if width_left > 28 {
83+
constraints.extend(vec![Constraint::Length(3), Constraint::Min(25)]);
84+
width_left -= 28;
85+
} else {
86+
constraints.extend(vec![Constraint::Length(0), Constraint::Length(0)]);
87+
}
88+
}
89+
let line =
90+
Layout::new(Direction::Horizontal, constraints).split(header_layout[i]);
91+
i += 1;
92+
i_columns = 0;
93+
cpu_column = Some(line);
94+
}
95+
96+
let column_offset = i_columns * 2;
97+
let area = cpu_column.as_ref().unwrap()[column_offset];
98+
if i_columns > 0 {
99+
Line::from(vec![
100+
Span::raw(" "),
101+
Span::styled(" ", Style::default().bg(Color::Yellow)),
102+
Span::raw(" "),
103+
])
104+
.render(cpu_column.as_ref().unwrap()[column_offset - 1], buf);
105+
}
69106
let line_layout = Layout::new(
70107
Direction::Horizontal,
71108
[
72109
Constraint::Length(10),
73-
Constraint::Length(16),
110+
Constraint::Length(if self.stat.cpu_column < 3 { 16 } else { 0 }),
74111
Constraint::Length(1),
75112
Constraint::Min(0),
76113
Constraint::Length(1),
77114
],
78115
)
79-
.split(header_layout[i]);
80-
i += 1;
116+
.split(area);
117+
i_columns += 1;
118+
81119
Span::styled(format!("%{tag:<6}:",), Style::default().red())
82120
.render(line_layout[0], buf);
83121
let percentage = if print_percentage {
@@ -120,15 +158,17 @@ impl<'a> Tui<'a> {
120158
i
121159
};
122160

123-
let uptime = format!(
124-
"top - {time} {uptime}, {user}, {load_average}",
125-
time = self.header.uptime.time,
126-
uptime = self.header.uptime.uptime,
127-
user = self.header.uptime.user,
128-
load_average = self.header.uptime.load_average,
129-
);
130-
Paragraph::new(uptime).render(header_layout[0], buf);
131-
i += 1;
161+
if self.stat.show_load_avg {
162+
let load_avg = format!(
163+
"top - {time} {uptime}, {user}, {load_average}",
164+
time = self.header.uptime.time,
165+
uptime = self.header.uptime.uptime,
166+
user = self.header.uptime.user,
167+
load_average = self.header.uptime.load_average,
168+
);
169+
Paragraph::new(load_avg).render(header_layout[i], buf);
170+
i += 1;
171+
}
132172

133173
if self.stat.cpu_graph_mode != CpuGraphMode::Hide {
134174
let task = &self.header.task;
@@ -145,7 +185,7 @@ impl<'a> Tui<'a> {
145185
Span::raw(task.zombie.to_string()),
146186
Span::styled(" zombie", Style::default().red()),
147187
];
148-
Line::from(task_line).render(header_layout[1], buf);
188+
Line::from(task_line).render(header_layout[i], buf);
149189
i += 1;
150190

151191
let mut cpu_bars = Vec::new();
@@ -253,15 +293,27 @@ impl<'a> Tui<'a> {
253293
bar_content,
254294
false,
255295
));
256-
mem_bars.push((
257-
format!("{unit_name} Swap"),
258-
mem.used_swap as f64 / mem.total_swap as f64 * 100.0,
259-
format_memory(mem.total_swap, unit),
260-
0.0,
261-
mem.used_swap as f64 / mem.total_swap as f64,
262-
bar_content,
263-
false,
264-
));
296+
if mem.total_swap > 0 {
297+
mem_bars.push((
298+
format!("{unit_name} Swap"),
299+
mem.used_swap as f64 / mem.total_swap as f64 * 100.0,
300+
format_memory(mem.total_swap, unit),
301+
0.0,
302+
mem.used_swap as f64 / mem.total_swap as f64,
303+
bar_content,
304+
false,
305+
));
306+
} else {
307+
mem_bars.push((
308+
format!("{unit_name} Swap"),
309+
0.0,
310+
0.0,
311+
0.0,
312+
0.0,
313+
bar_content,
314+
false,
315+
));
316+
}
265317
render_bars(mem_bars, &mut *buf, i);
266318
}
267319
}

src/uu/top/src/tui/stat.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,23 @@
66
use std::time::Duration;
77

88
pub(crate) struct TuiStat {
9+
pub show_load_avg: bool,
910
pub cpu_graph_mode: CpuGraphMode,
1011
pub cpu_value_mode: CpuValueMode,
1112
pub memory_graph_mode: MemoryGraphMode,
13+
pub cpu_column: u16,
1214
pub list_offset: usize,
1315
pub delay: Duration,
1416
}
1517

1618
impl TuiStat {
1719
pub fn new() -> Self {
1820
Self {
21+
show_load_avg: true,
1922
cpu_graph_mode: CpuGraphMode::default(),
2023
cpu_value_mode: CpuValueMode::default(),
2124
memory_graph_mode: MemoryGraphMode::default(),
25+
cpu_column: 2,
2226
list_offset: 0,
2327
delay: Duration::from_millis(1500), // 1.5s
2428
}

0 commit comments

Comments
 (0)