mirror of
https://github.com/sxyazi/yazi.git
synced 2026-07-22 23:31:05 +00:00
refactor: config
This commit is contained in:
parent
43ec2ada0b
commit
19fcc78a12
17 changed files with 237 additions and 230 deletions
|
|
@ -1,6 +1,6 @@
|
|||
use std::{collections::BTreeMap, fmt};
|
||||
|
||||
use serde::{de::Visitor, Deserializer};
|
||||
use serde::{de::{self, Visitor}, Deserializer};
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct Exec {
|
||||
|
|
@ -44,7 +44,7 @@ impl Exec {
|
|||
|
||||
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
|
||||
where
|
||||
A: serde::de::SeqAccess<'de>,
|
||||
A: de::SeqAccess<'de>,
|
||||
{
|
||||
let mut execs = Vec::new();
|
||||
while let Some(value) = &seq.next_element::<String>()? {
|
||||
|
|
@ -55,7 +55,7 @@ impl Exec {
|
|||
|
||||
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
|
||||
where
|
||||
E: serde::de::Error,
|
||||
E: de::Error,
|
||||
{
|
||||
Ok(value.split(';').map(Exec::from).collect())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
use anyhow::bail;
|
||||
use crossterm::event::{KeyCode, KeyEvent, KeyModifiers};
|
||||
use serde::{de::Visitor, Deserialize, Deserializer};
|
||||
use serde::Deserialize;
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||
#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Hash)]
|
||||
#[serde(try_from = "String")]
|
||||
pub struct Key {
|
||||
pub code: KeyCode,
|
||||
pub shift: bool,
|
||||
|
|
@ -13,21 +15,36 @@ impl Default for Key {
|
|||
fn default() -> Self { Self { code: KeyCode::Null, shift: false, ctrl: false, alt: false } }
|
||||
}
|
||||
|
||||
impl From<&str> for Key {
|
||||
fn from(value: &str) -> Self {
|
||||
let mut key = Default::default();
|
||||
if value.is_empty() {
|
||||
return key;
|
||||
impl From<KeyEvent> for Key {
|
||||
fn from(value: KeyEvent) -> Self {
|
||||
let shift = if let KeyCode::Char(c) = value.code { c.is_ascii_uppercase() } else { false };
|
||||
|
||||
Self {
|
||||
code: value.code,
|
||||
shift: shift || value.modifiers.contains(KeyModifiers::SHIFT),
|
||||
ctrl: value.modifiers.contains(KeyModifiers::CONTROL),
|
||||
alt: value.modifiers.contains(KeyModifiers::ALT),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<String> for Key {
|
||||
type Error = anyhow::Error;
|
||||
|
||||
fn try_from(s: String) -> Result<Self, Self::Error> {
|
||||
if s.is_empty() {
|
||||
bail!("empty key")
|
||||
}
|
||||
|
||||
if !value.starts_with("<") || !value.ends_with(">") {
|
||||
let c = value.chars().next().unwrap();
|
||||
let mut key = Self::default();
|
||||
if !s.starts_with("<") || !s.ends_with(">") {
|
||||
let c = s.chars().next().unwrap();
|
||||
key.code = KeyCode::Char(c);
|
||||
key.shift = c.is_ascii_uppercase();
|
||||
return key;
|
||||
return Ok(key);
|
||||
}
|
||||
|
||||
let mut it = value[1..value.len() - 1].split_inclusive('-').peekable();
|
||||
let mut it = s[1..s.len() - 1].split_inclusive('-').peekable();
|
||||
while let Some(x) = it.next() {
|
||||
match x {
|
||||
"S-" => key.shift = true,
|
||||
|
|
@ -65,48 +82,13 @@ impl From<&str> for Key {
|
|||
c if it.peek().is_none() => {
|
||||
key.code = KeyCode::Char(c.chars().next().unwrap());
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
key
|
||||
}
|
||||
}
|
||||
|
||||
impl From<KeyEvent> for Key {
|
||||
fn from(value: KeyEvent) -> Self {
|
||||
let shift = if let KeyCode::Char(c) = value.code { c.is_ascii_uppercase() } else { false };
|
||||
|
||||
Self {
|
||||
code: value.code,
|
||||
shift: shift || value.modifiers.contains(KeyModifiers::SHIFT),
|
||||
ctrl: value.modifiers.contains(KeyModifiers::CONTROL),
|
||||
alt: value.modifiers.contains(KeyModifiers::ALT),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for Key {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
struct KeyVisitor;
|
||||
|
||||
impl<'de> Visitor<'de> for KeyVisitor {
|
||||
type Value = Key;
|
||||
|
||||
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
formatter.write_str("a key string, e.g. <C-a>")
|
||||
}
|
||||
|
||||
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
|
||||
where
|
||||
E: serde::de::Error,
|
||||
{
|
||||
Ok(Key::from(value))
|
||||
k => bail!("unknown key: {}", k),
|
||||
}
|
||||
}
|
||||
|
||||
deserializer.deserialize_str(KeyVisitor)
|
||||
if key.code == KeyCode::Null {
|
||||
bail!("empty key")
|
||||
}
|
||||
Ok(key)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,41 +1,52 @@
|
|||
use std::fs;
|
||||
|
||||
use serde::Deserialize;
|
||||
use serde::{Deserialize, Deserializer};
|
||||
use xdg::BaseDirectories;
|
||||
|
||||
use super::{Exec, Key};
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub struct Single {
|
||||
pub on: Vec<Key>,
|
||||
#[serde(deserialize_with = "Exec::deserialize")]
|
||||
pub exec: Vec<Exec>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
#[derive(Debug)]
|
||||
pub struct Keymap {
|
||||
pub manager: Vec<Single>,
|
||||
pub tasks: Vec<Single>,
|
||||
pub input: Vec<Single>,
|
||||
}
|
||||
|
||||
impl Keymap {
|
||||
pub fn new() -> Self {
|
||||
impl<'de> Deserialize<'de> for Keymap {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
#[derive(Deserialize)]
|
||||
struct Shadow {
|
||||
manager: Inner,
|
||||
tasks: Inner,
|
||||
input: Inner,
|
||||
}
|
||||
#[derive(Deserialize)]
|
||||
struct Inner {
|
||||
keymap: Vec<Single>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct All {
|
||||
manager: Inner,
|
||||
tasks: Inner,
|
||||
input: Inner,
|
||||
}
|
||||
|
||||
let path = BaseDirectories::new().unwrap().get_config_file("yazi/keymap.toml");
|
||||
|
||||
let all: All = toml::from_str(&fs::read_to_string(path).unwrap()).unwrap();
|
||||
Self { manager: all.manager.keymap, tasks: all.tasks.keymap, input: all.input.keymap }
|
||||
let shadow = Shadow::deserialize(deserializer)?;
|
||||
Ok(Self {
|
||||
manager: shadow.manager.keymap,
|
||||
tasks: shadow.tasks.keymap,
|
||||
input: shadow.input.keymap,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Keymap {
|
||||
pub fn new() -> Self {
|
||||
let path = BaseDirectories::new().unwrap().get_config_file("yazi/keymap.toml");
|
||||
toml::from_str(&fs::read_to_string(path).unwrap()).unwrap()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ use xdg::BaseDirectories;
|
|||
|
||||
use super::SortBy;
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub struct Manager {
|
||||
#[serde(skip)]
|
||||
pub cwd: PathBuf,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
use serde::{de::Visitor, Deserialize, Deserializer};
|
||||
use anyhow::bail;
|
||||
use serde::Deserialize;
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
#[derive(Debug, Deserialize, Clone, Copy)]
|
||||
#[serde(try_from = "String")]
|
||||
pub enum SortBy {
|
||||
Alphabetical,
|
||||
Created,
|
||||
|
|
@ -8,39 +10,16 @@ pub enum SortBy {
|
|||
Size,
|
||||
}
|
||||
|
||||
impl From<&str> for SortBy {
|
||||
fn from(value: &str) -> Self {
|
||||
match value {
|
||||
impl TryFrom<String> for SortBy {
|
||||
type Error = anyhow::Error;
|
||||
|
||||
fn try_from(s: String) -> Result<Self, Self::Error> {
|
||||
Ok(match s.as_str() {
|
||||
"created" => Self::Created,
|
||||
"modified" => Self::Modified,
|
||||
"size" => Self::Size,
|
||||
_ => Self::Alphabetical,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for SortBy {
|
||||
fn deserialize<D>(deserializer: D) -> Result<SortBy, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
struct SortByVisitor;
|
||||
|
||||
impl<'de> Visitor<'de> for SortByVisitor {
|
||||
type Value = SortBy;
|
||||
|
||||
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
formatter.write_str("a sort_by string, e.g. modified")
|
||||
}
|
||||
|
||||
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
|
||||
where
|
||||
E: serde::de::Error,
|
||||
{
|
||||
Ok(SortBy::from(value))
|
||||
}
|
||||
}
|
||||
|
||||
deserializer.deserialize_str(SortByVisitor)
|
||||
"alphabetical" => Self::Alphabetical,
|
||||
_ => bail!("invalid sort_by value: {}", s),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
mod open;
|
||||
mod opener;
|
||||
|
||||
pub use open::*;
|
||||
pub use opener::*;
|
||||
|
|
|
|||
|
|
@ -1,29 +1,18 @@
|
|||
use std::{collections::BTreeMap, fs, path::Path};
|
||||
|
||||
use serde::Deserialize;
|
||||
use serde::{Deserialize, Deserializer};
|
||||
use xdg::BaseDirectories;
|
||||
|
||||
use super::Opener;
|
||||
use crate::config::Pattern;
|
||||
|
||||
#[derive(Clone, Deserialize, Debug, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub struct Opener {
|
||||
pub cmd: String,
|
||||
pub args: Vec<String>,
|
||||
#[serde(default)]
|
||||
pub block: bool,
|
||||
#[serde(skip)]
|
||||
pub spread: bool,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
#[derive(Debug)]
|
||||
pub struct Open {
|
||||
#[serde(skip)]
|
||||
openers: BTreeMap<String, Vec<Opener>>,
|
||||
|
||||
rules: Vec<OpenRule>,
|
||||
rules: Vec<OpenRule>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct OpenRule {
|
||||
name: Option<Pattern>,
|
||||
mime: Option<Pattern>,
|
||||
|
|
@ -32,23 +21,9 @@ struct OpenRule {
|
|||
}
|
||||
|
||||
impl Open {
|
||||
pub fn new() -> Open {
|
||||
#[derive(Deserialize)]
|
||||
struct Outer {
|
||||
opener: BTreeMap<String, Vec<Opener>>,
|
||||
open: Open,
|
||||
}
|
||||
|
||||
pub fn new() -> Self {
|
||||
let path = BaseDirectories::new().unwrap().get_config_file("yazi/yazi.toml");
|
||||
let mut outer = toml::from_str::<Outer>(&fs::read_to_string(path).unwrap()).unwrap();
|
||||
|
||||
for opener in outer.opener.values_mut() {
|
||||
for one in opener.iter_mut() {
|
||||
one.spread = one.args.iter().any(|a| a == "$*");
|
||||
}
|
||||
}
|
||||
|
||||
Self { openers: outer.opener, rules: outer.open.rules }
|
||||
toml::from_str(&fs::read_to_string(path).unwrap()).unwrap()
|
||||
}
|
||||
|
||||
pub fn opener(&self, path: &Path, mime: &str) -> Option<&Opener> {
|
||||
|
|
@ -63,3 +38,23 @@ impl Open {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for Open {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
#[derive(Deserialize)]
|
||||
struct Outer {
|
||||
opener: BTreeMap<String, Vec<Opener>>,
|
||||
open: OuterOpen,
|
||||
}
|
||||
#[derive(Deserialize)]
|
||||
struct OuterOpen {
|
||||
rules: Vec<OpenRule>,
|
||||
}
|
||||
|
||||
let outer = Outer::deserialize(deserializer)?;
|
||||
Ok(Self { openers: outer.opener, rules: outer.open.rules })
|
||||
}
|
||||
}
|
||||
|
|
|
|||
31
src/config/open/opener.rs
Normal file
31
src/config/open/opener.rs
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
use serde::{Deserialize, Deserializer};
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub struct Opener {
|
||||
pub cmd: String,
|
||||
pub args: Vec<String>,
|
||||
pub block: bool,
|
||||
pub spread: bool,
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for Opener {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
#[derive(Deserialize)]
|
||||
pub struct Shadow {
|
||||
pub cmd: String,
|
||||
pub args: Vec<String>,
|
||||
#[serde(default)]
|
||||
pub block: bool,
|
||||
#[serde(skip)]
|
||||
pub spread: bool,
|
||||
}
|
||||
|
||||
let shadow = Shadow::deserialize(deserializer)?;
|
||||
|
||||
let spread = shadow.args.contains(&"$*".to_string());
|
||||
Ok(Self { cmd: shadow.cmd, args: shadow.args, block: shadow.block, spread })
|
||||
}
|
||||
}
|
||||
|
|
@ -1,8 +1,9 @@
|
|||
use std::path::Path;
|
||||
|
||||
use serde::{de::Visitor, Deserialize, Deserializer};
|
||||
use serde::Deserialize;
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(try_from = "String")]
|
||||
pub struct Pattern {
|
||||
inner: glob::Pattern,
|
||||
is_folder: bool,
|
||||
|
|
@ -16,35 +17,17 @@ impl Pattern {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<&str> for Pattern {
|
||||
fn from(value: &str) -> Self {
|
||||
let is_folder = value.ends_with('/');
|
||||
Self { inner: glob::Pattern::new(value.trim_end_matches('/')).unwrap_or_default(), is_folder }
|
||||
impl TryFrom<&str> for Pattern {
|
||||
type Error = anyhow::Error;
|
||||
|
||||
fn try_from(s: &str) -> Result<Self, Self::Error> {
|
||||
let is_folder = s.ends_with('/');
|
||||
Ok(Self { inner: glob::Pattern::new(s.trim_end_matches('/'))?, is_folder })
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for Pattern {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
struct PatternVisitor;
|
||||
impl TryFrom<String> for Pattern {
|
||||
type Error = anyhow::Error;
|
||||
|
||||
impl<'de> Visitor<'de> for PatternVisitor {
|
||||
type Value = Pattern;
|
||||
|
||||
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
formatter.write_str("a glob pattern, e.g. *.rs")
|
||||
}
|
||||
|
||||
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
|
||||
where
|
||||
E: serde::de::Error,
|
||||
{
|
||||
Ok(Pattern::from(value))
|
||||
}
|
||||
}
|
||||
|
||||
deserializer.deserialize_str(PatternVisitor)
|
||||
}
|
||||
fn try_from(s: String) -> Result<Self, Self::Error> { Self::try_from(s.as_str()) }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,13 +3,7 @@ use std::fs;
|
|||
use serde::Deserialize;
|
||||
use xdg::BaseDirectories;
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
pub struct Manager {
|
||||
pub sort_by: String,
|
||||
pub sort_reverse: bool,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub struct Preview {
|
||||
pub tab_size: u32,
|
||||
|
||||
|
|
@ -25,6 +19,7 @@ impl Preview {
|
|||
}
|
||||
|
||||
let path = BaseDirectories::new().unwrap().get_config_file("yazi/yazi.toml");
|
||||
toml::from_str::<Outer>(&fs::read_to_string(path).unwrap()).unwrap().preview
|
||||
let outer: Outer = toml::from_str(&fs::read_to_string(path).unwrap()).unwrap();
|
||||
outer.preview
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,39 +1,42 @@
|
|||
use anyhow::Result;
|
||||
use std::ops::Deref;
|
||||
|
||||
use anyhow::{bail, Result};
|
||||
use ratatui::style;
|
||||
use serde::Deserialize;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct Color {
|
||||
pub fg: String,
|
||||
pub bg: String,
|
||||
#[serde(try_from = "String")]
|
||||
pub struct Color(style::Color);
|
||||
|
||||
impl Default for Color {
|
||||
fn default() -> Self { Self(style::Color::Reset) }
|
||||
}
|
||||
|
||||
impl Color {
|
||||
pub fn fg_rgb(&self) -> style::Color {
|
||||
if self.fg.len() < 7 {
|
||||
return style::Color::Reset;
|
||||
}
|
||||
let convert = || -> Result<style::Color> {
|
||||
Ok(style::Color::Rgb(
|
||||
u8::from_str_radix(&self.fg[1..3], 16)?,
|
||||
u8::from_str_radix(&self.fg[3..5], 16)?,
|
||||
u8::from_str_radix(&self.fg[5..7], 16)?,
|
||||
))
|
||||
};
|
||||
convert().unwrap_or(style::Color::Reset)
|
||||
}
|
||||
impl TryFrom<String> for Color {
|
||||
type Error = anyhow::Error;
|
||||
|
||||
pub fn bg_rgb(&self) -> style::Color {
|
||||
if self.bg.len() < 7 {
|
||||
return style::Color::Reset;
|
||||
fn try_from(s: String) -> Result<Self, Self::Error> {
|
||||
if s.len() < 7 {
|
||||
bail!("Invalid color: {}", s);
|
||||
}
|
||||
let convert = || -> Result<style::Color> {
|
||||
Ok(style::Color::Rgb(
|
||||
u8::from_str_radix(&self.bg[1..3], 16)?,
|
||||
u8::from_str_radix(&self.bg[3..5], 16)?,
|
||||
u8::from_str_radix(&self.bg[5..7], 16)?,
|
||||
))
|
||||
};
|
||||
convert().unwrap_or(style::Color::Reset)
|
||||
Ok(Self(style::Color::Rgb(
|
||||
u8::from_str_radix(&s[1..3], 16)?,
|
||||
u8::from_str_radix(&s[3..5], 16)?,
|
||||
u8::from_str_radix(&s[5..7], 16)?,
|
||||
)))
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for Color {
|
||||
type Target = style::Color;
|
||||
|
||||
fn deref(&self) -> &Self::Target { &self.0 }
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct ColorDual {
|
||||
#[serde(default)]
|
||||
pub fg: Color,
|
||||
#[serde(default)]
|
||||
pub bg: Color,
|
||||
}
|
||||
|
|
|
|||
29
src/config/theme/filetype.rs
Normal file
29
src/config/theme/filetype.rs
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
use serde::{Deserialize, Deserializer};
|
||||
|
||||
use crate::config::Pattern;
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub struct Filetype {
|
||||
pub name: Option<Pattern>,
|
||||
pub mime: Option<Pattern>,
|
||||
#[serde(default)]
|
||||
pub bg: String,
|
||||
#[serde(default)]
|
||||
pub fg: String,
|
||||
#[serde(default)]
|
||||
pub bold: bool,
|
||||
}
|
||||
|
||||
impl Filetype {
|
||||
pub fn deserialize<'de, D>(deserializer: D) -> Result<Vec<Filetype>, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
#[derive(Deserialize)]
|
||||
struct FiletypeOuter {
|
||||
rules: Vec<Filetype>,
|
||||
}
|
||||
|
||||
Ok(FiletypeOuter::deserialize(deserializer)?.rules)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
use std::fmt;
|
||||
|
||||
use serde::{de::Visitor, Deserializer};
|
||||
use serde::{de::{self, Visitor}, Deserializer};
|
||||
|
||||
use crate::config::Pattern;
|
||||
|
||||
|
|
@ -11,10 +11,6 @@ pub struct Icon {
|
|||
}
|
||||
|
||||
impl Icon {
|
||||
pub fn new(name: String, display: String) -> Self {
|
||||
Self { name: Pattern::from(name.as_ref()), display }
|
||||
}
|
||||
|
||||
pub fn deserialize<'de, D>(deserializer: D) -> Result<Vec<Icon>, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
|
|
@ -30,11 +26,15 @@ impl Icon {
|
|||
|
||||
fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
|
||||
where
|
||||
A: serde::de::MapAccess<'de>,
|
||||
A: de::MapAccess<'de>,
|
||||
{
|
||||
let mut icons = Vec::new();
|
||||
while let Some((key, value)) = &map.next_entry::<String, String>()? {
|
||||
icons.push(Icon::new(key.clone(), value.clone()));
|
||||
icons.push(Icon {
|
||||
name: Pattern::try_from(key.clone())
|
||||
.map_err(|e| de::Error::custom(e.to_string()))?,
|
||||
display: value.clone(),
|
||||
});
|
||||
}
|
||||
Ok(icons)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
mod color;
|
||||
mod filetype;
|
||||
mod icon;
|
||||
mod theme;
|
||||
|
||||
pub use color::*;
|
||||
pub use filetype::*;
|
||||
pub use icon::*;
|
||||
pub use theme::*;
|
||||
|
|
|
|||
|
|
@ -3,32 +3,29 @@ use std::{fs, path::PathBuf};
|
|||
use serde::Deserialize;
|
||||
use xdg::BaseDirectories;
|
||||
|
||||
use super::{Color, Icon};
|
||||
use super::{ColorDual, Filetype, Icon};
|
||||
use crate::misc::absolute_path;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct Mode {
|
||||
pub normal: Color,
|
||||
pub select: Color,
|
||||
pub unselect: Color,
|
||||
pub normal: ColorDual,
|
||||
pub select: ColorDual,
|
||||
pub unselect: ColorDual,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct Tab {
|
||||
pub active: Color,
|
||||
pub inactive: Color,
|
||||
pub active: ColorDual,
|
||||
pub inactive: ColorDual,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct Selection {
|
||||
pub normal: Color,
|
||||
pub hovered: Color,
|
||||
pub selected: Color,
|
||||
pub normal: ColorDual,
|
||||
pub hovered: ColorDual,
|
||||
pub selected: ColorDual,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct Filetype {}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct Syntect {
|
||||
pub theme: PathBuf,
|
||||
|
|
@ -39,10 +36,11 @@ pub struct Theme {
|
|||
pub mode: Mode,
|
||||
pub tab: Tab,
|
||||
pub selection: Selection,
|
||||
pub filetype: Filetype,
|
||||
pub syntect: Syntect,
|
||||
#[serde(deserialize_with = "Filetype::deserialize")]
|
||||
pub filetypes: Vec<Filetype>,
|
||||
#[serde(deserialize_with = "Icon::deserialize")]
|
||||
pub icons: Vec<Icon>,
|
||||
pub syntect: Syntect,
|
||||
}
|
||||
|
||||
impl Theme {
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ pub enum Mode {
|
|||
|
||||
impl Mode {
|
||||
#[inline]
|
||||
pub fn color(&self) -> &theme::Color {
|
||||
pub fn color(&self) -> &theme::ColorDual {
|
||||
match *self {
|
||||
Mode::Normal => &THEME.mode.normal,
|
||||
Mode::Select(_) => &THEME.mode.select,
|
||||
|
|
|
|||
|
|
@ -29,19 +29,16 @@ impl<'a> Widget for Layout<'a> {
|
|||
)
|
||||
.split(area);
|
||||
|
||||
Paragraph::new("").style(Style::default().fg(mode.color().bg_rgb())).render(chunks[0], buf);
|
||||
Paragraph::new("").style(Style::default().fg(*mode.color().bg)).render(chunks[0], buf);
|
||||
|
||||
Paragraph::new(format!(" {} ", mode))
|
||||
.style(
|
||||
Style::default()
|
||||
.fg(mode.color().fg_rgb())
|
||||
.bg(mode.color().bg_rgb())
|
||||
.add_modifier(Modifier::BOLD),
|
||||
Style::default().fg(*mode.color().fg).bg(*mode.color().bg).add_modifier(Modifier::BOLD),
|
||||
)
|
||||
.render(chunks[1], buf);
|
||||
|
||||
Paragraph::new(" master ")
|
||||
.style(Style::default().fg(mode.color().bg_rgb()).bg(Color::Rgb(72, 77, 102)))
|
||||
.style(Style::default().fg(*mode.color().bg).bg(Color::Rgb(72, 77, 102)))
|
||||
.render(chunks[2], buf);
|
||||
|
||||
Paragraph::new("").style(Style::default().fg(Color::Rgb(72, 77, 102))).render(chunks[3], buf);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue