Predefined variables/Magic vars (#117)

* basic idea

* generates docs

* hardcoded the gen script

* trying to hide magic vars

* eww-state is good now

* structure for cpu var is now there

* renamed cpu to diskstat, bc lib supports it after all

* not going to implement disk IO. go back to this commit, to see a rough idea

* removed it

* formatting

* stopped data race

* Update src/config/system_stats/ram.rs

Co-authored-by: ElKowar <5300871+elkowar@users.noreply.github.com>

* Update src/config/system_stats/disk.rs

Co-authored-by: ElKowar <5300871+elkowar@users.noreply.github.com>

* Explains macos better

* Update battery.rs

* Function for each OS when getting battery, a bit cleaner

* reworked battery a little

* all in one big file

* facepalm

* cleaner gen script and one huge file for the system stat stuff

* merge conflicts

* github interface for resolving merge conflicts sucks, this fixes it

* Apply suggestions from code review

Co-authored-by: ElKowar <5300871+elkowar@users.noreply.github.com>

* Update src/config/inbuilt.rs

Co-authored-by: ElKowar <5300871+elkowar@users.noreply.github.com>

* Apply suggestions from code review

Co-authored-by: ElKowar <5300871+elkowar@users.noreply.github.com>

* code suggestions

* component temperature is a json struct

* newlines in magic vars descriptions

* disks is now json, numbers are not wrapped in strings, and more idiomatic code

* Update gen-docs.ts

Co-authored-by: mlvzk <mlvzk@protonmail.com>

* removes a unneeded heading

* more doc updates and EWW_CPU_USAGE is now json

* calculates battery total avg and it's a json struct

Co-authored-by: ElKowar <5300871+elkowar@users.noreply.github.com>
Co-authored-by: mlvzk <mlvzk@protonmail.com>
This commit is contained in:
legendofmiracles 2021-05-11 18:45:29 +02:00 committed by GitHub
parent 6eea3e039d
commit df5793b204
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 434 additions and 42 deletions

View File

@ -21,7 +21,7 @@ jobs:
uses: denoland/setup-deno@main
with:
deno-version: "v1.x"
- run: deno run --allow-read gen-docs.ts ./src/widgets/widget_definitions.rs >> ./docs/content/main/widgets.md
- run: deno run --allow-read --allow-write gen-docs.ts ./src/widgets/widget_definitions.rs ./src/config/inbuilt.rs
# Build & deploy
- name: shalzz/zola-deploy-action

133
Cargo.lock generated
View File

@ -71,7 +71,7 @@ checksum = "db134ba52475c060f3329a8ef0f8786d6b872ed01515d4b79c162e5798da1340"
dependencies = [
"proc-macro2",
"quote 1.0.9",
"syn 1.0.71",
"syn 1.0.72",
]
[[package]]
@ -227,6 +227,12 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e"
[[package]]
name = "core-foundation-sys"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ea221b5284a47e40033bf9b66f35f984ec0ea2931eb03505246cd27a963f981b"
[[package]]
name = "crossbeam-channel"
version = "0.5.1"
@ -237,6 +243,30 @@ dependencies = [
"crossbeam-utils",
]
[[package]]
name = "crossbeam-deque"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94af6efb46fef72616855b036a624cf27ba656ffc9be1b9a3c931cfc7749a9a9"
dependencies = [
"cfg-if",
"crossbeam-epoch",
"crossbeam-utils",
]
[[package]]
name = "crossbeam-epoch"
version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "52fb27eab85b17fbb9f6fd667089e07d6a2eb8743d02639ee7f6a7a7729c9c94"
dependencies = [
"cfg-if",
"crossbeam-utils",
"lazy_static",
"memoffset",
"scopeguard",
]
[[package]]
name = "crossbeam-utils"
version = "0.8.4"
@ -255,7 +285,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5e98e2ad1a782e33928b96fc3948e7c355e5af34ba4de7670fe8bac2a3b2006d"
dependencies = [
"quote 1.0.9",
"syn 1.0.71",
"syn 1.0.72",
]
[[package]]
@ -277,7 +307,7 @@ dependencies = [
"convert_case",
"proc-macro2",
"quote 1.0.9",
"syn 1.0.71",
"syn 1.0.72",
]
[[package]]
@ -286,6 +316,12 @@ version = "0.1.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0e25ea47919b1560c4e3b7fe0aaab9becf5b84a10325ddf7db0f0ba5e1026499"
[[package]]
name = "doc-comment"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10"
[[package]]
name = "dyn-clone"
version = "1.0.4"
@ -353,6 +389,7 @@ dependencies = [
"simple-signal",
"smart-default",
"structopt",
"sysinfo",
"tokio",
"tokio-stream",
"tokio-util",
@ -370,7 +407,7 @@ dependencies = [
"proc-macro-error",
"proc-macro2",
"quote 1.0.9",
"syn 1.0.71",
"syn 1.0.72",
]
[[package]]
@ -467,7 +504,7 @@ dependencies = [
"proc-macro-hack",
"proc-macro2",
"quote 1.0.9",
"syn 1.0.71",
"syn 1.0.72",
]
[[package]]
@ -693,7 +730,7 @@ dependencies = [
"proc-macro-error",
"proc-macro2",
"quote 1.0.9",
"syn 1.0.71",
"syn 1.0.72",
]
[[package]]
@ -981,6 +1018,15 @@ version = "2.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b16bd47d9e329435e309c58469fe0791c2d0d1ba96ec0954152a5ae2b04387dc"
[[package]]
name = "memoffset"
version = "0.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f83fb6581e8ed1f85fd45c116db8405483899489e38406156c25eb743554361d"
dependencies = [
"autocfg",
]
[[package]]
name = "mio"
version = "0.7.11"
@ -1273,7 +1319,7 @@ dependencies = [
"proc-macro-hack",
"proc-macro2",
"quote 1.0.9",
"syn 1.0.71",
"syn 1.0.72",
]
[[package]]
@ -1349,7 +1395,7 @@ dependencies = [
"proc-macro-error-attr",
"proc-macro2",
"quote 1.0.9",
"syn 1.0.71",
"syn 1.0.72",
"version_check",
]
@ -1464,19 +1510,44 @@ dependencies = [
]
[[package]]
name = "redox_syscall"
version = "0.2.7"
name = "rayon"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "85dd92e586f7355c633911e11f77f3d12f04b1b1bd76a198bd34ae3af8341ef2"
checksum = "8b0d8e0819fadc20c74ea8373106ead0600e3a67ef1fe8da56e39b9ae7275674"
dependencies = [
"autocfg",
"crossbeam-deque",
"either",
"rayon-core",
]
[[package]]
name = "rayon-core"
version = "1.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ab346ac5921dc62ffa9f89b7a773907511cdfa5490c572ae9be1be33e8afa4a"
dependencies = [
"crossbeam-channel",
"crossbeam-deque",
"crossbeam-utils",
"lazy_static",
"num_cpus",
]
[[package]]
name = "redox_syscall"
version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "742739e41cd49414de871ea5e549afb7e2a3ac77b589bcbebe8c82fab37147fc"
dependencies = [
"bitflags",
]
[[package]]
name = "regex"
version = "1.5.2"
version = "1.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1efb2352a0f4d4b128f734b5c44c79ff80117351138733f12f982fe3e2b13343"
checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461"
dependencies = [
"aho-corasick",
"memchr",
@ -1485,9 +1556,9 @@ dependencies = [
[[package]]
name = "regex-syntax"
version = "0.6.24"
version = "0.6.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "00efb87459ba4f6fb2169d20f68565555688e1250ee6825cdf6254f8b48fafb2"
checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b"
[[package]]
name = "roxmltree"
@ -1536,7 +1607,7 @@ checksum = "b093b7a2bb58203b5da3056c05b4ec1fed827dcfdb37347a8841695263b3d06d"
dependencies = [
"proc-macro2",
"quote 1.0.9",
"syn 1.0.71",
"syn 1.0.72",
]
[[package]]
@ -1595,7 +1666,7 @@ checksum = "133659a15339456eeeb07572eb02a91c91e9815e9cbc89566944d2c8d3efdbf6"
dependencies = [
"proc-macro2",
"quote 1.0.9",
"syn 1.0.71",
"syn 1.0.72",
]
[[package]]
@ -1631,7 +1702,7 @@ dependencies = [
"proc-macro-error",
"proc-macro2",
"quote 1.0.9",
"syn 1.0.71",
"syn 1.0.72",
]
[[package]]
@ -1649,7 +1720,7 @@ dependencies = [
"heck",
"proc-macro2",
"quote 1.0.9",
"syn 1.0.71",
"syn 1.0.72",
]
[[package]]
@ -1665,9 +1736,9 @@ dependencies = [
[[package]]
name = "syn"
version = "1.0.71"
version = "1.0.72"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ad184cc9470f9117b2ac6817bfe297307418819ba40552f9b3846f05c33d5373"
checksum = "a1e8cdbefb79a9a5a65e0db8b47b723ee907b7c7f8496c76a1770b5c310bab82"
dependencies = [
"proc-macro2",
"quote 1.0.9",
@ -1683,6 +1754,22 @@ dependencies = [
"unicode-xid 0.0.4",
]
[[package]]
name = "sysinfo"
version = "0.16.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "567e910ef0207be81a4e1bb0491e9a8d9866cf45b20fe1a52c03d347da9ea51b"
dependencies = [
"cfg-if",
"core-foundation-sys",
"doc-comment",
"libc",
"ntapi",
"once_cell",
"rayon",
"winapi",
]
[[package]]
name = "system-deps"
version = "1.3.2"
@ -1739,7 +1826,7 @@ checksum = "7765189610d8241a44529806d6fd1f2e0a08734313a35d5b3a556f92b381f3c0"
dependencies = [
"proc-macro2",
"quote 1.0.9",
"syn 1.0.71",
"syn 1.0.72",
]
[[package]]
@ -1770,7 +1857,7 @@ checksum = "caf7b11a536f46a809a8a9f0bb4237020f70ecbf115b842360afb127ea2fda57"
dependencies = [
"proc-macro2",
"quote 1.0.9",
"syn 1.0.71",
"syn 1.0.72",
]
[[package]]

View File

@ -60,6 +60,7 @@ futures-core = "0.3"
futures-util = "0.3"
tokio-util = "0.6"
sysinfo = "0.16.1"
nom = "6.1"
dyn-clone = "1.0"

View File

@ -0,0 +1,13 @@
+++
title = "Magic Variables"
slug = "magic variables documenation"
weight = 3
+++
These are variables that are always there, without you having to import them.
The delay between the updating variables is always 2s.
## Updating magic variables

View File

@ -3,3 +3,4 @@ title = "Widgets"
slug = "widget documentation"
weight = 3
+++

View File

@ -12,6 +12,18 @@ interface Widget {
isVisible: boolean;
}
function parseMagicVariables(data: string) {
const pattern = /^.*\/\/\s*@desc\s*(\w+)\s*-\s*(.*)$/gm;
let output = [];
for (const [_, name, desc] of data.matchAll(pattern)) {
output.push(
`### \`${name}\`
${desc.replaceAll("\\n", "\n\n")}
`);
}
return output.join("\n");
}
function parseVars(code: string): Record<string, string> {
const VAR_PATTERN = /^.*\/\/+ *@var +(.*?) +- +(.*)$/;
const vars: Record<string, string> = {};
@ -121,7 +133,7 @@ function printDocs(vars: Record<string, string>, docs: Record<string, Widget>) {
.map((x) => printWidget(x))
.map((x) => x.replace(/\$\w+/g, (x) => vars[x.replace("$", "")]))
.join("\n\n");
console.log(output);
return output;
}
function printWidget(widget: Widget) {
@ -138,7 +150,13 @@ ${widget.props.map((prop) => `- **\`${prop.name}\`**: *\`${prop.type}\`* ${prop.
// deno run --allow-read gen-docs.ts ./src/widgets/widget_definitions.ts 2> /dev/null
Deno.readTextFile(Deno.args[0]).then(data => {
const vars = parseVars(data);
printDocs(vars, parseDocs(data));
Deno.writeTextFile("docs/content/main/widgets.md", printDocs(vars, parseDocs(data)), {"append": true});
}).catch(err => {
return console.error(err);
})
let magic = Deno.readTextFile(Deno.args[1]).then(data => {
Deno.writeTextFile("docs/content/main/magic-vars.md", parseMagicVariables(data), {"append": true});
}).catch(err => {
return console.error(err);
})

View File

@ -60,7 +60,10 @@ pub enum DaemonCommand {
},
KillServer,
CloseAll,
PrintState(DaemonResponseSender),
PrintState {
all: bool,
sender: DaemonResponseSender,
},
PrintDebug(DaemonResponseSender),
PrintWindows(DaemonResponseSender),
}
@ -157,9 +160,15 @@ impl App {
let result = self.close_window(&window_name);
respond_with_error(sender, result)?;
}
DaemonCommand::PrintState(sender) => {
let output =
self.eww_state.get_variables().iter().map(|(key, value)| format!("{}: {}", key, value)).join("\n");
DaemonCommand::PrintState { all, sender } => {
let vars = self.eww_state.get_variables().iter();
let output = if all {
vars.map(|(key, value)| format!("{}: {}", key, value)).join("\n")
} else {
vars.filter(|(x, _)| self.eww_state.referenced_vars().any(|var| x == &var))
.map(|(key, value)| format!("{}: {}", key, value))
.join("\n")
};
sender.send(DaemonResponse::Success(output)).context("sending response from main thread")?
}
DaemonCommand::PrintWindows(sender) => {
@ -219,7 +228,6 @@ impl App {
) -> Result<()> {
// remove and close existing window with the same name
let _ = self.close_window(window_name);
log::info!("Opening window {}", window_name);
let mut window_def = self.eww_config.get_window(window_name)?.clone();

View File

@ -90,7 +90,6 @@ impl RawEwwConfig {
included_path.display()
);
};
for included_config in includes {
for conflict in util::extend_safe(&mut eww_config.widgets, included_config.widgets) {
log_conflict("widget", &conflict, &included_config.filepath)
@ -197,6 +196,17 @@ fn parse_variables_block(xml: XmlElement) -> Result<(HashMap<VarName, PrimVal>,
_ => bail!("Illegal element in variables block: {}", node.as_tag_string()),
}
}
// Extends the variables with the predefined variables
let inbuilt = crate::config::inbuilt::get_inbuilt_vars();
for i in util::extend_safe(&mut script_vars, inbuilt) {
eprintln!(
"script-var '{}' defined twice (defined in your config and in the eww included variables)\nHint: don't define any \
varible like any of these: https://elkowar.github.io/eww/main/magic-variables-documenation/",
i,
);
}
Ok((normal_vars, script_vars))
}
@ -274,6 +284,6 @@ mod test {
assert_eq!(merged_config.widgets.len(), 2);
assert_eq!(merged_config.windows.len(), 2);
assert_eq!(merged_config.initial_variables.len(), 2);
assert_eq!(merged_config.script_vars.len(), 0);
assert_eq!(merged_config.script_vars.len(), 7);
}
}

48
src/config/inbuilt.rs Normal file
View File

@ -0,0 +1,48 @@
use crate::{
config::{system_stats::*, PollScriptVar, ScriptVar, VarSource},
value::{PrimVal as PrimitiveValue, VarName},
};
use std::{collections::HashMap, time::Duration};
macro_rules! builtin_vars {
($interval:expr, $($name:literal => $fun:expr),*$(,)?) => {{
maplit::hashmap! {
$(
VarName::from($name) => ScriptVar::Poll(PollScriptVar {
name: VarName::from($name),
command: VarSource::Function($fun),
interval: $interval,
})
),*
}
}}}
pub fn get_inbuilt_vars() -> HashMap<VarName, ScriptVar> {
builtin_vars! {Duration::new(2, 0),
// @desc EWW_TEMPS - Heat of the components in Celcius\nExample: `{{(CPU_TEMPS.core_1 + CPU_TEMPS.core_2) / 2}}`
"EWW_TEMPS" => || Ok(PrimitiveValue::from(cores())),
// @desc EWW_RAM - The current RAM + Swap usage
"EWW_RAM" => || Ok(PrimitiveValue::from(format!("{:.2}", ram()))),
// @desc EWW_DISK - Information on on all mounted partitions (Might report inaccurately on some filesystems, like btrfs)\nExample: `{{EWW_DISK["/"]}}`
"EWW_DISK" => || Ok(PrimitiveValue::from(disk())),
// @desc EWW_BATTERY - Battery capacity in procent of the main battery
"EWW_BATTERY" => || Ok(PrimitiveValue::from(
match get_battery_capacity() {
Err(e) => {
log::error!("Couldn't get the battery capacity: {:?}", e);
"Error: Check `eww log` for more details".to_string()
}
Ok(o) => o,
}
)),
// @desc EWW_CPU_USAGE - Average CPU usage (all cores) since the last update (No MacOS support)
"EWW_CPU_USAGE" => || Ok(PrimitiveValue::from(get_avg_cpu_usage())),
// @desc EWW_NET - Bytes up/down on all interfaces
"EWW_NET" => || Ok(PrimitiveValue::from(net())),
}
}

View File

@ -10,7 +10,9 @@ use xml_ext::*;
pub mod element;
pub mod eww_config;
pub mod inbuilt;
pub mod script_var;
pub mod system_stats;
pub mod window_definition;
pub mod window_geometry;
pub mod xml_ext;

View File

@ -6,16 +6,24 @@ use crate::ensure_xml_tag_is;
use super::*;
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum VarSource {
Shell(String),
Function(fn() -> Result<PrimVal>),
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct PollScriptVar {
pub name: VarName,
pub command: String,
pub command: VarSource,
pub interval: std::time::Duration,
}
impl PollScriptVar {
pub fn run_once(&self) -> Result<PrimVal> {
run_command(&self.command)
match &self.command {
VarSource::Shell(x) => run_command(x),
VarSource::Function(x) => x(),
}
}
}
@ -41,9 +49,12 @@ impl ScriptVar {
pub fn initial_value(&self) -> Result<PrimVal> {
match self {
ScriptVar::Poll(x) => {
run_command(&x.command).with_context(|| format!("Failed to compute initial value for {}", &self.name()))
}
ScriptVar::Poll(x) => match &x.command {
VarSource::Function(f) => f().with_context(|| format!("Failed to compute initial value for {}", &self.name())),
VarSource::Shell(f) => {
run_command(&f).with_context(|| format!("Failed to compute initial value for {}", &self.name()))
}
},
ScriptVar::Tail(_) => Ok(PrimVal::from_string(String::new())),
}
}
@ -55,7 +66,7 @@ impl ScriptVar {
let command = xml.only_child()?.as_text()?.text();
if let Ok(interval) = xml.attr("interval") {
let interval = util::parse_duration(&interval)?;
Ok(ScriptVar::Poll(PollScriptVar { name, command, interval }))
Ok(ScriptVar::Poll(PollScriptVar { name, command: crate::config::VarSource::Shell(command), interval }))
} else {
Ok(ScriptVar::Tail(TailScriptVar { name, command }))
}

153
src/config/system_stats.rs Normal file
View File

@ -0,0 +1,153 @@
use crate::util::IterAverage;
use anyhow::*;
use itertools::Itertools;
use lazy_static::lazy_static;
use std::{fs::read_to_string, sync::Mutex};
use sysinfo::{ComponentExt, DiskExt, NetworkExt, NetworksExt, ProcessorExt, System, SystemExt};
lazy_static! {
static ref SYSTEM: Mutex<System> = Mutex::new(System::new());
}
pub fn disk() -> String {
let mut c = SYSTEM.lock().unwrap();
c.refresh_disks_list();
format!(
"{{ {} }}",
c.get_disks()
.iter()
.map(|c| format!(
r#""{}": {{"name": {:?}, "total": {}, "free": {}}}"#,
c.get_mount_point().display(),
c.get_name(),
c.get_total_space(),
c.get_available_space(),
))
.join(",")
)
}
pub fn ram() -> f32 {
let mut c = SYSTEM.lock().unwrap();
c.refresh_memory();
(c.get_used_memory() as f32 + c.get_used_swap() as f32) / 1_000_000f32
}
pub fn cores() -> String {
let mut c = SYSTEM.lock().unwrap();
c.refresh_components_list();
c.refresh_components();
format!(
"{{ {} }}",
c.get_components()
.iter()
.map(|c| format!(r#""{}": {}"#, c.get_label().to_uppercase().replace(" ", "_"), c.get_temperature()))
.join(",")
)
}
pub fn get_avg_cpu_usage() -> String {
let mut c = SYSTEM.lock().unwrap();
c.refresh_cpu();
let processors = c.get_processors();
format!(
r#"{{ "cores": [{}], "avg": {} }}"#,
processors
.iter()
.map(|a| format!(r#"{{"core": "{}", "freq": {}, "usage": {}}}"#, a.get_name(), a.get_frequency(), a.get_cpu_usage()))
.join(","),
processors.iter().map(|a| a.get_cpu_usage()).avg()
)
}
#[cfg(target_os = "macos")]
pub fn get_battery_capacity() -> Result<String> {
use regex::Regex;
let capacity = String::from_utf8(
std::process::Command::new("pmset")
.args(&["-g", "batt"])
.output()
.context("\nError while getting the battery value on macos, with `pmset`: ")?
.stdout,
)?;
// Example output of that command:
// Now drawing from 'Battery Power'
//-InternalBattery-0 (id=11403363) 100%; discharging; (no estimate) present: true
let regex = Regex::new(r"[0-9]*%")?;
let mut number = regex.captures(&capacity).unwrap().get(0).unwrap().as_str().to_string();
// Removes the % at the end
number.pop();
Ok(format!(
"{{ \"BAT0\": {{ \"capacity\": \"{}\", \"status\": \"{}\" }}}}",
number,
capacity.split(";").collect::<Vec<&str>>()[1]
))
}
#[cfg(target_os = "linux")]
pub fn get_battery_capacity() -> Result<String> {
let mut current = 0_f64;
let mut total = 0_f64;
let mut json = String::from('{');
for i in
std::path::Path::new("/sys/class/power_supply").read_dir().context("Couldn't read /sys/class/power_supply directory")?
{
let i = i?.path();
if i.is_dir() {
// some ugly hack because if let Some(a) = a && Some(b) = b doesn't work yet
if let (Ok(o), Ok(s)) = (read_to_string(i.join("capacity")), read_to_string(i.join("status"))) {
json.push_str(&format!(
r#"{:?}: {{ "status": "{}", "capacity": {} }},"#,
i.file_name().context("couldn't convert file name to rust string")?,
s.replace("\n", ""),
o.replace("\n", "")
));
if let (Ok(t), Ok(c), Ok(v)) = (
read_to_string(i.join("charge_full")),
read_to_string(i.join("charge_now")),
read_to_string(i.join("voltage_now")),
) {
// (uAh / 1000000) * U = p and that / one million so that we have microwatt
current +=
((c.replace("\n", "").parse::<f64>()? / 1000000_f64) * v.replace("\n", "").parse::<f64>()?) / 1000000_f64;
total +=
((t.replace("\n", "").parse::<f64>()? / 1000000_f64) * v.replace("\n", "").parse::<f64>()?) / 1000000_f64;
} else if let (Ok(t), Ok(c)) = (read_to_string(i.join("energy_full")), read_to_string(i.join("energy_now"))) {
current += c.replace("\n", "").parse::<f64>()?;
total += t.replace("\n", "").parse::<f64>()?;
} else {
log::warn!(
"Failed to get/calculate uWh: the total_avg value of the battery magic var will probably be a garbage \
value that can not be trusted."
);
}
}
}
}
json.pop();
json.push_str(&format!(r#", "total_avg": {:.1}}}"#, (current / total) * 100_f64));
Ok(json)
}
#[cfg(not(target_os = "macos"))]
#[cfg(not(target_os = "linux"))]
pub fn get_battery_capacity() -> Result<u8> {
anyhow!("eww doesn't support your OS for getting the battery capacity")
}
pub fn net() -> String {
let mut c = SYSTEM.lock().unwrap();
let interfaces = format!(
"{{ {} }}",
&c.get_networks()
.iter()
.map(|a| format!(r#""{}": {{ "NET_UP": {}, "NET_DOWN": {} }}"#, a.0, a.1.get_transmitted(), a.1.get_received()))
.join(","),
);
c.refresh_networks_list();
interfaces
}

View File

@ -108,9 +108,13 @@ pub enum ActionWithServer {
#[structopt(name = "close-all", alias = "ca")]
CloseAll,
/// Print the current eww-state
/// Prints the variables used in all currently open window
#[structopt(name = "state")]
ShowState,
ShowState {
/// Shows all variables, including not currently used ones
#[structopt(short, long)]
all: bool,
},
/// Print the names of all configured windows. Windows with a * in front of them are currently opened.
#[structopt(name = "windows")]
@ -175,7 +179,9 @@ impl ActionWithServer {
}
ActionWithServer::Reload => return with_response_channel(app::DaemonCommand::ReloadConfigAndCss),
ActionWithServer::ShowWindows => return with_response_channel(app::DaemonCommand::PrintWindows),
ActionWithServer::ShowState => return with_response_channel(app::DaemonCommand::PrintState),
ActionWithServer::ShowState { all } => {
return with_response_channel(|sender| app::DaemonCommand::PrintState { all, sender })
}
ActionWithServer::ShowDebug => return with_response_channel(app::DaemonCommand::PrintDebug),
};
(command, None)

View File

@ -112,6 +112,23 @@ pub fn parse_duration(s: &str) -> Result<std::time::Duration> {
}
}
pub trait IterAverage {
fn avg(self) -> f32;
}
impl<I: Iterator<Item = f32>> IterAverage for I {
fn avg(self) -> f32 {
let mut total = 0f32;
let mut cnt = 0f32;
for value in self {
total += value;
cnt += 1f32;
}
total / cnt
}
}
/// Replace all env-var references of the format `"something ${foo}"` in a string
/// by the actual env-variables. If the env-var isn't found, will replace the
/// reference with an empty string.

View File

@ -65,6 +65,23 @@ impl From<i32> for PrimVal {
}
}
impl From<u32> for PrimVal {
fn from(s: u32) -> Self {
PrimVal(s.to_string())
}
}
impl From<f32> for PrimVal {
fn from(s: f32) -> Self {
PrimVal(s.to_string())
}
}
impl From<u8> for PrimVal {
fn from(s: u8) -> Self {
PrimVal(s.to_string())
}
}
impl From<f64> for PrimVal {
fn from(s: f64) -> Self {
PrimVal(s.to_string())