feat: align memory columns correctly, closes #20

use kB as minimum bytestats unit, screenshot updated
This commit is contained in:
Jack Wills
2023-01-14 18:01:38 +00:00
parent 0350293de3
commit bd7dfcd2c5
5 changed files with 47 additions and 66 deletions
Binary file not shown.

Before

Width:  |  Height:  |  Size: 107 KiB

After

Width:  |  Height:  |  Size: 106 KiB

+11 -12
View File
@@ -343,8 +343,7 @@ impl fmt::Display for ByteStats {
let p = match as_f64 { let p = match as_f64 {
x if x >= ONE_GB => format!("{y:.2} GB", y = as_f64 / ONE_GB), x if x >= ONE_GB => format!("{y:.2} GB", y = as_f64 / ONE_GB),
x if x >= ONE_MB => format!("{y:.2} MB", y = as_f64 / ONE_MB), x if x >= ONE_MB => format!("{y:.2} MB", y = as_f64 / ONE_MB),
x if x >= ONE_KB => format!("{y:.2} kB", y = as_f64 / ONE_KB), _ => format!("{y:.2} kB", y = as_f64 / ONE_KB),
_ => format!("{} B", self.0),
}; };
write!(f, "{p:>x$}", x = f.width().unwrap_or(1)) write!(f, "{p:>x$}", x = f.width().unwrap_or(1))
} }
@@ -463,15 +462,15 @@ impl ContainerItem {
/// Container information panel headings + widths, for nice pretty formatting /// Container information panel headings + widths, for nice pretty formatting
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
pub struct Columns { pub struct Columns {
pub state: (Header, usize), pub state: (Header, u8),
pub status: (Header, usize), pub status: (Header, u8),
pub cpu: (Header, usize), pub cpu: (Header, u8),
pub mem: (Header, usize), pub mem: (Header, u8, u8),
pub id: (Header, usize), pub id: (Header, u8),
pub name: (Header, usize), pub name: (Header, u8),
pub image: (Header, usize), pub image: (Header, u8),
pub net_rx: (Header, usize), pub net_rx: (Header, u8),
pub net_tx: (Header, usize), pub net_tx: (Header, u8),
} }
impl Columns { impl Columns {
@@ -482,7 +481,7 @@ impl Columns {
status: (Header::Status, 16), status: (Header::Status, 16),
// 7 to allow for "100.00%" // 7 to allow for "100.00%"
cpu: (Header::Cpu, 7), cpu: (Header::Cpu, 7),
mem: (Header::Memory, 12), mem: (Header::Memory, 6, 6),
id: (Header::Id, 8), id: (Header::Id, 8),
name: (Header::Name, 4), name: (Header::Name, 4),
image: (Header::Image, 5), image: (Header::Image, 5),
+8 -8
View File
@@ -364,7 +364,7 @@ impl AppData {
/// So can display nicely and evenly /// So can display nicely and evenly
pub fn get_width(&self) -> Columns { pub fn get_width(&self) -> Columns {
let mut output = Columns::new(); let mut output = Columns::new();
let count = |x: &String| x.chars().count(); let count = |x: &String| u8::try_from(x.chars().count()).unwrap_or(12);
// Should probably find a refactor here somewhere // Should probably find a refactor here somewhere
for container in &self.containers.items { for container in &self.containers.items {
@@ -375,11 +375,6 @@ impl AppData {
.unwrap_or(&CpuStats::default()) .unwrap_or(&CpuStats::default())
.to_string(), .to_string(),
); );
let mem_count = count(&format!(
"{} / {}",
container.mem_stats.back().unwrap_or(&ByteStats::default()),
container.mem_limit
));
let rx_count = count(&container.rx.to_string()); let rx_count = count(&container.rx.to_string());
let tx_count = count(&container.tx.to_string()); let tx_count = count(&container.tx.to_string());
@@ -387,6 +382,8 @@ impl AppData {
let name_count = count(&container.name); let name_count = count(&container.name);
let state_count = count(&container.state.to_string()); let state_count = count(&container.state.to_string());
let status_count = count(&container.status); let status_count = count(&container.status);
let mem_current_count = count(&container.mem_stats.back().unwrap_or(&ByteStats::default()).to_string());
let mem_limit_count= count(&container.mem_limit.to_string());
if cpu_count > output.cpu.1 { if cpu_count > output.cpu.1 {
output.cpu.1 = cpu_count; output.cpu.1 = cpu_count;
@@ -394,8 +391,11 @@ impl AppData {
if image_count > output.image.1 { if image_count > output.image.1 {
output.image.1 = image_count; output.image.1 = image_count;
}; };
if mem_count > output.mem.1 { if mem_current_count > output.mem.1 {
output.mem.1 = mem_count; output.mem.1 = mem_current_count;
};
if mem_limit_count > output.mem.2 {
output.mem.2 = mem_limit_count;
}; };
if name_count > output.name.1 { if name_count > output.name.1 {
output.name.1 = name_count; output.name.1 = name_count;
+10 -28
View File
@@ -40,59 +40,41 @@ async fn main() {
let app_data = Arc::new(Mutex::new(AppData::default(args))); let app_data = Arc::new(Mutex::new(AppData::default(args)));
let gui_state = Arc::new(Mutex::new(GuiState::default())); let gui_state = Arc::new(Mutex::new(GuiState::default()));
let is_running = Arc::new(AtomicBool::new(true)); let is_running = Arc::new(AtomicBool::new(true));
let docker_app_data = Arc::clone(&app_data);
let docker_gui_state = Arc::clone(&gui_state);
let (docker_sx, docker_rx) = tokio::sync::mpsc::channel(16); let (docker_sx, docker_rx) = tokio::sync::mpsc::channel(16);
let (input_sx, input_rx) = tokio::sync::mpsc::channel(16);
// Create docker daemon handler, and only spawn up the docker data handler if ping returns non-error // Create docker daemon handler, and only spawn up the docker data handler if ping returns non-error
if let Ok(docker) = Docker::connect_with_socket_defaults() { if let Ok(docker) = Docker::connect_with_socket_defaults() {
if docker.ping().await.is_ok() { if docker.ping().await.is_ok() {
let docker = Arc::new(docker); let app_data = Arc::clone(&app_data);
let gui_state = Arc::clone(&gui_state);
let is_running = Arc::clone(&is_running); let is_running = Arc::clone(&is_running);
tokio::spawn(DockerData::init( tokio::spawn(DockerData::init(
docker_app_data, app_data, docker, gui_state, docker_rx, is_running,
docker,
docker_gui_state,
docker_rx,
is_running,
)); ));
} else { } else {
app_data.lock().set_error(AppError::DockerConnect); app_data.lock().set_error(AppError::DockerConnect);
docker_gui_state.lock().status_push(Status::DockerConnect); gui_state.lock().status_push(Status::DockerConnect);
} }
} else { } else {
app_data.lock().set_error(AppError::DockerConnect); app_data.lock().set_error(AppError::DockerConnect);
docker_gui_state.lock().status_push(Status::DockerConnect); gui_state.lock().status_push(Status::DockerConnect);
} }
let input_app_data = Arc::clone(&app_data); let input_app_data = Arc::clone(&app_data);
let (input_sx, input_rx) = tokio::sync::mpsc::channel(16);
let input_is_running = Arc::clone(&is_running);
let input_gui_state = Arc::clone(&gui_state); let input_gui_state = Arc::clone(&gui_state);
let input_docker_sender = docker_sx.clone(); let input_is_running = Arc::clone(&is_running);
// Spawn input handling into own tokio thread // Spawn input handling into own tokio thread
tokio::spawn(input_handler::InputHandler::init( tokio::spawn(input_handler::InputHandler::init(
input_app_data, input_app_data,
input_rx, input_rx,
input_docker_sender, docker_sx.clone(),
input_gui_state, input_gui_state,
input_is_running, input_is_running,
)); ));
if args.gui { if args.gui {
let update_duration = std::time::Duration::from_millis(u64::from(args.docker_interval)); create_ui(app_data, input_sx, is_running, gui_state, docker_sx)
create_ui(
app_data,
input_sx,
is_running,
gui_state,
docker_sx,
update_duration,
)
.await .await
.unwrap_or(()); .unwrap_or(());
} else { } else {
+16 -16
View File
@@ -136,19 +136,19 @@ pub fn containers<B: Backend>(
let state_style = Style::default().fg(i.state.get_color()); let state_style = Style::default().fg(i.state.get_color());
let blue = Style::default().fg(Color::Blue); let blue = Style::default().fg(Color::Blue);
let mems = format!( // let mems = format!(
"{:>1} / {:>1}", // "{:>1} / {:>1}",
i.mem_stats.back().unwrap_or(&ByteStats::default()), // i.mem_stats.back().unwrap_or(&ByteStats::default()),
i.mem_limit // i.mem_limit
); // );
let lines = Spans::from(vec![ let lines = Spans::from(vec![
Span::styled( Span::styled(
format!("{:<width$}", i.state.to_string(), width = widths.state.1), format!("{:<width$}", i.state.to_string(), width = widths.state.1.into()),
state_style, state_style,
), ),
Span::styled( Span::styled(
format!("{MARGIN}{:>width$}", i.status, width = &widths.status.1), format!("{MARGIN}{:>width$}", i.status, width = &widths.status.1.into()),
state_style, state_style,
), ),
Span::styled( Span::styled(
@@ -156,12 +156,12 @@ pub fn containers<B: Backend>(
"{}{:>width$}", "{}{:>width$}",
MARGIN, MARGIN,
i.cpu_stats.back().unwrap_or(&CpuStats::default()), i.cpu_stats.back().unwrap_or(&CpuStats::default()),
width = &widths.cpu.1 width = &widths.cpu.1.into()
), ),
state_style, state_style,
), ),
Span::styled( Span::styled(
format!("{MARGIN}{mems:>width$}", width = &widths.mem.1), format!("{MARGIN}{:>width_current$} / {:>width_limit$}", i.mem_stats.back().unwrap_or(&ByteStats::default()), i.mem_limit, width_current = &widths.mem.1.into(), width_limit = &widths.mem.2.into()),
state_style, state_style,
), ),
Span::styled( Span::styled(
@@ -169,24 +169,24 @@ pub fn containers<B: Backend>(
"{}{:>width$}", "{}{:>width$}",
MARGIN, MARGIN,
i.id.get().chars().take(8).collect::<String>(), i.id.get().chars().take(8).collect::<String>(),
width = &widths.id.1 width = &widths.id.1.into()
), ),
blue, blue,
), ),
Span::styled( Span::styled(
format!("{MARGIN}{:>width$}", i.name, width = widths.name.1), format!("{MARGIN}{:>width$}", i.name, width = widths.name.1.into()),
blue, blue,
), ),
Span::styled( Span::styled(
format!("{MARGIN}{:>width$}", i.image, width = widths.image.1), format!("{MARGIN}{:>width$}", i.image, width = widths.image.1.into()),
blue, blue,
), ),
Span::styled( Span::styled(
format!("{MARGIN}{:>width$}", i.rx, width = widths.net_rx.1), format!("{MARGIN}{:>width$}", i.rx, width = widths.net_rx.1.into()),
Style::default().fg(Color::Rgb(255, 233, 193)), Style::default().fg(Color::Rgb(255, 233, 193)),
), ),
Span::styled( Span::styled(
format!("{MARGIN}{:>width$}", i.tx, width = widths.net_tx.1), format!("{MARGIN}{:>width$}", i.tx, width = widths.net_tx.1.into()),
Style::default().fg(Color::Rgb(205, 140, 140)), Style::default().fg(Color::Rgb(205, 140, 140)),
), ),
]); ]);
@@ -415,7 +415,7 @@ pub fn heading_bar<B: Backend>(
(Header::State, columns.state.1), (Header::State, columns.state.1),
(Header::Status, columns.status.1), (Header::Status, columns.status.1),
(Header::Cpu, columns.cpu.1), (Header::Cpu, columns.cpu.1),
(Header::Memory, columns.mem.1), (Header::Memory, columns.mem.1 + columns.mem.2 + 3),
(Header::Id, columns.id.1), (Header::Id, columns.id.1),
(Header::Name, columns.name.1), (Header::Name, columns.name.1),
(Header::Image, columns.image.1), (Header::Image, columns.image.1),
@@ -426,7 +426,7 @@ pub fn heading_bar<B: Backend>(
let header_data = header_meta let header_data = header_meta
.iter() .iter()
.map(|i| { .map(|i| {
let header_block = gen_header(&i.0, i.1); let header_block = gen_header(&i.0, i.1.into());
(header_block.0, i.0, Constraint::Max(header_block.1)) (header_block.0, i.0, Constraint::Max(header_block.1))
}) })
.collect::<Vec<_>>(); .collect::<Vec<_>>();