This commit is contained in:
sxyazi 2023-09-22 12:20:00 +08:00
parent befcd555f9
commit 03b1e8728b
No known key found for this signature in database
13 changed files with 409 additions and 156 deletions

86
Cargo.lock generated
View file

@ -133,6 +133,7 @@ dependencies = [
"crossterm",
"futures",
"libc",
"plugin",
"ratatui",
"shared",
"signal-hook-tokio",
@ -217,6 +218,16 @@ dependencies = [
"generic-array",
]
[[package]]
name = "bstr"
version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c79ad7fb2dd38f3dabd76b09c6a5a20c038fc0213ef1e9afd30eb777f120f019"
dependencies = [
"memchr",
"serde",
]
[[package]]
name = "bumpalo"
version = "3.14.0"
@ -544,6 +555,15 @@ version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
[[package]]
name = "erased-serde"
version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c138974f9d5e7fe373eb04df7cae98833802ae4b11c24ac7039a21d5af4b26c"
dependencies = [
"serde",
]
[[package]]
name = "error-code"
version = "2.3.1"
@ -1073,6 +1093,33 @@ dependencies = [
"windows-sys",
]
[[package]]
name = "mlua"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c3a7a7ff4481ec91b951a733390211a8ace1caba57266ccb5f4d4966704e560"
dependencies = [
"bstr",
"erased-serde",
"mlua-sys",
"num-traits",
"once_cell",
"rustc-hash",
"serde",
"serde-value",
]
[[package]]
name = "mlua-sys"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3ec8b54eddb76093069cce9eeffb4c7b3a1a0fe66962d7bd44c4867928149ca3"
dependencies = [
"cc",
"cfg-if",
"pkg-config",
]
[[package]]
name = "nom"
version = "7.1.3"
@ -1203,6 +1250,15 @@ version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d"
[[package]]
name = "ordered-float"
version = "2.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "68f19d67e5a2795c94e73e0bb1cc1a7edeb2e28efd39e2e1c9b7a40c1108b11c"
dependencies = [
"num-traits",
]
[[package]]
name = "overload"
version = "0.1.1"
@ -1276,6 +1332,19 @@ dependencies = [
"time",
]
[[package]]
name = "plugin"
version = "0.1.0"
dependencies = [
"anyhow",
"config",
"core",
"mlua",
"ratatui",
"shared",
"tracing",
]
[[package]]
name = "png"
version = "0.17.10"
@ -1450,6 +1519,12 @@ version = "0.1.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
[[package]]
name = "rustc-hash"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
[[package]]
name = "rustversion"
version = "1.0.14"
@ -1492,6 +1567,16 @@ dependencies = [
"serde_derive",
]
[[package]]
name = "serde-value"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f3a1a3341211875ef120e117ea7fd5228530ae7e7036a779fdc9117be6b3282c"
dependencies = [
"ordered-float",
"serde",
]
[[package]]
name = "serde_derive"
version = "1.0.188"
@ -1542,7 +1627,6 @@ dependencies = [
"libc",
"parking_lot",
"ratatui",
"regex",
"tokio",
]

View file

@ -1,15 +1,16 @@
use anyhow::Result;
use config::theme::Color;
use ratatui::{style::{Modifier, Style}, text::{Line, Span}, widgets::Paragraph};
use ratatui::{prelude::{Buffer, Rect}, style::{Modifier, Style}, text::{Line, Span}, widgets::{Paragraph, Widget}};
pub struct Parser;
impl Parser {
pub fn span(s: &str) -> Span<'static> {
fn span(s: &str) -> Span<'static> {
let Some((args, content)) = s.split_once(';') else {
return Span::raw(s.to_string());
};
let args = args.split(',').collect::<Vec<_>>();
let args: Vec<_> = args.split(',').collect();
if args.len() != 4 {
return Span::raw(s.to_string());
}
@ -30,7 +31,7 @@ impl Parser {
Span::styled(content.to_string(), style)
}
pub fn line(s: &str) -> Line<'static> {
fn line(s: &str) -> Line<'static> {
let mut last = '\0';
let mut spans: Vec<String> = vec![String::new()];
@ -49,7 +50,7 @@ impl Parser {
Line::from(spans.into_iter().map(|s| Self::span(&s)).collect::<Vec<_>>())
}
pub fn paragraph(s: &str) -> Paragraph {
fn paragraph(s: &str) -> Paragraph {
let mut last = '\0';
let mut lines: Vec<String> = vec![String::new()];
@ -68,22 +69,49 @@ impl Parser {
Paragraph::new(lines.into_iter().map(|s| Self::line(&s)).collect::<Vec<_>>())
}
pub fn layout(s: &str) -> Paragraph {
fn area(args: Vec<&str>) -> Result<Rect> {
Ok(Rect {
x: args[0].parse()?,
y: args[1].parse()?,
width: args[2].parse()?,
height: args[3].parse()?,
})
}
pub fn render(s: &str, buf: &mut Buffer) {
let Some(s) = s.strip_prefix('R') else {
return;
};
let mut last = '\0';
let mut lines: Vec<String> = vec![String::new()];
let mut paragraphs: Vec<String> = vec![String::new()];
for c in s.chars() {
if c == '\0' && last == '\\' {
let last = lines.last_mut().unwrap();
let last = paragraphs.last_mut().unwrap();
last.pop();
last.push(c);
} else if c == '\0' {
lines.push(String::new());
paragraphs.push(String::new());
} else {
lines.last_mut().unwrap().push(c);
paragraphs.last_mut().unwrap().push(c);
}
last = c;
}
Paragraph::new(lines.into_iter().map(|s| Self::line(&s)).collect::<Vec<_>>())
for paragraph in paragraphs {
let Some((args, content)) = paragraph.split_once(';') else {
continue;
};
let args: Vec<_> = args.split(',').collect();
if args.len() != 4 {
continue;
}
if let Ok(area) = Self::area(args) {
Self::paragraph(content).render(area, buf);
}
}
}
}

View file

@ -1,9 +1,9 @@
use core::Ctx;
use ratatui::{buffer::Buffer, layout::{self, Constraint, Direction, Rect}, text::Line, widgets::{Paragraph, Widget}};
use ratatui::{buffer::Buffer, layout::{self, Constraint, Direction, Rect}, widgets::Widget};
use tracing::info;
use crate::Parser;
use crate::parser::Parser;
pub(crate) struct Layout<'a> {
cx: &'a Ctx,
@ -20,63 +20,14 @@ impl<'a> Widget for Layout<'a> {
.constraints([Constraint::Percentage(50), Constraint::Percentage(50)].as_ref())
.split(area);
// Left::new(self.cx).render(chunks[0], buf);
// Right::new(self.cx).render(chunks[1], buf);
let mut spans = vec![];
if let Ok(mode) = plugin::Status::mode(self.cx) {
spans.extend(Parser::line(&mode).spans);
}
let x = plugin::Status::size(self.cx);
let x = plugin::Status::layout(self.cx, area);
if x.is_err() {
info!("Error: {:?}", x);
info!("{:?}", x);
return;
}
if let Ok(size) = x {
spans.extend(Parser::line(&size).spans);
}
let x = plugin::Status::name(self.cx);
if x.is_err() {
info!("Error: {:?}", x);
return;
if let Ok(s) = x {
Parser::render(&s, buf);
}
if let Ok(name) = x {
spans.extend(Parser::line(&name).spans);
}
Paragraph::new(Line::from(spans)).render(chunks[0], buf);
// Right
let mut spans = vec![];
let x = plugin::Status::permissions(self.cx);
if x.is_err() {
info!("Error: {:?}", x);
return;
}
if let Ok(name) = x {
spans.extend(Parser::line(&name).spans);
}
let x = plugin::Status::percentage(self.cx);
if x.is_err() {
info!("Error: {:?}", x);
return;
}
if let Ok(name) = x {
spans.extend(Parser::line(&name).spans);
}
let x = plugin::Status::position(self.cx);
if x.is_err() {
info!("Error: {:?}", x);
return;
}
if let Ok(name) = x {
spans.extend(Parser::line(&name).spans);
}
Paragraph::new(Line::from(spans)).render(chunks[1], buf);
}
}

View file

@ -1 +1 @@
{"flagWords":[],"words":["Punct","KEYMAP","splitn","crossterm","YAZI","unar","peekable","ratatui","syntect","pbpaste","pbcopy","ffmpegthumbnailer","oneshot","Posix","Lsar","XADDOS","zoxide","cands","Deque","precache","imageops","IFBLK","IFCHR","IFDIR","IFIFO","IFLNK","IFMT","IFSOCK","IRGRP","IROTH","IRUSR","ISGID","ISUID","ISVTX","IWGRP","IWOTH","IWUSR","IXGRP","IXOTH","IXUSR","libc","winsize","TIOCGWINSZ","xpixel","ypixel","ioerr","appender","Catppuccin","macchiato","gitmodules","Dotfiles","bashprofile","vimrc","flac","webp","exiftool","mediainfo","ripgrep","nvim","indexmap","indexmap","unwatch","canonicalize","serde","fsevent","Ueberzug","iterm","wezterm","sixel","chafa","ueberzugpp"," Überzug"," Überzug","Konsole","Alacritty","Überzug","pkgs","paru","unarchiver","pdftoppm","poppler","prebuild","singlefile","jpegopt","EXIF","rustfmt","mktemp","nanos","xclip","xsel","Mintty","nixos","nixpkgs","SIGTSTP","SIGCONT","SIGCONT","backstack","natsort","natsort","USERPROFILE"],"language":"en","version":"0.2"}
{"flagWords":[],"words":["Punct","KEYMAP","splitn","crossterm","YAZI","unar","peekable","ratatui","syntect","pbpaste","pbcopy","ffmpegthumbnailer","oneshot","Posix","Lsar","XADDOS","zoxide","cands","Deque","precache","imageops","IFBLK","IFCHR","IFDIR","IFIFO","IFLNK","IFMT","IFSOCK","IRGRP","IROTH","IRUSR","ISGID","ISUID","ISVTX","IWGRP","IWOTH","IWUSR","IXGRP","IXOTH","IXUSR","libc","winsize","TIOCGWINSZ","xpixel","ypixel","ioerr","appender","Catppuccin","macchiato","gitmodules","Dotfiles","bashprofile","vimrc","flac","webp","exiftool","mediainfo","ripgrep","nvim","indexmap","indexmap","unwatch","canonicalize","serde","fsevent","Ueberzug","iterm","wezterm","sixel","chafa","ueberzugpp"," Überzug"," Überzug","Konsole","Alacritty","Überzug","pkgs","paru","unarchiver","pdftoppm","poppler","prebuild","singlefile","jpegopt","EXIF","rustfmt","mktemp","nanos","xclip","xsel","natord","Mintty","nixos","nixpkgs","SIGTSTP","SIGCONT","SIGCONT","mlua","nonstatic","userdata"],"language":"en","version":"0.2"}

View file

@ -12,3 +12,4 @@ shared = { path = "../shared" }
anyhow = "^1"
mlua = { version = "^0", features = [ "lua54", "serialize" ] }
tracing = "^0"
ratatui = "^0"

View file

@ -1,4 +1,15 @@
function layout() end
function layout(area)
local chunks = yazi
.Layout()
:direction(false)
:constraints({ yazi.Constraint.Percentage(50), yazi.Constraint.Percentage(50) })
:split(area)
return yazi.Paragraph.render(
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()
@ -6,45 +17,41 @@ function mode()
mode = "UN-SET"
end
return yazi
.Line(
return yazi.Line(
yazi.Span(THEME.status.separator.opening):fg(THEME.status.mode_normal.bg),
yazi.Span(" " .. mode .. " "):style(THEME.status.mode_normal)
)
:to_string()
end
function size()
local hovered = cx.manager.current_hovered
if hovered == nil then
return ""
return yazi.Span("")
end
return yazi
.Line(
return yazi.Line(
yazi.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)
)
:to_string()
end
function name()
local hovered = cx.manager.current_hovered
if hovered == nil then
return ""
return yazi.Span("")
end
return yazi.Span(" " .. utils.basename(hovered.url)):to_string()
return yazi.Span(" " .. utils.basename(hovered.url))
end
function permissions()
local hovered = cx.manager.current_hovered
if hovered == nil then
return ""
return yazi.Span("")
end
if hovered.permissions == nil then
return ""
return yazi.Span("")
end
local spans = {}
@ -60,7 +67,7 @@ function permissions()
end
spans[i] = yazi.Span(c):style(style)
end
return yazi.Line:from(spans):to_string()
return yazi.Line:from(spans)
end
function percentage()
@ -77,16 +84,14 @@ function percentage()
percent = string.format(" %3d%% ", percent)
end
return yazi
.Line(
return yazi.Line(
yazi.Span(THEME.status.separator.opening):fg(THEME.status.fancy.bg),
yazi.Span(percent):fg(THEME.status.mode_normal.bg):bg(THEME.status.fancy.bg)
)
:to_string()
end
function position()
local cursor = cx.manager.current_cursor
local length = cx.manager.current_length
return string.format(" %d/%d ", cursor + 1, length)
return yazi.Span(string.format(" %d/%d ", cursor + 1, length))
end

View file

@ -2,6 +2,7 @@ local Paragraph = {}
function Paragraph:new(...)
local o = {
position = nil,
lines = { ... },
}
setmetatable(o, self)
@ -11,6 +12,11 @@ end
function Paragraph:from(lines) return self:new(table.unpack(lines)) end
function Paragraph:area(rect)
self.position = rect
return self
end
function Paragraph:to_string()
local s = ""
for _, line in ipairs(self.lines) do
@ -19,6 +25,26 @@ function Paragraph:to_string()
return s.sub(s, 1, -2)
end
function Paragraph:aaa() return self:to_string() end
function Paragraph.render(...)
local s = "R"
for _, paragraph in ipairs { ... } do
s = s
.. paragraph.position.x
.. ","
.. paragraph.position.y
.. ","
.. paragraph.position.width
.. ","
.. paragraph.position.height
.. ";"
.. paragraph:to_string():gsub("\0", "\\\0")
.. "\0"
end
return s.sub(s, 1, -2)
end
setmetatable(Paragraph, {
__call = function(self, ...) return self:new(...) end,
__tostring = function(self) return self:to_string() end,

View file

@ -10,12 +10,12 @@ impl<'a> Manager<'a> {
impl<'a> UserData for Manager<'a> {
fn add_fields<'lua, F: mlua::UserDataFields<'lua, Self>>(fields: &mut F) {
fields.add_field_method_get("mode", |_, this| Ok(this.0.active().mode().to_string()));
fields.add_field_method_get("mode", |_, me| Ok(me.0.active().mode().to_string()));
fields.add_field_method_get("current_cursor", |_, this| Ok(this.0.current().cursor()));
fields.add_field_method_get("current_length", |_, this| Ok(this.0.current().files.len()));
fields.add_field_method_get("current_hovered", |_, this| {
Ok(this.0.current().hovered.as_ref().map(File::from))
fields.add_field_method_get("current_cursor", |_, me| Ok(me.0.current().cursor()));
fields.add_field_method_get("current_length", |_, me| Ok(me.0.current().files.len()));
fields.add_field_method_get("current_hovered", |_, me| {
Ok(me.0.current().hovered.as_ref().map(File::from))
});
}
}
@ -30,7 +30,7 @@ impl<'a> Tasks<'a> {
impl<'a> UserData for Tasks<'a> {
fn add_fields<'lua, F: mlua::UserDataFields<'lua, Self>>(fields: &mut F) {
fields.add_field_method_get("progress", |lua, this| lua.to_value(&this.0.progress))
fields.add_field_method_get("progress", |lua, me| lua.to_value(&me.0.progress))
}
}
@ -44,17 +44,17 @@ impl From<&core::files::File> for File {
impl UserData for File {
fn add_fields<'lua, F: mlua::UserDataFields<'lua, Self>>(fields: &mut F) {
fields.add_field_method_get("url", |_, this| Ok(this.0.url().to_string_lossy().to_string()));
fields.add_field_method_get("length", |_, this| Ok(this.0.length()));
fields.add_field_method_get("link_to", |_, this| {
Ok(this.0.link_to().map(|l| l.to_string_lossy().to_string()))
fields.add_field_method_get("url", |_, me| Ok(me.0.url().to_string_lossy().to_string()));
fields.add_field_method_get("length", |_, me| Ok(me.0.length()));
fields.add_field_method_get("link_to", |_, me| {
Ok(me.0.link_to().map(|l| l.to_string_lossy().to_string()))
});
fields.add_field_method_get("is_link", |_, this| Ok(this.0.is_link()));
fields.add_field_method_get("is_hidden", |_, this| Ok(this.0.is_hidden()));
fields.add_field_method_get("is_link", |_, me| Ok(me.0.is_link()));
fields.add_field_method_get("is_hidden", |_, me| Ok(me.0.is_hidden()));
// Meta
fields.add_field_method_get("permissions", |_, this| {
Ok(shared::permissions(this.0.meta().permissions()))
fields.add_field_method_get("permissions", |_, me| {
Ok(shared::permissions(me.0.meta().permissions()))
});
}
}

178
plugin/src/layout.rs Normal file
View file

@ -0,0 +1,178 @@
use mlua::{AnyUserData, FromLua, Lua, Table, UserData, UserDataMethods, Value};
use ratatui::layout;
use crate::LUA;
// --- Rect
#[derive(Clone, Copy)]
pub struct Rect(layout::Rect);
impl From<layout::Rect> for Rect {
fn from(value: layout::Rect) -> Self { Self(value) }
}
impl<'lua> FromLua<'lua> for Rect {
fn from_lua(value: Value<'lua>, _: &'lua Lua) -> mlua::Result<Self> {
match value {
Value::UserData(ud) => Ok(*ud.borrow::<Self>()?),
_ => Err(mlua::Error::FromLuaConversionError {
from: value.type_name(),
to: "Rect",
message: Some("expected a Rect".to_string()),
}),
}
}
}
impl UserData for Rect {
fn add_fields<'lua, F: mlua::UserDataFields<'lua, Self>>(fields: &mut F) {
fields.add_field_method_get("x", |_, me| Ok(me.0.x));
fields.add_field_method_get("y", |_, me| Ok(me.0.y));
fields.add_field_method_get("width", |_, me| Ok(me.0.width));
fields.add_field_method_get("height", |_, me| Ok(me.0.height));
}
}
// --- Constraint
#[derive(Clone, Copy)]
pub struct Constraint(layout::Constraint);
impl Constraint {
pub(super) fn install() -> mlua::Result<()> {
let globals = LUA.globals();
let yazi = globals.get::<_, Table>("yazi")?;
let constraint = LUA.create_table()?;
constraint.set(
"Percentage",
LUA.create_function(|_, n: u16| Ok(Constraint(layout::Constraint::Percentage(n))))?,
)?;
constraint.set(
"Ratio",
LUA
.create_function(|_, (a, b): (u32, u32)| Ok(Constraint(layout::Constraint::Ratio(a, b))))?,
)?;
constraint.set(
"Length",
LUA.create_function(|_, n: u16| Ok(Constraint(layout::Constraint::Length(n))))?,
)?;
constraint
.set("Max", LUA.create_function(|_, n: u16| Ok(Constraint(layout::Constraint::Max(n))))?)?;
constraint
.set("Min", LUA.create_function(|_, n: u16| Ok(Constraint(layout::Constraint::Min(n))))?)?;
yazi.set("Constraint", constraint)
}
}
impl<'lua> FromLua<'lua> for Constraint {
fn from_lua(value: Value<'lua>, _: &'lua Lua) -> mlua::Result<Self> {
match value {
Value::UserData(ud) => Ok(*ud.borrow::<Self>()?),
_ => Err(mlua::Error::FromLuaConversionError {
from: value.type_name(),
to: "Constraint",
message: Some("expected a Constraint".to_string()),
}),
}
}
}
impl UserData for Constraint {}
// --- Layout
#[derive(Clone, Default)]
pub struct Layout {
direction: bool,
margin: Option<layout::Margin>,
constraints: Vec<layout::Constraint>,
}
impl Layout {
pub(super) fn install() -> mlua::Result<()> {
let globals = LUA.globals();
let yazi = globals.get::<_, Table>("yazi")?;
yazi.set("Layout", LUA.create_function(|_, ()| Ok(Self::default()))?)
}
}
impl<'lua> FromLua<'lua> for Layout {
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: "Layout",
message: Some("expected a Layout".to_string()),
}),
}
}
}
impl UserData for Layout {
fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) {
methods.add_function("direction", |_, (ud, value): (AnyUserData, bool)| {
{
let mut me = ud.borrow_mut::<Self>()?;
me.direction = value;
}
Ok(ud)
});
methods.add_function("margin", |_, (ud, value): (AnyUserData, u16)| {
{
let mut me = ud.borrow_mut::<Self>()?;
me.margin = Some(layout::Margin::new(value, value));
}
Ok(ud)
});
methods.add_function("margin_h", |_, (ud, value): (AnyUserData, u16)| {
{
let mut me = ud.borrow_mut::<Self>()?;
if let Some(margin) = &mut me.margin {
margin.horizontal = value;
} else {
me.margin = Some(layout::Margin::new(value, 0));
}
}
Ok(ud)
});
methods.add_function("margin_v", |_, (ud, value): (AnyUserData, u16)| {
{
let mut me = ud.borrow_mut::<Self>()?;
if let Some(margin) = &mut me.margin {
margin.vertical = value;
} else {
me.margin = Some(layout::Margin::new(0, value));
}
}
Ok(ud)
});
methods.add_function("constraints", |_, (ud, value): (AnyUserData, Vec<Constraint>)| {
{
let mut me = ud.borrow_mut::<Self>()?;
me.constraints = value.into_iter().map(|c| c.0).collect();
}
Ok(ud)
});
methods.add_function("split", |_, (ud, value): (AnyUserData, Rect)| {
let me = ud.borrow::<Self>()?;
let mut layout = layout::Layout::new()
.direction(if me.direction {
layout::Direction::Horizontal
} else {
layout::Direction::Vertical
})
.constraints(me.constraints.as_slice());
if let Some(margin) = me.margin {
layout = layout.horizontal_margin(margin.horizontal);
layout = layout.vertical_margin(margin.vertical);
}
let chunks: Vec<Rect> = layout.split(value.0).iter().copied().map(Rect).collect();
Ok(chunks)
});
}
}

View file

@ -1,9 +1,11 @@
#![allow(clippy::unit_arg)]
mod bindings;
mod layout;
mod plugin;
mod status;
pub use bindings::*;
pub use layout::*;
pub use plugin::*;
pub use status::*;

View file

@ -3,21 +3,34 @@ use config::THEME;
use mlua::{Lua, LuaSerdeExt};
use shared::RoCell;
use crate::layout;
pub(crate) static LUA: RoCell<Lua> = RoCell::new();
pub fn init() {
fn inner() -> Result<()> {
let lua = Lua::new();
// Base
lua.load(include_str!("../preset/utils.lua")).exec()?;
lua.load(include_str!("../preset/inspect/inspect.lua")).exec()?;
lua.load(include_str!("../preset/span.lua")).exec()?;
lua.load(include_str!("../preset/line.lua")).exec()?;
lua.load(include_str!("../preset/paragraph.lua")).exec()?;
lua.load(include_str!("../preset/status.lua")).exec()?;
// Elements
lua.load(include_str!("../preset/elements/span.lua")).exec()?;
lua.load(include_str!("../preset/elements/line.lua")).exec()?;
lua.load(include_str!("../preset/elements/paragraph.lua")).exec()?;
// Components
lua.load(include_str!("../preset/components/status.lua")).exec()?;
// Initialize
lua.globals().set("THEME", lua.to_value(&*THEME)?)?;
Ok(LUA.init(lua))
LUA.init(lua);
layout::Layout::install()?;
layout::Constraint::install()?;
Ok(())
}
inner().expect("failed to initialize Lua");

View file

@ -1,13 +1,14 @@
use core::Ctx;
use mlua::{Function, Result};
use ratatui::layout;
use crate::{bindings, LUA};
use crate::{bindings, Rect, LUA};
pub struct Status;
impl Status {
fn scoped<T, F: FnOnce() -> Result<T>>(cx: &Ctx, f: F) -> Result<T> {
fn scope<T, F: FnOnce() -> Result<T>>(cx: &Ctx, f: F) -> Result<T> {
LUA.scope(|scope| {
let manager = scope.create_nonstatic_userdata(bindings::Manager::new(&cx.manager))?;
let tasks = scope.create_nonstatic_userdata(bindings::Tasks::new(&cx.tasks))?;
@ -21,45 +22,10 @@ impl Status {
})
}
pub fn mode(cx: &Ctx) -> Result<String> {
Self::scoped(cx, || {
let mode: Function = LUA.globals().get("mode")?;
mode.call::<_, String>(())
})
}
pub fn size(cx: &Ctx) -> Result<String> {
Self::scoped(cx, || {
let size: Function = LUA.globals().get("size")?;
size.call::<_, String>(())
})
}
pub fn name(cx: &Ctx) -> Result<String> {
Self::scoped(cx, || {
let size: Function = LUA.globals().get("name")?;
size.call::<_, String>(())
})
}
pub fn permissions(cx: &Ctx) -> Result<String> {
Self::scoped(cx, || {
let size: Function = LUA.globals().get("permissions")?;
size.call::<_, String>(())
})
}
pub fn percentage(cx: &Ctx) -> Result<String> {
Self::scoped(cx, || {
let size: Function = LUA.globals().get("percentage")?;
size.call::<_, String>(())
})
}
pub fn position(cx: &Ctx) -> Result<String> {
Self::scoped(cx, || {
let size: Function = LUA.globals().get("position")?;
size.call::<_, String>(())
pub fn layout(cx: &Ctx, area: layout::Rect) -> Result<String> {
Self::scope(cx, || {
let layout: Function = LUA.globals().get("layout")?;
layout.call::<_, String>(Rect::from(area))
})
}
}

View file

@ -9,6 +9,5 @@ crossterm = "^0"
futures = "^0"
libc = "^0"
parking_lot = "^0"
ratatui = { version = "^0" }
regex = "^1"
ratatui = "^0"
tokio = { version = "^1", features = [ "parking_lot", "macros", "rt-multi-thread", "sync", "time", "fs" ] }