docker_stats/
utils.rs

1#![allow(dead_code)]
2
3use clap::ArgMatches;
4use colored::{ColoredString, Colorize};
5use terminal_size::{terminal_size, Width};
6
7/// Builds the command to run.
8pub fn build_command(matches: ArgMatches) -> Vec<String> {
9    let mut command = vec!["stats".to_string(), "--format".to_string(), "json".to_string()];
10
11    if let Some(containers) = matches.get_many::<String>("CONTAINER") {
12        command.extend(containers.cloned());
13    }
14
15    command
16}
17
18pub fn get_flag(args: &ArgMatches, id: &str) -> bool { args.get_one::<bool>(id).is_some_and(|x| *x) }
19
20/// Gets the current terminal width.
21pub fn get_terminal_width() -> usize {
22    if let Some((Width(w), _)) = terminal_size() {
23        w.into()
24    } else {
25        80
26    }
27}
28
29/// Fills the size with the given char.
30pub fn filler(char: &str, max: usize, used: usize) -> String {
31    if max == 0 || max <= used {
32        String::new()
33    } else {
34        char.repeat(max - used)
35    }
36}
37
38/// Fills the size with the given char, but only on even numbers.
39pub fn fill_on_even(char: &str, size: usize, len: usize) -> String {
40    if size == 0 || size <= len {
41        String::new()
42    } else {
43        let mut filler = String::new();
44
45        for i in 0..(size - len) {
46            if i % 2 == 0 {
47                filler.push_str(char);
48            } else {
49                filler.push(' ');
50            }
51        }
52
53        filler
54    }
55}
56
57/// Parses a percentage string into a usize.
58pub fn perc_to_float(perc: &str) -> f32 {
59    if let Some(stripped) = perc.strip_suffix('%') {
60        stripped.parse::<f32>().unwrap_or(0.0)
61    } else {
62        0.0
63    }
64}
65
66/// Converts a usize to a colored status bar.
67pub fn usize_to_status(perc: usize, max: usize) -> ColoredString {
68    let fill = filler("█", perc, 0);
69
70    if perc < max / 2 {
71        fill.green()
72    } else if perc < max - (max / 4) {
73        fill.yellow()
74    } else {
75        fill.red()
76    }
77}
78
79/// Splits a value into two balanced parts.
80pub fn balanced_split(value: usize) -> Vec<usize> { vec![value / 2, value / 2 + value % 2] }
81
82/// Scales a vector of numbers between a min and max value.
83pub fn scale_between(nums: Vec<u128>, floor: usize, ceil: usize) -> Option<Vec<usize>> {
84    let min = *nums.iter().min()?;
85    let max = *nums.iter().max()?;
86    let [floor, ceil] = [floor as u128, ceil as u128];
87
88    if min == max {
89        return None;
90    }
91
92    let scaled = nums
93        .iter()
94        .map(|num| {
95            let scaled_val = (ceil - floor) * (num - min) / (max - min) + floor;
96            usize::try_from(scaled_val).unwrap_or(0)
97        })
98        .collect();
99
100    Some(scaled)
101}