mirror of
https://github.com/LGUG2Z/komorebi.git
synced 2026-11-15 05:12:28 +01:00
feat(config): the platform table, read from the markers of the one StaticConfig
platforms::reads(platform, key) says whether a platform reads a top-level key and platforms::unsupported_keys(raw, platform) lists the keys of a configuration text that are keys of komorebi.json but that the platform does not read, which is what a daemon can say at load time instead of dropping them silently. The table is the x-komorebi-platforms markers themselves, so a key cannot be added without saying who reads it. The daemons do not call it yet: reporting at load time is a visible change of behaviour for the user's decision. The oracle test checks the table against the three checked-in schemas (every key of a tree's schema.json is read by that platform) and on examples. Verified: native cargo test -p komorebi-config: 4 unit + 9 schemas + 1 doctest passed, 0 failed (tier 1).
This commit is contained in:
1 parent
657360d358
commit
5763df9f73
3 files changed
+102
No files matched your search
@@ -19,4 +19,6 @@ pub mod changes;
|
||||
pub mod defaults;
|
||||
pub mod matching;
|
||||
pub mod placement;
|
||||
#[cfg(feature = "schemars")]
|
||||
pub mod platforms;
|
||||
pub mod static_config;
|
||||
@@ -0,0 +1,48 @@
|
||||
//! Which platform reads which key of `komorebi.json`.
|
||||
//!
|
||||
//! The table is not written a second time: it is read from the `x-komorebi-platforms` markers
|
||||
//! of the one `StaticConfig`, so a key cannot be added without saying who reads it.
|
||||
|
||||
use komorebi_protocol::platforms::Platform;
|
||||
use serde_json::Value;
|
||||
|
||||
use crate::schema::PLATFORMS;
|
||||
use crate::schema::platform_name;
|
||||
use crate::schema::union;
|
||||
use crate::static_config::StaticConfig;
|
||||
|
||||
/// Whether `platform` reads the top-level `key` of a configuration. A key the type does not
|
||||
/// know is read by nobody (it is ignored everywhere).
|
||||
#[must_use]
|
||||
pub fn reads(platform: Platform, key: &str) -> bool {
|
||||
let schema = union::<StaticConfig>();
|
||||
match schema["properties"].get(key) {
|
||||
None => false,
|
||||
Some(property) => match property.get(PLATFORMS) {
|
||||
Some(Value::Array(platforms)) => platforms
|
||||
.iter()
|
||||
.any(|p| p.as_str() == Some(platform_name(platform))),
|
||||
_ => true,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
/// The top-level keys of the configuration text `raw` that are keys of `komorebi.json` but that
|
||||
/// `platform` does not read, in file order: what a daemon says at load time instead of silently
|
||||
/// dropping them. Keys that are not known at all are not reported.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// The text is not JSON.
|
||||
pub fn unsupported_keys(raw: &str, platform: Platform) -> color_eyre::Result<Vec<String>> {
|
||||
let value: Value = serde_json::from_str(raw)?;
|
||||
let schema = union::<StaticConfig>();
|
||||
let known = schema["properties"].as_object();
|
||||
Ok(value
|
||||
.as_object()
|
||||
.into_iter()
|
||||
.flat_map(|object| object.keys())
|
||||
.filter(|key| known.is_some_and(|k| k.contains_key(*key)) && !reads(platform, key))
|
||||
.cloned()
|
||||
.collect())
|
||||
}
|
||||
@@ -251,3 +251,55 @@ fn the_schema_of_each_platform_is_a_view_of_the_one_static_config() {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn the_platform_table_comes_from_the_markers() {
|
||||
use komorebi_config::platforms::reads;
|
||||
use komorebi_config::platforms::unsupported_keys;
|
||||
use komorebi_protocol::platforms::Platform;
|
||||
|
||||
let windows_only = ["stackbar", "border_style", "slow_application_identifiers"];
|
||||
let kde_macos_only = [
|
||||
"border_radius",
|
||||
"titleless_applications",
|
||||
"tabbed_applications",
|
||||
];
|
||||
let windows_kde = ["transparency", "focus_follows_mouse"];
|
||||
|
||||
for key in windows_only {
|
||||
assert!(reads(Platform::Windows, key));
|
||||
assert!(
|
||||
!reads(Platform::Kde, key) && !reads(Platform::MacOs, key),
|
||||
"{key}"
|
||||
);
|
||||
}
|
||||
for key in kde_macos_only {
|
||||
assert!(!reads(Platform::Windows, key), "{key}");
|
||||
assert!(reads(Platform::Kde, key) && reads(Platform::MacOs, key));
|
||||
}
|
||||
for key in windows_kde {
|
||||
assert!(reads(Platform::Windows, key) && reads(Platform::Kde, key));
|
||||
assert!(!reads(Platform::MacOs, key), "{key}");
|
||||
}
|
||||
assert!(reads(Platform::MacOs, "monitors") && !reads(Platform::MacOs, "no_such_key"));
|
||||
|
||||
// the keys each tree's schema.json holds are the keys that platform reads
|
||||
for (tree, platform) in [
|
||||
(&TREES[0], Platform::Windows),
|
||||
(&TREES[1], Platform::Kde),
|
||||
(&TREES[2], Platform::MacOs),
|
||||
] {
|
||||
let schema: Value = serde_json::from_str(&checked_in(tree, "schema.json")).unwrap();
|
||||
for key in schema["properties"].as_object().unwrap().keys() {
|
||||
assert!(reads(platform, key), "{} reads {key}", tree.name);
|
||||
}
|
||||
}
|
||||
|
||||
let raw = r#"{ "stackbar": {}, "border": true, "a_key_nobody_knows": 1, "border_radius": 5 }"#;
|
||||
assert_eq!(unsupported_keys(raw, Platform::Kde).unwrap(), ["stackbar"]);
|
||||
assert_eq!(
|
||||
unsupported_keys(raw, Platform::Windows).unwrap(),
|
||||
["border_radius"]
|
||||
);
|
||||
assert!(unsupported_keys("{ ", Platform::Kde).is_err());
|
||||
}
|
||||
Reference in new issue
Block a user