mirror of
https://github.com/sxyazi/yazi.git
synced 2026-07-25 08:41:05 +00:00
..
This commit is contained in:
parent
9ff11b2dbc
commit
befcd555f9
18 changed files with 299 additions and 262 deletions
|
|
@ -53,6 +53,25 @@ impl Parser {
|
||||||
let mut last = '\0';
|
let mut last = '\0';
|
||||||
let mut lines: Vec<String> = vec![String::new()];
|
let mut lines: Vec<String> = vec![String::new()];
|
||||||
|
|
||||||
|
for c in s.chars() {
|
||||||
|
if c == '\r' && last == '\\' {
|
||||||
|
let last = lines.last_mut().unwrap();
|
||||||
|
last.pop();
|
||||||
|
last.push(c);
|
||||||
|
} else if c == '\r' {
|
||||||
|
lines.push(String::new());
|
||||||
|
} else {
|
||||||
|
lines.last_mut().unwrap().push(c);
|
||||||
|
}
|
||||||
|
last = c;
|
||||||
|
}
|
||||||
|
Paragraph::new(lines.into_iter().map(|s| Self::line(&s)).collect::<Vec<_>>())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn layout(s: &str) -> Paragraph {
|
||||||
|
let mut last = '\0';
|
||||||
|
let mut lines: Vec<String> = vec![String::new()];
|
||||||
|
|
||||||
for c in s.chars() {
|
for c in s.chars() {
|
||||||
if c == '\0' && last == '\\' {
|
if c == '\0' && last == '\\' {
|
||||||
let last = lines.last_mut().unwrap();
|
let last = lines.last_mut().unwrap();
|
||||||
|
|
|
||||||
|
|
@ -47,5 +47,36 @@ impl<'a> Widget for Layout<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
Paragraph::new(Line::from(spans)).render(chunks[0], buf);
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,46 +0,0 @@
|
||||||
use core::Ctx;
|
|
||||||
|
|
||||||
use ratatui::{buffer::Buffer, layout::Rect, widgets::Widget};
|
|
||||||
|
|
||||||
pub(super) struct Left<'a> {
|
|
||||||
cx: &'a Ctx,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> Left<'a> {
|
|
||||||
pub(super) fn new(cx: &'a Ctx) -> Self { Self { cx } }
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> Widget for Left<'a> {
|
|
||||||
fn render(self, area: Rect, buf: &mut Buffer) {
|
|
||||||
// let folder = self.cx.manager.current();
|
|
||||||
// let mode = self.cx.manager.active().mode();
|
|
||||||
//
|
|
||||||
// // Separator
|
|
||||||
// let separator = &THEME.status.separator;
|
|
||||||
//
|
|
||||||
// // Mode
|
|
||||||
// let mut spans = Vec::with_capacity(5);
|
|
||||||
// spans.push(Span::styled(&separator.opening, primary.fg()));
|
|
||||||
// spans.push(Span::styled(
|
|
||||||
// format!(" {mode} "),
|
|
||||||
// primary.bg().fg(**secondary).add_modifier(Modifier::BOLD),
|
|
||||||
// ));
|
|
||||||
//
|
|
||||||
// if let Some(h) = &folder.hovered {
|
|
||||||
// // Length
|
|
||||||
// {
|
|
||||||
// let size = if h.is_dir() { folder.files.size(h.url()) } else { None };
|
|
||||||
// spans.push(Span::styled(
|
|
||||||
// format!(" {} ", readable_size(size.unwrap_or(h.length()))),
|
|
||||||
// body.bg().fg(**primary),
|
|
||||||
// ));
|
|
||||||
// spans.push(Span::styled(&separator.closing, body.fg()));
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // Filename
|
|
||||||
// spans.push(Span::raw(format!(" {} ", h.name_display().unwrap())));
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// Paragraph::new(Line::from(spans)).render(area, buf);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,9 +1,4 @@
|
||||||
mod layout;
|
mod layout;
|
||||||
mod left;
|
|
||||||
mod progress;
|
mod progress;
|
||||||
mod right;
|
|
||||||
|
|
||||||
pub(super) use layout::*;
|
pub(super) use layout::*;
|
||||||
use left::*;
|
|
||||||
use progress::*;
|
|
||||||
use right::*;
|
|
||||||
|
|
|
||||||
|
|
@ -1,96 +0,0 @@
|
||||||
use core::Ctx;
|
|
||||||
|
|
||||||
use config::THEME;
|
|
||||||
use ratatui::{buffer::Buffer, layout::{Alignment, Rect}, text::{Line, Span}, widgets::{Paragraph, Widget}};
|
|
||||||
|
|
||||||
use super::Progress;
|
|
||||||
|
|
||||||
pub(super) struct Right<'a> {
|
|
||||||
cx: &'a Ctx,
|
|
||||||
}
|
|
||||||
|
|
||||||
// impl<'a> Right<'a> {
|
|
||||||
// pub(super) fn new(cx: &'a Ctx) -> Self { Self { cx } }
|
|
||||||
//
|
|
||||||
// #[cfg(not(target_os = "windows"))]
|
|
||||||
// fn permissions(&self, s: &str) -> Vec<Span> {
|
|
||||||
// // Colors
|
|
||||||
// let mode = self.cx.manager.active().mode();
|
|
||||||
// let tertiary = mode.color(&THEME.status.tertiary);
|
|
||||||
// let info = mode.color(&THEME.status.info);
|
|
||||||
// let success = mode.color(&THEME.status.success);
|
|
||||||
// let warning = mode.color(&THEME.status.warning);
|
|
||||||
// let danger = mode.color(&THEME.status.danger);
|
|
||||||
//
|
|
||||||
// s.chars()
|
|
||||||
// .map(|c| match c {
|
|
||||||
// '-' => Span::styled("-", tertiary.fg()),
|
|
||||||
// 'r' => Span::styled("r", warning.fg()),
|
|
||||||
// 'w' => Span::styled("w", danger.fg()),
|
|
||||||
// 'x' | 's' | 'S' | 't' | 'T' => Span::styled(c.to_string(), info.fg()),
|
|
||||||
// _ => Span::styled(c.to_string(), success.fg()),
|
|
||||||
// })
|
|
||||||
// .collect()
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// fn position(&self) -> Vec<Span> {
|
|
||||||
// // Colors
|
|
||||||
// let mode = self.cx.manager.active().mode();
|
|
||||||
// let primary = mode.color(&THEME.status.primary);
|
|
||||||
// let secondary = mode.color(&THEME.status.secondary);
|
|
||||||
// let body = mode.color(&THEME.status.body);
|
|
||||||
//
|
|
||||||
// // Separator
|
|
||||||
// let separator = &THEME.status.separator;
|
|
||||||
//
|
|
||||||
// let cursor = self.cx.manager.current().cursor();
|
|
||||||
// let length = self.cx.manager.current().files.len();
|
|
||||||
// let percent = if cursor == 0 || length == 0 { 0 } else { (cursor + 1) * 100 /
|
|
||||||
// length };
|
|
||||||
//
|
|
||||||
// vec![
|
|
||||||
// Span::raw(" "),
|
|
||||||
// Span::styled(&separator.opening, body.fg()),
|
|
||||||
// Span::styled(
|
|
||||||
// if percent == 0 { " Top ".to_string() } else { format!(" {:>3}% ", percent)
|
|
||||||
// }, body.bg().fg(**primary),
|
|
||||||
// ),
|
|
||||||
// Span::styled(
|
|
||||||
// format!(" {:>2}/{:<2} ", (cursor + 1).min(length), length),
|
|
||||||
// primary.bg().fg(**secondary),
|
|
||||||
// ),
|
|
||||||
// Span::styled(&separator.closing, primary.fg()),
|
|
||||||
// ]
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
impl Widget for Right<'_> {
|
|
||||||
fn render(self, area: Rect, buf: &mut Buffer) {
|
|
||||||
// let manager = self.cx.manager.current();
|
|
||||||
// let mut spans = Vec::with_capacity(20);
|
|
||||||
//
|
|
||||||
// // Permissions
|
|
||||||
// #[cfg(not(target_os = "windows"))]
|
|
||||||
// if let Some(h) = &manager.hovered {
|
|
||||||
// use std::os::unix::prelude::PermissionsExt;
|
|
||||||
// spans.extend(self.permissions(&shared::file_mode(h.meta().permissions().
|
|
||||||
// mode()))) }
|
|
||||||
//
|
|
||||||
// // Position
|
|
||||||
// spans.extend(self.position());
|
|
||||||
//
|
|
||||||
// // Progress
|
|
||||||
// let line = Line::from(spans);
|
|
||||||
// Progress::new(self.cx).render(
|
|
||||||
// Rect {
|
|
||||||
// x: area.x + area.width.saturating_sub(21 + line.width() as u16),
|
|
||||||
// y: area.y,
|
|
||||||
// width: 20.min(area.width),
|
|
||||||
// height: 1,
|
|
||||||
// },
|
|
||||||
// buf,
|
|
||||||
// );
|
|
||||||
//
|
|
||||||
// Paragraph::new(line).alignment(Alignment::Right).render(area, buf);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -17,6 +17,12 @@ mode_unset = { fg = "#1E1E30", bg = "#FFAF80", bold = true }
|
||||||
progress_label = { fg = "#FFFFFF", bold = true }
|
progress_label = { fg = "#FFFFFF", bold = true }
|
||||||
progress_gauge = { fg = "#FFA577", bg = "#484D66" }
|
progress_gauge = { fg = "#FFA577", bg = "#484D66" }
|
||||||
|
|
||||||
|
# Permissions
|
||||||
|
permissions_t = { fg = "#6D738F" }
|
||||||
|
permissions_r = { fg = "#F3D398" }
|
||||||
|
permissions_w = { fg = "#FA7F94" }
|
||||||
|
permissions_x = { fg = "#7AD9E5" }
|
||||||
|
|
||||||
[selection]
|
[selection]
|
||||||
hovered = { fg = "#1E2031", bg = "#80AEFA" }
|
hovered = { fg = "#1E2031", bg = "#80AEFA" }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,12 @@ pub struct Status {
|
||||||
// Progress
|
// Progress
|
||||||
pub progress_label: Style,
|
pub progress_label: Style,
|
||||||
pub progress_gauge: Style,
|
pub progress_gauge: Style,
|
||||||
|
|
||||||
|
// Permissions
|
||||||
|
pub permissions_t: Style,
|
||||||
|
pub permissions_r: Style,
|
||||||
|
pub permissions_w: Style,
|
||||||
|
pub permissions_x: Style,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize)]
|
#[derive(Deserialize, Serialize)]
|
||||||
|
|
|
||||||
|
|
@ -81,4 +81,8 @@ impl File {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn is_link(&self) -> bool { self.is_link }
|
pub fn is_link(&self) -> bool { self.is_link }
|
||||||
|
|
||||||
|
// -- Is hidden
|
||||||
|
#[inline]
|
||||||
|
pub fn is_hidden(&self) -> bool { self.is_hidden }
|
||||||
}
|
}
|
||||||
|
|
|
||||||
92
plugin/preset/components/status.lua
Normal file
92
plugin/preset/components/status.lua
Normal file
|
|
@ -0,0 +1,92 @@
|
||||||
|
function layout() end
|
||||||
|
|
||||||
|
function mode()
|
||||||
|
local mode = cx.manager.mode:upper()
|
||||||
|
if mode == "UNSET" then
|
||||||
|
mode = "UN-SET"
|
||||||
|
end
|
||||||
|
|
||||||
|
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 ""
|
||||||
|
end
|
||||||
|
|
||||||
|
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 ""
|
||||||
|
end
|
||||||
|
|
||||||
|
return yazi.Span(" " .. utils.basename(hovered.url)):to_string()
|
||||||
|
end
|
||||||
|
|
||||||
|
function permissions()
|
||||||
|
local hovered = cx.manager.current_hovered
|
||||||
|
if hovered == nil then
|
||||||
|
return ""
|
||||||
|
end
|
||||||
|
|
||||||
|
if hovered.permissions == nil then
|
||||||
|
return ""
|
||||||
|
end
|
||||||
|
|
||||||
|
local spans = {}
|
||||||
|
for i = 1, #hovered.permissions do
|
||||||
|
local c = hovered.permissions:sub(i, i)
|
||||||
|
local style = THEME.status.permissions_t
|
||||||
|
if c == "r" then
|
||||||
|
style = THEME.status.permissions_r
|
||||||
|
elseif c == "w" then
|
||||||
|
style = THEME.status.permissions_w
|
||||||
|
elseif c == "x" or c == "s" or c == "S" or c == "t" or c == "T" then
|
||||||
|
style = THEME.status.permissions_x
|
||||||
|
end
|
||||||
|
spans[i] = yazi.Span(c):style(style)
|
||||||
|
end
|
||||||
|
return yazi.Line:from(spans):to_string()
|
||||||
|
end
|
||||||
|
|
||||||
|
function percentage()
|
||||||
|
local percent = 0
|
||||||
|
local cursor = cx.manager.current_cursor
|
||||||
|
local length = cx.manager.current_length
|
||||||
|
if cursor ~= 0 and length ~= 0 then
|
||||||
|
percent = math.floor((cursor + 1) * 100 / length)
|
||||||
|
end
|
||||||
|
|
||||||
|
if percent == 0 then
|
||||||
|
percent = " Top "
|
||||||
|
else
|
||||||
|
percent = string.format(" %3d%% ", percent)
|
||||||
|
end
|
||||||
|
|
||||||
|
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)
|
||||||
|
end
|
||||||
|
|
@ -14,7 +14,7 @@ function Paragraph:from(lines) return self:new(table.unpack(lines)) end
|
||||||
function Paragraph:to_string()
|
function Paragraph:to_string()
|
||||||
local s = ""
|
local s = ""
|
||||||
for _, line in ipairs(self.lines) do
|
for _, line in ipairs(self.lines) do
|
||||||
s = s .. line:to_string():gsub("\0", "\\\0") .. "\0"
|
s = s .. line:to_string():gsub("\r", "\\\r") .. "\r"
|
||||||
end
|
end
|
||||||
return s.sub(s, 1, -2)
|
return s.sub(s, 1, -2)
|
||||||
end
|
end
|
||||||
43
plugin/preset/layout.lua
Normal file
43
plugin/preset/layout.lua
Normal file
|
|
@ -0,0 +1,43 @@
|
||||||
|
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
|
||||||
|
|
@ -1,42 +0,0 @@
|
||||||
function mode()
|
|
||||||
local mode = cx.manager.mode:upper()
|
|
||||||
if mode == "UNSET" then
|
|
||||||
mode = "UN-SET"
|
|
||||||
end
|
|
||||||
|
|
||||||
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.hovered
|
|
||||||
if hovered == nil then
|
|
||||||
return ""
|
|
||||||
end
|
|
||||||
|
|
||||||
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.hovered
|
|
||||||
if hovered == nil then
|
|
||||||
return ""
|
|
||||||
end
|
|
||||||
|
|
||||||
return yazi.Span(" " .. yazi.basename(hovered.url)):to_string()
|
|
||||||
end
|
|
||||||
|
|
||||||
function permissions() end
|
|
||||||
|
|
||||||
function percentage() end
|
|
||||||
|
|
||||||
function position() end
|
|
||||||
|
|
@ -1,3 +1,3 @@
|
||||||
yazi = yazi or {}
|
utils = utils or {}
|
||||||
|
|
||||||
function yazi.basename(str) return string.gsub(str, "(.*[/\\])(.*)", "%2") end
|
function utils.basename(str) return string.gsub(str, "(.*[/\\])(.*)", "%2") end
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
use mlua::{LuaSerdeExt, UserData, Value};
|
use mlua::{LuaSerdeExt, UserData};
|
||||||
use shared::Url;
|
|
||||||
|
|
||||||
// Manager
|
// Manager
|
||||||
|
|
||||||
|
|
@ -13,9 +12,11 @@ impl<'a> UserData for Manager<'a> {
|
||||||
fn add_fields<'lua, F: mlua::UserDataFields<'lua, Self>>(fields: &mut F) {
|
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", |_, this| Ok(this.0.active().mode().to_string()));
|
||||||
|
|
||||||
fields.add_field_method_get("hovered", |_, this| {
|
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))
|
Ok(this.0.current().hovered.as_ref().map(File::from))
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -35,31 +36,25 @@ impl<'a> UserData for Tasks<'a> {
|
||||||
|
|
||||||
// File
|
// File
|
||||||
|
|
||||||
pub struct File {
|
pub struct File(core::files::File);
|
||||||
pub(super) url: Url,
|
|
||||||
pub(super) length: u64,
|
|
||||||
pub(super) link_to: Option<Url>,
|
|
||||||
pub(super) is_link: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<&core::files::File> for File {
|
impl From<&core::files::File> for File {
|
||||||
fn from(value: &core::files::File) -> Self {
|
fn from(value: &core::files::File) -> Self { Self(value.clone()) }
|
||||||
Self {
|
|
||||||
url: value.url_owned(),
|
|
||||||
length: value.length(),
|
|
||||||
link_to: value.link_to().cloned(),
|
|
||||||
is_link: value.is_link(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UserData for File {
|
impl UserData for File {
|
||||||
fn add_fields<'lua, F: mlua::UserDataFields<'lua, Self>>(fields: &mut F) {
|
fn add_fields<'lua, F: mlua::UserDataFields<'lua, Self>>(fields: &mut F) {
|
||||||
fields.add_field_method_get("url", |_, this| Ok(this.url.to_string_lossy().to_string()));
|
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.length));
|
fields.add_field_method_get("length", |_, this| Ok(this.0.length()));
|
||||||
fields.add_field_method_get("link_to", |_, this| {
|
fields.add_field_method_get("link_to", |_, this| {
|
||||||
Ok(this.link_to.as_ref().map(|l| l.to_string_lossy().to_string()))
|
Ok(this.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()));
|
||||||
|
|
||||||
|
// Meta
|
||||||
|
fields.add_field_method_get("permissions", |_, this| {
|
||||||
|
Ok(shared::permissions(this.0.meta().permissions()))
|
||||||
});
|
});
|
||||||
fields.add_field_method_get("is_link", |_, this| Ok(this.is_link));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -41,4 +41,25 @@ impl Status {
|
||||||
size.call::<_, String>(())
|
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>(())
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
105
shared/src/fs.rs
105
shared/src/fs.rs
|
|
@ -1,4 +1,4 @@
|
||||||
use std::{collections::VecDeque, path::{Path, PathBuf}};
|
use std::{collections::VecDeque, fs::Permissions, path::{Path, PathBuf}};
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use tokio::{fs, io, select, sync::{mpsc, oneshot}, time};
|
use tokio::{fs, io, select, sync::{mpsc, oneshot}, time};
|
||||||
|
|
@ -92,61 +92,70 @@ pub fn copy_with_progress(from: &Path, to: &Path) -> mpsc::Receiver<Result<u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert a file mode to a string representation
|
// Convert a file mode to a string representation
|
||||||
#[cfg(not(target_os = "windows"))]
|
#[cfg(unix)]
|
||||||
#[allow(clippy::collapsible_else_if)]
|
#[allow(clippy::collapsible_else_if)]
|
||||||
pub fn file_mode(mode: u32) -> String {
|
pub fn permissions(permissions: Permissions) -> Option<String> {
|
||||||
use libc::{S_IFBLK, S_IFCHR, S_IFDIR, S_IFIFO, S_IFLNK, S_IFMT, S_IFSOCK, S_IRGRP, S_IROTH, S_IRUSR, S_ISGID, S_ISUID, S_ISVTX, S_IWGRP, S_IWOTH, S_IWUSR, S_IXGRP, S_IXOTH, S_IXUSR};
|
#[cfg(windows)]
|
||||||
|
{
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(target_os = "macos")]
|
Some({
|
||||||
let m = mode as u16;
|
use std::os::unix::prelude::PermissionsExt;
|
||||||
#[cfg(target_os = "freebsd")]
|
|
||||||
let m = mode as u16;
|
|
||||||
#[cfg(target_os = "netbsd")]
|
|
||||||
let m = mode;
|
|
||||||
#[cfg(target_os = "linux")]
|
|
||||||
let m = mode;
|
|
||||||
|
|
||||||
let mut s = String::with_capacity(10);
|
use libc::{S_IFBLK, S_IFCHR, S_IFDIR, S_IFIFO, S_IFLNK, S_IFMT, S_IFSOCK, S_IRGRP, S_IROTH, S_IRUSR, S_ISGID, S_ISUID, S_ISVTX, S_IWGRP, S_IWOTH, S_IWUSR, S_IXGRP, S_IXOTH, S_IXUSR};
|
||||||
|
|
||||||
// File type
|
#[cfg(target_os = "macos")]
|
||||||
s.push(match m & S_IFMT {
|
let m = permissions.mode() as u16;
|
||||||
S_IFBLK => 'b',
|
#[cfg(target_os = "freebsd")]
|
||||||
S_IFCHR => 'c',
|
let m = permissions.mode() as u16;
|
||||||
S_IFDIR => 'd',
|
#[cfg(target_os = "netbsd")]
|
||||||
S_IFIFO => 'p',
|
let m = permissions.mode();
|
||||||
S_IFLNK => 'l',
|
#[cfg(target_os = "linux")]
|
||||||
S_IFSOCK => 's',
|
let m = permissions.mode();
|
||||||
_ => '-',
|
|
||||||
});
|
|
||||||
|
|
||||||
// Owner
|
let mut s = String::with_capacity(10);
|
||||||
s.push(if m & S_IRUSR != 0 { 'r' } else { '-' });
|
|
||||||
s.push(if m & S_IWUSR != 0 { 'w' } else { '-' });
|
|
||||||
s.push(if m & S_IXUSR != 0 {
|
|
||||||
if m & S_ISUID != 0 { 's' } else { 'x' }
|
|
||||||
} else {
|
|
||||||
if m & S_ISUID != 0 { 'S' } else { '-' }
|
|
||||||
});
|
|
||||||
|
|
||||||
// Group
|
// File type
|
||||||
s.push(if m & S_IRGRP != 0 { 'r' } else { '-' });
|
s.push(match m & S_IFMT {
|
||||||
s.push(if m & S_IWGRP != 0 { 'w' } else { '-' });
|
S_IFBLK => 'b',
|
||||||
s.push(if m & S_IXGRP != 0 {
|
S_IFCHR => 'c',
|
||||||
if m & S_ISGID != 0 { 's' } else { 'x' }
|
S_IFDIR => 'd',
|
||||||
} else {
|
S_IFIFO => 'p',
|
||||||
if m & S_ISGID != 0 { 'S' } else { '-' }
|
S_IFLNK => 'l',
|
||||||
});
|
S_IFSOCK => 's',
|
||||||
|
_ => '-',
|
||||||
|
});
|
||||||
|
|
||||||
// Other
|
// Owner
|
||||||
s.push(if m & S_IROTH != 0 { 'r' } else { '-' });
|
s.push(if m & S_IRUSR != 0 { 'r' } else { '-' });
|
||||||
s.push(if m & S_IWOTH != 0 { 'w' } else { '-' });
|
s.push(if m & S_IWUSR != 0 { 'w' } else { '-' });
|
||||||
s.push(if m & S_IXOTH != 0 {
|
s.push(if m & S_IXUSR != 0 {
|
||||||
if m & S_ISVTX != 0 { 't' } else { 'x' }
|
if m & S_ISUID != 0 { 's' } else { 'x' }
|
||||||
} else {
|
} else {
|
||||||
if m & S_ISVTX != 0 { 'T' } else { '-' }
|
if m & S_ISUID != 0 { 'S' } else { '-' }
|
||||||
});
|
});
|
||||||
|
|
||||||
s
|
// Group
|
||||||
|
s.push(if m & S_IRGRP != 0 { 'r' } else { '-' });
|
||||||
|
s.push(if m & S_IWGRP != 0 { 'w' } else { '-' });
|
||||||
|
s.push(if m & S_IXGRP != 0 {
|
||||||
|
if m & S_ISGID != 0 { 's' } else { 'x' }
|
||||||
|
} else {
|
||||||
|
if m & S_ISGID != 0 { 'S' } else { '-' }
|
||||||
|
});
|
||||||
|
|
||||||
|
// Other
|
||||||
|
s.push(if m & S_IROTH != 0 { 'r' } else { '-' });
|
||||||
|
s.push(if m & S_IWOTH != 0 { 'w' } else { '-' });
|
||||||
|
s.push(if m & S_IXOTH != 0 {
|
||||||
|
if m & S_ISVTX != 0 { 't' } else { 'x' }
|
||||||
|
} else {
|
||||||
|
if m & S_ISVTX != 0 { 'T' } else { '-' }
|
||||||
|
});
|
||||||
|
|
||||||
|
s
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find the max common root of a list of files
|
// Find the max common root of a list of files
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue