mirror of
https://github.com/ClementTsang/bottom.git
synced 2025-04-08 17:05:59 +02:00
parent
663ae6c5c2
commit
22278d7d75
@ -4,4 +4,4 @@ echo "Executing: cargo +nightly clippy -- -D clippy::all"
|
||||
cargo +nightly clippy -- -D clippy::all
|
||||
|
||||
echo "Executing: cargo test"
|
||||
cargo test
|
||||
cargo test
|
||||
|
@ -1,4 +1,8 @@
|
||||
[target.x86_64-pc-windows-msvc]
|
||||
rustflags = ["-Ctarget-feature=+crt-static"]
|
||||
|
||||
[target.i686-pc-windows-msvc]
|
||||
rustflags = ["-Ctarget-feature=+crt-static"]
|
||||
|
||||
[target.armv7-unknown-linux-gnueabihf]
|
||||
linker = "arm-linux-gnueabihf-gcc"
|
118
.travis.yml
118
.travis.yml
@ -1,16 +1,75 @@
|
||||
language: rust
|
||||
rust:
|
||||
- stable
|
||||
- beta
|
||||
os:
|
||||
- linux
|
||||
- osx
|
||||
- windows
|
||||
jobs:
|
||||
cache: cargo
|
||||
notifications:
|
||||
email:
|
||||
on_success: never
|
||||
|
||||
matrix:
|
||||
include:
|
||||
# Standard x86-64 stuff, stable and beta
|
||||
- os: linux
|
||||
env: TARGET=x86_64-unknown-linux-gnu
|
||||
arch: amd64
|
||||
rust: stable
|
||||
- os: linux
|
||||
env: TARGET=x86_64-unknown-linux-gnu
|
||||
arch: amd64
|
||||
rust: beta
|
||||
- os: osx
|
||||
env: TARGET=x86_64-apple-darwin
|
||||
arch: amd64
|
||||
rust: stable
|
||||
- os: osx
|
||||
env: TARGET=x86_64-apple-darwin
|
||||
arch: amd64
|
||||
rust: beta
|
||||
- os: windows
|
||||
env: TARGET=x86_64-pc-windows-msvc
|
||||
arch: amd64
|
||||
rust: stable
|
||||
- os: windows
|
||||
env: TARGET=x86_64-pc-windows-msvc
|
||||
arch: amd64
|
||||
rust: beta
|
||||
|
||||
# musl
|
||||
- os: linux
|
||||
env: TARGET=x86_64-unknown-linux-musl
|
||||
arch: amd64
|
||||
rust: stable
|
||||
- os: linux
|
||||
env: TARGET=x86_64-unknown-linux-musl
|
||||
arch: amd64
|
||||
rust: beta
|
||||
|
||||
# ARM stuff (skip beta for now, see https://github.com/rust-lang/rust/issues/62896)
|
||||
- os: linux
|
||||
env: TARGET=aarch64-unknown-linux-gnu
|
||||
arch: arm64
|
||||
rust: stable
|
||||
- os: linux
|
||||
env: TARGET=armv7-unknown-linux-gnueabihf
|
||||
arch: amd64
|
||||
rust: stable
|
||||
addons:
|
||||
apt:
|
||||
packages: &armhf
|
||||
- gcc-arm-linux-gnueabihf
|
||||
- libc6-armhf-cross
|
||||
- libc6-dev-armhf-cross
|
||||
|
||||
fast_finish: true
|
||||
exclude:
|
||||
- if: tag IS present
|
||||
rust: beta
|
||||
- if: tag IS present
|
||||
arch: arm64
|
||||
- if: tag IS present
|
||||
env: TARGET=armv7-unknown-linux-gnueabihf
|
||||
allow_failures:
|
||||
- arch: arm64 # ARM will be run, but support is still gonna be limited for now... may change.
|
||||
- env: TARGET=armv7-unknown-linux-gnueabihf
|
||||
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
@ -19,10 +78,7 @@ branches:
|
||||
before_install:
|
||||
- export RUST_BACKTRACE=1
|
||||
- |
|
||||
if [[ $TRAVIS_OS_NAME == "linux" ]]; then
|
||||
export TARGET=x86_64-unknown-linux-gnu;
|
||||
elif [[ $TRAVIS_OS_NAME == "windows" ]]; then
|
||||
export TARGET=x86_64-pc-windows-msvc;
|
||||
if [[ $TRAVIS_OS_NAME == "windows" ]]; then
|
||||
if [[ -n $TRAVIS_TAG ]]; then
|
||||
powershell Install-WindowsFeature Net-Framework-Core;
|
||||
choco install -y wixtoolset;
|
||||
@ -30,21 +86,29 @@ before_install:
|
||||
choco install zip;
|
||||
rustup target add i686-pc-windows-msvc;
|
||||
fi
|
||||
elif [[ $TRAVIS_OS_NAME == "osx" ]]; then
|
||||
export TARGET=x86_64-apple-darwin;
|
||||
fi
|
||||
|
||||
before_script:
|
||||
- rustup target add $TARGET
|
||||
- rustup component add clippy
|
||||
- rustup update
|
||||
- |
|
||||
# Only check clippy if stable...
|
||||
if [[ $TRAVIS_RUST_VERSION == "stable" ]]; then
|
||||
rustup component add clippy
|
||||
fi
|
||||
|
||||
script:
|
||||
- cargo clippy -- -D clippy::all
|
||||
- cargo test --verbose --target $TARGET
|
||||
|
||||
cache: cargo
|
||||
|
||||
notifications:
|
||||
email:
|
||||
on_success: never
|
||||
- |
|
||||
# Only check clippy if stable...
|
||||
if [[ $TRAVIS_RUST_VERSION == "stable" ]]; then
|
||||
cargo clippy -- -D clippy::all
|
||||
fi
|
||||
- |
|
||||
if [[ $TARGET = "armv7-unknown-linux-gnueabihf" ]]; then
|
||||
cargo build --verbose --target $TARGET
|
||||
else
|
||||
cargo test --verbose --target $TARGET
|
||||
fi
|
||||
|
||||
before_deploy:
|
||||
- |
|
||||
@ -98,11 +162,10 @@ before_deploy:
|
||||
strip btm;
|
||||
local target_dir=$(ls target/release/build/bottom-*/out/rg.bash | head -n1 | xargs dirname)
|
||||
cp -r $target_dir completions
|
||||
echo "Tar-ing macOS/Linux binary and completions..."
|
||||
tar -czvf bottom_$TARGET.tar.gz btm completions;
|
||||
|
||||
if [[ $TRAVIS_OS_NAME == "linux" ]]; then
|
||||
echo "Tar-ing Linux binary and completions..."
|
||||
tar -czvf bottom_x86_64-unknown-linux-gnu.tar.gz btm completions;
|
||||
|
||||
echo "Generating AUR template...";
|
||||
python "./deployment/packager.py" $TRAVIS_TAG "./deployment/linux/arch/PKGBUILD_BIN.template" "./PKGBUILD_BIN" "SHA512" "./bottom_x86_64-unknown-linux-gnu.tar.gz";
|
||||
curl -LO "https://github.com/ClementTsang/bottom/archive/$TRAVIS_TAG.tar.gz";
|
||||
@ -120,9 +183,6 @@ before_deploy:
|
||||
cargo deb;
|
||||
cp ./target/debian/bottom_*.deb .;
|
||||
elif [[ $TRAVIS_OS_NAME == "osx" ]]; then
|
||||
|
||||
echo "Tar-ing macOS binary and completions..."
|
||||
tar -czvf bottom_x86_64-apple-darwin.tar.gz btm completions;
|
||||
# The bottom.rb file must be generated AFTER, since it relies on the Linux binary file.
|
||||
fi
|
||||
|
||||
|
5
.vscode/settings.json
vendored
5
.vscode/settings.json
vendored
@ -19,6 +19,7 @@
|
||||
"Mousebindings",
|
||||
"Nonexhaustive",
|
||||
"PKGBUILD",
|
||||
"PKGBUILDs",
|
||||
"Polishchuk",
|
||||
"Qudsi",
|
||||
"SIGTERM",
|
||||
@ -30,6 +31,7 @@
|
||||
"WASD",
|
||||
"Wojnarowski",
|
||||
"andys",
|
||||
"armv",
|
||||
"atim",
|
||||
"choco",
|
||||
"cmdline",
|
||||
@ -39,6 +41,7 @@
|
||||
"czvf",
|
||||
"fpath",
|
||||
"fract",
|
||||
"gnueabihf",
|
||||
"gotop",
|
||||
"gtop",
|
||||
"haase",
|
||||
@ -48,6 +51,7 @@
|
||||
"markdownlint",
|
||||
"memb",
|
||||
"minwindef",
|
||||
"musl",
|
||||
"n'th",
|
||||
"noheader",
|
||||
"ntdef",
|
||||
@ -81,6 +85,7 @@
|
||||
"winget",
|
||||
"winnt",
|
||||
"wixtoolset",
|
||||
"xargs",
|
||||
"xzvf",
|
||||
"ytop"
|
||||
]
|
||||
|
@ -32,7 +32,6 @@ ctrlc = {version = "3.1", features = ["termination"]}
|
||||
clap = "2.33"
|
||||
dirs = "3.0.1"
|
||||
futures = "0.3.5"
|
||||
heim = "0.0.10"
|
||||
itertools = "0.9.0"
|
||||
libc = "0.2"
|
||||
regex = "1.3"
|
||||
@ -51,6 +50,9 @@ tui = {version = "0.9.5", features = ["crossterm"], default-features = false }
|
||||
fern = "0.6.0"
|
||||
log = "0.4.11"
|
||||
|
||||
[target.'cfg(not(any(target_arch = "arm", target_arch = "aarch64")))'.dependencies]
|
||||
heim = "0.0.10"
|
||||
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
winapi = "0.3.9"
|
||||
|
||||
|
@ -62,7 +62,9 @@ Note that bottom is:
|
||||
- Officially tested and released for only `x86_64` (and `i686` for Windows)
|
||||
- Developed mainly for macOS, Windows, and Linux
|
||||
|
||||
As such, support beyond that is not guaranteed.
|
||||
As such, support beyond that is not guaranteed. There is now _technically_ support for AArch64 builds,
|
||||
and I do run them in Travis, but I am currently not guaranteeing their stability. In theory, they should
|
||||
work fine, but I've had some troubles with building on ARM in some situations.
|
||||
|
||||
### Manually
|
||||
|
||||
|
@ -15,8 +15,9 @@ use lazy_static::lazy_static;
|
||||
/// more points as this is used!
|
||||
use std::{time::Instant, vec::Vec};
|
||||
|
||||
use crate::data_harvester::{
|
||||
battery_harvester, cpu, disks, mem, network, processes, temperature, Data,
|
||||
use crate::{
|
||||
data_harvester::{battery_harvester, cpu, disks, mem, network, processes, temperature, Data},
|
||||
utils::gen_util::get_simple_byte_values,
|
||||
};
|
||||
use regex::Regex;
|
||||
|
||||
@ -54,6 +55,7 @@ pub struct DataCollection {
|
||||
pub disk_harvest: Vec<disks::DiskHarvest>,
|
||||
pub io_harvest: disks::IOHarvest,
|
||||
pub io_labels_and_prev: Vec<((u64, u64), (u64, u64))>,
|
||||
pub io_labels: Vec<(String, String)>,
|
||||
pub temp_harvest: Vec<temperature::TempHarvest>,
|
||||
pub battery_harvest: Vec<battery_harvester::BatteryHarvest>,
|
||||
}
|
||||
@ -72,6 +74,7 @@ impl Default for DataCollection {
|
||||
disk_harvest: Vec::default(),
|
||||
io_harvest: disks::IOHarvest::default(),
|
||||
io_labels_and_prev: Vec::default(),
|
||||
io_labels: Vec::default(),
|
||||
temp_harvest: Vec::default(),
|
||||
battery_harvest: Vec::default(),
|
||||
}
|
||||
@ -232,7 +235,6 @@ impl DataCollection {
|
||||
if let Some(trim) = device.name.split('/').last() {
|
||||
let io_device = if cfg!(target_os = "macos") {
|
||||
// Must trim one level further!
|
||||
|
||||
lazy_static! {
|
||||
static ref DISK_REGEX: Regex = Regex::new(r"disk\d+").unwrap();
|
||||
}
|
||||
@ -244,24 +246,50 @@ impl DataCollection {
|
||||
} else {
|
||||
io.get(trim)
|
||||
};
|
||||
let (io_r_pt, io_w_pt) = if let Some(io) = io_device {
|
||||
(io.read_bytes, io.write_bytes)
|
||||
|
||||
if let Some(io_device) = io_device {
|
||||
let (io_r_pt, io_w_pt) = if let Some(io) = io_device {
|
||||
(io.read_bytes, io.write_bytes)
|
||||
} else {
|
||||
(0, 0)
|
||||
};
|
||||
|
||||
if self.io_labels.len() <= itx {
|
||||
self.io_labels.push((String::default(), String::default()));
|
||||
}
|
||||
|
||||
if self.io_labels_and_prev.len() <= itx {
|
||||
self.io_labels_and_prev.push(((0, 0), (io_r_pt, io_w_pt)));
|
||||
}
|
||||
|
||||
if let Some((io_curr, io_prev)) = self.io_labels_and_prev.get_mut(itx) {
|
||||
let r_rate = ((io_r_pt.saturating_sub(io_prev.0)) as f64
|
||||
/ time_since_last_harvest)
|
||||
.round() as u64;
|
||||
let w_rate = ((io_w_pt.saturating_sub(io_prev.1)) as f64
|
||||
/ time_since_last_harvest)
|
||||
.round() as u64;
|
||||
|
||||
*io_curr = (r_rate, w_rate);
|
||||
*io_prev = (io_r_pt, io_w_pt);
|
||||
|
||||
if let Some(io_labels) = self.io_labels.get_mut(itx) {
|
||||
let converted_read = get_simple_byte_values(r_rate, false);
|
||||
let converted_write = get_simple_byte_values(w_rate, false);
|
||||
*io_labels = (
|
||||
format!("{:.*}{}/s", 0, converted_read.0, converted_read.1),
|
||||
format!("{:.*}{}/s", 0, converted_write.0, converted_write.1),
|
||||
);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
(0, 0)
|
||||
};
|
||||
if self.io_labels.len() <= itx {
|
||||
self.io_labels.push((String::default(), String::default()));
|
||||
}
|
||||
|
||||
if self.io_labels_and_prev.len() <= itx {
|
||||
self.io_labels_and_prev.push(((0, 0), (io_r_pt, io_w_pt)));
|
||||
} else if let Some((io_curr, io_prev)) = self.io_labels_and_prev.get_mut(itx) {
|
||||
let r_rate = ((io_r_pt.saturating_sub(io_prev.0)) as f64
|
||||
/ time_since_last_harvest)
|
||||
.round() as u64;
|
||||
let w_rate = ((io_w_pt.saturating_sub(io_prev.1)) as f64
|
||||
/ time_since_last_harvest)
|
||||
.round() as u64;
|
||||
|
||||
*io_curr = (r_rate, w_rate);
|
||||
*io_prev = (io_r_pt, io_w_pt);
|
||||
if let Some(io_labels) = self.io_labels.get_mut(itx) {
|
||||
*io_labels = ("N/A".to_string(), "N/A".to_string());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -160,16 +160,32 @@ impl DataCollector {
|
||||
self.sys.refresh_cpu();
|
||||
}
|
||||
|
||||
if cfg!(not(target_os = "linux")) {
|
||||
if cfg!(any(target_arch = "arm", target_arch = "aarch64")) {
|
||||
// ARM stuff
|
||||
if self.widgets_to_harvest.use_proc {
|
||||
self.sys.refresh_processes();
|
||||
}
|
||||
if self.widgets_to_harvest.use_temp {
|
||||
self.sys.refresh_components();
|
||||
}
|
||||
}
|
||||
if cfg!(target_os = "windows") && self.widgets_to_harvest.use_net {
|
||||
self.sys.refresh_networks();
|
||||
if self.widgets_to_harvest.use_net {
|
||||
self.sys.refresh_networks();
|
||||
}
|
||||
if self.widgets_to_harvest.use_mem {
|
||||
self.sys.refresh_memory();
|
||||
}
|
||||
} else {
|
||||
if cfg!(not(target_os = "linux")) {
|
||||
if self.widgets_to_harvest.use_proc {
|
||||
self.sys.refresh_processes();
|
||||
}
|
||||
if self.widgets_to_harvest.use_temp {
|
||||
self.sys.refresh_components();
|
||||
}
|
||||
}
|
||||
if cfg!(target_os = "windows") && self.widgets_to_harvest.use_net {
|
||||
self.sys.refresh_networks();
|
||||
}
|
||||
}
|
||||
|
||||
let current_instant = std::time::Instant::now();
|
||||
@ -230,25 +246,96 @@ impl DataCollector {
|
||||
}
|
||||
}
|
||||
|
||||
// ASYNC
|
||||
let network_data_fut = network::get_network_data(
|
||||
&self.sys,
|
||||
self.last_collection_time,
|
||||
&mut self.total_rx,
|
||||
&mut self.total_tx,
|
||||
current_instant,
|
||||
self.widgets_to_harvest.use_net,
|
||||
);
|
||||
// Async if Heim
|
||||
let network_data_fut = {
|
||||
#[cfg(any(target_os = "windows", target_arch = "aarch64", target_arch = "arm"))]
|
||||
{
|
||||
network::get_sysinfo_network_data(
|
||||
&self.sys,
|
||||
self.last_collection_time,
|
||||
&mut self.total_rx,
|
||||
&mut self.total_tx,
|
||||
current_instant,
|
||||
self.widgets_to_harvest.use_net,
|
||||
)
|
||||
}
|
||||
#[cfg(not(any(target_os = "windows", target_arch = "aarch64", target_arch = "arm")))]
|
||||
{
|
||||
network::get_heim_network_data(
|
||||
self.last_collection_time,
|
||||
&mut self.total_rx,
|
||||
&mut self.total_tx,
|
||||
current_instant,
|
||||
self.widgets_to_harvest.use_net,
|
||||
)
|
||||
}
|
||||
};
|
||||
let mem_data_fut = {
|
||||
#[cfg(any(target_arch = "aarch64", target_arch = "arm"))]
|
||||
{
|
||||
mem::get_sysinfo_mem_data_list(&self.sys, self.widgets_to_harvest.use_mem)
|
||||
}
|
||||
|
||||
let mem_data_fut = mem::get_mem_data_list(self.widgets_to_harvest.use_mem);
|
||||
let swap_data_fut = mem::get_swap_data_list(self.widgets_to_harvest.use_mem);
|
||||
let disk_data_fut = disks::get_disk_usage_list(self.widgets_to_harvest.use_disk);
|
||||
let disk_io_usage_fut = disks::get_io_usage_list(false, self.widgets_to_harvest.use_disk);
|
||||
let temp_data_fut = temperature::get_temperature_data(
|
||||
&self.sys,
|
||||
&self.temperature_type,
|
||||
self.widgets_to_harvest.use_temp,
|
||||
);
|
||||
#[cfg(not(any(target_arch = "aarch64", target_arch = "arm")))]
|
||||
{
|
||||
mem::get_heim_mem_data_list(self.widgets_to_harvest.use_mem)
|
||||
}
|
||||
};
|
||||
let swap_data_fut = {
|
||||
#[cfg(any(target_arch = "aarch64", target_arch = "arm"))]
|
||||
{
|
||||
mem::get_sysinfo_swap_data_list(&self.sys, self.widgets_to_harvest.use_mem)
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_arch = "aarch64", target_arch = "arm")))]
|
||||
{
|
||||
mem::get_heim_swap_data_list(self.widgets_to_harvest.use_mem)
|
||||
}
|
||||
};
|
||||
let disk_data_fut = {
|
||||
#[cfg(any(target_arch = "aarch64", target_arch = "arm"))]
|
||||
{
|
||||
disks::get_sysinfo_disk_usage_list(&self.sys, self.widgets_to_harvest.use_disk)
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_arch = "aarch64", target_arch = "arm")))]
|
||||
{
|
||||
disks::get_heim_disk_usage_list(self.widgets_to_harvest.use_disk)
|
||||
}
|
||||
};
|
||||
let disk_io_usage_fut = {
|
||||
#[cfg(any(target_arch = "aarch64", target_arch = "arm"))]
|
||||
{
|
||||
disks::get_sysinfo_io_usage_list(&self.sys, self.widgets_to_harvest.use_disk)
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_arch = "aarch64", target_arch = "arm")))]
|
||||
{
|
||||
disks::get_heim_io_usage_list(false, self.widgets_to_harvest.use_disk)
|
||||
}
|
||||
};
|
||||
let temp_data_fut = {
|
||||
#[cfg(any(not(target_os = "linux"), target_arch = "aarch64", target_arch = "arm"))]
|
||||
{
|
||||
temperature::get_sysinfo_temperature_data(
|
||||
&self.sys,
|
||||
&self.temperature_type,
|
||||
self.widgets_to_harvest.use_temp,
|
||||
)
|
||||
}
|
||||
|
||||
#[cfg(not(any(
|
||||
not(target_os = "linux"),
|
||||
target_arch = "aarch64",
|
||||
target_arch = "arm"
|
||||
)))]
|
||||
{
|
||||
temperature::get_heim_temperature_data(
|
||||
&self.temperature_type,
|
||||
self.widgets_to_harvest.use_temp,
|
||||
)
|
||||
}
|
||||
};
|
||||
|
||||
let (net_data, mem_res, swap_res, disk_res, io_res, temp_res) = join!(
|
||||
network_data_fut,
|
||||
@ -259,7 +346,6 @@ impl DataCollector {
|
||||
temp_data_fut
|
||||
);
|
||||
|
||||
// After async
|
||||
if let Some(net_data) = net_data {
|
||||
self.total_rx = net_data.total_rx;
|
||||
self.total_tx = net_data.total_tx;
|
||||
|
@ -1,6 +1,3 @@
|
||||
use futures::stream::StreamExt;
|
||||
use heim::units::information;
|
||||
|
||||
#[derive(Debug, Clone, Default)]
|
||||
pub struct DiskHarvest {
|
||||
pub name: String,
|
||||
@ -16,16 +13,60 @@ pub struct IOData {
|
||||
pub write_bytes: u64,
|
||||
}
|
||||
|
||||
pub type IOHarvest = std::collections::HashMap<String, IOData>;
|
||||
pub type IOHarvest = std::collections::HashMap<String, Option<IOData>>;
|
||||
|
||||
pub async fn get_io_usage_list(
|
||||
get_physical: bool, actually_get: bool,
|
||||
/// Meant for ARM use.
|
||||
#[cfg(any(target_arch = "aarch64", target_arch = "arm"))]
|
||||
pub async fn get_sysinfo_io_usage_list(
|
||||
_sys: &sysinfo::System, _actually_get: bool,
|
||||
) -> crate::utils::error::Result<Option<IOHarvest>> {
|
||||
let io_hash: std::collections::HashMap<String, Option<IOData>> =
|
||||
std::collections::HashMap::new();
|
||||
Ok(Some(io_hash))
|
||||
|
||||
// TODO: Sysinfo disk I/O usage.
|
||||
// ...sadly, this cannot be done as of now (other than me writing my own), it requires further
|
||||
// work. See https://github.com/GuillaumeGomez/sysinfo/issues/304.
|
||||
}
|
||||
|
||||
/// Meant for ARM use.
|
||||
#[cfg(any(target_arch = "aarch64", target_arch = "arm"))]
|
||||
pub async fn get_sysinfo_disk_usage_list(
|
||||
sys: &sysinfo::System, actually_get: bool,
|
||||
) -> crate::utils::error::Result<Option<Vec<DiskHarvest>>> {
|
||||
use sysinfo::{DiskExt, SystemExt};
|
||||
if !actually_get {
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
let mut io_hash: std::collections::HashMap<String, IOData> = std::collections::HashMap::new();
|
||||
let mut vec_disks = sys
|
||||
.get_disks()
|
||||
.iter()
|
||||
.map(|disk| DiskHarvest {
|
||||
name: disk.get_name().to_string_lossy().into(),
|
||||
mount_point: disk.get_mount_point().to_string_lossy().into(),
|
||||
free_space: disk.get_available_space(),
|
||||
used_space: disk.get_total_space() - disk.get_available_space(),
|
||||
total_space: disk.get_total_space(),
|
||||
})
|
||||
.collect::<Vec<DiskHarvest>>();
|
||||
vec_disks.sort_by(|a, b| a.name.cmp(&b.name));
|
||||
|
||||
Ok(Some(vec_disks))
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_arch = "aarch64", target_arch = "arm")))]
|
||||
pub async fn get_heim_io_usage_list(
|
||||
get_physical: bool, actually_get: bool,
|
||||
) -> crate::utils::error::Result<Option<IOHarvest>> {
|
||||
use futures::stream::StreamExt;
|
||||
|
||||
if !actually_get {
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
let mut io_hash: std::collections::HashMap<String, Option<IOData>> =
|
||||
std::collections::HashMap::new();
|
||||
if get_physical {
|
||||
let mut physical_counter_stream = heim::disk::io_counters_physical();
|
||||
while let Some(io) = physical_counter_stream.next().await {
|
||||
@ -33,10 +74,10 @@ pub async fn get_io_usage_list(
|
||||
let mount_point = io.device_name().to_str().unwrap_or("Name Unavailable");
|
||||
io_hash.insert(
|
||||
mount_point.to_string(),
|
||||
IOData {
|
||||
read_bytes: io.read_bytes().get::<information::megabyte>(),
|
||||
write_bytes: io.write_bytes().get::<information::megabyte>(),
|
||||
},
|
||||
Some(IOData {
|
||||
read_bytes: io.read_bytes().get::<heim::units::information::megabyte>(),
|
||||
write_bytes: io.write_bytes().get::<heim::units::information::megabyte>(),
|
||||
}),
|
||||
);
|
||||
}
|
||||
} else {
|
||||
@ -46,10 +87,10 @@ pub async fn get_io_usage_list(
|
||||
let mount_point = io.device_name().to_str().unwrap_or("Name Unavailable");
|
||||
io_hash.insert(
|
||||
mount_point.to_string(),
|
||||
IOData {
|
||||
read_bytes: io.read_bytes().get::<information::byte>(),
|
||||
write_bytes: io.write_bytes().get::<information::byte>(),
|
||||
},
|
||||
Some(IOData {
|
||||
read_bytes: io.read_bytes().get::<heim::units::information::byte>(),
|
||||
write_bytes: io.write_bytes().get::<heim::units::information::byte>(),
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -57,9 +98,12 @@ pub async fn get_io_usage_list(
|
||||
Ok(Some(io_hash))
|
||||
}
|
||||
|
||||
pub async fn get_disk_usage_list(
|
||||
#[cfg(not(any(target_arch = "aarch64", target_arch = "arm")))]
|
||||
pub async fn get_heim_disk_usage_list(
|
||||
actually_get: bool,
|
||||
) -> crate::utils::error::Result<Option<Vec<DiskHarvest>>> {
|
||||
use futures::stream::StreamExt;
|
||||
|
||||
if !actually_get {
|
||||
return Ok(None);
|
||||
}
|
||||
@ -73,9 +117,9 @@ pub async fn get_disk_usage_list(
|
||||
let usage = heim::disk::usage(partition.mount_point().to_path_buf()).await?;
|
||||
|
||||
vec_disks.push(DiskHarvest {
|
||||
free_space: usage.free().get::<information::byte>(),
|
||||
used_space: usage.used().get::<information::byte>(),
|
||||
total_space: usage.total().get::<information::byte>(),
|
||||
free_space: usage.free().get::<heim::units::information::byte>(),
|
||||
used_space: usage.used().get::<heim::units::information::byte>(),
|
||||
total_space: usage.total().get::<heim::units::information::byte>(),
|
||||
mount_point: (partition
|
||||
.mount_point()
|
||||
.to_str()
|
||||
|
@ -1,5 +1,3 @@
|
||||
use heim::units::information;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct MemHarvest {
|
||||
pub mem_total_in_mb: u64,
|
||||
@ -15,7 +13,40 @@ impl Default for MemHarvest {
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn get_mem_data_list(
|
||||
/// Meant for ARM use.
|
||||
#[cfg(any(target_arch = "aarch64", target_arch = "arm"))]
|
||||
pub async fn get_sysinfo_mem_data_list(
|
||||
sys: &sysinfo::System, actually_get: bool,
|
||||
) -> crate::utils::error::Result<Option<MemHarvest>> {
|
||||
use sysinfo::SystemExt;
|
||||
if !actually_get {
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
Ok(Some(MemHarvest {
|
||||
mem_total_in_mb: sys.get_total_memory() / 1024,
|
||||
mem_used_in_mb: sys.get_used_memory() / 1024,
|
||||
}))
|
||||
}
|
||||
|
||||
/// Meant for ARM use.
|
||||
#[cfg(any(target_arch = "aarch64", target_arch = "arm"))]
|
||||
pub async fn get_sysinfo_swap_data_list(
|
||||
sys: &sysinfo::System, actually_get: bool,
|
||||
) -> crate::utils::error::Result<Option<MemHarvest>> {
|
||||
use sysinfo::SystemExt;
|
||||
if !actually_get {
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
Ok(Some(MemHarvest {
|
||||
mem_total_in_mb: sys.get_total_swap() / 1024,
|
||||
mem_used_in_mb: sys.get_used_swap() / 1024,
|
||||
}))
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_arch = "aarch64", target_arch = "arm")))]
|
||||
pub async fn get_heim_mem_data_list(
|
||||
actually_get: bool,
|
||||
) -> crate::utils::error::Result<Option<MemHarvest>> {
|
||||
if !actually_get {
|
||||
@ -25,13 +56,16 @@ pub async fn get_mem_data_list(
|
||||
let memory = heim::memory::memory().await?;
|
||||
|
||||
Ok(Some(MemHarvest {
|
||||
mem_total_in_mb: memory.total().get::<information::megabyte>(),
|
||||
mem_used_in_mb: memory.total().get::<information::megabyte>()
|
||||
- memory.available().get::<information::megabyte>(),
|
||||
mem_total_in_mb: memory.total().get::<heim::units::information::megabyte>(),
|
||||
mem_used_in_mb: memory.total().get::<heim::units::information::megabyte>()
|
||||
- memory
|
||||
.available()
|
||||
.get::<heim::units::information::megabyte>(),
|
||||
}))
|
||||
}
|
||||
|
||||
pub async fn get_swap_data_list(
|
||||
#[cfg(not(any(target_arch = "aarch64", target_arch = "arm")))]
|
||||
pub async fn get_heim_swap_data_list(
|
||||
actually_get: bool,
|
||||
) -> crate::utils::error::Result<Option<MemHarvest>> {
|
||||
if !actually_get {
|
||||
@ -41,7 +75,7 @@ pub async fn get_swap_data_list(
|
||||
let memory = heim::memory::swap().await?;
|
||||
|
||||
Ok(Some(MemHarvest {
|
||||
mem_total_in_mb: memory.total().get::<information::megabyte>(),
|
||||
mem_used_in_mb: memory.used().get::<information::megabyte>(),
|
||||
mem_total_in_mb: memory.total().get::<heim::units::information::megabyte>(),
|
||||
mem_used_in_mb: memory.used().get::<heim::units::information::megabyte>(),
|
||||
}))
|
||||
}
|
||||
|
@ -1,10 +1,5 @@
|
||||
use std::time::Instant;
|
||||
|
||||
use futures::StreamExt;
|
||||
use heim::net;
|
||||
use heim::units::information::byte;
|
||||
use sysinfo::{NetworkExt, System, SystemExt};
|
||||
|
||||
#[derive(Default, Clone, Debug)]
|
||||
pub struct NetworkHarvest {
|
||||
pub rx: u64,
|
||||
@ -20,30 +15,67 @@ impl NetworkHarvest {
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn get_network_data(
|
||||
sys: &System, prev_net_access_time: Instant, prev_net_rx: &mut u64, prev_net_tx: &mut u64,
|
||||
curr_time: Instant, actually_get: bool,
|
||||
/// Meant for Windows and ARM use.
|
||||
#[cfg(any(target_os = "windows", target_arch = "aarch64", target_arch = "arm"))]
|
||||
pub async fn get_sysinfo_network_data(
|
||||
sys: &sysinfo::System, prev_net_access_time: Instant, prev_net_rx: &mut u64,
|
||||
prev_net_tx: &mut u64, curr_time: Instant, actually_get: bool,
|
||||
) -> Option<NetworkHarvest> {
|
||||
use sysinfo::{NetworkExt, SystemExt};
|
||||
|
||||
if !actually_get {
|
||||
return None;
|
||||
}
|
||||
|
||||
let mut io_data = net::io_counters();
|
||||
let mut total_rx: u64 = 0;
|
||||
let mut total_tx: u64 = 0;
|
||||
|
||||
if cfg!(target_os = "windows") {
|
||||
let networks = sys.get_networks();
|
||||
for (_, network) in networks {
|
||||
total_rx += network.get_total_received();
|
||||
total_tx += network.get_total_transmitted();
|
||||
}
|
||||
let networks = sys.get_networks();
|
||||
for (_, network) in networks {
|
||||
total_rx += network.get_total_received();
|
||||
total_tx += network.get_total_transmitted();
|
||||
}
|
||||
|
||||
let elapsed_time = curr_time.duration_since(prev_net_access_time).as_secs_f64();
|
||||
|
||||
let (rx, tx) = if elapsed_time == 0.0 {
|
||||
(0, 0)
|
||||
} else {
|
||||
while let Some(io) = io_data.next().await {
|
||||
if let Ok(io) = io {
|
||||
total_rx += io.bytes_recv().get::<byte>();
|
||||
total_tx += io.bytes_sent().get::<byte>();
|
||||
}
|
||||
(
|
||||
((total_rx.saturating_sub(*prev_net_rx)) as f64 / elapsed_time) as u64,
|
||||
((total_tx.saturating_sub(*prev_net_tx)) as f64 / elapsed_time) as u64,
|
||||
)
|
||||
};
|
||||
|
||||
*prev_net_rx = total_rx;
|
||||
*prev_net_tx = total_tx;
|
||||
Some(NetworkHarvest {
|
||||
rx,
|
||||
tx,
|
||||
total_rx,
|
||||
total_tx,
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "windows", target_arch = "aarch64", target_arch = "arm")))]
|
||||
pub async fn get_heim_network_data(
|
||||
prev_net_access_time: Instant, prev_net_rx: &mut u64, prev_net_tx: &mut u64,
|
||||
curr_time: Instant, actually_get: bool,
|
||||
) -> Option<NetworkHarvest> {
|
||||
use futures::StreamExt;
|
||||
|
||||
if !actually_get {
|
||||
return None;
|
||||
}
|
||||
|
||||
let mut io_data = heim::net::io_counters();
|
||||
let mut total_rx: u64 = 0;
|
||||
let mut total_tx: u64 = 0;
|
||||
|
||||
while let Some(io) = io_data.next().await {
|
||||
if let Ok(io) = io {
|
||||
total_rx += io.bytes_recv().get::<heim::units::information::byte>();
|
||||
total_tx += io.bytes_sent().get::<heim::units::information::byte>();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,9 +1,5 @@
|
||||
use std::cmp::Ordering;
|
||||
|
||||
use futures::StreamExt;
|
||||
use heim::units::thermodynamic_temperature;
|
||||
use sysinfo::{ComponentExt, System, SystemExt};
|
||||
|
||||
#[derive(Default, Debug, Clone)]
|
||||
pub struct TempHarvest {
|
||||
pub component_name: Option<String>,
|
||||
@ -24,61 +20,90 @@ impl Default for TemperatureType {
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn get_temperature_data(
|
||||
sys: &System, temp_type: &TemperatureType, actually_get: bool,
|
||||
/// Meant for ARM and non-Linux usage.
|
||||
#[cfg(any(not(target_os = "linux"), target_arch = "aarch64", target_arch = "arm"))]
|
||||
pub async fn get_sysinfo_temperature_data(
|
||||
sys: &sysinfo::System, temp_type: &TemperatureType, actually_get: bool,
|
||||
) -> crate::utils::error::Result<Option<Vec<TempHarvest>>> {
|
||||
use sysinfo::{ComponentExt, SystemExt};
|
||||
|
||||
fn convert_celsius_to_kelvin(celsius: f32) -> f32 {
|
||||
celsius + 273.15
|
||||
}
|
||||
|
||||
fn convert_celsius_to_fahrenheit(celsius: f32) -> f32 {
|
||||
(celsius * (9.0 / 5.0)) + 32.0
|
||||
}
|
||||
|
||||
if !actually_get {
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
let mut temperature_vec: Vec<TempHarvest> = Vec::new();
|
||||
|
||||
if cfg!(target_os = "linux") {
|
||||
let mut sensor_data = heim::sensors::temperatures();
|
||||
while let Some(sensor) = sensor_data.next().await {
|
||||
if let Ok(sensor) = sensor {
|
||||
temperature_vec.push(TempHarvest {
|
||||
component_name: Some(sensor.unit().to_string()),
|
||||
component_label: if let Some(label) = sensor.label() {
|
||||
Some(label.to_string())
|
||||
} else {
|
||||
None
|
||||
},
|
||||
temperature: match temp_type {
|
||||
TemperatureType::Celsius => sensor
|
||||
.current()
|
||||
.get::<thermodynamic_temperature::degree_celsius>(
|
||||
),
|
||||
TemperatureType::Kelvin => {
|
||||
sensor.current().get::<thermodynamic_temperature::kelvin>()
|
||||
}
|
||||
TemperatureType::Fahrenheit => sensor
|
||||
.current()
|
||||
.get::<thermodynamic_temperature::degree_fahrenheit>(
|
||||
),
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let sensor_data = sys.get_components();
|
||||
for component in sensor_data {
|
||||
let sensor_data = sys.get_components();
|
||||
for component in sensor_data {
|
||||
temperature_vec.push(TempHarvest {
|
||||
component_name: None,
|
||||
component_label: Some(component.get_label().to_string()),
|
||||
temperature: match temp_type {
|
||||
TemperatureType::Celsius => component.get_temperature(),
|
||||
TemperatureType::Kelvin => convert_celsius_to_kelvin(component.get_temperature()),
|
||||
TemperatureType::Fahrenheit => {
|
||||
convert_celsius_to_fahrenheit(component.get_temperature())
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
temp_vec_sort(&mut temperature_vec);
|
||||
Ok(Some(temperature_vec))
|
||||
}
|
||||
|
||||
#[cfg(not(any(not(target_os = "linux"), target_arch = "aarch64", target_arch = "arm")))]
|
||||
pub async fn get_heim_temperature_data(
|
||||
temp_type: &TemperatureType, actually_get: bool,
|
||||
) -> crate::utils::error::Result<Option<Vec<TempHarvest>>> {
|
||||
use futures::StreamExt;
|
||||
|
||||
if !actually_get {
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
let mut temperature_vec: Vec<TempHarvest> = Vec::new();
|
||||
|
||||
use heim::units::thermodynamic_temperature;
|
||||
let mut sensor_data = heim::sensors::temperatures();
|
||||
while let Some(sensor) = sensor_data.next().await {
|
||||
if let Ok(sensor) = sensor {
|
||||
temperature_vec.push(TempHarvest {
|
||||
component_name: None,
|
||||
component_label: Some(component.get_label().to_string()),
|
||||
component_name: Some(sensor.unit().to_string()),
|
||||
component_label: if let Some(label) = sensor.label() {
|
||||
Some(label.to_string())
|
||||
} else {
|
||||
None
|
||||
},
|
||||
temperature: match temp_type {
|
||||
TemperatureType::Celsius => component.get_temperature(),
|
||||
TemperatureType::Celsius => sensor
|
||||
.current()
|
||||
.get::<thermodynamic_temperature::degree_celsius>(),
|
||||
TemperatureType::Kelvin => {
|
||||
convert_celsius_to_kelvin(component.get_temperature())
|
||||
}
|
||||
TemperatureType::Fahrenheit => {
|
||||
convert_celsius_to_fahrenheit(component.get_temperature())
|
||||
sensor.current().get::<thermodynamic_temperature::kelvin>()
|
||||
}
|
||||
TemperatureType::Fahrenheit => sensor
|
||||
.current()
|
||||
.get::<thermodynamic_temperature::degree_fahrenheit>(
|
||||
),
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
temp_vec_sort(&mut temperature_vec);
|
||||
Ok(Some(temperature_vec))
|
||||
}
|
||||
|
||||
fn temp_vec_sort(temperature_vec: &mut Vec<TempHarvest>) {
|
||||
// By default, sort temperature, then by alphabetically!
|
||||
// TODO: [TEMPS] Allow users to control this.
|
||||
|
||||
@ -97,14 +122,4 @@ pub async fn get_temperature_data(
|
||||
.partial_cmp(&b.component_name)
|
||||
.unwrap_or(Ordering::Equal)
|
||||
});
|
||||
|
||||
Ok(Some(temperature_vec))
|
||||
}
|
||||
|
||||
fn convert_celsius_to_kelvin(celsius: f32) -> f32 {
|
||||
celsius + 273.15
|
||||
}
|
||||
|
||||
fn convert_celsius_to_fahrenheit(celsius: f32) -> f32 {
|
||||
(celsius * (9.0 / 5.0)) + 32.0
|
||||
}
|
||||
|
@ -117,15 +117,8 @@ pub fn convert_disk_row(current_data: &data_farmer::DataCollection) -> Vec<Vec<S
|
||||
current_data
|
||||
.disk_harvest
|
||||
.iter()
|
||||
.zip(¤t_data.io_labels_and_prev)
|
||||
.for_each(|(disk, (io_label, _io_prev))| {
|
||||
let converted_read = get_simple_byte_values(io_label.0, false);
|
||||
let converted_write = get_simple_byte_values(io_label.1, false);
|
||||
let io_activity = (
|
||||
format!("{:.*}{}/s", 0, converted_read.0, converted_read.1),
|
||||
format!("{:.*}{}/s", 0, converted_write.0, converted_write.1),
|
||||
);
|
||||
|
||||
.zip(¤t_data.io_labels)
|
||||
.for_each(|(disk, (io_read, io_write))| {
|
||||
let converted_free_space = get_simple_byte_values(disk.free_space, false);
|
||||
let converted_total_space = get_simple_byte_values(disk.total_space, false);
|
||||
disk_vector.push(vec![
|
||||
@ -140,8 +133,8 @@ pub fn convert_disk_row(current_data: &data_farmer::DataCollection) -> Vec<Vec<S
|
||||
"{:.*}{}",
|
||||
0, converted_total_space.0, converted_total_space.1
|
||||
),
|
||||
io_activity.0,
|
||||
io_activity.1,
|
||||
io_read.to_string(),
|
||||
io_write.to_string(),
|
||||
]);
|
||||
});
|
||||
|
||||
@ -348,7 +341,7 @@ pub fn convert_network_data_points(
|
||||
}
|
||||
} else {
|
||||
let rx_display = format!(
|
||||
"RX: {:<9} Total: {:<9}",
|
||||
"RX: {:<9} All: {:<9}",
|
||||
format!("{:.1}{:3}", rx_converted_result.0, rx_converted_result.1),
|
||||
format!(
|
||||
"{:.1}{:3}",
|
||||
@ -356,7 +349,7 @@ pub fn convert_network_data_points(
|
||||
)
|
||||
);
|
||||
let tx_display = format!(
|
||||
"TX: {:<9} Total: {:<9}",
|
||||
"TX: {:<9} All: {:<9}",
|
||||
format!("{:.1}{:3}", tx_converted_result.0, tx_converted_result.1),
|
||||
format!(
|
||||
"{:.1}{:3}",
|
||||
|
@ -42,6 +42,7 @@ impl From<std::io::Error> for BottomError {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_arch = "aarch64", target_arch = "arm")))]
|
||||
impl From<heim::Error> for BottomError {
|
||||
fn from(err: heim::Error) -> Self {
|
||||
BottomError::InvalidHeim(err.to_string())
|
||||
|
@ -148,6 +148,17 @@ fn test_empty_battery() -> Result<(), Box<dyn std::error::Error>> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_lone_default_widget_count() -> Result<(), Box<dyn std::error::Error>> {
|
||||
Command::new(get_binary_location())
|
||||
.arg("-C")
|
||||
.arg("./tests/invalid_configs/lone_default_widget_count.toml")
|
||||
.assert()
|
||||
.failure()
|
||||
.stderr(predicate::str::contains("it must be used with"));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_invalid_default_widget_count() -> Result<(), Box<dyn std::error::Error>> {
|
||||
Command::new(get_binary_location())
|
||||
@ -155,6 +166,6 @@ fn test_invalid_default_widget_count() -> Result<(), Box<dyn std::error::Error>>
|
||||
.arg("./tests/invalid_configs/invalid_default_widget_count.toml")
|
||||
.assert()
|
||||
.failure()
|
||||
.stderr(predicate::str::contains("it must be used with"));
|
||||
.stderr(predicate::str::contains("invalid number"));
|
||||
Ok(())
|
||||
}
|
||||
|
@ -1,2 +1,3 @@
|
||||
[flags]
|
||||
default_widget_count = 3
|
||||
default_widget_type="CPU"
|
||||
default_widget_count=18446744073709551616
|
||||
|
@ -2,4 +2,5 @@
|
||||
[[row.child]]
|
||||
type="cpu"
|
||||
[[row.child]]
|
||||
type="not_real"
|
||||
type="not_real"
|
||||
|
2
tests/invalid_configs/lone_default_widget_count.toml
Normal file
2
tests/invalid_configs/lone_default_widget_count.toml
Normal file
@ -0,0 +1,2 @@
|
||||
[flags]
|
||||
default_widget_count = 3
|
@ -1,2 +1,2 @@
|
||||
[flags]
|
||||
basic = "test"
|
||||
basic = "test"
|
||||
|
Loading…
x
Reference in New Issue
Block a user