feat: status color customing

This commit is contained in:
sxyazi 2023-07-15 00:54:58 +08:00
parent 19fcc78a12
commit ca08a8447a
No known key found for this signature in database
9 changed files with 119 additions and 63 deletions

8
Cargo.lock generated
View file

@ -1844,9 +1844,9 @@ dependencies = [
[[package]]
name = "toml_edit"
version = "0.19.12"
version = "0.19.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c500344a19072298cd05a7224b3c0c629348b78692bf48466c5238656e315a78"
checksum = "5f8751d9c1b03c6500c387e96f81f815a4f8e72d142d2d4a9ffa6fedd51ddee7"
dependencies = [
"indexmap 2.0.0",
"serde",
@ -2328,9 +2328,9 @@ checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a"
[[package]]
name = "winnow"
version = "0.4.9"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "81a2094c43cc94775293eaa0e499fbc30048a6d824ac82c0351a8c0bf9112529"
checksum = "81fac9742fd1ad1bd9643b991319f72dd031016d44b77039a26977eb667141e7"
dependencies = [
"memchr",
]

View file

@ -6,7 +6,7 @@ use serde::Deserialize;
#[derive(Deserialize)]
#[serde(try_from = "String")]
pub struct Color(style::Color);
pub struct Color(pub(super) style::Color);
impl Default for Color {
fn default() -> Self { Self(style::Color::Reset) }
@ -33,10 +33,15 @@ impl Deref for Color {
fn deref(&self) -> &Self::Target { &self.0 }
}
#[derive(Deserialize)]
pub struct ColorDual {
#[serde(default)]
pub fg: Color,
#[serde(default)]
pub bg: Color,
impl Color {
pub fn fg(&self) -> style::Style { style::Style::new().fg(self.0) }
pub fn bg(&self) -> style::Style { style::Style::new().bg(self.0) }
}
#[derive(Deserialize)]
pub struct ColorGroup {
pub normal: Color,
pub select: Color,
pub unselect: Color,
}

View file

@ -1,9 +1,11 @@
mod color;
mod filetype;
mod icon;
mod style;
mod theme;
pub use color::*;
pub use filetype::*;
pub use icon::*;
pub use style::*;
pub use theme::*;

40
src/config/theme/style.rs Normal file
View file

@ -0,0 +1,40 @@
use ratatui::style::{self, Modifier};
use serde::Deserialize;
use super::Color;
#[derive(Deserialize)]
pub struct Style {
pub fg: Option<Color>,
pub bg: Option<Color>,
pub bold: Option<bool>,
pub underline: Option<bool>,
}
impl Style {
pub fn get(&self) -> style::Style {
let mut style = style::Style::new();
if let Some(fg) = &self.fg {
style = style.fg(fg.0);
}
if let Some(bg) = &self.bg {
style = style.bg(bg.0);
}
if let Some(bold) = self.bold {
if bold {
style = style.add_modifier(Modifier::BOLD);
} else {
style = style.remove_modifier(Modifier::BOLD);
}
}
if let Some(underline) = self.underline {
if underline {
style = style.add_modifier(Modifier::UNDERLINED);
} else {
style = style.remove_modifier(Modifier::UNDERLINED);
}
}
style
}
}

View file

@ -3,27 +3,36 @@ use std::{fs, path::PathBuf};
use serde::Deserialize;
use xdg::BaseDirectories;
use super::{ColorDual, Filetype, Icon};
use super::{ColorGroup, Filetype, Icon, Style};
use crate::misc::absolute_path;
#[derive(Deserialize)]
pub struct Mode {
pub normal: ColorDual,
pub select: ColorDual,
pub unselect: ColorDual,
pub struct Tab {
pub active: Style,
pub inactive: Style,
}
#[derive(Deserialize)]
pub struct Tab {
pub active: ColorDual,
pub inactive: ColorDual,
pub struct Status {
pub primary: ColorGroup,
pub secondary: ColorGroup,
pub emphasis: ColorGroup,
pub body: ColorGroup,
pub info: ColorGroup,
pub success: ColorGroup,
pub warning: ColorGroup,
pub danger: ColorGroup,
}
#[derive(Deserialize)]
pub struct Selection {
pub normal: ColorDual,
pub hovered: ColorDual,
pub selected: ColorDual,
pub hovered: Style,
}
#[derive(Deserialize)]
pub struct Marker {
pub selecting: Style,
pub selected: Style,
}
#[derive(Deserialize)]
@ -33,9 +42,10 @@ pub struct Syntect {
#[derive(Deserialize)]
pub struct Theme {
pub mode: Mode,
pub tab: Tab,
pub status: Status,
pub selection: Selection,
pub marker: Marker,
#[serde(deserialize_with = "Filetype::deserialize")]
pub filetypes: Vec<Filetype>,
#[serde(deserialize_with = "Icon::deserialize")]

View file

@ -1,6 +1,6 @@
use std::fmt::Display;
use crate::config::{theme, THEME};
use crate::config::theme::{self, ColorGroup};
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
pub enum Mode {
@ -12,11 +12,11 @@ pub enum Mode {
impl Mode {
#[inline]
pub fn color(&self) -> &theme::ColorDual {
pub fn color<'a>(&self, group: &'a ColorGroup) -> &'a theme::Color {
match *self {
Mode::Normal => &THEME.mode.normal,
Mode::Select(_) => &THEME.mode.select,
Mode::Unselect(_) => &THEME.mode.unselect,
Mode::Normal => &group.normal,
Mode::Select(_) => &group.select,
Mode::Unselect(_) => &group.unselect,
}
}

View file

@ -10,7 +10,7 @@ pub struct Folder<'a> {
impl<'a> Folder<'a> {
pub fn new(folder: &'a core::manager::Folder) -> Self {
Self { folder, is_preview: false, is_selection: false }
Self { folder, is_preview: false, is_selection: true }
}
#[inline]
@ -28,11 +28,12 @@ impl<'a> Folder<'a> {
impl<'a> Widget for Folder<'a> {
fn render(self, area: Rect, buf: &mut Buffer) {
let items = self
.folder
.paginate()
let page = self.folder.paginate();
let items = page
.iter()
.map(|(k, v)| {
.enumerate()
.map(|(i, (k, v))| {
let icon = THEME
.icons
.iter()
@ -40,34 +41,32 @@ impl<'a> Widget for Folder<'a> {
.map(|x| x.display.as_ref())
.unwrap_or("");
let name = readable_path(k, &self.folder.cwd);
let item = ListItem::new(if v.is_selected {
format!("> {} {}", icon, name)
} else {
format!("{} {}", icon, name)
});
let hovered = matches!(self.folder.hovered, Some(ref h) if h.path == *k);
if v.is_selected {
buf.set_style(
Rect { x: area.x.saturating_sub(1), y: i as u16 + 1, width: 1, height: 1 },
Style::default().fg(Color::Red).bg(Color::Red),
);
}
let name = if self.is_selection && v.is_selected {
format!(" {} {}", icon, readable_path(k, &self.folder.cwd))
} else {
format!(" {} {}", icon, readable_path(k, &self.folder.cwd))
};
let hovered = matches!(self.folder.hovered, Some(ref h) if h.path == *k);
let mut style = Style::default();
if self.is_selection {
if hovered {
style = style.fg(Color::Black).bg(Color::Red);
} else if v.is_selected {
style = style.fg(Color::Red);
}
} else if self.is_preview {
if self.is_preview {
if hovered {
style = style.add_modifier(Modifier::UNDERLINED)
}
} else {
if hovered {
style = style.fg(Color::Black).bg(Color::Yellow);
} else if v.is_selected {
style = style.fg(Color::Red);
}
}
item.style(style)
ListItem::new(name).style(style)
})
.collect::<Vec<_>>();

View file

@ -1,4 +1,4 @@
use ratatui::{buffer::Buffer, layout::{self, Constraint, Direction, Rect}, widgets::{Block, Borders, Widget}};
use ratatui::{buffer::Buffer, layout::{self, Constraint, Direction, Rect}, widgets::{Block, Borders, Padding, Widget}};
use super::{Folder, Preview};
use crate::{core::manager::{Mode, ALL_RATIO, CURRENT_RATIO, PARENT_RATIO, PREVIEW_RATIO}, ui::Ctx};
@ -28,7 +28,7 @@ impl<'a> Widget for Layout<'a> {
.split(area);
// Parent
let block = Block::default().borders(Borders::RIGHT);
let block = Block::default().borders(Borders::RIGHT).padding(Padding::new(1, 0, 0, 0));
if let Some(ref parent) = manager.parent() {
Folder::new(parent).render(block.inner(chunks[0]), buf);
}
@ -40,7 +40,7 @@ impl<'a> Widget for Layout<'a> {
.render(chunks[1], buf);
// Preview
let block = Block::default().borders(Borders::LEFT);
let block = Block::default().borders(Borders::LEFT).padding(Padding::new(0, 1, 0, 0));
Preview::new(self.cx).render(block.inner(chunks[2]), buf);
block.render(chunks[2], buf);
}

View file

@ -1,7 +1,7 @@
use ratatui::{buffer::Buffer, layout::{self, Constraint, Direction, Rect}, style::{Color, Modifier, Style}, widgets::{Paragraph, Widget}};
use ratatui::{buffer::Buffer, layout::{self, Constraint, Direction, Rect}, style::Modifier, widgets::{Paragraph, Widget}};
use super::Progress;
use crate::ui::Ctx;
use crate::{config::THEME, ui::Ctx};
pub struct Layout<'a> {
cx: &'a Ctx,
@ -29,19 +29,19 @@ impl<'a> Widget for Layout<'a> {
)
.split(area);
Paragraph::new("").style(Style::default().fg(*mode.color().bg)).render(chunks[0], buf);
let primary = mode.color(&THEME.status.primary);
let secondary = mode.color(&THEME.status.secondary);
let body = mode.color(&THEME.status.body);
Paragraph::new("").style(primary.fg()).render(chunks[0], buf);
Paragraph::new(format!(" {} ", mode))
.style(
Style::default().fg(*mode.color().fg).bg(*mode.color().bg).add_modifier(Modifier::BOLD),
)
.style(primary.bg().fg(**secondary).add_modifier(Modifier::BOLD))
.render(chunks[1], buf);
Paragraph::new(" master ")
.style(Style::default().fg(*mode.color().bg).bg(Color::Rgb(72, 77, 102)))
.render(chunks[2], buf);
Paragraph::new(" master ").style(body.bg().fg(**primary)).render(chunks[2], buf);
Paragraph::new("").style(Style::default().fg(Color::Rgb(72, 77, 102))).render(chunks[3], buf);
Paragraph::new("").style(body.fg()).render(chunks[3], buf);
Progress::new(self.cx).render(chunks[4], buf);
}