commit 45abf417992e6f0a06df60dbfb8fb8baed79e80d Author: Seoxi Ryouko Date: Thu Aug 27 00:17:19 2026 -0500 Intial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..ded3150 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,34 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "colored" +version = "3.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "faf9468729b8cbcea668e36183cb69d317348c2e08e994829fb56ebfdfbaac34" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "shitass" +version = "0.1.0" +dependencies = [ + "colored", +] + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link", +] diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..7168a22 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "shitass" +version = "0.1.0" +edition = "2024" + +[dependencies] +colored = "3.1.1" diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..69037fc --- /dev/null +++ b/src/main.rs @@ -0,0 +1,145 @@ +use std::{env::args,process::Command,str::from_utf8,error::Error}; +use colored::{Color,Colorize}; + +#[derive(Debug, Copy, Clone)] +enum BatteryState { + Charging, + Discharging, + Charged, + Error, +} + +fn get_state(s: Option<&str>) -> BatteryState { + match s { + Some("Battery 0: Discharging") => BatteryState::Discharging, + Some("Battery 0: Charging") => BatteryState::Charging, + Some("Battery 0: Charged") => BatteryState::Charged, + _ => BatteryState::Error, + } +} + +fn get_charge(s: Option<&str>) -> Result> { + let f = match s { + Some(s) => s.replace('%', "").parse()?, + None => 1. / 0., + }; + Ok(f) +} + +fn get_battery_state_symbol(state: BatteryState, charge: f32) -> char { + match (state, charge) { + (BatteryState::Charging, ..10.0) => '\u{f089c}', + (BatteryState::Charging, 10.0..20.0) => '\u{f0086}', + (BatteryState::Charging, 20.0..30.0) => '\u{f0087}', + (BatteryState::Charging, 30.0..40.0) => '\u{f0088}', + (BatteryState::Charging, 40.0..50.0) => '\u{f089d}', + (BatteryState::Charging, 50.0..60.0) => '\u{f0089}', + (BatteryState::Charging, 60.0..70.0) => '\u{f089e}', + (BatteryState::Charging, 70.0..80.0) => '\u{f008a}', + (BatteryState::Charging, 80.0..90.0) => '\u{f008b}', + (BatteryState::Charging, 90.0.. ) => '\u{f0085}', + (BatteryState::Charged, _ ) => '\u{f0084}', + (BatteryState::Discharging, ..10.0) => '\u{f007a}', + (BatteryState::Discharging, 10.0..20.0) => '\u{f007b}', + (BatteryState::Discharging, 20.0..30.0) => '\u{f007c}', + (BatteryState::Discharging, 30.0..40.0) => '\u{f007d}', + (BatteryState::Discharging, 40.0..50.0) => '\u{f007e}', + (BatteryState::Discharging, 50.0..60.0) => '\u{f007f}', + (BatteryState::Discharging, 60.0..70.0) => '\u{f0080}', + (BatteryState::Discharging, 70.0..80.0) => '\u{f0081}', + (BatteryState::Discharging, 80.0..90.0) => '\u{f0082}', + (BatteryState::Discharging, 90.0.. ) => '\u{f0079}', + _ => '\u{f0083}', + } +} + +fn get_battery_colors(state: BatteryState, charge: f32) -> (Color, Color) { + match (state, charge) { + (BatteryState::Charging, _ ) => (Color::Blue, Color::Black), + (BatteryState::Charged, _ ) => (Color::Cyan, Color::Black), + (BatteryState::Discharging, ..33.3) => (Color::Red, Color::Black), + (BatteryState::Discharging, 33.0..66.0) => (Color::Yellow, Color::Black), + (BatteryState::Discharging, 66.0.. ) => (Color::Green, Color::Black), + _ => (Color::Black, Color::White), + } +} + +fn run_cmd(cmd: &str, args: Vec<&str>) -> Result> { + let output = Command::new(cmd).args(&args).output()?; + let stdout = from_utf8(&output.stdout)?; + Ok(stdout.to_owned()) +} + +fn battery_beginning() -> Result> { + let stdout = run_cmd("acpi", vec!["-b"])?; + let mut parts = stdout.split(", "); + let charge_state = get_state(parts.next()); + let charge_remaining = get_charge(parts.next())?; + let charge_time = parts.next().ok_or("aaa")?.lines().next().ok_or("aaaaa")?; + let charge_symbol = get_battery_state_symbol(charge_state, charge_remaining); + let (bg, fg) = get_battery_colors(charge_state, charge_remaining); + Ok(format!("{}{}{}", format!(" {charge_remaining:>3}% {charge_symbol} ").on_color(bg).color(fg), "\u{0e0bc}".on_black().color(bg), format!(" {charge_time} ").on_black().white())) +} + +fn battery() -> Result> { + Ok(format!("{}{}", battery_beginning()?, "\u{e0bc}".black())) +} + +fn volume_wrapper() -> Result<(String, Color), Box> { + let stdout = run_cmd("wpctl", vec!["get-volume", "@DEFAULT_SINK@"])?.replace("\n", ""); + let mut words = stdout.split(" "); + words.next(); + let vol_ = words.next().ok_or("AAA")?; + println!(":{vol_}:"); + let vol: f32 = vol_.parse()?; + let (symbol, bg) = match (words.next(), vol) { + (Some("[MUTED]"), _) => ("\u{f0581}", Color::White), + (None, ..0.33 ) => ("\u{f057f}", Color::Blue), + (None, 0.33..0.66 ) => ("\u{f0580}", Color::Cyan), + (None, 0.66..=1.0 ) => ("\u{f057e}", Color::Green), + (None, 1.0.. ) => ("\u{f057e}", Color::Red), + _ => ("\u{f1120}", Color::Yellow), + }; + Ok((format!("{}{}", format!(" {symbol} {:>3}% ", (vol * 100.0).round()).on_color(bg).black(), "\u{e0bc}".color(bg)), bg)) +} + +fn volume() -> Result> { + Ok(volume_wrapper()?.0) +} + +fn bat_vol() -> Result> { + let (volume_str, color) = volume_wrapper()?; + Ok(format!("{}{}{}", battery_beginning()?, "\u{e0bc}".on_color(color).black(), volume_str)) +} + +fn music() -> Result> { + let artist_stdout = run_cmd("mpc", vec!["-f", "%artist%"])?; + let mut artist_lines = artist_stdout.split("\n"); + let title_stdout = run_cmd("mpc", vec!["-f", "%title%"])?; + let mut title_lines = title_stdout.split("\n"); + let status_stdout = run_cmd("mpc", vec!["status", "%state%"])?.replace("\n", ""); + let artist = artist_lines.next().ok_or("aaaa")?; + let title = title_lines.next().ok_or("aaaaa")?; + let status = status_stdout.as_str(); + let (symbol, bg) = match status { + "playing" => ('\u{f04b}', Color::Cyan), + "paused" => ('\u{f04c}', Color::Yellow), + "stopped" => return Ok(format!("{}{}", " \u{f04d} ".on_red().black(), "\u{0e0bc}".red())), + _ => Err(format!("Unknown state: {status}"))?, + }; + Ok(format!("{}{}{}{}", format!(" {symbol} ").on_color(bg).black(), "\u{0e0bc}".on_white().color(bg), format!(" {artist} \u{E0BB} {title} ").on_white().black(), "\u{e0bc}".white())) +} + +fn main() -> Result<(), Box> { + let mut args = args(); + args.next(); + let arg = args.next().ok_or("Argument required: ")?; + match arg.as_str() { + "battery" => println!("{}", battery()?), + "bat-vol" => println!("{}", bat_vol()?), + "volume" => println!("{}", volume()?), + "music" => println!("{}", music()?), + _ => Err(format!("invalid argument: {arg}"))?, + } + Ok(()) +}