breadmon: clear error for missing BOS hyprctl eval extension, doc, version fix
- apply_monitors() shells out to `hyprctl eval` with a `hl.monitor()` Lua call, a BOS-only Hyprland extension. On vanilla Hyprland the eval request itself isn't recognized and failed with a confusing raw hyprctl response. Detect that case and fail with an explicit 'this feature requires BOS' message instead, with tests. - README: documented the BOS dependency for the apply step under Requirements; noted everything else in the TUI works without it. - Cargo.toml: 0.1.0 -> 0.1.1, matching the latest tag (v0.1.1).
This commit is contained in:
parent
4bbe976e7a
commit
ddbc9e63d3
4 changed files with 44 additions and 3 deletions
2
Cargo.lock
generated
2
Cargo.lock
generated
|
|
@ -22,7 +22,7 @@ checksum = "b4388bee8683e3d04af747c73422af53102d2bd24d9eadb6cbc100baef4b43f8"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "breadmon"
|
name = "breadmon"
|
||||||
version = "0.1.0"
|
version = "0.1.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"crossterm",
|
"crossterm",
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "breadmon"
|
name = "breadmon"
|
||||||
version = "0.1.0"
|
version = "0.1.1"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
description = "TUI monitor manager for Hyprland"
|
description = "TUI monitor manager for Hyprland"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,8 @@ A terminal UI monitor manager for Hyprland. Lets you position, configure, and mi
|
||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
|
|
||||||
- Hyprland compositor (the `hyprctl` binary must be on `PATH`)
|
- **[BOS (Bread OS)](https://git.breadway.dev/breadway/bos)'s patched Hyprland build.** Applying changes (the `a` key / Global keys "Apply") runs `hyprctl eval` with a `hl.monitor({...})` Lua call — a BOS-specific extension that does not exist on vanilla/upstream Hyprland. On a non-BOS Hyprland install, `hyprctl eval` itself is not a recognized request, and breadmon will fail to apply with an explicit error explaining this instead of the raw hyprctl response. Everything else in the TUI (viewing/arranging/saving profiles) works regardless; only the live-apply step needs BOS.
|
||||||
|
- The `hyprctl` binary must be on `PATH`
|
||||||
- Rust toolchain (to build from source)
|
- Rust toolchain (to build from source)
|
||||||
|
|
||||||
## Build
|
## Build
|
||||||
|
|
|
||||||
|
|
@ -367,6 +367,15 @@ pub async fn apply_monitors(monitors: &[Monitor]) -> Result<()> {
|
||||||
|
|
||||||
let stdout = String::from_utf8_lossy(&output.stdout).trim().to_owned();
|
let stdout = String::from_utf8_lossy(&output.stdout).trim().to_owned();
|
||||||
if stdout != "ok" {
|
if stdout != "ok" {
|
||||||
|
if is_missing_eval_extension(&stdout) {
|
||||||
|
return Err(anyhow::anyhow!(
|
||||||
|
"breadmon: `hyprctl eval` (and the `hl.monitor()` Lua extension it uses \
|
||||||
|
to apply monitor changes) is not available on this compositor. \
|
||||||
|
This feature requires BOS (Bread OS)'s patched Hyprland build — it \
|
||||||
|
does not exist on vanilla/upstream Hyprland. See the breadmon README \
|
||||||
|
for details. (raw hyprctl response: {stdout:?})"
|
||||||
|
));
|
||||||
|
}
|
||||||
return Err(anyhow::anyhow!("hyprctl: {}", stdout));
|
return Err(anyhow::anyhow!("hyprctl: {}", stdout));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -382,6 +391,37 @@ pub async fn apply_monitors(monitors: &[Monitor]) -> Result<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Vanilla/upstream Hyprland doesn't recognize the `eval` request at all
|
||||||
|
/// (BOS's Hyprland fork adds it, along with the `hl.monitor()` Lua global
|
||||||
|
/// used above), and responds with an "unknown request" style message rather
|
||||||
|
/// than an error about `hl`. Detect that case so we can point the user at
|
||||||
|
/// the actual cause instead of surfacing the raw hyprctl text.
|
||||||
|
fn is_missing_eval_extension(hyprctl_stdout: &str) -> bool {
|
||||||
|
let s = hyprctl_stdout.to_lowercase();
|
||||||
|
s.contains("unknown request") || s.contains("unknown command")
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod eval_extension_tests {
|
||||||
|
use super::is_missing_eval_extension;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn detects_unknown_request() {
|
||||||
|
assert!(is_missing_eval_extension("unknown request"));
|
||||||
|
assert!(is_missing_eval_extension("Unknown Request"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn does_not_flag_lua_errors() {
|
||||||
|
// A real Lua/apply-time error from a BOS build should still surface
|
||||||
|
// as a normal hyprctl error, not the "requires BOS" message.
|
||||||
|
assert!(!is_missing_eval_extension(
|
||||||
|
"error: attempt to call a nil value"
|
||||||
|
));
|
||||||
|
assert!(!is_missing_eval_extension("ok"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue