Skip to content

Commit b133d9c

Browse files
authored
Merge pull request #535 from Bluemangoo/feature/top-tui-infobar
Feature/top tui infobar
2 parents 108415d + 0c71dec commit b133d9c

File tree

5 files changed

+256
-73
lines changed

5 files changed

+256
-73
lines changed

src/uu/top/src/picker.rs

Lines changed: 87 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
// For the full copyright and license information, please view the LICENSE
44
// file that was distributed with this source code.
55

6-
use crate::tui::stat::TuiStat;
6+
use crate::tui::stat::{TimeScale, TuiStat};
77
use crate::Settings;
88
use std::any::Any;
99
use std::cmp::Ordering;
@@ -24,13 +24,13 @@ pub fn sysinfo() -> &'static RwLock<System> {
2424
}
2525

2626
pub trait Column {
27-
fn as_string(&self, show_zeros: bool) -> String;
27+
fn as_string(&self, tui_stat: &TuiStat) -> String;
2828
fn cmp_dyn(&self, other: &dyn Column) -> Ordering;
2929
fn as_any(&self) -> &dyn Any;
3030
}
3131

3232
impl Column for String {
33-
fn as_string(&self, _show_zeros: bool) -> String {
33+
fn as_string(&self, _tui_stat: &TuiStat) -> String {
3434
self.clone()
3535
}
3636

@@ -47,8 +47,8 @@ impl Column for String {
4747
}
4848

4949
impl Column for u32 {
50-
fn as_string(&self, show_zeros: bool) -> String {
51-
if !show_zeros && self == &0 {
50+
fn as_string(&self, tui_stat: &TuiStat) -> String {
51+
if !tui_stat.show_zeros && self == &0 {
5252
return String::new();
5353
}
5454
self.to_string()
@@ -67,8 +67,8 @@ impl Column for u32 {
6767
}
6868

6969
impl Column for Option<i32> {
70-
fn as_string(&self, show_zeros: bool) -> String {
71-
if !show_zeros && self == &Some(0) {
70+
fn as_string(&self, tui_stat: &TuiStat) -> String {
71+
if !tui_stat.show_zeros && self == &Some(0) {
7272
return String::new();
7373
}
7474
self.map(|v| v.to_string()).unwrap_or_default()
@@ -102,8 +102,8 @@ impl PercentValue {
102102
}
103103

104104
impl Column for PercentValue {
105-
fn as_string(&self, show_zeros: bool) -> String {
106-
if !show_zeros && self.value == 0.0 {
105+
fn as_string(&self, tui_stat: &TuiStat) -> String {
106+
if !tui_stat.show_zeros && self.value == 0.0 {
107107
return String::new();
108108
}
109109
format!("{:.1}", self.value)
@@ -132,8 +132,8 @@ impl MemValue {
132132
}
133133

134134
impl Column for MemValue {
135-
fn as_string(&self, show_zeros: bool) -> String {
136-
if !show_zeros && self.value == 0 {
135+
fn as_string(&self, tui_stat: &TuiStat) -> String {
136+
if !tui_stat.show_zeros && self.value == 0 {
137137
return String::new();
138138
}
139139
let mem_mb = self.value as f64 / bytesize::MIB as f64;
@@ -156,33 +156,63 @@ impl Column for MemValue {
156156
}
157157
}
158158

159-
struct TimeMSValue {
160-
min: u64,
159+
struct TimeValue {
161160
sec: f64,
162161
}
163162

164-
impl TimeMSValue {
165-
fn new_boxed(min: u64, sec: f64) -> Box<Self> {
166-
Box::new(Self { min, sec })
163+
impl TimeValue {
164+
fn new_boxed(sec: f64) -> Box<Self> {
165+
Box::new(Self { sec })
167166
}
168167
}
169168

170-
impl Column for TimeMSValue {
171-
fn as_string(&self, show_zeros: bool) -> String {
172-
if !show_zeros && self.min == 0 && self.sec < 0.01 {
169+
impl Column for TimeValue {
170+
fn as_string(&self, tui_stat: &TuiStat) -> String {
171+
if !tui_stat.show_zeros && self.sec < 0.01 {
173172
return String::new();
174173
}
175-
format!("{}:{:0>5.2}", self.min, self.sec)
174+
match tui_stat.time_scale {
175+
TimeScale::MinSecondCent => {
176+
let min = (self.sec / 60.0).floor() as u32;
177+
let sec = self.sec - (min * 60) as f64;
178+
format!("{}:{:0>5.2}", min, sec)
179+
}
180+
TimeScale::MinSecond => {
181+
let min = (self.sec / 60.0).floor() as u32;
182+
let sec = (self.sec - (min * 60) as f64).floor() as u32;
183+
format!("{}:{:0>2}", min, sec)
184+
}
185+
TimeScale::HourMin => {
186+
let hour = (self.sec / 3600.0).floor() as u32;
187+
let min = ((self.sec - (hour * 3600) as f64) / 60.0).floor() as u32;
188+
format!("{},{:0>2}", hour, min)
189+
}
190+
TimeScale::DayHour => {
191+
let day = (self.sec / 86400.0).floor() as u32;
192+
let hour = ((self.sec - (day * 86400) as f64) / 3600.0).floor() as u32;
193+
format!("{}d+{}h", day, hour)
194+
}
195+
TimeScale::Day => {
196+
let day = (self.sec / 86400.0).floor() as u32;
197+
format!("{}d", day)
198+
}
199+
TimeScale::WeekDay => {
200+
let week = (self.sec / 604800.0).floor() as u32;
201+
let day = ((self.sec - (week * 604800) as f64) / 86400.0).floor() as u32;
202+
format!("{}w+{}d", week, day)
203+
}
204+
TimeScale::Week => {
205+
let week = (self.sec / 604800.0).floor() as u32;
206+
format!("{}w", week)
207+
}
208+
}
176209
}
177210

178211
fn cmp_dyn(&self, other: &dyn Column) -> Ordering {
179212
other
180213
.as_any()
181-
.downcast_ref::<TimeMSValue>()
182-
.map(|o| match self.min.cmp(&o.min) {
183-
Ordering::Equal => self.sec.partial_cmp(&o.sec).unwrap_or(Ordering::Equal),
184-
ord => ord,
185-
})
214+
.downcast_ref::<TimeValue>()
215+
.map(|o| self.sec.partial_cmp(&o.sec).unwrap_or(Ordering::Equal))
186216
.unwrap_or(Ordering::Equal)
187217
}
188218
fn as_any(&self) -> &dyn Any {
@@ -383,18 +413,12 @@ fn s(pid: u32, _stat: Stat) -> Box<dyn Column> {
383413
fn time_plus(pid: u32, _stat: Stat) -> Box<dyn Column> {
384414
let binding = sysinfo().read().unwrap();
385415
let Some(proc) = binding.process(Pid::from_u32(pid)) else {
386-
return TimeMSValue::new_boxed(0, 0.0);
416+
return TimeValue::new_boxed(0.0);
387417
};
388418

389-
let (min, sec) = {
390-
let total = proc.accumulated_cpu_time();
391-
let minute = total / (60 * 1000);
392-
let second = (total % (60 * 1000)) as f64 / 1000.0;
393-
394-
(minute, second)
395-
};
419+
let second = proc.accumulated_cpu_time() as f64 / 1000.0;
396420

397-
TimeMSValue::new_boxed(min, sec)
421+
TimeValue::new_boxed(second)
398422
}
399423

400424
fn mem(pid: u32, _stat: Stat) -> Box<dyn Column> {
@@ -408,8 +432,16 @@ fn mem(pid: u32, _stat: Stat) -> Box<dyn Column> {
408432
)
409433
}
410434

411-
fn command(pid: u32, stat: Stat) -> Box<dyn Column> {
412-
let full_command_line = stat.1.full_command_line;
435+
pub(crate) fn get_cgroup(pid: u32) -> String {
436+
let path = PathBuf::from_str(&format!("/proc/{pid}/cgroup")).unwrap();
437+
if let Ok(file) = File::open(path) {
438+
read_to_string(file).unwrap()
439+
} else {
440+
String::new()
441+
}
442+
}
443+
444+
pub(crate) fn get_command(pid: u32, full_command_line: bool) -> String {
413445
let f = |cmd: &[OsString]| -> String {
414446
let binding = cmd
415447
.iter()
@@ -444,23 +476,26 @@ fn command(pid: u32, stat: Stat) -> Box<dyn Column> {
444476

445477
let binding = sysinfo().read().unwrap();
446478
let Some(proc) = binding.process(Pid::from_u32(pid)) else {
447-
return Box::new("?".to_string());
479+
return "?".to_string();
448480
};
449481

450-
Box::new(
451-
proc.exe()
452-
.and_then(|it| {
453-
if full_command_line {
454-
it.iter().next_back()
455-
} else {
456-
it.file_name()
457-
}
458-
})
459-
.map(|it| it.to_str().unwrap().to_string())
460-
.unwrap_or(if full_command_line {
461-
f(proc.cmd())
482+
proc.exe()
483+
.and_then(|it| {
484+
if full_command_line {
485+
it.iter().next_back()
462486
} else {
463-
proc.name().to_str().unwrap().to_string()
464-
}),
465-
)
487+
it.file_name()
488+
}
489+
})
490+
.map(|it| it.to_str().unwrap().to_string())
491+
.unwrap_or(if full_command_line {
492+
f(proc.cmd())
493+
} else {
494+
proc.name().to_str().unwrap().to_string()
495+
})
496+
}
497+
498+
fn command(pid: u32, stat: Stat) -> Box<dyn Column> {
499+
let full_command_line = stat.1.full_command_line;
500+
Box::new(get_command(pid, full_command_line))
466501
}

src/uu/top/src/top.rs

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ impl Settings {
5454

5555
pub(crate) struct ProcList {
5656
pub fields: Vec<String>,
57-
pub collected: Vec<Vec<String>>,
57+
pub collected: Vec<(u32, Vec<String>)>,
5858
}
5959

6060
impl ProcList {
@@ -66,6 +66,11 @@ impl ProcList {
6666
}
6767
}
6868

69+
pub(crate) struct InfoBar {
70+
pub title: String,
71+
pub content: String,
72+
}
73+
6974
#[uucore::main]
7075
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
7176
let matches = uu_app().try_get_matches_from(args)?;
@@ -107,6 +112,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
107112
let data = Arc::new(RwLock::new((
108113
Header::new(&tui_stat.read().unwrap()),
109114
ProcList::new(&settings, &tui_stat.read().unwrap()),
115+
None,
110116
)));
111117

112118
// update
@@ -122,7 +128,9 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
122128
let header = Header::new(&tui_stat.read().unwrap());
123129
let proc_list = ProcList::new(&settings, &tui_stat.read().unwrap());
124130
tui_stat.write().unwrap().input_message = None;
125-
*data.write().unwrap() = (header, proc_list);
131+
let mut data = data.write().unwrap();
132+
data.0 = header;
133+
data.1 = proc_list;
126134
should_update.store(true, Ordering::Relaxed);
127135
}
128136
});
@@ -194,7 +202,7 @@ fn selected_fields() -> Vec<String> {
194202
.collect()
195203
}
196204

197-
fn collect(settings: &Settings, fields: &[String], tui_stat: &TuiStat) -> Vec<Vec<String>> {
205+
fn collect(settings: &Settings, fields: &[String], tui_stat: &TuiStat) -> Vec<(u32, Vec<String>)> {
198206
let pickers = pickers(fields);
199207

200208
let pids = sysinfo()
@@ -211,12 +219,15 @@ fn collect(settings: &Settings, fields: &[String], tui_stat: &TuiStat) -> Vec<Ve
211219
.into_iter()
212220
.filter(|pid| filter(*pid))
213221
.map(|it| {
214-
pickers
215-
.iter()
216-
.map(move |picker| picker(it, (settings, tui_stat)))
217-
.collect::<Vec<_>>()
222+
(
223+
it,
224+
pickers
225+
.iter()
226+
.map(move |picker| picker(it, (settings, tui_stat)))
227+
.collect::<Vec<_>>(),
228+
)
218229
})
219-
.collect::<Vec<Vec<Box<dyn Column>>>>();
230+
.collect::<Vec<(u32, Vec<Box<dyn Column>>)>>();
220231

221232
let sorter = if tui_stat.sort_by_pid {
222233
"PID"
@@ -225,16 +236,17 @@ fn collect(settings: &Settings, fields: &[String], tui_stat: &TuiStat) -> Vec<Ve
225236
};
226237
let sorter_nth = fields.iter().position(|f| f == sorter).unwrap_or(0);
227238
if tui_stat.sort_by_pid {
228-
collected.sort_by(|a, b| a[sorter_nth].cmp_dyn(&*b[sorter_nth])); // reverse
239+
collected.sort_by(|a, b| a.1[sorter_nth].cmp_dyn(&*b.1[sorter_nth])); // reverse
229240
} else {
230-
collected.sort_by(|a, b| b[sorter_nth].cmp_dyn(&*a[sorter_nth]));
241+
collected.sort_by(|a, b| b.1[sorter_nth].cmp_dyn(&*a.1[sorter_nth]));
231242
}
232243
collected
233244
.into_iter()
234245
.map(|it| {
235-
it.into_iter()
236-
.map(|c| c.as_string(tui_stat.show_zeros))
237-
.collect()
246+
(
247+
it.0,
248+
it.1.into_iter().map(|c| c.as_string(tui_stat)).collect(),
249+
)
238250
})
239251
.collect()
240252
}

0 commit comments

Comments
 (0)