Add EWW_CONFIG_DIR, EWW_CMD, EWW_EXECUTABLE variables

This commit is contained in:
elkowar 2022-05-21 15:06:42 +02:00
parent c0dcc43336
commit 6b5c35cbf9
No known key found for this signature in database
GPG key ID: E321AD71B1D1F27F
5 changed files with 113 additions and 66 deletions

View file

@ -32,6 +32,7 @@ All notable changes to eww will be listed here, starting at changes since versio
- Add `matches` function
- Add transform widget (By: druskus20)
- Add `:onaccept` to input field, add `:onclick` to eventbox
- Add `EWW_CMD`, `EWW_CONFIG_DIR`, `EWW_EXECUTABLE` magic variables
### Notable Internal changes
- Rework state management completely, now making local state and dynamic widget hierarchy changes possible.

View file

@ -126,7 +126,7 @@ impl App {
DaemonCommand::ReloadConfigAndCss(sender) => {
let mut errors = Vec::new();
let config_result = config::read_from_file(&self.paths.get_yuck_path());
let config_result = config::read_from_eww_paths(&self.paths);
if let Err(e) = config_result.and_then(|new_config| self.load_config(new_config)) {
errors.push(e)
}

View file

@ -1,6 +1,6 @@
use anyhow::{bail, Context, Result};
use eww_shared_util::VarName;
use std::{collections::HashMap, path::Path};
use std::collections::HashMap;
use yuck::{
config::{
file_provider::YuckFiles, script_var_definition::ScriptVarDefinition, validate::ValidationError,
@ -11,14 +11,15 @@ use yuck::{
use simplexpr::dynval::DynVal;
use crate::error_handling_ctx;
use crate::{config::inbuilt, error_handling_ctx, widgets::widget_definitions, EwwPaths};
use super::script_var;
/// Load an [EwwConfig] from a given file, resetting and applying the global YuckFiles object in [`crate::error_handling_ctx`].
pub fn read_from_file(path: impl AsRef<Path>) -> Result<EwwConfig> {
/// Load an [`EwwConfig`] from the config dir of the given [`crate::EwwPaths`],
/// resetting and applying the global YuckFiles object in [`crate::error_handling_ctx`].
pub fn read_from_eww_paths(eww_paths: &EwwPaths) -> Result<EwwConfig> {
error_handling_ctx::clear_files();
EwwConfig::read_from_file(&mut error_handling_ctx::YUCK_FILES.write().unwrap(), path)
EwwConfig::read_from_dir(&mut error_handling_ctx::YUCK_FILES.write().unwrap(), eww_paths)
}
/// Eww configuration structure.
@ -46,25 +47,34 @@ impl Default for EwwConfig {
}
impl EwwConfig {
pub fn read_from_file(files: &mut YuckFiles, path: impl AsRef<Path>) -> Result<Self> {
if !path.as_ref().exists() {
bail!("The configuration file `{}` does not exist", path.as_ref().display());
/// Load an [`EwwConfig`] from the config dir of the given [`crate::EwwPaths`], reading the main config file.
pub fn read_from_dir(files: &mut YuckFiles, eww_paths: &EwwPaths) -> Result<Self> {
let yuck_path = eww_paths.get_yuck_path();
if !yuck_path.exists() {
bail!("The configuration file `{}` does not exist", yuck_path.display());
}
let config = Config::generate_from_main_file(files, path)?;
let config = Config::generate_from_main_file(files, yuck_path)?;
// run some validations on the configuration
yuck::config::validate::validate(&config, super::inbuilt::get_inbuilt_vars().keys().cloned().collect())?;
let magic_globals: Vec<_> = inbuilt::MAGIC_CONSTANT_NAMES
.into_iter()
.chain(inbuilt::MAGIC_CONSTANT_NAMES)
.into_iter()
.map(|x| VarName::from(x.clone()))
.collect();
yuck::config::validate::validate(&config, magic_globals)?;
for (name, def) in &config.widget_definitions {
if crate::widgets::widget_definitions::BUILTIN_WIDGET_NAMES.contains(&name.as_str()) {
if widget_definitions::BUILTIN_WIDGET_NAMES.contains(&name.as_str()) {
return Err(
AstError::ValidationError(ValidationError::AccidentalBuiltinOverride(def.span, name.to_string())).into()
);
}
}
let Config { widget_definitions, window_definitions, var_definitions, mut script_vars } = config;
script_vars.extend(crate::config::inbuilt::get_inbuilt_vars());
let Config { widget_definitions, window_definitions, mut var_definitions, mut script_vars } = config;
script_vars.extend(inbuilt::get_inbuilt_vars());
var_definitions.extend(inbuilt::get_magic_constants(eww_paths));
let mut poll_var_links = HashMap::<VarName, Vec<VarName>>::new();
script_vars

View file

@ -1,60 +1,96 @@
use std::{collections::HashMap, time::Duration};
use simplexpr::{dynval::DynVal, SimplExpr};
use yuck::config::script_var_definition::{PollScriptVar, ScriptVarDefinition, VarSource};
use yuck::config::{
script_var_definition::{PollScriptVar, ScriptVarDefinition, VarSource},
var_definition::VarDefinition,
};
use crate::config::system_stats::*;
use crate::{config::system_stats::*, EwwPaths};
use eww_shared_util::VarName;
macro_rules! builtin_vars {
($interval:expr, $($name:literal => $fun:expr),*$(,)?) => {{
maplit::hashmap! {
$(
VarName::from($name) => ScriptVarDefinition::Poll(PollScriptVar {
name: VarName::from($name),
run_while_expr: SimplExpr::Literal(DynVal::from(true)),
run_while_var_refs: Vec::new(),
command: VarSource::Function($fun),
initial_value: None,
interval: $interval,
name_span: eww_shared_util::span::Span::DUMMY,
})
),*
}
}}}
pub fn get_inbuilt_vars() -> HashMap<VarName, ScriptVarDefinition> {
builtin_vars! {Duration::new(2, 0),
// @desc EWW_TEMPS - Heat of the components in Celcius
// @prop { <name>: temperature }
"EWW_TEMPS" => || Ok(DynVal::from(get_temperatures())),
// @desc EWW_RAM - Information on ram and swap usage in kB.
// @prop { total_mem, free_mem, total_swap, free_swap, available_mem, used_mem, used_mem_perc }
"EWW_RAM" => || Ok(DynVal::from(get_ram())),
// @desc EWW_DISK - Information on on all mounted partitions (Might report inaccurately on some filesystems, like btrfs)\nExample: `{EWW_DISK["/"]}`
// @prop { <mount_point>: { name, total, free, used, used_perc } }
"EWW_DISK" => || Ok(DynVal::from(get_disks())),
// @desc EWW_BATTERY - Battery capacity in procent of the main battery
// @prop { <name>: { capacity, status } }
"EWW_BATTERY" => || Ok(DynVal::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,
macro_rules! define_builtin_vars {
($interval:expr, $($name:literal => $fun:expr),*$(,)?) => {
pub static INBUILT_VAR_NAMES: &[&'static str] = &[$($name),*];
pub fn get_inbuilt_vars() -> HashMap<VarName, ScriptVarDefinition> {
maplit::hashmap! {
$(
VarName::from($name) => ScriptVarDefinition::Poll(PollScriptVar {
name: VarName::from($name),
run_while_expr: SimplExpr::Literal(DynVal::from(true)),
run_while_var_refs: Vec::new(),
command: VarSource::Function($fun),
initial_value: None,
interval: $interval,
name_span: eww_shared_util::span::Span::DUMMY,
})
),*
}
)),
// @desc EWW_CPU - Information on the CPU cores: frequency and usage (No MacOS support)
// @prop { cores: [{ core, freq, usage }], avg }
"EWW_CPU" => || Ok(DynVal::from(get_cpus())),
// @desc EWW_NET - Bytes up/down on all interfaces
// @prop { <name>: { up, down } }
"EWW_NET" => || Ok(DynVal::from(net())),
}
}
}
define_builtin_vars! { Duration::new(2, 0),
// @desc EWW_TEMPS - Heat of the components in Celcius
// @prop { <name>: temperature }
"EWW_TEMPS" => || Ok(DynVal::from(get_temperatures())),
// @desc EWW_RAM - Information on ram and swap usage in kB.
// @prop { total_mem, free_mem, total_swap, free_swap, available_mem, used_mem, used_mem_perc }
"EWW_RAM" => || Ok(DynVal::from(get_ram())),
// @desc EWW_DISK - Information on on all mounted partitions (Might report inaccurately on some filesystems, like btrfs)\nExample: `{EWW_DISK["/"]}`
// @prop { <mount_point>: { name, total, free, used, used_perc } }
"EWW_DISK" => || Ok(DynVal::from(get_disks())),
// @desc EWW_BATTERY - Battery capacity in procent of the main battery
// @prop { <name>: { capacity, status } }
"EWW_BATTERY" => || Ok(DynVal::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 - Information on the CPU cores: frequency and usage (No MacOS support)
// @prop { cores: [{ core, freq, usage }], avg }
"EWW_CPU" => || Ok(DynVal::from(get_cpus())),
// @desc EWW_NET - Bytes up/down on all interfaces
// @prop { <name>: { up, down } }
"EWW_NET" => || Ok(DynVal::from(net())),
}
macro_rules! define_magic_constants {
($eww_paths:ident, $($name:literal => $value:expr),*$(,)?) => {
pub static MAGIC_CONSTANT_NAMES: &[&'static str] = &[$($name),*];
pub fn get_magic_constants($eww_paths: &EwwPaths) -> HashMap<VarName, VarDefinition> {
maplit::hashmap! {
$(VarName::from($name) => VarDefinition {
name: VarName::from($name),
initial_value: $value,
span: eww_shared_util::span::Span::DUMMY
}),*
}
}
}
}
define_magic_constants! { eww_paths,
// @desc EWW_CONFIG_DIR - Path to the eww configuration of the current process
"EWW_CONFIG_DIR" => DynVal::from_string(eww_paths.get_config_dir().to_string_lossy().into_owned()),
// @desc EWW_CMD - eww command running in the current configuration, useful in event handlers. I.e.: `:onclick "${EWW_CMD} update foo=bar"`
"EWW_CMD" => DynVal::from_string(
format!("\"{}\" --config \"{}\"",
std::env::current_exe().map(|x| x.to_string_lossy().into_owned()).unwrap_or_else(|_| "eww".to_string()),
eww_paths.get_config_dir().to_string_lossy().into_owned()
)
),
// @desc EWW_EXECUTABLE - Full path of the eww executable
"EWW_EXECUTABLE" => DynVal::from_string(
std::env::current_exe().map(|x| x.to_string_lossy().into_owned()).unwrap_or_else(|_| "eww".to_string()),
),
}

View file

@ -24,7 +24,7 @@ pub fn initialize_server(paths: EwwPaths, action: Option<DaemonCommand>, should_
log::info!("Loading paths: {}", &paths);
let read_config = config::read_from_file(&paths.get_yuck_path());
let read_config = config::read_from_eww_paths(&paths);
let eww_config = match read_config {
Ok(config) => config,