Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: launch from preset settings if the user's config cannot be parsed #1832

Merged
merged 2 commits into from
Oct 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 12 additions & 6 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ panic = "abort"
strip = true

[workspace.dependencies]
ansi-to-tui = "6.0.0"
ansi-to-tui = "7.0.0"
anyhow = "1.0.91"
arc-swap = "1.7.1"
base64 = "0.22.1"
Expand All @@ -24,7 +24,7 @@ libc = "0.2.161"
md-5 = "0.10.6"
mlua = { version = "0.9.9", features = [ "lua54", "serialize", "macros", "async" ] }
parking_lot = "0.12.3"
ratatui = { version = "0.28.1", features = [ "unstable-rendered-line-info" ] }
ratatui = { version = "0.29.0", features = [ "unstable-rendered-line-info" ] }
regex = "1.11.1"
scopeguard = "1.2.0"
serde = { version = "1.0.213", features = [ "derive" ] }
Expand Down
9 changes: 6 additions & 3 deletions yazi-config/src/keymap/keymap.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::{collections::HashSet, str::FromStr};

use anyhow::Context;
use indexmap::IndexSet;
use serde::{Deserialize, Deserializer};
use yazi_shared::Layer;
Expand All @@ -20,7 +21,7 @@ pub struct Keymap {

impl Keymap {
#[inline]
pub fn get(&self, layer: Layer) -> &Vec<Chord> {
pub fn get(&self, layer: Layer) -> &[Chord] {
match layer {
Layer::App => unreachable!(),
Layer::Manager => &self.manager,
Expand All @@ -36,9 +37,11 @@ impl Keymap {
}

impl FromStr for Keymap {
type Err = toml::de::Error;
type Err = anyhow::Error;

fn from_str(s: &str) -> Result<Self, Self::Err> { toml::from_str(s) }
fn from_str(s: &str) -> Result<Self, Self::Err> {
toml::from_str(s).context("Failed to parse your keymap.toml")
}
}

impl<'de> Deserialize<'de> for Keymap {
Expand Down
74 changes: 57 additions & 17 deletions yazi-config/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,25 +24,25 @@ pub static PICK: RoCell<popup::Pick> = RoCell::new();
pub static WHICH: RoCell<which::Which> = RoCell::new();

pub fn init() -> anyhow::Result<()> {
let config_dir = Xdg::config_dir();
let yazi_toml = &Preset::yazi(&config_dir)?;
let keymap_toml = &Preset::keymap(&config_dir)?;
let theme_toml = &Preset::theme(&config_dir)?;
if let Err(e) = try_init(true) {
eprintln!("{e}");
if let Some(src) = e.source() {
eprintln!("\nCaused by:\n{src}");
}

LAYOUT.with(<_>::default);
use crossterm::style::{Attribute, Print, SetAttributes};
crossterm::execute!(
std::io::stderr(),
SetAttributes(Attribute::Reverse.into()),
SetAttributes(Attribute::Bold.into()),
Print("Press <Enter> to continue with preset settings..."),
SetAttributes(Attribute::Reset.into()),
Print("\n"),
)?;

KEYMAP.init(<_>::from_str(keymap_toml)?);
LOG.init(<_>::from_str(yazi_toml)?);
MANAGER.init(<_>::from_str(yazi_toml)?);
OPEN.init(<_>::from_str(yazi_toml)?);
PLUGIN.init(<_>::from_str(yazi_toml)?);
PREVIEW.init(<_>::from_str(yazi_toml)?);
TASKS.init(<_>::from_str(yazi_toml)?);
THEME.init(<_>::from_str(theme_toml)?);
INPUT.init(<_>::from_str(yazi_toml)?);
CONFIRM.init(<_>::from_str(yazi_toml)?);
PICK.init(<_>::from_str(yazi_toml)?);
WHICH.init(<_>::from_str(yazi_toml)?);
std::io::stdin().read_line(&mut String::new())?;
try_init(false)?;
}

// TODO: Remove in v0.3.2
for c in &KEYMAP.manager {
Expand Down Expand Up @@ -78,3 +78,43 @@ Please change `create_title = "Create:"` to `create_title = ["Create:", "Create

Ok(())
}

fn try_init(merge: bool) -> anyhow::Result<()> {
let (yazi_toml, keymap_toml, theme_toml) = if merge {
let p = Xdg::config_dir();
(Preset::yazi(&p)?, Preset::keymap(&p)?, Preset::theme(&p)?)
} else {
use yazi_macro::config_preset as preset;
(preset!("yazi"), preset!("keymap"), preset!("theme"))
};

let keymap = <_>::from_str(&keymap_toml)?;
let log = <_>::from_str(&yazi_toml)?;
let manager = <_>::from_str(&yazi_toml)?;
let open = <_>::from_str(&yazi_toml)?;
let plugin = <_>::from_str(&yazi_toml)?;
let preview = <_>::from_str(&yazi_toml)?;
let tasks = <_>::from_str(&yazi_toml)?;
let theme = <_>::from_str(&theme_toml)?;
let input = <_>::from_str(&yazi_toml)?;
let confirm = <_>::from_str(&yazi_toml)?;
let pick = <_>::from_str(&yazi_toml)?;
let which = <_>::from_str(&yazi_toml)?;

LAYOUT.with(<_>::default);

KEYMAP.init(keymap);
LOG.init(log);
MANAGER.init(manager);
OPEN.init(open);
PLUGIN.init(plugin);
PREVIEW.init(preview);
TASKS.init(tasks);
THEME.init(theme);
INPUT.init(input);
CONFIRM.init(confirm);
PICK.init(pick);
WHICH.init(which);

Ok(())
}
7 changes: 5 additions & 2 deletions yazi-config/src/log/log.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::str::FromStr;

use anyhow::Context;
use serde::{Deserialize, Deserializer};

#[derive(Debug)]
Expand All @@ -8,9 +9,11 @@ pub struct Log {
}

impl FromStr for Log {
type Err = toml::de::Error;
type Err = anyhow::Error;

fn from_str(s: &str) -> Result<Self, Self::Err> { toml::from_str(s) }
fn from_str(s: &str) -> Result<Self, Self::Err> {
toml::from_str(s).context("Failed to parse the [log] section in your yazi.toml")
}
}

impl<'de> Deserialize<'de> for Log {
Expand Down
8 changes: 5 additions & 3 deletions yazi-config/src/manager/manager.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::str::FromStr;

use anyhow::Context;
use serde::{Deserialize, Serialize};
use validator::Validate;

Expand Down Expand Up @@ -35,9 +36,10 @@ impl FromStr for Manager {
manager: Manager,
}

let manager = toml::from_str::<Outer>(s)?.manager;
manager.validate()?;
let outer = toml::from_str::<Outer>(s)
.context("Failed to parse the [manager] section in your yazi.toml")?;
outer.manager.validate()?;

Ok(manager)
Ok(outer.manager)
}
}
7 changes: 5 additions & 2 deletions yazi-config/src/open/open.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::{collections::HashMap, path::Path, str::FromStr};

use anyhow::Context;
use indexmap::IndexSet;
use serde::{Deserialize, Deserializer};
use yazi_shared::MIME_DIR;
Expand Down Expand Up @@ -55,9 +56,11 @@ impl Open {
}

impl FromStr for Open {
type Err = toml::de::Error;
type Err = anyhow::Error;

fn from_str(s: &str) -> Result<Self, Self::Err> { toml::from_str(s) }
fn from_str(s: &str) -> Result<Self, Self::Err> {
toml::from_str(s).context("Failed to parse the [open] or [opener] section in your yazi.toml")
}
}

impl<'de> Deserialize<'de> for Open {
Expand Down
17 changes: 13 additions & 4 deletions yazi-config/src/plugin/plugin.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
use std::{collections::HashSet, path::Path, str::FromStr};

use serde::Deserialize;
use anyhow::Context;
use serde::{Deserialize, Deserializer};

use super::{Fetcher, Preloader, Previewer};
use crate::{Preset, plugin::MAX_PREWORKERS};

#[derive(Deserialize)]
pub struct Plugin {
pub fetchers: Vec<Fetcher>,
pub preloaders: Vec<Preloader>,
Expand Down Expand Up @@ -55,9 +55,18 @@ impl Plugin {
}

impl FromStr for Plugin {
type Err = toml::de::Error;
type Err = anyhow::Error;

fn from_str(s: &str) -> Result<Self, Self::Err> {
toml::from_str(s).context("Failed to parse the [plugin] section in your yazi.toml")
}
}

impl<'de> Deserialize<'de> for Plugin {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
#[derive(Deserialize)]
struct Outer {
plugin: Shadow,
Expand All @@ -84,7 +93,7 @@ impl FromStr for Plugin {
append_previewers: Vec<Previewer>,
}

let mut shadow = toml::from_str::<Outer>(s)?.plugin;
let mut shadow = Outer::deserialize(deserializer)?.plugin;
if shadow.append_previewers.iter().any(|r| r.any_file()) {
shadow.previewers.retain(|r| !r.any_file());
}
Expand Down
8 changes: 6 additions & 2 deletions yazi-config/src/popup/confirm.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::str::FromStr;

use anyhow::Context;
use serde::Deserialize;

use super::{Offset, Origin};
Expand Down Expand Up @@ -30,15 +31,18 @@ pub struct Confirm {
}

impl FromStr for Confirm {
type Err = toml::de::Error;
type Err = anyhow::Error;

fn from_str(s: &str) -> Result<Self, Self::Err> {
#[derive(Deserialize)]
struct Outer {
confirm: Confirm,
}

Ok(toml::from_str::<Outer>(s)?.confirm)
let outer = toml::from_str::<Outer>(s)
.context("Failed to parse the [confirm] section in your yazi.toml")?;

Ok(outer.confirm)
}
}

Expand Down
8 changes: 6 additions & 2 deletions yazi-config/src/popup/input.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::str::FromStr;

use anyhow::Context;
use serde::Deserialize;

use super::{Offset, Origin};
Expand Down Expand Up @@ -49,15 +50,18 @@ impl Input {
}

impl FromStr for Input {
type Err = toml::de::Error;
type Err = anyhow::Error;

fn from_str(s: &str) -> Result<Self, Self::Err> {
#[derive(Deserialize)]
struct Outer {
input: Input,
}

Ok(toml::from_str::<Outer>(s)?.input)
let outer = toml::from_str::<Outer>(s)
.context("Failed to parse the [input] section in your yazi.toml")?;

Ok(outer.input)
}
}

Expand Down
8 changes: 6 additions & 2 deletions yazi-config/src/popup/pick.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::str::FromStr;

use anyhow::Context;
use serde::Deserialize;

use super::{Offset, Origin};
Expand All @@ -17,14 +18,17 @@ impl Pick {
}

impl FromStr for Pick {
type Err = toml::de::Error;
type Err = anyhow::Error;

fn from_str(s: &str) -> Result<Self, Self::Err> {
#[derive(Deserialize)]
struct Outer {
pick: Pick,
}

Ok(toml::from_str::<Outer>(s)?.pick)
let outer =
toml::from_str::<Outer>(s).context("Failed to parse the [pick] section in your yazi.toml")?;

Ok(outer.pick)
}
}
6 changes: 3 additions & 3 deletions yazi-config/src/preset.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,15 @@ use crate::theme::Flavor;
pub(crate) struct Preset;

impl Preset {
pub(crate) fn yazi(p: &Path) -> Result<Cow<str>> {
pub(crate) fn yazi(p: &Path) -> Result<Cow<'static, str>> {
Self::merge_path(p.join("yazi.toml"), preset!("yazi"))
}

pub(crate) fn keymap(p: &Path) -> Result<Cow<str>> {
pub(crate) fn keymap(p: &Path) -> Result<Cow<'static, str>> {
Self::merge_path(p.join("keymap.toml"), preset!("keymap"))
}

pub(crate) fn theme(p: &Path) -> Result<Cow<str>> {
pub(crate) fn theme(p: &Path) -> Result<Cow<'static, str>> {
let Ok(user) = std::fs::read_to_string(p.join("theme.toml")) else {
return Ok(preset!("theme"));
};
Expand Down
Loading