feat: readable toml parsing error (#854)

Previously, the yazi displayed the following error.
```
Backtrace omitted. Run with RUST_BACKTRACE=1 to display it.
Run with RUST_BACKTRACE=full to include source snippets.

The application panicked (crashed).
  called `Result::unwrap()` on an `Err` value: Error { inner: Error { inner: TomlError { message: "invalid key", raw: Some("{ mime = \"application/octet-stream\",\nuse = [ \"extract_zlib\", \"reveal\" ] }\n"), keys: [], span: Some(0..1) } } }
in yazi-config/src/preset.rs, line 42
thread: main
```

It now displays the following message instead:

```
Error: Loading "/home/solo/.config/yazi/yazi.toml"

Caused by:
    TOML parse error at line 1, column 1
      |
    1 | { mime = "application/octet-stream",
      | ^
    invalid key
```

For more information see issue GH-847.

---------

Co-authored-by: sxyazi <sxyazi@gmail.com>
This commit is contained in:
Solomon Jacobs 2024-03-31 15:44:17 +02:00 committed by GitHub
parent 3553a4a61e
commit fd455a1ae4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 23 additions and 23 deletions

View File

@ -47,11 +47,11 @@ pub static INPUT: RoCell<popup::Input> = RoCell::new();
pub static SELECT: RoCell<popup::Select> = RoCell::new(); pub static SELECT: RoCell<popup::Select> = RoCell::new();
pub static WHICH: RoCell<which::Which> = RoCell::new(); pub static WHICH: RoCell<which::Which> = RoCell::new();
pub fn init() { pub fn init() -> anyhow::Result<()> {
let config_dir = Xdg::config_dir(); let config_dir = Xdg::config_dir();
MERGED_YAZI.init(Preset::yazi(&config_dir)); MERGED_YAZI.init(Preset::yazi(&config_dir)?);
MERGED_KEYMAP.init(Preset::keymap(&config_dir)); MERGED_KEYMAP.init(Preset::keymap(&config_dir)?);
MERGED_THEME.init(Preset::theme(&config_dir)); MERGED_THEME.init(Preset::theme(&config_dir)?);
LAYOUT.with(Default::default); LAYOUT.with(Default::default);
@ -81,4 +81,5 @@ Add `disable_exec_warn = true` to your `yazi.toml` under `[headsup]` to suppress
"# "#
); );
} }
Ok(())
} }

View File

@ -1,6 +1,6 @@
use std::{mem, path::{Path, PathBuf}}; use std::{mem, path::{Path, PathBuf}};
use anyhow::Context; use anyhow::{anyhow, Context, Result};
use toml::{Table, Value}; use toml::{Table, Value};
use crate::theme::Flavor; use crate::theme::Flavor;
@ -8,28 +8,27 @@ use crate::theme::Flavor;
pub(crate) struct Preset; pub(crate) struct Preset;
impl Preset { impl Preset {
pub(crate) fn yazi(p: &Path) -> String { pub(crate) fn yazi(p: &Path) -> Result<String> {
Self::merge_path(p.join("yazi.toml"), include_str!("../preset/yazi.toml")) Self::merge_path(p.join("yazi.toml"), include_str!("../preset/yazi.toml"))
} }
pub(crate) fn keymap(p: &Path) -> String { pub(crate) fn keymap(p: &Path) -> Result<String> {
Self::merge_path(p.join("keymap.toml"), include_str!("../preset/keymap.toml")) Self::merge_path(p.join("keymap.toml"), include_str!("../preset/keymap.toml"))
} }
pub(crate) fn theme(p: &Path) -> String { pub(crate) fn theme(p: &Path) -> Result<String> {
let Ok(user) = std::fs::read_to_string(p.join("theme.toml")) else { let Ok(user) = std::fs::read_to_string(p.join("theme.toml")) else {
return include_str!("../preset/theme.toml").to_owned(); return Ok(include_str!("../preset/theme.toml").to_owned());
}; };
let Some(use_) = Flavor::parse_use(&user) else { let Some(use_) = Flavor::parse_use(&user) else {
return Self::merge_str(&user, include_str!("../preset/theme.toml")); return Self::merge_str(&user, include_str!("../preset/theme.toml"));
}; };
let p = p.join(format!("flavors/{}.yazi/flavor.toml", use_)); let p = p.join(format!("flavors/{use_}.yazi/flavor.toml"));
let flavor = std::fs::read_to_string(&p) let flavor =
.with_context(|| format!("Failed to load flavor {:?}", p)) std::fs::read_to_string(&p).with_context(|| anyhow!("Failed to load flavor {p:?}"))?;
.unwrap();
Self::merge_str(&user, &Self::merge_str(&flavor, include_str!("../preset/theme.toml"))) Self::merge_str(&user, &Self::merge_str(&flavor, include_str!("../preset/theme.toml"))?)
} }
#[inline] #[inline]
@ -38,21 +37,21 @@ impl Preset {
} }
#[inline] #[inline]
pub(crate) fn merge_str(user: &str, base: &str) -> String { pub(crate) fn merge_str(user: &str, base: &str) -> Result<String> {
let mut t = user.parse().unwrap(); let mut t = user.parse()?;
Self::merge(&mut t, base.parse().unwrap(), 2); Self::merge(&mut t, base.parse()?, 2);
t.to_string() Ok(t.to_string())
} }
#[inline] #[inline]
fn merge_path(user: PathBuf, base: &str) -> String { fn merge_path(user: PathBuf, base: &str) -> Result<String> {
let s = std::fs::read_to_string(user).unwrap_or_default(); let s = std::fs::read_to_string(&user).unwrap_or_default();
if s.is_empty() { if s.is_empty() {
return base.to_string(); return Ok(base.to_string());
} }
Self::merge_str(&s, base) Self::merge_str(&s, base).with_context(|| anyhow!("Loading {user:?}"))
} }
fn merge(a: &mut Table, b: Table, max: u8) { fn merge(a: &mut Table, b: Table, max: u8) {

View File

@ -39,7 +39,7 @@ async fn main() -> anyhow::Result<()> {
_ = fdlimit::raise_fd_limit(); _ = fdlimit::raise_fd_limit();
yazi_config::init(); yazi_config::init()?;
yazi_adaptor::init(); yazi_adaptor::init();