top: tui impl ^e

This commit is contained in:
Bluemangoo
2025-10-10 18:33:47 +08:00
parent 6af80eff0d
commit 8c0bab5a09
4 changed files with 101 additions and 37 deletions
+58 -34
View File
@@ -3,7 +3,7 @@
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code.
use crate::tui::stat::TuiStat;
use crate::tui::stat::{TimeScale, TuiStat};
use crate::Settings;
use std::any::Any;
use std::cmp::Ordering;
@@ -24,13 +24,13 @@ pub fn sysinfo() -> &'static RwLock<System> {
}
pub trait Column {
fn as_string(&self, show_zeros: bool) -> String;
fn as_string(&self, tui_stat: &TuiStat) -> String;
fn cmp_dyn(&self, other: &dyn Column) -> Ordering;
fn as_any(&self) -> &dyn Any;
}
impl Column for String {
fn as_string(&self, _show_zeros: bool) -> String {
fn as_string(&self, _tui_stat: &TuiStat) -> String {
self.clone()
}
@@ -47,8 +47,8 @@ impl Column for String {
}
impl Column for u32 {
fn as_string(&self, show_zeros: bool) -> String {
if !show_zeros && self == &0 {
fn as_string(&self, tui_stat: &TuiStat) -> String {
if !tui_stat.show_zeros && self == &0 {
return String::new();
}
self.to_string()
@@ -67,8 +67,8 @@ impl Column for u32 {
}
impl Column for Option<i32> {
fn as_string(&self, show_zeros: bool) -> String {
if !show_zeros && self == &Some(0) {
fn as_string(&self, tui_stat: &TuiStat) -> String {
if !tui_stat.show_zeros && self == &Some(0) {
return String::new();
}
self.map(|v| v.to_string()).unwrap_or_default()
@@ -102,8 +102,8 @@ impl PercentValue {
}
impl Column for PercentValue {
fn as_string(&self, show_zeros: bool) -> String {
if !show_zeros && self.value == 0.0 {
fn as_string(&self, tui_stat: &TuiStat) -> String {
if !tui_stat.show_zeros && self.value == 0.0 {
return String::new();
}
format!("{:.1}", self.value)
@@ -132,8 +132,8 @@ impl MemValue {
}
impl Column for MemValue {
fn as_string(&self, show_zeros: bool) -> String {
if !show_zeros && self.value == 0 {
fn as_string(&self, tui_stat: &TuiStat) -> String {
if !tui_stat.show_zeros && self.value == 0 {
return String::new();
}
let mem_mb = self.value as f64 / bytesize::MIB as f64;
@@ -156,33 +156,63 @@ impl Column for MemValue {
}
}
struct TimeMSValue {
min: u64,
struct TimeValue {
sec: f64,
}
impl TimeMSValue {
fn new_boxed(min: u64, sec: f64) -> Box<Self> {
Box::new(Self { min, sec })
impl TimeValue {
fn new_boxed(sec: f64) -> Box<Self> {
Box::new(Self { sec })
}
}
impl Column for TimeMSValue {
fn as_string(&self, show_zeros: bool) -> String {
if !show_zeros && self.min == 0 && self.sec < 0.01 {
impl Column for TimeValue {
fn as_string(&self, tui_stat: &TuiStat) -> String {
if !tui_stat.show_zeros && self.sec < 0.01 {
return String::new();
}
format!("{}:{:0>5.2}", self.min, self.sec)
match tui_stat.time_scale {
TimeScale::MinSecondCent => {
let min = (self.sec / 60.0).floor() as u32;
let sec = self.sec - (min * 60) as f64;
format!("{}:{:0>5.2}", min, sec)
}
TimeScale::MinSecond => {
let min = (self.sec / 60.0).floor() as u32;
let sec = (self.sec - (min * 60) as f64).floor() as u32;
format!("{}:{:0>2}", min, sec)
}
TimeScale::HourMin => {
let hour = (self.sec / 3600.0).floor() as u32;
let min = ((self.sec - (hour * 3600) as f64) / 60.0).floor() as u32;
format!("{},{:0>2}", hour, min)
}
TimeScale::DayHour => {
let day = (self.sec / 86400.0).floor() as u32;
let hour = ((self.sec - (day * 86400) as f64) / 3600.0).floor() as u32;
format!("{}d+{}h", day, hour)
}
TimeScale::Day => {
let day = (self.sec / 86400.0).floor() as u32;
format!("{}d", day)
}
TimeScale::WeekDay => {
let week = (self.sec / 604800.0).floor() as u32;
let day = ((self.sec - (week * 604800) as f64) / 86400.0).floor() as u32;
format!("{}w+{}d", week, day)
}
TimeScale::Week => {
let week = (self.sec / 604800.0).floor() as u32;
format!("{}w", week)
}
}
}
fn cmp_dyn(&self, other: &dyn Column) -> Ordering {
other
.as_any()
.downcast_ref::<TimeMSValue>()
.map(|o| match self.min.cmp(&o.min) {
Ordering::Equal => self.sec.partial_cmp(&o.sec).unwrap_or(Ordering::Equal),
ord => ord,
})
.downcast_ref::<TimeValue>()
.map(|o| self.sec.partial_cmp(&o.sec).unwrap_or(Ordering::Equal))
.unwrap_or(Ordering::Equal)
}
fn as_any(&self) -> &dyn Any {
@@ -383,18 +413,12 @@ fn s(pid: u32, _stat: Stat) -> Box<dyn Column> {
fn time_plus(pid: u32, _stat: Stat) -> Box<dyn Column> {
let binding = sysinfo().read().unwrap();
let Some(proc) = binding.process(Pid::from_u32(pid)) else {
return TimeMSValue::new_boxed(0, 0.0);
return TimeValue::new_boxed(0.0);
};
let (min, sec) = {
let total = proc.accumulated_cpu_time();
let minute = total / (60 * 1000);
let second = (total % (60 * 1000)) as f64 / 1000.0;
let second = proc.accumulated_cpu_time() as f64 / 1000.0;
(minute, second)
};
TimeMSValue::new_boxed(min, sec)
TimeValue::new_boxed(second)
}
fn mem(pid: u32, _stat: Stat) -> Box<dyn Column> {
+1 -1
View File
@@ -233,7 +233,7 @@ fn collect(settings: &Settings, fields: &[String], tui_stat: &TuiStat) -> Vec<Ve
.into_iter()
.map(|it| {
it.into_iter()
.map(|c| c.as_string(tui_stat.show_zeros))
.map(|c| c.as_string(tui_stat))
.collect()
})
.collect()
+13
View File
@@ -84,6 +84,19 @@ pub fn handle_input(
should_update.store(true, Ordering::Relaxed);
}
Event::Key(KeyEvent {
code: KeyCode::Char('e'),
modifiers: KeyModifiers::CONTROL,
..
}) => {
{
let mut stat = tui_stat.write().unwrap();
stat.time_scale = stat.time_scale.next();
}
data.write().unwrap().1 = ProcList::new(settings, &tui_stat.read().unwrap());
should_update.store(true, Ordering::Relaxed);
}
char!('I') => {
{
let mut stat = tui_stat.write().unwrap();
+29 -2
View File
@@ -32,6 +32,7 @@ pub(crate) struct TuiStat {
pub show_zeros: bool,
pub irix_mode: bool,
pub width_increment: Option<usize>, // None means auto
pub time_scale: TimeScale,
pub filter: Option<crate::Filter>,
}
@@ -69,7 +70,8 @@ impl TuiStat {
show_coordinates: false,
show_zeros: true,
irix_mode: true,
width_increment: None,
width_increment: Some(0), // fixed
time_scale: TimeScale::default(),
filter: None,
}
@@ -123,7 +125,6 @@ impl CpuValueMode {
}
}
#[allow(unused)]
#[derive(Debug, Default, PartialEq)]
pub enum MemoryGraphMode {
#[default]
@@ -143,3 +144,29 @@ impl MemoryGraphMode {
}
}
}
#[derive(Debug, Default, PartialEq)]
pub enum TimeScale {
#[default]
MinSecondCent, // 00:00.00
MinSecond, // 00:00
HourMin, // 0,00
DayHour, // 0d+0h
Day, // 0d
WeekDay, // 0w+0d
Week, // 0w
}
impl TimeScale {
pub fn next(&self) -> TimeScale {
match self {
TimeScale::MinSecondCent => TimeScale::MinSecond,
TimeScale::MinSecond => TimeScale::HourMin,
TimeScale::HourMin => TimeScale::DayHour,
TimeScale::DayHour => TimeScale::Day,
TimeScale::Day => TimeScale::WeekDay,
TimeScale::WeekDay => TimeScale::Week,
TimeScale::Week => TimeScale::MinSecondCent,
}
}
}