This commit is contained in:
sxyazi 2023-09-23 09:51:54 +08:00
parent 03b1e8728b
commit 528e4a6130
No known key found for this signature in database
11 changed files with 110 additions and 118 deletions

View file

@ -18,7 +18,6 @@ mod which;
use app::*; use app::*;
use executor::*; use executor::*;
use logs::*; use logs::*;
use parser::*;
use root::*; use root::*;
use signals::*; use signals::*;

View file

@ -1,6 +1,6 @@
use anyhow::Result; use anyhow::Result;
use config::theme::Color; use config::theme::Color;
use ratatui::{prelude::{Buffer, Rect}, style::{Modifier, Style}, text::{Line, Span}, widgets::{Paragraph, Widget}}; use ratatui::{prelude::{Alignment, Buffer, Rect}, style::{Modifier, Style}, text::{Line, Span}, widgets::{Paragraph, Widget}};
pub struct Parser; pub struct Parser;
@ -69,7 +69,7 @@ impl Parser {
Paragraph::new(lines.into_iter().map(|s| Self::line(&s)).collect::<Vec<_>>()) Paragraph::new(lines.into_iter().map(|s| Self::line(&s)).collect::<Vec<_>>())
} }
fn area(args: Vec<&str>) -> Result<Rect> { fn area(args: &[&str]) -> Result<Rect> {
Ok(Rect { Ok(Rect {
x: args[0].parse()?, x: args[0].parse()?,
y: args[1].parse()?, y: args[1].parse()?,
@ -105,13 +105,24 @@ impl Parser {
}; };
let args: Vec<_> = args.split(',').collect(); let args: Vec<_> = args.split(',').collect();
if args.len() != 4 { if args.len() != 5 {
continue; continue;
} }
if let Ok(area) = Self::area(args) { let Ok(area) = Self::area(&args) else {
Self::paragraph(content).render(area, buf); continue;
};
let mut paragraph = Self::paragraph(content);
if let Ok(align) = args[4].parse::<u8>() {
paragraph = paragraph.alignment(match align {
1 => Alignment::Center,
2 => Alignment::Right,
_ => Alignment::Left,
});
} }
paragraph.render(area, buf);
} }
} }
} }

View file

@ -1,6 +1,6 @@
use core::Ctx; use core::Ctx;
use ratatui::{buffer::Buffer, layout::{self, Constraint, Direction, Rect}, widgets::Widget}; use ratatui::{buffer::Buffer, prelude::Rect, widgets::Widget};
use tracing::info; use tracing::info;
use crate::parser::Parser; use crate::parser::Parser;
@ -15,12 +15,7 @@ impl<'a> Layout<'a> {
impl<'a> Widget for Layout<'a> { impl<'a> Widget for Layout<'a> {
fn render(self, area: Rect, buf: &mut Buffer) { fn render(self, area: Rect, buf: &mut Buffer) {
let chunks = layout::Layout::new() let x = plugin::Status::render(self.cx, area);
.direction(Direction::Horizontal)
.constraints([Constraint::Percentage(50), Constraint::Percentage(50)].as_ref())
.split(area);
let x = plugin::Status::layout(self.cx, area);
if x.is_err() { if x.is_err() {
info!("{:?}", x); info!("{:?}", x);
return; return;

View file

@ -1,57 +1,46 @@
function layout(area) Status = {}
local chunks = yazi
.Layout()
:direction(false)
:constraints({ yazi.Constraint.Percentage(50), yazi.Constraint.Percentage(50) })
:split(area)
return yazi.Paragraph.render( function Status.mode()
yazi.Paragraph(mode(), size(), name()):area(chunks[1]),
yazi.Paragraph(permissions(), percentage(), position()):area(chunks[2])
)
end
function mode()
local mode = cx.manager.mode:upper() local mode = cx.manager.mode:upper()
if mode == "UNSET" then if mode == "UNSET" then
mode = "UN-SET" mode = "UN-SET"
end end
return yazi.Line( return ui.Line(
yazi.Span(THEME.status.separator.opening):fg(THEME.status.mode_normal.bg), ui.Span(THEME.status.separator.opening):fg(THEME.status.mode_normal.bg),
yazi.Span(" " .. mode .. " "):style(THEME.status.mode_normal) ui.Span(" " .. mode .. " "):style(THEME.status.mode_normal)
) )
end end
function size() function Status.size()
local hovered = cx.manager.current_hovered local hovered = cx.manager.current_hovered
if hovered == nil then if hovered == nil then
return yazi.Span("") return ui.Span("")
end end
return yazi.Line( return ui.Line(
yazi.Span(" " .. hovered.length .. " "):fg(THEME.status.mode_normal.bg):bg(THEME.status.fancy.bg), ui.Span(" " .. hovered.length .. " "):fg(THEME.status.mode_normal.bg):bg(THEME.status.fancy.bg),
yazi.Span(THEME.status.separator.closing):fg(THEME.status.fancy.bg) ui.Span(THEME.status.separator.closing):fg(THEME.status.fancy.bg)
) )
end end
function name() function Status.name()
local hovered = cx.manager.current_hovered local hovered = cx.manager.current_hovered
if hovered == nil then if hovered == nil then
return yazi.Span("") return ui.Span("")
end end
return yazi.Span(" " .. utils.basename(hovered.url)) return ui.Span(" " .. utils.basename(hovered.url))
end end
function permissions() function Status.permissions()
local hovered = cx.manager.current_hovered local hovered = cx.manager.current_hovered
if hovered == nil then if hovered == nil then
return yazi.Span("") return ui.Span("")
end end
if hovered.permissions == nil then if hovered.permissions == nil then
return yazi.Span("") return ui.Span("")
end end
local spans = {} local spans = {}
@ -65,12 +54,12 @@ function permissions()
elseif c == "x" or c == "s" or c == "S" or c == "t" or c == "T" then elseif c == "x" or c == "s" or c == "S" or c == "t" or c == "T" then
style = THEME.status.permissions_x style = THEME.status.permissions_x
end end
spans[i] = yazi.Span(c):style(style) spans[i] = ui.Span(c):style(style)
end end
return yazi.Line:from(spans) return ui.Line:from(spans)
end end
function percentage() function Status.percentage()
local percent = 0 local percent = 0
local cursor = cx.manager.current_cursor local cursor = cx.manager.current_cursor
local length = cx.manager.current_length local length = cx.manager.current_length
@ -84,14 +73,28 @@ function percentage()
percent = string.format(" %3d%% ", percent) percent = string.format(" %3d%% ", percent)
end end
return yazi.Line( return ui.Line(
yazi.Span(THEME.status.separator.opening):fg(THEME.status.fancy.bg), ui.Span(THEME.status.separator.opening):fg(THEME.status.fancy.bg),
yazi.Span(percent):fg(THEME.status.mode_normal.bg):bg(THEME.status.fancy.bg) ui.Span(percent):fg(THEME.status.mode_normal.bg):bg(THEME.status.fancy.bg)
) )
end end
function position() function Status.position()
local cursor = cx.manager.current_cursor local cursor = cx.manager.current_cursor
local length = cx.manager.current_length local length = cx.manager.current_length
return yazi.Span(string.format(" %d/%d ", cursor + 1, length)) return ui.Span(string.format(" %d/%d ", cursor + 1, length))
end
function Status:render(area)
local chunks = ui.Layout()
:direction(ui.Direction.HORIZONTAL)
:constraints({ ui.Constraint.Percentage(50), ui.Constraint.Percentage(50) })
:split(area)
local left = ui.Line(self.mode(), self.size(), self.name())
local right = ui.Line(self.permissions(), self.percentage(), self.position())
return ui.Paragraph.render(
ui.Paragraph(left):area(chunks[1]),
ui.Paragraph(right):align(ui.Alignment.RIGHT):area(chunks[2])
)
end end

View file

@ -13,8 +13,15 @@ function Line:from(spans) return self:new(table.unpack(spans)) end
function Line:to_string() function Line:to_string()
local s = "" local s = ""
for _, span in ipairs(self.spans) do for _, el in ipairs(self.spans) do
s = s .. span:to_string():gsub("\n", "\\\n") .. "\n" local mt = getmetatable(el)
if mt == ui.Line then
for _, span in ipairs(el.spans) do
s = s .. span:to_string():gsub("\n", "\\\n") .. "\n"
end
else
s = s .. el:to_string():gsub("\n", "\\\n") .. "\n"
end
end end
return s.sub(s, 1, -2) return s.sub(s, 1, -2)
end end
@ -24,5 +31,5 @@ setmetatable(Line, {
__tostring = function(self) return self:to_string() end, __tostring = function(self) return self:to_string() end,
}) })
yazi = yazi or {} ui = ui or {}
yazi.Line = Line ui.Line = Line

View file

@ -1,7 +1,13 @@
local Paragraph = {} local Paragraph = {}
local Alignment = {
LEFT = 0,
CENTER = 1,
RIGHT = 2,
}
function Paragraph:new(...) function Paragraph:new(...)
local o = { local o = {
alignment = 0,
position = nil, position = nil,
lines = { ... }, lines = { ... },
} }
@ -12,6 +18,11 @@ end
function Paragraph:from(lines) return self:new(table.unpack(lines)) end function Paragraph:from(lines) return self:new(table.unpack(lines)) end
function Paragraph:align(align)
self.alignment = align
return self
end
function Paragraph:area(rect) function Paragraph:area(rect)
self.position = rect self.position = rect
return self return self
@ -25,8 +36,6 @@ function Paragraph:to_string()
return s.sub(s, 1, -2) return s.sub(s, 1, -2)
end end
function Paragraph:aaa() return self:to_string() end
function Paragraph.render(...) function Paragraph.render(...)
local s = "R" local s = "R"
for _, paragraph in ipairs { ... } do for _, paragraph in ipairs { ... } do
@ -38,6 +47,8 @@ function Paragraph.render(...)
.. paragraph.position.width .. paragraph.position.width
.. "," .. ","
.. paragraph.position.height .. paragraph.position.height
.. ","
.. paragraph.alignment
.. ";" .. ";"
.. paragraph:to_string():gsub("\0", "\\\0") .. paragraph:to_string():gsub("\0", "\\\0")
.. "\0" .. "\0"
@ -50,5 +61,6 @@ setmetatable(Paragraph, {
__tostring = function(self) return self:to_string() end, __tostring = function(self) return self:to_string() end,
}) })
yazi = yazi or {} ui = ui or {}
yazi.Paragraph = Paragraph ui.Paragraph = Paragraph
ui.Alignment = Alignment

View file

@ -120,5 +120,5 @@ setmetatable(Span, {
__tostring = function(self) return self:to_string() end, __tostring = function(self) return self:to_string() end,
}) })
yazi = yazi or {} ui = ui or {}
yazi.Span = Span ui.Span = Span

View file

@ -1,43 +0,0 @@
local Layout = {}
function Layout:new(...)
local o = {
direction = "R",
dimension = {},
elements = { ... },
}
setmetatable(o, self)
self.__index = self
return o
end
function Layout:from(elements) return self:new(table.unpack(elements)) end
function Layout:rows(rows)
self.direction = "R"
self.dimension = rows
return self:to_string()
end
function Layout:cols(cols)
self.direction = "C"
self.dimension = cols
return self:to_string()
end
function Layout:to_string()
local s = ""
for i, element in ipairs(self.elements) do
if i == 1 then
s = s .. self.direction
end
s = s .. self.dimension[i] .. "\0" .. element:to_string():gsub("\0", "\\\0")
end
end
setmetatable(Layout, {
__call = function(self, ...) return self:new(...) end,
})
yazi = yazi or {}
yazi.Layout = Layout

View file

@ -1,7 +1,7 @@
use mlua::{AnyUserData, FromLua, Lua, Table, UserData, UserDataMethods, Value}; use mlua::{AnyUserData, FromLua, Lua, Table, UserData, UserDataMethods, Value};
use ratatui::layout; use ratatui::layout;
use crate::LUA; use crate::{GLOBALS, LUA};
// --- Rect // --- Rect
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
@ -39,8 +39,7 @@ pub struct Constraint(layout::Constraint);
impl Constraint { impl Constraint {
pub(super) fn install() -> mlua::Result<()> { pub(super) fn install() -> mlua::Result<()> {
let globals = LUA.globals(); let ui: Table = GLOBALS.get("ui")?;
let yazi = globals.get::<_, Table>("yazi")?;
let constraint = LUA.create_table()?; let constraint = LUA.create_table()?;
constraint.set( constraint.set(
@ -61,7 +60,7 @@ impl Constraint {
constraint constraint
.set("Min", LUA.create_function(|_, n: u16| Ok(Constraint(layout::Constraint::Min(n))))?)?; .set("Min", LUA.create_function(|_, n: u16| Ok(Constraint(layout::Constraint::Min(n))))?)?;
yazi.set("Constraint", constraint) ui.set("Constraint", constraint)
} }
} }
@ -90,10 +89,13 @@ pub struct Layout {
impl Layout { impl Layout {
pub(super) fn install() -> mlua::Result<()> { pub(super) fn install() -> mlua::Result<()> {
let globals = LUA.globals(); let ui: Table = GLOBALS.get("ui")?;
ui.set("Layout", LUA.create_function(|_, ()| Ok(Self::default()))?)?;
let yazi = globals.get::<_, Table>("yazi")?; let direction = LUA.create_table()?;
yazi.set("Layout", LUA.create_function(|_, ()| Ok(Self::default()))?) direction.set("HORIZONTAL", false)?;
direction.set("VERTICAL", true)?;
ui.set("Direction", direction)
} }
} }
@ -160,9 +162,9 @@ impl UserData for Layout {
let mut layout = layout::Layout::new() let mut layout = layout::Layout::new()
.direction(if me.direction { .direction(if me.direction {
layout::Direction::Horizontal
} else {
layout::Direction::Vertical layout::Direction::Vertical
} else {
layout::Direction::Horizontal
}) })
.constraints(me.constraints.as_slice()); .constraints(me.constraints.as_slice());

View file

@ -1,11 +1,12 @@
use anyhow::Result; use anyhow::Result;
use config::THEME; use config::THEME;
use mlua::{Lua, LuaSerdeExt}; use mlua::{Lua, LuaSerdeExt, SerializeOptions, Table};
use shared::RoCell; use shared::RoCell;
use crate::layout; use crate::layout;
pub(crate) static LUA: RoCell<Lua> = RoCell::new(); pub(crate) static LUA: RoCell<Lua> = RoCell::new();
pub(crate) static GLOBALS: RoCell<Table> = RoCell::new();
pub fn init() { pub fn init() {
fn inner() -> Result<()> { fn inner() -> Result<()> {
@ -24,12 +25,17 @@ pub fn init() {
lua.load(include_str!("../preset/components/status.lua")).exec()?; lua.load(include_str!("../preset/components/status.lua")).exec()?;
// Initialize // Initialize
lua.globals().set("THEME", lua.to_value(&*THEME)?)?;
LUA.init(lua); LUA.init(lua);
GLOBALS.init(LUA.globals());
// Install
layout::Layout::install()?; layout::Layout::install()?;
layout::Constraint::install()?; layout::Constraint::install()?;
let options =
SerializeOptions::new().serialize_none_to_null(false).serialize_unit_to_null(false);
GLOBALS.set("THEME", LUA.to_value_with(&*THEME, options)?)?;
Ok(()) Ok(())
} }

View file

@ -1,9 +1,9 @@
use core::Ctx; use core::Ctx;
use mlua::{Function, Result}; use mlua::{Result, Table, TableExt};
use ratatui::layout; use ratatui::layout;
use crate::{bindings, Rect, LUA}; use crate::{bindings, Rect, GLOBALS, LUA};
pub struct Status; pub struct Status;
@ -16,16 +16,16 @@ impl Status {
let cx = LUA.create_table()?; let cx = LUA.create_table()?;
cx.set("manager", manager)?; cx.set("manager", manager)?;
cx.set("tasks", tasks)?; cx.set("tasks", tasks)?;
LUA.globals().set("cx", cx)?; GLOBALS.set("cx", cx)?;
f() f()
}) })
} }
pub fn layout(cx: &Ctx, area: layout::Rect) -> Result<String> { pub fn render(cx: &Ctx, area: layout::Rect) -> Result<String> {
Self::scope(cx, || { Self::scope(cx, || {
let layout: Function = LUA.globals().get("layout")?; let status: Table = GLOBALS.get("Status")?;
layout.call::<_, String>(Rect::from(area)) status.call_method::<_, String>("render", Rect::from(area))
}) })
} }
} }