Compare commits

...

14 Commits

Author SHA1 Message Date
a3fb70c55c
Update README 2025-08-27 21:29:20 -04:00
7bf4dfe8a8
Updated README.md 2024-09-30 10:30:51 -04:00
Shibe Drill
1f56893387
Update README.md 2024-09-18 13:59:56 -04:00
Shibe Drill
23286a7539
Update README.md 2024-08-15 17:55:44 -04:00
shibedrill
03e9dfebee Clippy autofixes 2024-08-15 17:47:26 -04:00
shibedrill
8f6aa2a6f4 Add support for NixOS 2024-08-15 17:47:11 -04:00
shibedrill
0701c34673 Fixed logic that would panic 2024-05-07 17:06:04 -04:00
shibedrill
9b689dabaf add steamOS support 2024-05-03 14:29:45 -04:00
Shibe Drill
c4cffa0b3c subdevice instead of full name 2024-03-07 17:03:37 -05:00
shibedrill
c0f7467e3e fixed some more stuff 2024-03-07 15:57:57 -05:00
shibedrill
3d8d0f14fe updated APIs, and serialization 2024-03-07 15:57:40 -05:00
shibedrill
73c5245100 more detailed test output 2024-02-13 13:52:02 -05:00
shibedrill
a437c5f34f clippy fixes, changed libpci-rs source to git 2024-02-13 13:42:07 -05:00
shibedrill
5cb6a8b9f3 stack swap, doc fixes. waiting on PCIIDs 2024-02-13 13:34:41 -05:00
4 changed files with 842 additions and 295 deletions

936
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
[package] [package]
name = "oxidefetch" name = "oxidefetch"
description = "A fast, cross platform Fetch program for your terminal" description = "A fast, cross platform Fetch program for your terminal"
version = "1.4.8" version = "2.0.0-beta.4"
edition = "2021" edition = "2021"
authors = [ "NamedNeon", "shibedrill" ] authors = [ "NamedNeon", "shibedrill" ]
license = "MIT" license = "MIT"
@ -21,6 +21,9 @@ ron = "0.8.1"
sysinfo = "0.29.1" sysinfo = "0.29.1"
whoami = "1.3.0" whoami = "1.3.0"
[dependencies.libpci-rs]
git = "https://github.com/gibsonpil/libpci-rs"
[dependencies.serde] [dependencies.serde]
version = "1.0.192" version = "1.0.192"
features = ["derive"] features = ["derive"]

View File

@ -1,20 +1,25 @@
# oxidefetch 1.4.8 # oxidefetch 2.0.0-beta.4
Fully cross platform Neofetch clone written in Rust. Up to 25 times faster than Neofetch! Fully cross platform Neofetch clone written in Rust. Up to 25 times faster than Neofetch!
![alt text](image.png "Example output of OxideFetch on a WSL2 Arch Linux host") ![alt text](image.png "Example output of OxideFetch on a WSL2 Arch Linux host")
### Why Oxidefetch? ## Why Oxidefetch
Neofetch, being a BASH script, has a few downsides in my opinion. Neofetch, being a BASH script, has a few downsides in my opinion.
1: It's slow. 1: It's slow.
2: It only works on platforms which have the BASH shell. 2: It only works on platforms which have the BASH shell.
3: It's kinda big, and I like having more compact info. 3: It's kinda big, and I like having more compact info.
As such, I wrote OxideFetch. How cool is that? It displays your information in a manner that's compact, cross-platform, and BLAZINGLY fast. I've measured speeds of up to 25 times faster than normal Neofetch on WSL2. As such, I wrote OxideFetch. How cool is that? It displays your information in a manner that's compact, cross-platform, and BLAZINGLY fast. I've measured speeds of up to 25 times faster than normal Neofetch on WSL2. Its primary advantage over other fetch programs is its usage of [libpci-rs](https://github.com/gibsonpil/libpci-rs), which is significantly (up to 35 times) faster than the system-provided `lspci` on Linux when looking up display names for GPUs.
### Special Thanks ### Special Thanks
The most heartfelt of thanks goes out to NamedNeon, who contributed the code to perform terminal detection.
The most heartfelt of thanks goes out to NamedNeon, who contributed the code to perform terminal detection, and to perform GPU detection on Darwin and Windows.
### Features ### Features
OxideFetch can display all of the following information: OxideFetch can display all of the following information:
- Date, time, and day of week - Date, time, and day of week
- Username and hostname - Username and hostname
- Operating system name, symbol, and matching color - Operating system name, symbol, and matching color
@ -28,33 +33,35 @@ OxideFetch can display all of the following information:
Also, the field-titles feature can be enabled at compile-time, which will display the name of each field in white before the information within that field. By default, it is disabled. Also, the field-titles feature can be enabled at compile-time, which will display the name of each field in white before the information within that field. By default, it is disabled.
### Installation ### Installation
Download a binary for your platform, and place it in your `$PATH`. Download a binary for your platform, and place it in your `$PATH`.
Currently, only Windows (x86_64, gnu/msvc) and Linux (x86_64/aarch64, gnu/musl) have binaries available. If you want a binary for another platform, you will have to follow the instructions to build from source. Currently, only Windows (x86_64, gnu/msvc) and Linux (x86_64/aarch64, gnu/musl) have binaries available. If you want a binary for another platform, you will have to follow the instructions to build from source.
### Dependencies ### Dependencies
#### Build/Install #### Build/Install
To build Oxidefetch, you need Cargo. If you do not already have Cargo installed on your system, you can do so by installing Rustup- either via the [instructions on their website](https://doc.rust-lang.org/cargo/getting-started/installation.html "instructions on their website") or via your system package manager. To build Oxidefetch, you need Cargo. If you do not already have Cargo installed on your system, you can do so by installing Rustup- either via the [instructions on their website](https://doc.rust-lang.org/cargo/getting-started/installation.html "instructions on their website") or via your system package manager.
You will also probably need a C/C++ compiler and a build system- most likely CMake and Visual Studio Build Tools, or GNU Make and the GNU compiler collection. You will be prompted to install these if they're not found during compilation. You will also probably need a C/C++ compiler and a build system- most likely CMake and Visual Studio Build Tools, or GNU Make and the GNU compiler collection. You will be prompted to install these if they're not found during compilation.
You can use Cargo, once it's installed, to automatically build and install Oxidefetch like so: You can use Cargo, once it's installed, to automatically build and install Oxidefetch like so:
`cargo install --git https://github.com/shibedrill/oxidefetch`. `cargo install --git https://git.shibedrill.site/shibedrill/oxidefetch`.
Alternatively, you can get it from the Crates repos, using `cargo install oxidefetch`. But it might be slightly out of date. Alternatively, you can get it from the Crates repos, using `cargo install oxidefetch`. But it might be slightly out of date.
From there, it *should* be in your `$PATH`. If not, add `source ~/.cargo/env` to your profile, or add `~/.cargo/bin` to your `$PATH`. From there, it *should* be in your `$PATH`. If not, add `source ~/.cargo/env` to your profile, or add `~/.cargo/bin` to your `$PATH`.
#### Runtime #### Runtime
There's only a couple runtime dependencies for this project.
1: `sh` shell installed for GPU detection on \*nix systems. The only runtime dependency for this project is a font with Nerd Fonts Symbols. If this is not used, the symbols in the output will not appear correctly.
2: `lspci` installed for GPU detection on \*nix systems.
(If either of these above dependencies are absent, chances are the GPU field will simply not show up. It won't crash or anything.
GPU detection runs on Windows without any dependencies.)
3: Nerd fonts symbols are used in the output. Install a patched font on your system, or patch an already installed font.
### How you can help with the project ### How you can help with the project
I need to verify the output of the OS information detection libraries I'm pulling in. To do this, I need the help of people with varying types of systems. I've tested a few, but there's some I'm unable to test. To help, you can kindly clone this repo, and inside the folder, run `cargo test -- --nocapture`, and send the resultant `test_output.txt` file to my noreply email address, or directly to me on Discord at `@shibedrill`. This program does NOT collect information regarding your real name, IP, location, hardware serial numbers, etc. You can look at the file it generates to be sure- it's all plaintext, babey. Also, consider contributing to [libpci-rs](https://github.com/namedneon/libpci-rs), which will eventually take responsibility for the GPU detection.
#### Tested distributions/platforms: I need to verify the output of the OS information detection libraries I'm pulling in. To do this, I need the help of people with varying types of systems. I've tested a few, but there's some I'm unable to test. To help, you can kindly clone this repo, and inside the folder, run `cargo test -- --nocapture`, and send the resultant `test_output.txt` file to my noreply email address, or directly to me on Discord at `@shibedrill`. This program does NOT collect information regarding your real name, IP, location, hardware serial numbers, etc. You can look at the file it generates to be sure- it's all plaintext, babey. Also, consider contributing to [libpci-rs](https://github.com/namedneon/libpci-rs) to improve its functionality, efficiency, and cleanliness.
#### Tested distributions/platforms
- Alma Linux - Alma Linux
- Alpine Linux - Alpine Linux
- Android
- Arch Linux - Arch Linux
- CentOS - CentOS
- Debian GNU/Linux - Debian GNU/Linux
@ -67,28 +74,39 @@ I need to verify the output of the OS information detection libraries I'm pullin
- Ubuntu - Ubuntu
- Windows - Windows
### Bugs, Quirks, Unintended Behavior, And Other Shenanigans ### Bugs, Quirks, Unintended Behavior, And Other Shenanigans
No weird quirks to report at this time.
- Some information may be vague or incorrect on Android. I might consider switching to new stacks for certain pieces of information.
- GPU detection might require root on certain platforms, such as Android and MacOS.
### To Do & Roadmap
#### Semi-urgent fixes
### To Do & Roadmap
#### Semi-urgent fixes:
- None so far. - None so far.
#### Very near future:
- Add support for user configurability for entries (whether or not an entry shows, its color, units for memory and time) #### Very near future
- Add support for user configurability for entries (whether or not an entry shows, its color, units for memory and time)
- Add process count detection - Add process count detection
- Refactor logic for cleaner code - Refactor logic for cleaner code
- Edit \*nix GPU detection to include GPUs that do not include `VGA Compatible Controller` in the name - Fix Android-specific problems
#### Future: - Make GPU display names more compact (how?)
#### Future
- Add host system name detection such as "Windows Subsystem for Linux", "IdeaPad 3", "Dell Optiplex", etc. - Add host system name detection such as "Windows Subsystem for Linux", "IdeaPad 3", "Dell Optiplex", etc.
- Add package count/package manager detection - Add package count/package manager detection
- Crosstest on more distributions to verify `sys.name()` outputs - Crosstest on more distributions to verify `sys.name()` outputs
- Refactor GPU detection logic into separate crate, remove dependencies on `sh` and `lspci`, and put any platform-specific code in separate files (This is slated for the 2.0.0 release. If you want to help accelerate this effort, consider contributing to [libpci-rs](https://github.com/namedneon/libpci-rs).)
#### Distant future: #### Distant future
- More extensible user configuration for entry formatting - More extensible user configuration for entry formatting
- Separate all information-getting logic into a new Fetch crate, allowing people to make their own fetch programs using a unified cross-platform API - Separate all information-getting logic into a new Fetch crate, allowing people to make their own fetch programs using a unified cross-platform API
### Changelog ### Changelog
**1.0.0:** Official full stable release
**1.0.0:** Official full stable release
**1.0.1:** Fixed distro name for Debian GNU/Linux. Logo & color works now. **1.0.1:** Fixed distro name for Debian GNU/Linux. Logo & color works now.
**1.1.0:** Refactored some poorly written typing, and added support for memory. **1.1.0:** Refactored some poorly written typing, and added support for memory.
**1.1.1:** Made sure that linux system detection won't fail if Linux has a capital L. **1.1.1:** Made sure that linux system detection won't fail if Linux has a capital L.
@ -107,6 +125,12 @@ No weird quirks to report at this time.
**1.4.6:** Cargo formatting applied to all files. Mild string reformatting in print statements. **1.4.6:** Cargo formatting applied to all files. Mild string reformatting in print statements.
**1.4.7:** Removed several `unwrap()` calls. Changed debug output to serialize to RON. **1.4.7:** Removed several `unwrap()` calls. Changed debug output to serialize to RON.
**1.4.8:** Applied Clippy suggestions. Added stuff to README. **1.4.8:** Applied Clippy suggestions. Added stuff to README.
**2.0.0-beta.0:** Switch from deprecated, platform-dependent GPU backends to [libpci-rs](https://github.com/gibsonpil/libpci-rs)
**2.0.0-beta.1:** Updated test functionality to include package version in the log file.
**2.0.0-beta.2:** Updated use of `libpci-rs` as its API approaches stability.
**2.0.0-beta.3:** GPU subsystem names will display instead of long names, if available.
**2.0.0-beta.4:** Added NixOS as a recognized distro.
### License ### License
This software is covered by the MIT license. See license.txt for details. This software is covered by the MIT license. See license.txt for details.

View File

@ -28,11 +28,10 @@ use crate::terminal::get_terminal;
use byte_unit::*; use byte_unit::*;
use chrono::*; use chrono::*;
use colored::*; use colored::*;
use libpci_rs::{ids::*, pci::*};
use std::env; use std::env;
use sysinfo::*; use sysinfo::*;
#[cfg(test)] #[cfg(test)]
use serde::Serialize; use serde::Serialize;
@ -55,7 +54,11 @@ fn main() {
color_print( color_print(
"Host:\t", "Host:\t",
'', '',
&Some(format!("{}@{}", sys_info.username, sys_info.hostname)), &Some(format!(
"{}@{}",
sys_info.username,
sys_info.hostname.unwrap_or("unknown".to_string())
)),
"purple", "purple",
); );
color_print("OS:\t", sys_info.icon, &sys_info.os_name, &sys_info.color); color_print("OS:\t", sys_info.icon, &sys_info.os_name, &sys_info.color);
@ -64,7 +67,7 @@ fn main() {
color_print("Uptime:\t", '', &Some(sys_info.uptime), "bright gray"); color_print("Uptime:\t", '', &Some(sys_info.uptime), "bright gray");
color_print("Shell:\t", '', &sys_info.shell, "bright magenta"); color_print("Shell:\t", '', &sys_info.shell, "bright magenta");
color_print("Terminal:\t", '', &sys_info.terminal, "magenta"); color_print("Terminal:\t", '', &sys_info.terminal, "magenta");
color_print("CPU:\t", '', &Some(sys_info.cpu), "green"); color_print("CPU:\t", '', &sys_info.cpu, "green");
if let Some(gpuvec) = sys_info.gpu { if let Some(gpuvec) = sys_info.gpu {
for gpu in gpuvec { for gpu in gpuvec {
@ -81,10 +84,7 @@ fn color_print(field_title: &str, icon: char, field: &Option<String>, color: &st
if let Some(fieldvalue) = field { if let Some(fieldvalue) = field {
#[cfg(feature = "field-titles")] #[cfg(feature = "field-titles")]
print!("{} ", field_title.bright_white()); print!("{} ", field_title.bright_white());
println!( println!("{}", format!("{} {}", icon, fieldvalue).color(color));
"{}",
format!("{} {}", icon, fieldvalue).color(color)
);
} }
} }
@ -96,14 +96,14 @@ struct Information {
// within the args of color_print, since that function only accepts args of // within the args of color_print, since that function only accepts args of
// type Option<String>. // type Option<String>.
username: String, username: String,
hostname: String, hostname: Option<String>,
os_name: Option<String>, os_name: Option<String>,
os_ver: Option<String>, os_ver: Option<String>,
kernel_ver: Option<String>, kernel_ver: Option<String>,
uptime: String, uptime: String,
shell: Option<String>, shell: Option<String>,
terminal: Option<String>, terminal: Option<String>,
cpu: String, cpu: Option<String>,
gpu: Option<Vec<String>>, gpu: Option<Vec<String>>,
memory: String, memory: String,
icon: char, icon: char,
@ -131,7 +131,7 @@ impl Information {
Self { Self {
username: whoami::username(), username: whoami::username(),
hostname: whoami::hostname(), hostname: whoami::fallible::hostname().ok(),
os_name: os_name.clone(), os_name: os_name.clone(),
os_ver: sys.os_version(), os_ver: sys.os_version(),
kernel_ver: sys.kernel_version(), kernel_ver: sys.kernel_version(),
@ -148,60 +148,46 @@ impl Information {
}, },
terminal: get_terminal(), terminal: get_terminal(),
cpu: String::from(sys.cpus()[0].brand()), cpu: {
let cpus = sys.cpus();
cpus.first().map(|first_cpu| first_cpu.brand().into())
},
gpu: { gpu: {
match sys if let Ok(pci_list) = get_pci_list() {
.name() let mut gpu_name_vec: Vec<String> = vec![];
.unwrap_or(String::from("Unknown System")) for device in pci_list {
.as_ref() if device.class == 3 {
{ let vendor_entry = lookup_vendor(device.vendor_id).unwrap();
"Windows" => { let device_entry = vendor_entry.device(device.device_id).unwrap();
// On windows, we run "wmic path win32_VideoController get name" and gpu_name_vec.push(format!(
// the second line is our GPU name. "{} {} {}",
let command_output = std::process::Command::new("wmic") vendor_entry.name(),
.args(["path", "win32_VideoController", "get", "name"]) // Get the subdevice name if it's available. Otherwise, use the long device name.
.output(); {
match command_output { if let Some(subsystem_entry) = device_entry.subsystem(device.subsys_device_id, device.subsys_vendor_id) {
Ok(gpu_info) => { subsystem_entry.name()
let gpu_info_as_string = String::from_utf8(gpu_info.stdout); } else {
Some(vec![String::from( device_entry.name()
gpu_info_as_string
.unwrap() // TODO: Please figure out a way to get rid of this unwrap() call.
// I feel like I did so well avoiding unwrap calls everywhere except for here.
.lines()
.collect::<Vec<&str>>()[1],
)])
}
Err(_) => None,
}
}
_ => {
// On *nix, hopefully, "lspci | grep VGA | awk -F 'VGA compatible controller: ' '{print $2}'" gives us our GPU name.
// Since pipes can't be processed as arguments, we need to do all this in a subshell under SH.
let command_output = std::process::Command::new("sh")
.args(["-c", "lspci | grep VGA | awk -F'VGA compatible controller: ' '{print $2}'"])
.output();
// Check if running the command resulted in an error. If not, convert to a vector.
// TODO: Please fix this horrible logic. It needs refactoring.
match command_output {
Err(_) => None,
Ok(output_bytes) => match String::from_utf8(output_bytes.stdout) {
Err(_) => None,
Ok(output_string) => match output_string.as_ref() {
"" => None,
_ => {
let mut gpu_vec = vec![];
for s in output_string.trim().split('\n') {
gpu_vec.push(s.to_string());
}
Some(gpu_vec)
} }
}, },
}, // Only show the revision when it's relevant.
{
if device.revision_id != 0 {
format!(" (rev {:02x})", device.revision_id)
} else {
"".to_string()
}
}
));
} }
} }
match gpu_name_vec.len() {
0 => None,
1.. => Some(gpu_name_vec),
}
} else {
None
} }
}, },
@ -235,10 +221,12 @@ impl Information {
"openSUSE Tumbleweed" | "openSUSE Leap" => '', "openSUSE Tumbleweed" | "openSUSE Leap" => '',
"PopOS" => '', "PopOS" => '',
"Ubuntu" => '', "Ubuntu" => '',
"SteamOS" => '',
"Windows" => '', "Windows" => '',
"Android" => '', "Android" => '',
"iOS" => '', "iOS" => '',
"MacOS" => '', "MacOS" => '',
"NixOS" => '󱄅',
"Unknown System" => '?', "Unknown System" => '?',
_ => { _ => {
if sys if sys
@ -268,10 +256,10 @@ impl Information {
"FreeBSD" => "red", "FreeBSD" => "red",
"Ubuntu" => "orange", "Ubuntu" => "orange",
"Arch Linux" | "Windows" | "PopOS" => "bright cyan", "Arch Linux" | "Windows" | "PopOS" => "bright cyan",
"Fedora Linux" | "Kali GNU/Linux" | "Alpine Linux" => "bright blue", "Fedora Linux" | "Kali GNU/Linux" | "Alpine Linux" | "NixOS" => "bright blue",
"openSUSE Tumbleweed" | "openSUSE Leap" | "Linux Mint" | "Android" => "bright green", "openSUSE Tumbleweed" | "openSUSE Leap" | "Linux Mint" | "Android" => "bright green",
"EndeavourOS" | "Gentoo" | "CentOS Linux" | "CentOS Stream" => "purple", "EndeavourOS" | "Gentoo" | "CentOS Linux" | "CentOS Stream" => "purple",
"iOS" | "macOS" | "ElementaryOS" => "bright white", "iOS" | "macOS" | "ElementaryOS" | "SteamOS" => "bright white",
"AlmaLinux" => "yellow", "AlmaLinux" => "yellow",
_ => "bright white", _ => "bright white",
@ -292,8 +280,12 @@ mod test {
pub fn log_gathered_data() { pub fn log_gathered_data() {
let sys_info = Information::new(); let sys_info = Information::new();
//let data_string = format!("{:#?}", sys_info); //let data_string = format!("{:#?}", sys_info);
let data_string = ron::ser::to_string_pretty(&sys_info, ron::ser::PrettyConfig::default()) let data_string = format!(
.expect("Failed to serialize data structure. Aborting..."); "// Version: {}\n// Begin structure dump:\n{}",
env!("CARGO_PKG_VERSION"),
ron::ser::to_string_pretty(&sys_info, ron::ser::PrettyConfig::default())
.expect("Failed to serialize data structure. Aborting...")
);
let result = fs::write("./test_output.ron", data_string); let result = fs::write("./test_output.ron", data_string);
if result.is_ok() { if result.is_ok() {