diff --git a/plugin-audio/Cargo.toml b/plugin-audio/Cargo.toml index b07ebf3..e2ea52b 100644 --- a/plugin-audio/Cargo.toml +++ b/plugin-audio/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "audio" -version = "0.0.0" +version = "0.0.1" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/plugin-desktop/Cargo.toml b/plugin-desktop/Cargo.toml index 442dd79..c40af3b 100644 --- a/plugin-desktop/Cargo.toml +++ b/plugin-desktop/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "desktop" -version = "0.0.0" +version = "0.0.1" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/plugin-network-old/Cargo.toml b/plugin-network-old/Cargo.toml new file mode 100644 index 0000000..ffcacdc --- /dev/null +++ b/plugin-network-old/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "network" +version = "0.0.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +thiserror = "1.0.44" diff --git a/plugin-network-old/src/main.rs b/plugin-network-old/src/main.rs new file mode 100644 index 0000000..2407d3d --- /dev/null +++ b/plugin-network-old/src/main.rs @@ -0,0 +1,8 @@ +mod nmcli; + +fn main() { + let networks = nmcli::scan().unwrap(); + for network in networks { + println!("{network:?}"); + } +} diff --git a/plugin-network-old/src/nmcli.rs b/plugin-network-old/src/nmcli.rs new file mode 100644 index 0000000..2d00421 --- /dev/null +++ b/plugin-network-old/src/nmcli.rs @@ -0,0 +1,112 @@ +//! Command Bindings to NetworkManager-CLI +use std::collections::BTreeMap; +use std::io::{BufRead, BufReader}; +use std::process::{Command, ExitStatus, Stdio}; +use thiserror::Error; + +#[derive(Debug, Error)] +pub enum NetworkError { + #[error("Execution Error")] + ExecError(#[from] std::io::Error), + #[error("No Stdout")] + NoStdout, + #[error("Unexpected Command Output")] + UnexpectedOutput(String), + #[error("Invalid Integer")] + ParseError(#[from] std::num::ParseIntError), + #[error("Unexpected ExitCode")] + StatusCode(ExitStatus), +} + +#[derive(Debug)] +pub struct Network { + pub in_use: bool, + pub ssid: String, + pub rate: u32, + pub signal: u32, + pub bars: String, + pub security: String, +} + +/// Retrieve Key from HashMap of Fields +#[inline] +fn get_key<'a>( + m: &'a BTreeMap<&str, &str>, + key: &'a str, + line: &'a str, +) -> Result<&'a &'a str, NetworkError> { + m.get(key) + .ok_or_else(|| NetworkError::UnexpectedOutput(line.to_owned())) +} + +/// Complete Network Scan and Retrieve Available Networks +pub fn scan() -> Result, NetworkError> { + // spawn command + let mut command = Command::new("nmcli") + .args(["dev", "wifi", "list", "--rescan", "auto"]) + .stdout(Stdio::piped()) + .spawn()?; + // retrieve stdout + let stdout = command.stdout.as_mut().ok_or(NetworkError::NoStdout)?; + let mut reader = BufReader::new(stdout); + // parse initial header + let mut line = String::new(); + reader.read_line(&mut line)?; + let headers: Vec<&str> = line.trim().split(" ").filter(|i| i.len() > 0).collect(); + // parse body elements + let mut netmap = BTreeMap::::new(); + for line in reader.lines().filter_map(|l| l.ok()) { + // parse into key/value pairs + let mut values = vec![]; + let mut state = line.as_str(); + for _ in 0..headers.len() { + let (value, rest) = state.trim().split_once(" ").unwrap_or((state, "")); + if value.is_empty() { + break; + } + values.push(value); + state = rest; + } + if values.len() < headers.len() { + values.insert(0, ""); + } + let fields: BTreeMap<&str, &str> = + headers.iter().cloned().zip(values.into_iter()).collect(); + // retrieve required fields + let bars = get_key(&fields, "BARS", &line).map(|s| s.to_string())?; + let ssid = get_key(&fields, "SSID", &line).map(|s| s.to_string())?; + let in_use = get_key(&fields, "IN-USE", &line).map(|s| s.len() > 0)?; + let security = get_key(&fields, "SECURITY", &line).map(|s| s.to_string())?; + let rate = get_key(&fields, "RATE", &line)? + .split_once(" ") + .ok_or_else(|| NetworkError::UnexpectedOutput(line.to_owned()))? + .0 + .parse()?; + let signal = get_key(&fields, "SIGNAL", &line)?.parse()?; + let network = Network { + in_use, + bars, + rate, + ssid, + signal, + security, + }; + // skip entry if the current entry has better rate/signal + if let Some(other) = netmap.get(&network.ssid) { + if other.rate > network.rate && other.signal > network.signal { + continue; + } + } + netmap.insert(network.ssid.to_owned(), network); + } + // check status of response + let status = command.wait()?; + if !status.success() { + return Err(NetworkError::StatusCode(status)); + } + // collect networks into a vector and sort by signal + let mut networks: Vec = netmap.into_values().collect(); + networks.sort_by_key(|n| n.rate * n.signal); + networks.reverse(); + Ok(networks) +} diff --git a/plugin-network/Cargo.toml b/plugin-network/Cargo.toml index 9c0fc04..cc05139 100644 --- a/plugin-network/Cargo.toml +++ b/plugin-network/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rmenu-network" -version = "0.0.0" +version = "0.0.1" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/plugin-run/Cargo.toml b/plugin-run/Cargo.toml index 59999c5..f63ada4 100644 --- a/plugin-run/Cargo.toml +++ b/plugin-run/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "run" -version = "0.0.0" +version = "0.0.1" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/rmenu-plugin/Cargo.toml b/rmenu-plugin/Cargo.toml index c20b9ba..af7ddb1 100644 --- a/rmenu-plugin/Cargo.toml +++ b/rmenu-plugin/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rmenu-plugin" -version = "0.0.0" +version = "0.0.1" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html