mirror of
https://github.com/sxyazi/yazi.git
synced 2026-07-25 08:41:05 +00:00
feat: add a new Bar component, and make border styles customizable (#278)
This commit is contained in:
parent
56cd3dc940
commit
c9d9418920
10 changed files with 182 additions and 15 deletions
|
|
@ -1,6 +1,7 @@
|
|||
use core::Ctx;
|
||||
|
||||
use config::MANAGER;
|
||||
use config::{MANAGER, THEME};
|
||||
use plugin::layout::Bar;
|
||||
use ratatui::{buffer::Buffer, layout::{self, Constraint, Direction, Rect}, widgets::{Block, Borders, Padding, Widget}};
|
||||
|
||||
use super::{Folder, Preview};
|
||||
|
|
@ -28,18 +29,23 @@ impl<'a> Widget for Layout<'a> {
|
|||
.split(area);
|
||||
|
||||
// Parent
|
||||
let block = Block::new().borders(Borders::RIGHT).padding(Padding::new(1, 0, 0, 0));
|
||||
Bar::new(chunks[0], Borders::RIGHT)
|
||||
.symbol(&THEME.manager.border_symbol)
|
||||
.style(THEME.manager.border_style.into())
|
||||
.render(buf);
|
||||
if manager.parent().is_some() {
|
||||
Folder::Parent.render(block.inner(chunks[0]), buf);
|
||||
Folder::Parent.render(Block::new().padding(Padding::new(1, 1, 0, 0)).inner(chunks[0]), buf);
|
||||
}
|
||||
block.render(chunks[0], buf);
|
||||
|
||||
// Current
|
||||
Folder::Current.render(chunks[1], buf);
|
||||
|
||||
// Preview
|
||||
let block = Block::new().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);
|
||||
Bar::new(chunks[2], Borders::LEFT)
|
||||
.symbol(&THEME.manager.border_symbol)
|
||||
.style(THEME.manager.border_style.into())
|
||||
.render(buf);
|
||||
Preview::new(self.cx)
|
||||
.render(Block::new().padding(Padding::new(1, 1, 0, 0)).inner(chunks[2]), buf);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,6 +23,10 @@ tab_active = { fg = "black", bg = "blue" }
|
|||
tab_inactive = { bg = "darkgray" }
|
||||
tab_width = 1
|
||||
|
||||
# Border
|
||||
border_symbol = "│"
|
||||
border_style = { fg = "gray" }
|
||||
|
||||
# Highlighting
|
||||
syntect_theme = ""
|
||||
|
||||
|
|
@ -134,7 +138,7 @@ rules = [
|
|||
{ mime = "application/x-rar", fg = "magenta" },
|
||||
|
||||
# Fallback
|
||||
{ name = "*", blink = true },
|
||||
# { name = "*", fg = "white" },
|
||||
{ name = "*/", fg = "blue" }
|
||||
]
|
||||
|
||||
|
|
|
|||
|
|
@ -30,6 +30,10 @@ pub struct Manager {
|
|||
#[validate(range(min = 1, message = "Must be greater than 0"))]
|
||||
tab_width: u8,
|
||||
|
||||
// Border
|
||||
pub border_symbol: String,
|
||||
pub border_style: Style,
|
||||
|
||||
// Highlighting
|
||||
pub syntect_theme: PathBuf,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,13 @@ ui = {
|
|||
HORIZONTAL = false,
|
||||
VERTICAL = true,
|
||||
},
|
||||
Position = {
|
||||
NONE = 0,
|
||||
TOP = 1,
|
||||
RIGHT = 2,
|
||||
BOTTOM = 3,
|
||||
LEFT = 4,
|
||||
},
|
||||
}
|
||||
|
||||
function ui.highlight_ranges(s, ranges)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use mlua::{AnyUserData, Table, TableExt};
|
||||
|
||||
use crate::{layout::{Gauge, List, Paragraph, Rect}, GLOBALS, LUA};
|
||||
use crate::{layout::{Bar, Gauge, List, Paragraph, Rect}, GLOBALS, LUA};
|
||||
|
||||
#[inline]
|
||||
fn layout(values: Vec<AnyUserData>, buf: &mut ratatui::prelude::Buffer) -> mlua::Result<()> {
|
||||
|
|
@ -9,6 +9,8 @@ fn layout(values: Vec<AnyUserData>, buf: &mut ratatui::prelude::Buffer) -> mlua:
|
|||
c.render(buf)
|
||||
} else if let Ok(c) = value.take::<List>() {
|
||||
c.render(buf)
|
||||
} else if let Ok(c) = value.take::<Bar>() {
|
||||
c.render(buf)
|
||||
} else if let Ok(c) = value.take::<Gauge>() {
|
||||
c.render(buf)
|
||||
}
|
||||
|
|
|
|||
141
plugin/src/layout/bar.rs
Normal file
141
plugin/src/layout/bar.rs
Normal file
|
|
@ -0,0 +1,141 @@
|
|||
use mlua::{AnyUserData, FromLua, Lua, Table, UserData, Value};
|
||||
|
||||
use super::{Rect, Style};
|
||||
use crate::{GLOBALS, LUA};
|
||||
|
||||
// --- Bar
|
||||
#[derive(Clone)]
|
||||
pub struct Bar {
|
||||
area: ratatui::layout::Rect,
|
||||
|
||||
position: ratatui::widgets::Borders,
|
||||
symbol: String,
|
||||
style: Option<ratatui::style::Style>,
|
||||
}
|
||||
|
||||
impl Bar {
|
||||
pub(crate) fn install() -> mlua::Result<()> {
|
||||
let ui: Table = GLOBALS.get("ui")?;
|
||||
ui.set(
|
||||
"Bar",
|
||||
LUA.create_function(|_, (area, direction): (Rect, u8)| {
|
||||
Ok(Self {
|
||||
area: area.0,
|
||||
|
||||
position: match direction {
|
||||
1 => ratatui::widgets::Borders::TOP,
|
||||
2 => ratatui::widgets::Borders::RIGHT,
|
||||
3 => ratatui::widgets::Borders::BOTTOM,
|
||||
4 => ratatui::widgets::Borders::LEFT,
|
||||
_ => ratatui::widgets::Borders::NONE,
|
||||
},
|
||||
symbol: Default::default(),
|
||||
style: Default::default(),
|
||||
})
|
||||
})?,
|
||||
)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn new(area: ratatui::layout::Rect, position: ratatui::widgets::Borders) -> Self {
|
||||
Self { area, position, symbol: Default::default(), style: Default::default() }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn symbol(mut self, symbol: &str) -> Self {
|
||||
self.symbol = symbol.to_owned();
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn style(mut self, style: ratatui::style::Style) -> Self {
|
||||
self.style = Some(style);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn render(self, buf: &mut ratatui::buffer::Buffer) {
|
||||
use ratatui::widgets::Borders;
|
||||
if self.area.area() == 0 {
|
||||
return;
|
||||
}
|
||||
|
||||
let symbol = if !self.symbol.is_empty() {
|
||||
&self.symbol
|
||||
} else if self.position.intersects(Borders::TOP | Borders::BOTTOM) {
|
||||
"─"
|
||||
} else if self.position.intersects(Borders::LEFT | Borders::RIGHT) {
|
||||
"│"
|
||||
} else {
|
||||
" "
|
||||
};
|
||||
|
||||
if self.position.contains(Borders::LEFT) {
|
||||
for y in self.area.top()..self.area.bottom() {
|
||||
let cell = buf.get_mut(self.area.left(), y).set_symbol(symbol);
|
||||
if let Some(style) = self.style {
|
||||
cell.set_style(style);
|
||||
}
|
||||
}
|
||||
}
|
||||
if self.position.contains(Borders::TOP) {
|
||||
for x in self.area.left()..self.area.right() {
|
||||
let cell = buf.get_mut(x, self.area.top()).set_symbol(symbol);
|
||||
if let Some(style) = self.style {
|
||||
cell.set_style(style);
|
||||
}
|
||||
}
|
||||
}
|
||||
if self.position.contains(Borders::RIGHT) {
|
||||
let x = self.area.right() - 1;
|
||||
for y in self.area.top()..self.area.bottom() {
|
||||
let cell = buf.get_mut(x, y).set_symbol(symbol);
|
||||
if let Some(style) = self.style {
|
||||
cell.set_style(style);
|
||||
}
|
||||
}
|
||||
}
|
||||
if self.position.contains(Borders::BOTTOM) {
|
||||
let y = self.area.bottom() - 1;
|
||||
for x in self.area.left()..self.area.right() {
|
||||
let cell = buf.get_mut(x, y).set_symbol(symbol);
|
||||
if let Some(style) = self.style {
|
||||
cell.set_style(style);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'lua> FromLua<'lua> for Bar {
|
||||
fn from_lua(value: Value<'lua>, _: &'lua Lua) -> mlua::Result<Self> {
|
||||
match value {
|
||||
Value::UserData(ud) => Ok(ud.borrow::<Self>()?.clone()),
|
||||
_ => Err(mlua::Error::FromLuaConversionError {
|
||||
from: value.type_name(),
|
||||
to: "Bar",
|
||||
message: Some("expected a Bar".to_string()),
|
||||
}),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl UserData for Bar {
|
||||
fn add_methods<'lua, M: mlua::UserDataMethods<'lua, Self>>(methods: &mut M) {
|
||||
methods.add_function("symbol", |_, (ud, symbol): (AnyUserData, String)| {
|
||||
ud.borrow_mut::<Self>()?.symbol = symbol;
|
||||
Ok(ud)
|
||||
});
|
||||
methods.add_function("style", |_, (ud, value): (AnyUserData, Value)| {
|
||||
{
|
||||
let mut me = ud.borrow_mut::<Self>()?;
|
||||
match value {
|
||||
Value::Nil => me.style = None,
|
||||
Value::Table(tbl) => me.style = Some(Style::from(tbl).0),
|
||||
Value::UserData(ud) => me.style = Some(ud.borrow::<Style>()?.0),
|
||||
_ => return Err(mlua::Error::external("expected a Style or Table or nil")),
|
||||
}
|
||||
}
|
||||
Ok(ud)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -70,11 +70,11 @@ impl UserData for Layout {
|
|||
let me = ud.borrow::<Self>()?;
|
||||
|
||||
let mut layout = ratatui::layout::Layout::new()
|
||||
.direction(if me.direction {
|
||||
ratatui::layout::Direction::Vertical
|
||||
} else {
|
||||
ratatui::layout::Direction::Horizontal
|
||||
})
|
||||
.direction(
|
||||
me.direction
|
||||
.then_some(ratatui::layout::Direction::Vertical)
|
||||
.unwrap_or(ratatui::layout::Direction::Horizontal),
|
||||
)
|
||||
.constraints(me.constraints.as_slice());
|
||||
|
||||
if let Some(margin) = me.margin {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
#![allow(clippy::module_inception)]
|
||||
|
||||
mod bar;
|
||||
mod constraint;
|
||||
mod gauge;
|
||||
mod layout;
|
||||
|
|
@ -10,6 +11,7 @@ mod rect;
|
|||
mod span;
|
||||
mod style;
|
||||
|
||||
pub use bar::*;
|
||||
pub(super) use constraint::*;
|
||||
pub(super) use gauge::*;
|
||||
pub(super) use layout::*;
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
mod bindings;
|
||||
mod components;
|
||||
mod config;
|
||||
mod layout;
|
||||
pub mod layout;
|
||||
mod plugin;
|
||||
mod scope;
|
||||
mod utils;
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ pub fn init() {
|
|||
// Install
|
||||
crate::Config.install()?;
|
||||
|
||||
layout::Bar::install()?;
|
||||
layout::Constraint::install()?;
|
||||
layout::Gauge::install()?;
|
||||
layout::Layout::install()?;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue