mirror of
https://github.com/NotAShelf/microfetch.git
synced 2025-12-14 16:31:02 +00:00
Compare commits
22 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
8d863c64c9 |
|||
|
2066d781fe |
|||
|
|
6640fdd559 |
||
|
cf3321b17a |
|||
|
7b8e736ff7 |
|||
|
927dce4127 |
|||
|
|
f883723608 |
||
|
|
f0cf18dba7 |
||
|
a3b169bbc4 |
|||
|
|
e4880661ae |
||
|
|
80e64a1c70 |
||
|
|
9da87b933d |
||
|
|
8376e9d323 |
||
|
8c32f5f408 |
|||
|
3ad14a95a6 |
|||
|
7683e6dfcf |
|||
|
96b02c9ed9 |
|||
|
6666644d3a |
|||
|
ff8af87747 |
|||
|
|
d2a981b070 |
||
|
|
5c23cb2665 |
||
|
|
5196ced487 |
15 changed files with 193 additions and 105 deletions
4
.cargo/config.toml
Normal file
4
.cargo/config.toml
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
# https://github.com/rui314/mold?tab=readme-ov-file#how-to-use
|
||||
[target.'cfg(target_os = "linux")']
|
||||
linker = "clang"
|
||||
rustflags = ["-C", "link-arg=-fuse-ld=mold"]
|
||||
4
.github/workflows/hotpath-comment.yml
vendored
4
.github/workflows/hotpath-comment.yml
vendored
|
|
@ -17,10 +17,10 @@ jobs:
|
|||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Download profiling results
|
||||
uses: actions/download-artifact@v4
|
||||
uses: actions/download-artifact@v6
|
||||
with:
|
||||
name: hotpath-results
|
||||
path: /tmp/
|
||||
|
|
|
|||
4
.github/workflows/hotpath-profile.yml
vendored
4
.github/workflows/hotpath-profile.yml
vendored
|
|
@ -13,7 +13,7 @@ jobs:
|
|||
|
||||
steps:
|
||||
- name: Checkout PR HEAD
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
|
|
@ -53,7 +53,7 @@ jobs:
|
|||
echo '${{ github.event.pull_request.number }}' > /tmp/pr_number.txt
|
||||
|
||||
- name: Upload profiling results
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v5
|
||||
with:
|
||||
name: hotpath-results
|
||||
path: |
|
||||
|
|
|
|||
2
.github/workflows/rust.yml
vendored
2
.github/workflows/rust.yml
vendored
|
|
@ -24,7 +24,7 @@ jobs:
|
|||
|
||||
steps:
|
||||
- name: "Checkout"
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: "Setup Rust toolchain"
|
||||
uses: actions-rust-lang/setup-rust-toolchain@v1
|
||||
|
|
|
|||
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -1,2 +1,3 @@
|
|||
/target
|
||||
result*
|
||||
/.direnv
|
||||
|
|
|
|||
22
Cargo.lock
generated
22
Cargo.lock
generated
|
|
@ -280,9 +280,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "criterion"
|
||||
version = "0.8.0"
|
||||
version = "0.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a0dfe5e9e71bdcf4e4954f7d14da74d1cdb92a3a07686452d1509652684b1aab"
|
||||
checksum = "4d883447757bb0ee46f233e9dc22eb84d93a9508c9b868687b274fc431d886bf"
|
||||
dependencies = [
|
||||
"alloca",
|
||||
"anes",
|
||||
|
|
@ -305,9 +305,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "criterion-plot"
|
||||
version = "0.8.0"
|
||||
version = "0.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5de36c2bee19fba779808f92bf5d9b0fa5a40095c277aba10c458a12b35d21d6"
|
||||
checksum = "ed943f81ea2faa8dcecbbfa50164acf95d555afec96a27871663b300e387b2e4"
|
||||
dependencies = [
|
||||
"cast",
|
||||
"itertools",
|
||||
|
|
@ -557,9 +557,9 @@ checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c"
|
|||
|
||||
[[package]]
|
||||
name = "hotpath"
|
||||
version = "0.7.5"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "08382b985a19a79d95d35e2e201b02cc4b99efe2f47d82f3fd4301bb0005bb68"
|
||||
checksum = "4b0a2c66c081fe3684a54a7e5d059c9d9ad6b3ee5ccea14f6e4f056dbd77becf"
|
||||
dependencies = [
|
||||
"arc-swap",
|
||||
"base64",
|
||||
|
|
@ -586,9 +586,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "hotpath-macros"
|
||||
version = "0.7.5"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7d618063f89423ebe079a69f5435a13d4909219d4e359757118b75fd05ae65d0"
|
||||
checksum = "a38fa43ca80cf906cd05127e490d740a51abb38316db7bce9d95e89724a81761"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
|
@ -786,9 +786,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
|
|||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.177"
|
||||
version = "0.2.178"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976"
|
||||
checksum = "37c93d8daa9d8a012fd8ab92f088405fb202ea0b6ab73ee2482ae66af4f42091"
|
||||
|
||||
[[package]]
|
||||
name = "libredox"
|
||||
|
|
@ -832,7 +832,7 @@ checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
|
|||
|
||||
[[package]]
|
||||
name = "microfetch"
|
||||
version = "0.4.11"
|
||||
version = "0.4.12"
|
||||
dependencies = [
|
||||
"criterion",
|
||||
"hotpath",
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "microfetch"
|
||||
version = "0.4.11"
|
||||
version = "0.4.12"
|
||||
edition = "2024"
|
||||
|
||||
[lib]
|
||||
|
|
@ -12,11 +12,11 @@ name = "microfetch"
|
|||
path = "src/main.rs"
|
||||
|
||||
[dependencies]
|
||||
hotpath = { optional = true, version = "0.7.5" }
|
||||
libc = "0.2.177"
|
||||
hotpath = { optional = true, version = "0.8.0" }
|
||||
libc = "0.2.178"
|
||||
|
||||
[dev-dependencies]
|
||||
criterion = "0.8.0"
|
||||
criterion = "0.8.1"
|
||||
|
||||
[features]
|
||||
hotpath = [ "dep:hotpath", "hotpath/hotpath" ]
|
||||
|
|
|
|||
119
README.md
119
README.md
|
|
@ -6,15 +6,11 @@
|
|||
</div>
|
||||
|
||||
<div id="doc-begin" align="center">
|
||||
<h1 id="header">
|
||||
Microfetch
|
||||
</h1>
|
||||
<p>
|
||||
Microscopic fetch tool in Rust, for NixOS systems, with special emphasis on speed
|
||||
</p>
|
||||
<h1 id="header">Microfetch</h1>
|
||||
<p>Microscopic fetch tool in Rust, for NixOS systems, with special emphasis on speed</p>
|
||||
<br/>
|
||||
<a href="#synopsis">Synopsis</a><br/>
|
||||
<a href="#features">Features</a> | <a href="#motivation">Motivation</a><br/>
|
||||
<a href="#features">Features</a> | <a href="#motivation">Motivation</a><br/> | <a href="#benchmarks">Benchmarks</a><br/>
|
||||
<a href="#installation">Installation</a>
|
||||
<br/>
|
||||
</div>
|
||||
|
|
@ -43,7 +39,7 @@ on your system: it is pretty _[fast](#benchmarks)_...
|
|||
- Fast
|
||||
- Really fast
|
||||
- Minimal dependencies
|
||||
- Tiny binary (~370kb)
|
||||
- Tiny binary (~370kb [^1])
|
||||
- Actually really fast
|
||||
- Cool NixOS logo (other, inferior, distros are not supported)
|
||||
- Reliable detection of following info:
|
||||
|
|
@ -60,36 +56,47 @@ on your system: it is pretty _[fast](#benchmarks)_...
|
|||
- Did I mention fast?
|
||||
- Respects [`NO_COLOR` spec](https://no-color.org/)
|
||||
|
||||
[^1]: With the Mold linker, which is enabled by default in the Flake package,
|
||||
the binary size is roughly 350kb. That's nearly 20kb reduction in size :)
|
||||
|
||||
## Motivation
|
||||
|
||||
Fastfetch, as its name probably hinted, is a very fast fetch tool written in C.
|
||||
However, I am not interested in _any_ of its additional features, and I'm not
|
||||
interested in its configuration options. Sure I can _configure_ it when I
|
||||
dislike the defaults, but how often would I really change the configuration...
|
||||
[Rube-Goldmark Machine]: https://en.wikipedia.org/wiki/Rube_Goldberg_machine
|
||||
|
||||
Microfetch is my response to this problem. It is an _even faster_ fetch tool
|
||||
that I would've written in Bash and put in my `~/.bashrc` but is _actually_
|
||||
incredibly fast because it opts out of all the customization options provided by
|
||||
tools such as Fastfetch. Ultimately, it's a small, opinionated binary with a
|
||||
nice size that doesn't bother me, and incredible speed. Customization? No thank
|
||||
you. I cannot re-iterate it enough, Microfetch is _annoyingly fast_.
|
||||
Fastfetch, as its name _probably_ already hinted, is a very fast fetch tool
|
||||
written in C. I used to use Fastfetch on my systems, but I eventually came to
|
||||
the realization that I am _not interested in any of its additional features_. I
|
||||
don't use Sixel, I don't change my configuration more than maybe once a year and
|
||||
I don't even display most of the fields that it does. Sure the configurability
|
||||
is nice and I can configure the defaults that I do not like but how often do I
|
||||
really do that?
|
||||
|
||||
The project is written in Rust, which comes at the cost of "bloated" dependency
|
||||
trees and the increased build times, but we make an extended effort to keep the
|
||||
dependencies minimal and build times managable. The latter is also very easily
|
||||
mitigated with Nix's binary cache systems. Since Microfetch is already in
|
||||
Nixpkgs, you are recommended to use it to utilize the binary cache properly. The
|
||||
usage of Rust _is_ nice, however, since it provides us with incredible tooling
|
||||
and a very powerful language that allows for Microfetch to be as fast as
|
||||
possible. Sure C could've been used here as well, but do you think I hate
|
||||
myself?
|
||||
Since I already enjoy programming challenges, and don't use a fetch program that
|
||||
often, I eventually came to try and answer the question _how fast can I make my
|
||||
fetch script?_ It is an _even faster_ fetch tool that I would've written in Bash
|
||||
and put in my `~/.bashrc` but is _actually_ incredibly fast because it opts out
|
||||
of all the customization options provided by tools such as Fastfetch. Since
|
||||
Fetch scripts are kind of a coming-of-age ritual for most Linux users, I've
|
||||
decided to use it on my system. You also might be interested if you like the
|
||||
defaults and like speed.
|
||||
|
||||
> [!IMPORTANT]
|
||||
> **Update as of November 30th, 2025**:
|
||||
>
|
||||
> Microfetch now inlines handwritten assembly for even better performance. I
|
||||
> know I previously said I do not hate myself but I'm beginning to suspect this
|
||||
> is no longer the case. Enjoy the performance benefits!
|
||||
Ultimately, it's a small, opinionated binary with a nice size that doesn't
|
||||
bother me, and incredible speed. Customization? No thank you. I cannot
|
||||
re-iterate it enough, Microfetch is _annoyingly fast_. It does not, however,
|
||||
solve a technical problem. The "problem" Microfetch solves is entirely
|
||||
self-imposed. On the matter of _size_, the project is written in Rust, which
|
||||
comes at the cost of "bloated" dependency trees and the increased build times,
|
||||
but we make an extended effort to keep the dependencies minimal and build times
|
||||
managable. The latter is also very easily mitigated with Nix's binary cache
|
||||
systems. Since Microfetch is already in Nixpkgs, you are recommended to use it
|
||||
to utilize the binary cache properly. The usage of Rust _is_ nice, however,
|
||||
since it provides us with incredible tooling and a very powerful language that
|
||||
allows for Microfetch to be as fast as possible. ~~Sure C could've been used
|
||||
here as well, but do you think I hate myself?~~ Microfetch now features
|
||||
handwritten assembly to unsafely optimize some areas. In hindsight you all
|
||||
should have seen this coming. Is it faster? Yes.
|
||||
|
||||
Also see: [Rube-Goldmark Machine]
|
||||
|
||||
## Benchmarks
|
||||
|
||||
|
|
@ -197,17 +204,31 @@ You can't.
|
|||
|
||||
### Why?
|
||||
|
||||
Customization, of any kind, is expensive: I could try reading environment
|
||||
variables, parse command-line arguments or read a configuration file but all of
|
||||
those increment execution time and resource consumption by a lot.
|
||||
Customization, of most kinds, are expensive: I could try reading environment
|
||||
variables, parse command-line arguments or read a configuration file to allow
|
||||
configuring various fields but those inflate execution time and the resource
|
||||
consumption by a lot. Since Microfetch is closer to a code golf challenge than a
|
||||
program that attempts to fill a gap, I have elected not to make this trade.
|
||||
|
||||
### Really?
|
||||
|
||||
To be fair, you _can_ customize Microfetch by, well, patching it. It's not the
|
||||
best way per se, but it will be the only way that does not compromise on speed.
|
||||
[main module]: ./src/main.rs
|
||||
[discussions tab]: https://github.com/NotAShelf/microfetch/discussions
|
||||
|
||||
To be fair, you _can_ customize Microfetch by, well, patching it. It is
|
||||
certainly not the easiest way of doing so but if you are planning to change
|
||||
something in Microfetch, patching is the best way to go. It will also the only
|
||||
way that does not compromise on speed, unless you patch in bad code. Various
|
||||
users have adapted Microfetch to their distribution by patching the
|
||||
[main module] and inserting the logo of their choice. This is also the best way
|
||||
to go if you plan to make small changes. If your changes are not small, you
|
||||
might want to look for a program that is designed to be customizable; Microfetch
|
||||
is built for maximum performance.
|
||||
|
||||
The Nix package allows passing patches in a streamlined manner by passing
|
||||
`.overrideAttrs` to the derivation.
|
||||
`.overrideAttrs` to the derivation. You can apply your patches in `patches` and
|
||||
share your derivations with people. Feel free to use the [discussions tab] to
|
||||
share your own variants of Microfetch!
|
||||
|
||||
## Contributing
|
||||
|
||||
|
|
@ -219,13 +240,22 @@ Contributions that help improve performance in specific areas of Microfetch are
|
|||
welcome. Though, prepare to be bombarded with questions if your changes are
|
||||
large.
|
||||
|
||||
## Hacking
|
||||
### Hacking
|
||||
|
||||
A Nix flake is provided. `nix develop` to get started. Direnv users may simply
|
||||
run `direnv allow` to get started.
|
||||
A Nix flake is provided. You may use `nix develop` to get started. Direnv users
|
||||
may instead run `direnv allow` to get a complete environment with shell
|
||||
integration.
|
||||
|
||||
Non-nix users will need `cargo` and `gcc` installed on their system, see
|
||||
`Cargo.toml` for available release profiles.
|
||||
Non-Nix user will need `cargo`, `clang` and `mold` installed on their system to
|
||||
build Microfetch. As Mold seems to yield _slightly_ better results than the
|
||||
default linker, it has been set as the default in `.cargo/config.toml` for
|
||||
x86-64 Linux. You may override those defaults using the `RUSTFLAGS` environment
|
||||
variable. For example:
|
||||
|
||||
```sh
|
||||
# Use ld instead of Mold
|
||||
$ RUSTFLAGS="-C linker=/path/to/ld.lld" cargo build
|
||||
```
|
||||
|
||||
## Thanks
|
||||
|
||||
|
|
@ -242,6 +272,7 @@ person about current issues. To list a few, special thanks to:
|
|||
- [@sioodmy](https://github.com/sioodmy) - Being cute
|
||||
- [@mewoocat](https://github.com/mewoocat) - The awesome NixOS logo ASCII used
|
||||
in Microfetch
|
||||
- [@uzaaft](https://github.com/uzaaft) - Helping me going faster
|
||||
|
||||
Additionally a big thank you to everyone who used, talked about or criticized
|
||||
Microfetch. I might have missed your name here, but you have my thanks.
|
||||
|
|
|
|||
|
|
@ -10,9 +10,12 @@
|
|||
forEachSystem = nixpkgs.lib.genAttrs systems;
|
||||
pkgsForEach = nixpkgs.legacyPackages;
|
||||
in {
|
||||
packages = forEachSystem (system: {
|
||||
packages = forEachSystem (system: let
|
||||
pkgs = pkgsForEach.${system};
|
||||
in {
|
||||
default = self.packages.${system}.microfetch;
|
||||
microfetch = pkgsForEach.${system}.callPackage ./nix/package.nix {};
|
||||
microfetch = pkgs.callPackage ./nix/package.nix {};
|
||||
microfetch-mold = pkgs.callPackage ./nix/package.nix {useMold = true;};
|
||||
});
|
||||
|
||||
devShells = forEachSystem (system: {
|
||||
|
|
|
|||
|
|
@ -1,14 +1,22 @@
|
|||
{
|
||||
lib,
|
||||
rustPlatform,
|
||||
stdenv,
|
||||
stdenvAdapters,
|
||||
rustPlatform,
|
||||
llvm,
|
||||
useMold ? stdenv.isLinux && !stdenv.hostPlatform.isAarch,
|
||||
}: let
|
||||
toml = (lib.importTOML ../Cargo.toml).package;
|
||||
pname = toml.name;
|
||||
inherit (toml) version;
|
||||
|
||||
# Select stdenv based on useMold flag
|
||||
stdenv =
|
||||
if useMold
|
||||
then stdenvAdapters.useMoldLinker llvm.stdenv
|
||||
else llvm.stdenv;
|
||||
in
|
||||
rustPlatform.buildRustPackage.override {stdenv = stdenvAdapters.useMoldLinker llvm.stdenv;} {
|
||||
rustPlatform.buildRustPackage.override {inherit stdenv;} {
|
||||
inherit pname version;
|
||||
src = let
|
||||
fs = lib.fileset;
|
||||
|
|
@ -26,7 +34,14 @@ in
|
|||
|
||||
cargoLock.lockFile = ../Cargo.lock;
|
||||
enableParallelBuilding = true;
|
||||
env.RUSTFLAGS = "-C link-arg=-fuse-ld=mold";
|
||||
buildNoDefaultFeatures = true;
|
||||
doCheck = false;
|
||||
|
||||
# Only set RUSTFLAGS for mold if useMold is enabled
|
||||
env = lib.optionalAttrs useMold {
|
||||
CARGO_LINKER = "clang";
|
||||
RUSTFLAGS = "-C link-arg=-fuse-ld=mold";
|
||||
};
|
||||
|
||||
meta = {
|
||||
description = "Microscopic fetch script in Rust, for NixOS systems";
|
||||
|
|
|
|||
|
|
@ -1,27 +1,31 @@
|
|||
{
|
||||
mkShell,
|
||||
cargo,
|
||||
rustc,
|
||||
mold,
|
||||
clang,
|
||||
rust-analyzer-unwrapped,
|
||||
rustfmt,
|
||||
clippy,
|
||||
cargo,
|
||||
taplo,
|
||||
rustc,
|
||||
rustPlatform,
|
||||
gnuplot,
|
||||
}:
|
||||
mkShell {
|
||||
name = "microfetch";
|
||||
strictDeps = true;
|
||||
|
||||
nativeBuildInputs = [
|
||||
cargo
|
||||
rustc
|
||||
mold
|
||||
clang
|
||||
|
||||
rust-analyzer-unwrapped
|
||||
(rustfmt.override {asNightly = true;})
|
||||
clippy
|
||||
taplo
|
||||
|
||||
gnuplot # For Criterion.rs plots
|
||||
gnuplot # for Criterion.rs plots
|
||||
];
|
||||
|
||||
env.RUST_SRC_PATH = "${rustPlatform.rustLibSrc}";
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use std::{env, sync::LazyLock};
|
||||
use std::sync::LazyLock;
|
||||
|
||||
pub struct Colors {
|
||||
pub reset: &'static str,
|
||||
|
|
@ -37,8 +37,8 @@ impl Colors {
|
|||
}
|
||||
|
||||
pub static COLORS: LazyLock<Colors> = LazyLock::new(|| {
|
||||
// Check for NO_COLOR once at startup
|
||||
let is_no_color = env::var("NO_COLOR").is_ok();
|
||||
const NO_COLOR: *const libc::c_char = c"NO_COLOR".as_ptr();
|
||||
let is_no_color = unsafe { !libc::getenv(NO_COLOR).is_null() };
|
||||
Colors::new(is_no_color)
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -1,22 +1,27 @@
|
|||
use std::fmt::Write;
|
||||
use std::{ffi::CStr, fmt::Write};
|
||||
|
||||
#[must_use]
|
||||
#[cfg_attr(feature = "hotpath", hotpath::measure)]
|
||||
pub fn get_desktop_info() -> String {
|
||||
// Retrieve the environment variables and handle Result types
|
||||
let desktop_env = std::env::var("XDG_CURRENT_DESKTOP");
|
||||
let display_backend = std::env::var("XDG_SESSION_TYPE");
|
||||
|
||||
let desktop_str = match desktop_env {
|
||||
Err(_) => "Unknown",
|
||||
Ok(ref s) if s.starts_with("none+") => &s[5..],
|
||||
Ok(ref s) => s.as_str(),
|
||||
let desktop_str = unsafe {
|
||||
let ptr = libc::getenv(c"XDG_CURRENT_DESKTOP".as_ptr());
|
||||
if ptr.is_null() {
|
||||
"Unknown"
|
||||
} else {
|
||||
let s = CStr::from_ptr(ptr).to_str().unwrap_or("Unknown");
|
||||
s.strip_prefix("none+").unwrap_or(s)
|
||||
}
|
||||
};
|
||||
|
||||
let backend_str = match display_backend {
|
||||
Err(_) => "Unknown",
|
||||
Ok(ref s) if s.is_empty() => "Unknown",
|
||||
Ok(ref s) => s.as_str(),
|
||||
let backend_str = unsafe {
|
||||
let ptr = libc::getenv(c"XDG_SESSION_TYPE".as_ptr());
|
||||
if ptr.is_null() {
|
||||
"Unknown"
|
||||
} else {
|
||||
let s = CStr::from_ptr(ptr).to_str().unwrap_or("Unknown");
|
||||
if s.is_empty() { "Unknown" } else { s }
|
||||
}
|
||||
};
|
||||
|
||||
// Pre-calculate capacity: desktop_len + " (" + backend_len + ")"
|
||||
|
|
|
|||
26
src/main.rs
26
src/main.rs
|
|
@ -5,7 +5,7 @@ mod syscall;
|
|||
mod system;
|
||||
mod uptime;
|
||||
|
||||
use std::io::{Write, stdout};
|
||||
use std::io::{self, Cursor, Write};
|
||||
|
||||
pub use microfetch_lib::UtsName;
|
||||
|
||||
|
|
@ -81,16 +81,32 @@ fn print_system_info(
|
|||
let cyan = COLORS.cyan;
|
||||
let blue = COLORS.blue;
|
||||
let reset = COLORS.reset;
|
||||
let system_info = format!("
|
||||
|
||||
let mut buf = [0u8; 2048];
|
||||
let mut cursor = Cursor::new(&mut buf[..]);
|
||||
|
||||
write!(
|
||||
cursor,
|
||||
"
|
||||
{cyan} ▟█▖ {blue}▝█▙ ▗█▛ {user_info} ~{reset}
|
||||
{cyan} ▗▄▄▟██▄▄▄▄▄{blue}▝█▙█▛ {cyan}▖ {cyan} {blue}System{reset} {os_name}
|
||||
{cyan} ▀▀▀▀▀▀▀▀▀▀▀▘{blue}▝██ {cyan}▟█▖ {cyan} {blue}Kernel{reset} {kernel_version}
|
||||
{blue} ▟█▛ {blue}▝█▘{cyan}▟█▛ {cyan} {blue}Shell{reset} {shell}
|
||||
{blue}▟█████▛ {cyan}▟█████▛ {cyan} {blue}Uptime{reset} {uptime}
|
||||
{blue} ▟█▛{cyan}▗█▖ {cyan}▟█▛ {cyan} {blue}Desktop{reset} {desktop}
|
||||
{blue} ▝█▛ {cyan}██▖{blue}▗▄▄▄▄▄▄▄▄▄▄▄ {cyan} {blue}Memory{reset} {memory_usage}
|
||||
{blue} ▝█▛ {cyan}██▖{blue}▗▄▄▄▄▄▄▄▄▄▄▄ {cyan} {blue}Memory{reset} {memory_usage}
|
||||
{blue} ▝ {cyan}▟█▜█▖{blue}▀▀▀▀▀██▛▀▀▘ {cyan} {blue}Storage (/){reset} {storage}
|
||||
{cyan} ▟█▘ ▜█▖ {blue}▝█▛ {cyan} {blue}Colors{reset} {colors}\n");
|
||||
{cyan} ▟█▘ ▜█▖ {blue}▝█▛ {cyan} {blue}Colors{reset} {colors}\n\n"
|
||||
)?;
|
||||
|
||||
Ok(stdout().write_all(system_info.as_bytes())?)
|
||||
let len = cursor.position() as usize;
|
||||
// Direct syscall to avoid stdout buffering allocation
|
||||
let written = unsafe { libc::write(libc::STDOUT_FILENO, buf.as_ptr().cast(), len) };
|
||||
if written < 0 {
|
||||
return Err(io::Error::last_os_error().into());
|
||||
}
|
||||
if written as usize != len {
|
||||
return Err(io::Error::new(io::ErrorKind::WriteZero, "partial write to stdout").into());
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,18 @@
|
|||
use std::{env, fmt::Write as _, io, mem::MaybeUninit};
|
||||
use std::{ffi::CStr, fmt::Write as _, io, mem::MaybeUninit};
|
||||
|
||||
use crate::{UtsName, colors::COLORS, syscall::read_file_fast};
|
||||
|
||||
#[must_use]
|
||||
#[cfg_attr(feature = "hotpath", hotpath::measure)]
|
||||
pub fn get_username_and_hostname(utsname: &UtsName) -> String {
|
||||
let username = env::var("USER").unwrap_or_else(|_| "unknown_user".to_owned());
|
||||
let username = unsafe {
|
||||
let ptr = libc::getenv(c"USER".as_ptr());
|
||||
if ptr.is_null() {
|
||||
"unknown_user"
|
||||
} else {
|
||||
CStr::from_ptr(ptr).to_str().unwrap_or("unknown_user")
|
||||
}
|
||||
};
|
||||
let hostname = utsname.nodename().to_str().unwrap_or("unknown_host");
|
||||
|
||||
let capacity = COLORS.yellow.len()
|
||||
|
|
@ -18,7 +25,7 @@ pub fn get_username_and_hostname(utsname: &UtsName) -> String {
|
|||
let mut result = String::with_capacity(capacity);
|
||||
|
||||
result.push_str(COLORS.yellow);
|
||||
result.push_str(&username);
|
||||
result.push_str(username);
|
||||
result.push_str(COLORS.red);
|
||||
result.push('@');
|
||||
result.push_str(COLORS.green);
|
||||
|
|
@ -31,15 +38,17 @@ pub fn get_username_and_hostname(utsname: &UtsName) -> String {
|
|||
#[must_use]
|
||||
#[cfg_attr(feature = "hotpath", hotpath::measure)]
|
||||
pub fn get_shell() -> String {
|
||||
let shell_path =
|
||||
env::var("SHELL").unwrap_or_else(|_| "unknown_shell".to_owned());
|
||||
unsafe {
|
||||
let ptr = libc::getenv(c"SHELL".as_ptr());
|
||||
if ptr.is_null() {
|
||||
return "unknown_shell".into();
|
||||
}
|
||||
|
||||
// Find last '/' and get the part after it, avoiding allocation
|
||||
shell_path
|
||||
.rsplit('/')
|
||||
.next()
|
||||
.unwrap_or("unknown_shell")
|
||||
.to_owned()
|
||||
let bytes = CStr::from_ptr(ptr).to_bytes();
|
||||
let start = bytes.iter().rposition(|&b| b == b'/').map_or(0, |i| i + 1);
|
||||
let name = std::str::from_utf8_unchecked(&bytes[start..]);
|
||||
name.into()
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets the root disk usage information.
|
||||
|
|
@ -106,7 +115,7 @@ pub fn get_memory_usage() -> Result<String, io::Error> {
|
|||
fn parse_memory_info() -> Result<(f64, f64), io::Error> {
|
||||
let mut total_memory_kb = 0u64;
|
||||
let mut available_memory_kb = 0u64;
|
||||
let mut buffer = [0u8; 2048];
|
||||
let mut buffer = [0u8; 1024];
|
||||
|
||||
// Use fast syscall-based file reading
|
||||
let bytes_read = read_file_fast("/proc/meminfo", &mut buffer)?;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue