Refactored code such that it fits more of tui-rs' example.
This commit is contained in:
parent
d80c2387fb
commit
471209f511
|
@ -7,12 +7,17 @@ edition = "2018"
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
crossterm = "0.10.2"
|
||||||
futures-preview = "0.3.0-alpha.18"
|
futures-preview = "0.3.0-alpha.18"
|
||||||
futures-timer = "0.3"
|
futures-timer = "0.3"
|
||||||
futures-util = "0.2.1"
|
futures-util = "0.2.1"
|
||||||
heim = "0.0.7"
|
heim = "0.0.7"
|
||||||
heim-common = "0.0.7"
|
heim-common = "0.0.7"
|
||||||
sysinfo = "0.9.4"
|
sysinfo = "0.9.4"
|
||||||
termion = "1.5.3"
|
|
||||||
tokio = "0.2.0-alpha.4"
|
tokio = "0.2.0-alpha.4"
|
||||||
tui = "0.6.2"
|
|
||||||
|
|
||||||
|
[dependencies.tui]
|
||||||
|
version = "0.6.2"
|
||||||
|
default-features = false
|
||||||
|
features = ['crossterm']
|
||||||
|
|
194
src/main.rs
194
src/main.rs
|
@ -1,92 +1,120 @@
|
||||||
use sysinfo::{System, SystemExt};
|
use crossterm::{input, AlternateScreen, InputEvent, KeyEvent};
|
||||||
|
use std::{
|
||||||
|
io::{self, stdin, stdout, Write},
|
||||||
|
sync::mpsc,
|
||||||
|
thread,
|
||||||
|
time::Duration,
|
||||||
|
};
|
||||||
|
use tui::{
|
||||||
|
backend::CrosstermBackend,
|
||||||
|
layout::{Constraint, Direction, Layout},
|
||||||
|
widgets::{Block, Borders, Widget},
|
||||||
|
Terminal,
|
||||||
|
};
|
||||||
|
|
||||||
mod widgets;
|
mod widgets;
|
||||||
use widgets::{cpu, disks, mem, network, processes, temperature};
|
|
||||||
|
|
||||||
mod window;
|
enum Event<I> {
|
||||||
|
Input(I),
|
||||||
fn set_if_valid<T : std::clone::Clone>(result : &Result<T, heim::Error>, value_to_set : &mut T) {
|
Tick,
|
||||||
if let Ok(result) = result {
|
|
||||||
*value_to_set = (*result).clone();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> Result<(), std::io::Error> {
|
async fn main() -> Result<(), io::Error> {
|
||||||
// Initialize
|
let screen = AlternateScreen::to_alternate(true)?;
|
||||||
let refresh_interval = 1; // TODO: Make changing this possible!
|
let backend = CrosstermBackend::with_alternate_screen(screen)?;
|
||||||
let mut sys = System::new();
|
let mut terminal = Terminal::new(backend)?;
|
||||||
|
terminal.hide_cursor()?;
|
||||||
let mut list_of_cpu_packages : Vec<cpu::CPUData> = Vec::new();
|
// Setup input handling
|
||||||
let mut list_of_io : Vec<disks::IOInfo> = Vec::new();
|
let (tx, rx) = mpsc::channel();
|
||||||
let mut list_of_physical_io : Vec<disks::IOInfo> = Vec::new();
|
{
|
||||||
let mut memory : mem::MemData = mem::MemData::default();
|
let tx = tx.clone();
|
||||||
let mut swap : mem::MemData = mem::MemData::default();
|
thread::spawn(move || {
|
||||||
let mut list_of_temperature : Vec<temperature::TempData> = Vec::new();
|
let input = input();
|
||||||
let mut network : network::NetworkData = network::NetworkData::default();
|
let reader = input.read_sync();
|
||||||
let mut list_of_processes = Vec::new();
|
for event in reader {
|
||||||
let mut list_of_disks = Vec::new();
|
if let InputEvent::Keyboard(key) = event {
|
||||||
|
if tx.send(Event::Input(key.clone())).is_err() {
|
||||||
window::create_terminal()?;
|
return;
|
||||||
|
}
|
||||||
loop {
|
}
|
||||||
sys.refresh_system();
|
}
|
||||||
sys.refresh_network();
|
});
|
||||||
|
}
|
||||||
// What we want to do: For timed data, if there is an error, just do not add. For other data, just don't update!
|
{
|
||||||
set_if_valid(&network::get_network_data(&sys), &mut network);
|
let tx = tx.clone();
|
||||||
set_if_valid(&cpu::get_cpu_data_list(&sys), &mut list_of_cpu_packages);
|
thread::spawn(move || {
|
||||||
|
let tx = tx.clone();
|
||||||
// TODO: Joining all futures would be better...
|
loop {
|
||||||
set_if_valid(&processes::get_sorted_processes_list(processes::ProcessSorting::NAME, false).await, &mut list_of_processes);
|
tx.send(Event::Tick).unwrap();
|
||||||
set_if_valid(&disks::get_disk_usage_list().await, &mut list_of_disks);
|
thread::sleep(Duration::from_millis(250));
|
||||||
set_if_valid(&disks::get_io_usage_list(false).await, &mut list_of_io);
|
}
|
||||||
set_if_valid(&disks::get_io_usage_list(true).await, &mut list_of_physical_io);
|
});
|
||||||
set_if_valid(&mem::get_mem_data_list().await, &mut memory);
|
|
||||||
set_if_valid(&mem::get_swap_data_list().await, &mut swap);
|
|
||||||
set_if_valid(&temperature::get_temperature_data().await, &mut list_of_temperature);
|
|
||||||
|
|
||||||
/*
|
|
||||||
// DEBUG - output results
|
|
||||||
for process in &list_of_processes {
|
|
||||||
println!(
|
|
||||||
"Process: {} with PID {}, CPU: {}%, MEM: {} MB",
|
|
||||||
process.command, process.pid, process.cpu_usage_percent, process.mem_usage_in_mb,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
for disk in &list_of_disks {
|
|
||||||
println!("{} is mounted on {}: {} used.", disk.name, disk.mount_point, disk.used_space as f64 / disk.total_space as f64);
|
|
||||||
// TODO: Check if this is valid
|
|
||||||
}
|
|
||||||
|
|
||||||
for io in &list_of_io {
|
|
||||||
println!("IO counter for {}: {} writes, {} reads.", &io.mount_point, io.write_bytes, io.read_bytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
for io in &list_of_physical_io {
|
|
||||||
println!("Physical IO counter for {}: {} writes, {} reads.", &io.mount_point, io.write_bytes, io.read_bytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
for cpu in &list_of_cpu_packages {
|
|
||||||
println!("CPU {} has {}% usage!", &cpu.cpu_name, cpu.cpu_usage);
|
|
||||||
}
|
|
||||||
|
|
||||||
println!("Memory usage: {} out of {} is used", memory.mem_used, memory.mem_total);
|
|
||||||
|
|
||||||
println!("Memory usage: {} out of {} is used", swap.mem_used, swap.mem_total);
|
|
||||||
|
|
||||||
for sensor in &list_of_temperature {
|
|
||||||
println!("Sensor for {} is at {} degrees Celsius", sensor.component_name, sensor.temperature);
|
|
||||||
}
|
|
||||||
|
|
||||||
println!("Network: {} rx, {} tx", network.rx, network.tx);
|
|
||||||
*/
|
|
||||||
|
|
||||||
// TODO: Send to drawing module
|
|
||||||
|
|
||||||
// Repeat on interval
|
|
||||||
std::thread::sleep(std::time::Duration::from_secs(refresh_interval));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Exit on quit command/ctrl-c
|
let mut app : widgets::App = widgets::App::new("rustop");
|
||||||
|
terminal.clear()?;
|
||||||
|
|
||||||
|
loop {
|
||||||
|
terminal.draw(|mut f| {
|
||||||
|
let vertical_chunks = Layout::default()
|
||||||
|
.direction(Direction::Vertical)
|
||||||
|
.margin(1)
|
||||||
|
.constraints([Constraint::Percentage(33), Constraint::Percentage(34), Constraint::Percentage(33)].as_ref())
|
||||||
|
.split(f.size());
|
||||||
|
let top_chunks = Layout::default()
|
||||||
|
.direction(Direction::Horizontal)
|
||||||
|
.margin(0)
|
||||||
|
.constraints([Constraint::Percentage(50), Constraint::Percentage(50)].as_ref())
|
||||||
|
.split(vertical_chunks[0]);
|
||||||
|
let middle_chunks = Layout::default()
|
||||||
|
.direction(Direction::Horizontal)
|
||||||
|
.margin(0)
|
||||||
|
.constraints([Constraint::Percentage(40), Constraint::Percentage(60)].as_ref())
|
||||||
|
.split(vertical_chunks[1]);
|
||||||
|
let middle_divided_chunk = Layout::default()
|
||||||
|
.direction(Direction::Vertical)
|
||||||
|
.margin(0)
|
||||||
|
.constraints([Constraint::Percentage(50), Constraint::Percentage(50)].as_ref())
|
||||||
|
.split(middle_chunks[0]);
|
||||||
|
let bottom_chunks = Layout::default()
|
||||||
|
.direction(Direction::Horizontal)
|
||||||
|
.margin(0)
|
||||||
|
.constraints([Constraint::Percentage(50), Constraint::Percentage(50)].as_ref())
|
||||||
|
.split(vertical_chunks[2]);
|
||||||
|
|
||||||
|
Block::default().title("CPU Usage").borders(Borders::ALL).render(&mut f, top_chunks[0]);
|
||||||
|
Block::default().title("Memory Usage").borders(Borders::ALL).render(&mut f, top_chunks[1]);
|
||||||
|
|
||||||
|
Block::default().title("Temperatures").borders(Borders::ALL).render(&mut f, middle_divided_chunk[0]);
|
||||||
|
Block::default().title("Disk Usage").borders(Borders::ALL).render(&mut f, middle_divided_chunk[1]);
|
||||||
|
Block::default().title("IO Usage").borders(Borders::ALL).render(&mut f, middle_chunks[1]);
|
||||||
|
|
||||||
|
Block::default().title("Network").borders(Borders::ALL).render(&mut f, bottom_chunks[0]);
|
||||||
|
Block::default().title("Processes").borders(Borders::ALL).render(&mut f, bottom_chunks[1]);
|
||||||
|
})?;
|
||||||
|
|
||||||
|
// TODO: Ctrl-C?
|
||||||
|
if let Ok(recv) = rx.recv() {
|
||||||
|
match recv {
|
||||||
|
Event::Input(event) => match event {
|
||||||
|
KeyEvent::Char(c) => app.on_key(c),
|
||||||
|
KeyEvent::Left => {}
|
||||||
|
KeyEvent::Right => {}
|
||||||
|
KeyEvent::Up => {}
|
||||||
|
KeyEvent::Down => {}
|
||||||
|
KeyEvent::Ctrl('c') => break,
|
||||||
|
_ => {}
|
||||||
|
},
|
||||||
|
Event::Tick => {
|
||||||
|
app.update_data();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if app.should_quit {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use heim_common::prelude::StreamExt;
|
use heim_common::prelude::StreamExt;
|
||||||
|
|
||||||
#[derive(Clone, Default)]
|
#[derive(Clone, Default)]
|
||||||
pub struct DiskInfo {
|
pub struct DiskData {
|
||||||
pub name : Box<str>,
|
pub name : Box<str>,
|
||||||
pub mount_point : Box<str>,
|
pub mount_point : Box<str>,
|
||||||
pub free_space : u64,
|
pub free_space : u64,
|
||||||
|
@ -10,19 +10,19 @@ pub struct DiskInfo {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Default)]
|
#[derive(Clone, Default)]
|
||||||
pub struct IOInfo {
|
pub struct IOData {
|
||||||
pub mount_point : Box<str>,
|
pub mount_point : Box<str>,
|
||||||
pub read_bytes : u64,
|
pub read_bytes : u64,
|
||||||
pub write_bytes : u64,
|
pub write_bytes : u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_io_usage_list(get_physical : bool) -> Result<Vec<IOInfo>, heim::Error> {
|
pub async fn get_io_usage_list(get_physical : bool) -> Result<Vec<IOData>, heim::Error> {
|
||||||
let mut io_list : Vec<IOInfo> = Vec::new();
|
let mut io_list : Vec<IOData> = Vec::new();
|
||||||
if get_physical {
|
if get_physical {
|
||||||
let mut physical_counter_stream = heim::disk::io_counters_physical();
|
let mut physical_counter_stream = heim::disk::io_counters_physical();
|
||||||
while let Some(io) = physical_counter_stream.next().await {
|
while let Some(io) = physical_counter_stream.next().await {
|
||||||
let io = io?;
|
let io = io?;
|
||||||
io_list.push(IOInfo {
|
io_list.push(IOData {
|
||||||
mount_point : Box::from(io.device_name().to_str().unwrap_or("Name Unavailable")),
|
mount_point : Box::from(io.device_name().to_str().unwrap_or("Name Unavailable")),
|
||||||
read_bytes : io.read_bytes().get::<heim_common::units::information::megabyte>(),
|
read_bytes : io.read_bytes().get::<heim_common::units::information::megabyte>(),
|
||||||
write_bytes : io.write_bytes().get::<heim_common::units::information::megabyte>(),
|
write_bytes : io.write_bytes().get::<heim_common::units::information::megabyte>(),
|
||||||
|
@ -33,7 +33,7 @@ pub async fn get_io_usage_list(get_physical : bool) -> Result<Vec<IOInfo>, heim:
|
||||||
let mut counter_stream = heim::disk::io_counters();
|
let mut counter_stream = heim::disk::io_counters();
|
||||||
while let Some(io) = counter_stream.next().await {
|
while let Some(io) = counter_stream.next().await {
|
||||||
let io = io?;
|
let io = io?;
|
||||||
io_list.push(IOInfo {
|
io_list.push(IOData {
|
||||||
mount_point : Box::from(io.device_name().to_str().unwrap_or("Name Unavailable")),
|
mount_point : Box::from(io.device_name().to_str().unwrap_or("Name Unavailable")),
|
||||||
read_bytes : io.read_bytes().get::<heim_common::units::information::megabyte>(),
|
read_bytes : io.read_bytes().get::<heim_common::units::information::megabyte>(),
|
||||||
write_bytes : io.write_bytes().get::<heim_common::units::information::megabyte>(),
|
write_bytes : io.write_bytes().get::<heim_common::units::information::megabyte>(),
|
||||||
|
@ -44,15 +44,15 @@ pub async fn get_io_usage_list(get_physical : bool) -> Result<Vec<IOInfo>, heim:
|
||||||
Ok(io_list)
|
Ok(io_list)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_disk_usage_list() -> Result<Vec<DiskInfo>, heim::Error> {
|
pub async fn get_disk_usage_list() -> Result<Vec<DiskData>, heim::Error> {
|
||||||
let mut vec_disks : Vec<DiskInfo> = Vec::new();
|
let mut vec_disks : Vec<DiskData> = Vec::new();
|
||||||
let mut partitions_stream = heim::disk::partitions_physical();
|
let mut partitions_stream = heim::disk::partitions_physical();
|
||||||
|
|
||||||
while let Some(part) = partitions_stream.next().await {
|
while let Some(part) = partitions_stream.next().await {
|
||||||
let partition = part?; // TODO: Change this? We don't want to error out immediately...
|
let partition = part?; // TODO: Change this? We don't want to error out immediately...
|
||||||
let usage = heim::disk::usage(partition.mount_point().to_path_buf()).await?;
|
let usage = heim::disk::usage(partition.mount_point().to_path_buf()).await?;
|
||||||
|
|
||||||
vec_disks.push(DiskInfo {
|
vec_disks.push(DiskData {
|
||||||
free_space : usage.free().get::<heim_common::units::information::megabyte>(),
|
free_space : usage.free().get::<heim_common::units::information::megabyte>(),
|
||||||
used_space : usage.used().get::<heim_common::units::information::megabyte>(),
|
used_space : usage.used().get::<heim_common::units::information::megabyte>(),
|
||||||
total_space : usage.total().get::<heim_common::units::information::megabyte>(),
|
total_space : usage.total().get::<heim_common::units::information::megabyte>(),
|
||||||
|
|
|
@ -1,6 +1,101 @@
|
||||||
|
pub mod cpu;
|
||||||
pub mod disks;
|
pub mod disks;
|
||||||
pub mod temperature;
|
pub mod mem;
|
||||||
pub mod network;
|
pub mod network;
|
||||||
pub mod processes;
|
pub mod processes;
|
||||||
pub mod mem;
|
pub mod temperature;
|
||||||
pub mod cpu;
|
|
||||||
|
use sysinfo::{System, SystemExt};
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct App<'a> {
|
||||||
|
pub should_quit : bool,
|
||||||
|
pub list_of_cpu_packages : Vec<cpu::CPUData>,
|
||||||
|
pub list_of_io : Vec<disks::IOData>,
|
||||||
|
pub list_of_physical_io : Vec<disks::IOData>,
|
||||||
|
pub memory : mem::MemData,
|
||||||
|
pub swap : mem::MemData,
|
||||||
|
pub list_of_temperature : Vec<temperature::TempData>,
|
||||||
|
pub network : network::NetworkData,
|
||||||
|
pub list_of_processes : Vec<processes::ProcessData>,
|
||||||
|
pub list_of_disks : Vec<disks::DiskData>,
|
||||||
|
pub title : &'a str,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_if_valid<T : std::clone::Clone>(result : &Result<T, heim::Error>, value_to_set : &mut T) {
|
||||||
|
if let Ok(result) = result {
|
||||||
|
*value_to_set = (*result).clone();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> App<'a> {
|
||||||
|
pub fn new(title : &str) -> App {
|
||||||
|
let mut app = App::default();
|
||||||
|
app.title = title;
|
||||||
|
app
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn on_key(&mut self, c : char) {
|
||||||
|
match c {
|
||||||
|
'q' => self.should_quit = true,
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn update_data(&mut self) {
|
||||||
|
// Initialize
|
||||||
|
let mut sys = System::new();
|
||||||
|
|
||||||
|
sys.refresh_system();
|
||||||
|
sys.refresh_network();
|
||||||
|
|
||||||
|
// What we want to do: For timed data, if there is an error, just do not add. For other data, just don't update!
|
||||||
|
set_if_valid(&network::get_network_data(&sys), &mut self.network);
|
||||||
|
set_if_valid(&cpu::get_cpu_data_list(&sys), &mut self.list_of_cpu_packages);
|
||||||
|
|
||||||
|
// TODO: Joining all futures would be better...
|
||||||
|
set_if_valid(&processes::get_sorted_processes_list(processes::ProcessSorting::NAME, false).await, &mut self.list_of_processes);
|
||||||
|
set_if_valid(&disks::get_disk_usage_list().await, &mut self.list_of_disks);
|
||||||
|
set_if_valid(&disks::get_io_usage_list(false).await, &mut self.list_of_io);
|
||||||
|
set_if_valid(&disks::get_io_usage_list(true).await, &mut self.list_of_physical_io);
|
||||||
|
set_if_valid(&mem::get_mem_data_list().await, &mut self.memory);
|
||||||
|
set_if_valid(&mem::get_swap_data_list().await, &mut self.swap);
|
||||||
|
set_if_valid(&temperature::get_temperature_data().await, &mut self.list_of_temperature);
|
||||||
|
|
||||||
|
/*
|
||||||
|
// DEBUG - output results
|
||||||
|
for process in &list_of_processes {
|
||||||
|
println!(
|
||||||
|
"Process: {} with PID {}, CPU: {}%, MEM: {} MB",
|
||||||
|
process.command, process.pid, process.cpu_usage_percent, process.mem_usage_in_mb,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
for disk in &list_of_disks {
|
||||||
|
println!("{} is mounted on {}: {} used.", disk.name, disk.mount_point, disk.used_space as f64 / disk.total_space as f64);
|
||||||
|
// TODO: Check if this is valid
|
||||||
|
}
|
||||||
|
|
||||||
|
for io in &list_of_io {
|
||||||
|
println!("IO counter for {}: {} writes, {} reads.", &io.mount_point, io.write_bytes, io.read_bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
for io in &list_of_physical_io {
|
||||||
|
println!("Physical IO counter for {}: {} writes, {} reads.", &io.mount_point, io.write_bytes, io.read_bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
for cpu in &list_of_cpu_packages {
|
||||||
|
println!("CPU {} has {}% usage!", &cpu.cpu_name, cpu.cpu_usage);
|
||||||
|
}
|
||||||
|
|
||||||
|
println!("Memory usage: {} out of {} is used", memory.mem_used, memory.mem_total);
|
||||||
|
|
||||||
|
println!("Memory usage: {} out of {} is used", swap.mem_used, swap.mem_total);
|
||||||
|
|
||||||
|
for sensor in &list_of_temperature {
|
||||||
|
println!("Sensor for {} is at {} degrees Celsius", sensor.component_name, sensor.temperature);
|
||||||
|
}
|
||||||
|
|
||||||
|
println!("Network: {} rx, {} tx", network.rx, network.tx);
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@ pub enum ProcessSorting {
|
||||||
|
|
||||||
// Possible process info struct?
|
// Possible process info struct?
|
||||||
#[derive(Clone, Default)]
|
#[derive(Clone, Default)]
|
||||||
pub struct ProcessInfo {
|
pub struct ProcessData {
|
||||||
pub pid : u32,
|
pub pid : u32,
|
||||||
pub cpu_usage_percent : f32,
|
pub cpu_usage_percent : f32,
|
||||||
pub mem_usage_in_mb : u64,
|
pub mem_usage_in_mb : u64,
|
||||||
|
@ -50,10 +50,10 @@ async fn cpu_usage(process : heim::process::Process) -> heim::process::ProcessRe
|
||||||
Ok((process, usage_2 - usage_1))
|
Ok((process, usage_2 - usage_1))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_sorted_processes_list(sorting_method : ProcessSorting, reverse_order : bool) -> Result<Vec<ProcessInfo>, heim::Error> {
|
pub async fn get_sorted_processes_list(sorting_method : ProcessSorting, reverse_order : bool) -> Result<Vec<ProcessData>, heim::Error> {
|
||||||
let mut process_stream = heim::process::processes().map_ok(cpu_usage).try_buffer_unordered(std::usize::MAX);
|
let mut process_stream = heim::process::processes().map_ok(cpu_usage).try_buffer_unordered(std::usize::MAX);
|
||||||
|
|
||||||
let mut process_vector : Vec<ProcessInfo> = Vec::new();
|
let mut process_vector : Vec<ProcessData> = Vec::new();
|
||||||
while let Some(process) = process_stream.next().await {
|
while let Some(process) = process_stream.next().await {
|
||||||
if let Ok(process) = process {
|
if let Ok(process) = process {
|
||||||
let (process, cpu_usage) = process;
|
let (process, cpu_usage) = process;
|
||||||
|
@ -69,7 +69,7 @@ pub async fn get_sorted_processes_list(sorting_method : ProcessSorting, reverse_
|
||||||
});
|
});
|
||||||
*/
|
*/
|
||||||
|
|
||||||
process_vector.push(ProcessInfo {
|
process_vector.push(ProcessData {
|
||||||
command : process.name().await.unwrap_or_else(|_| "".to_string()),
|
command : process.name().await.unwrap_or_else(|_| "".to_string()),
|
||||||
pid : process.pid() as u32,
|
pid : process.pid() as u32,
|
||||||
cpu_usage_percent : cpu_usage.get::<units::ratio::percent>(),
|
cpu_usage_percent : cpu_usage.get::<units::ratio::percent>(),
|
||||||
|
@ -83,7 +83,7 @@ pub async fn get_sorted_processes_list(sorting_method : ProcessSorting, reverse_
|
||||||
Ok(process_vector)
|
Ok(process_vector)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn sort_processes(sorting_method : ProcessSorting, process_vector : &mut Vec<ProcessInfo>, reverse_order : bool) {
|
pub fn sort_processes(sorting_method : ProcessSorting, process_vector : &mut Vec<ProcessData>, reverse_order : bool) {
|
||||||
match sorting_method {
|
match sorting_method {
|
||||||
ProcessSorting::CPU => process_vector.sort_by(|a, b| get_ordering(a.cpu_usage_percent, b.cpu_usage_percent, reverse_order)),
|
ProcessSorting::CPU => process_vector.sort_by(|a, b| get_ordering(a.cpu_usage_percent, b.cpu_usage_percent, reverse_order)),
|
||||||
ProcessSorting::MEM => process_vector.sort_by(|a, b| get_ordering(a.mem_usage_in_mb, b.mem_usage_in_mb, reverse_order)),
|
ProcessSorting::MEM => process_vector.sort_by(|a, b| get_ordering(a.mem_usage_in_mb, b.mem_usage_in_mb, reverse_order)),
|
||||||
|
|
|
@ -1,52 +0,0 @@
|
||||||
use std::io;
|
|
||||||
use termion::raw::IntoRawMode;
|
|
||||||
use tui::{
|
|
||||||
backend::TermionBackend,
|
|
||||||
layout::{Constraint, Direction, Layout},
|
|
||||||
widgets::{Block, Borders, Widget},
|
|
||||||
Terminal,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub fn create_terminal() -> Result<(), io::Error> {
|
|
||||||
let stdout = io::stdout().into_raw_mode()?;
|
|
||||||
let backend = TermionBackend::new(stdout);
|
|
||||||
let mut terminal = Terminal::new(backend)?;
|
|
||||||
terminal.clear()?;
|
|
||||||
terminal.draw(|mut f| {
|
|
||||||
let vertical_chunks = Layout::default()
|
|
||||||
.direction(Direction::Vertical)
|
|
||||||
.margin(1)
|
|
||||||
.constraints([Constraint::Percentage(33), Constraint::Percentage(34), Constraint::Percentage(33)].as_ref())
|
|
||||||
.split(f.size());
|
|
||||||
let top_chunks = Layout::default()
|
|
||||||
.direction(Direction::Horizontal)
|
|
||||||
.margin(0)
|
|
||||||
.constraints([Constraint::Percentage(50), Constraint::Percentage(50)].as_ref())
|
|
||||||
.split(vertical_chunks[0]);
|
|
||||||
let middle_chunks = Layout::default()
|
|
||||||
.direction(Direction::Horizontal)
|
|
||||||
.margin(0)
|
|
||||||
.constraints([Constraint::Percentage(40), Constraint::Percentage(60)].as_ref())
|
|
||||||
.split(vertical_chunks[1]);
|
|
||||||
let middle_divided_chunk = Layout::default()
|
|
||||||
.direction(Direction::Vertical)
|
|
||||||
.margin(0)
|
|
||||||
.constraints([Constraint::Percentage(50), Constraint::Percentage(50)].as_ref())
|
|
||||||
.split(middle_chunks[0]);
|
|
||||||
let bottom_chunks = Layout::default()
|
|
||||||
.direction(Direction::Horizontal)
|
|
||||||
.margin(0)
|
|
||||||
.constraints([Constraint::Percentage(50), Constraint::Percentage(50)].as_ref())
|
|
||||||
.split(vertical_chunks[2]);
|
|
||||||
|
|
||||||
Block::default().title("CPU Usage").borders(Borders::ALL).render(&mut f, top_chunks[0]);
|
|
||||||
Block::default().title("Memory Usage").borders(Borders::ALL).render(&mut f, top_chunks[1]);
|
|
||||||
|
|
||||||
Block::default().title("Temperatures").borders(Borders::ALL).render(&mut f, middle_divided_chunk[0]);
|
|
||||||
Block::default().title("Disk Usage").borders(Borders::ALL).render(&mut f, middle_divided_chunk[1]);
|
|
||||||
Block::default().title("IO Usage").borders(Borders::ALL).render(&mut f, middle_chunks[1]);
|
|
||||||
|
|
||||||
Block::default().title("Network").borders(Borders::ALL).render(&mut f, bottom_chunks[0]);
|
|
||||||
Block::default().title("Processes").borders(Borders::ALL).render(&mut f, bottom_chunks[1]);
|
|
||||||
})
|
|
||||||
}
|
|
Loading…
Reference in New Issue