fix: doctor lists errors on one line with the hint last
This commit is contained in:
1 parent
272f2d30ab
commit
77ae14ed1d
2 files changed
+56
-3
No files matched your search
+27
-3
@@ -4,6 +4,7 @@ use std::path::Path;
|
||||
use anyhow::{Result, bail};
|
||||
|
||||
use crate::config;
|
||||
use crate::error::one_line;
|
||||
use crate::niri;
|
||||
use crate::wayland::Wayland;
|
||||
|
||||
@@ -96,7 +97,10 @@ pub fn check_niri(version: Result<String>) -> Check {
|
||||
match version {
|
||||
Err(e) => check(
|
||||
Level::Warn,
|
||||
format!("niri IPC unavailable ({e:#}); using the first output for `screen`"),
|
||||
format!(
|
||||
"niri IPC unavailable ({}); using the first output for `screen`",
|
||||
one_line(&e)
|
||||
),
|
||||
),
|
||||
Ok(v) => match niri::parse_version(&v) {
|
||||
Some(found) if found == niri::IPC_VERSION => check(Level::Ok, format!("niri {v}")),
|
||||
@@ -117,7 +121,7 @@ pub fn check_config(path: &Path) -> Check {
|
||||
Level::Ok,
|
||||
format!("config {} not found, using defaults", path.display()),
|
||||
),
|
||||
Err(e) => check(Level::Fail, format!("config: {e:#}")),
|
||||
Err(e) => check(Level::Fail, format!("config: {}", one_line(&e))),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -155,7 +159,7 @@ pub fn run() -> Result<()> {
|
||||
));
|
||||
}
|
||||
}
|
||||
Err(e) => checks.push(check(Level::Fail, format!("wayland: {e:#}"))),
|
||||
Err(e) => checks.push(check(Level::Fail, format!("wayland: {}", one_line(&e)))),
|
||||
}
|
||||
checks.push(check_niri(niri::version()));
|
||||
let config_path = config::default_path();
|
||||
@@ -246,6 +250,26 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn broken_config_fails_with_hint_last() {
|
||||
let dir = tempfile::tempdir().unwrap();
|
||||
let path = dir.path().join("config.toml");
|
||||
std::fs::write(&path, "[save]\ndirectory = \n").unwrap();
|
||||
let c = check_config(&path);
|
||||
assert_eq!(c.level, Level::Fail);
|
||||
assert!(
|
||||
c.text.starts_with("config: invalid config file"),
|
||||
"{}",
|
||||
c.text
|
||||
);
|
||||
assert!(
|
||||
c.text
|
||||
.ends_with("(hint: fix the file or delete it to use the defaults)"),
|
||||
"{}",
|
||||
c.text
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn save_dir_checks() {
|
||||
let dir = tempfile::tempdir().unwrap();
|
||||
|
||||
@@ -58,6 +58,22 @@ pub fn render(err: &anyhow::Error, log: Option<&Path>) -> String {
|
||||
out
|
||||
}
|
||||
|
||||
/// The error on one line, hint last: `msg: cause (hint: ...)`. For places
|
||||
/// that list several results, like `valw doctor`.
|
||||
pub fn one_line(err: &anyhow::Error) -> String {
|
||||
let hint = err.downcast_ref::<Hint>().map(|h| h.0.as_str());
|
||||
let messages: Vec<String> = err
|
||||
.chain()
|
||||
.map(|e| e.to_string())
|
||||
.filter(|m| Some(m.as_str()) != hint)
|
||||
.collect();
|
||||
let mut out = messages.join(": ");
|
||||
if let Some(hint) = hint {
|
||||
out.push_str(&format!(" (hint: {hint})"));
|
||||
}
|
||||
out
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
@@ -101,6 +117,19 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn one_line_puts_hint_last() {
|
||||
let err = Err::<(), _>(anyhow!("Could not find wayland compositor"))
|
||||
.context("could not connect to the Wayland compositor")
|
||||
.hint("valw needs a Wayland session; is WAYLAND_DISPLAY set?")
|
||||
.unwrap_err();
|
||||
assert_eq!(
|
||||
one_line(&err),
|
||||
"could not connect to the Wayland compositor: Could not find wayland compositor \
|
||||
(hint: valw needs a Wayland session; is WAYLAND_DISPLAY set?)"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cancelled_is_detectable() {
|
||||
let err = anyhow::Error::new(Cancelled).context("region selection");
|
||||
|
||||
Reference in new issue
Block a user