mirror of
https://github.com/sxyazi/yazi.git
synced 2026-07-25 08:41:05 +00:00
..
This commit is contained in:
parent
e2dfa9813a
commit
ebe6714ef6
6 changed files with 149 additions and 193 deletions
|
|
@ -15,42 +15,11 @@ impl Folder {
|
||||||
pub(super) fn new(kind: FolderKind) -> Self { Self { kind } }
|
pub(super) fn new(kind: FolderKind) -> Self { Self { kind } }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Folder {
|
|
||||||
// let short = short_path(file.url(), &self.folder.cwd);
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Widget for Folder {
|
impl Widget for Folder {
|
||||||
fn render(self, area: Rect, buf: &mut Buffer) {
|
fn render(self, area: Rect, buf: &mut Buffer) {
|
||||||
let x = plugin::Folder { kind: self.kind as u8 }.render(area, buf);
|
let x = plugin::Folder { kind: self.kind as u8 }.render(area, buf);
|
||||||
if x.is_err() {
|
if x.is_err() {
|
||||||
info!("{:?}", x);
|
info!("{:?}", x);
|
||||||
}
|
}
|
||||||
|
|
||||||
// let items: Vec<_> = window
|
|
||||||
// .iter()
|
|
||||||
// .enumerate()
|
|
||||||
// .map(|(i, f)| {
|
|
||||||
// if let Some(idx) = active
|
|
||||||
// .finder()
|
|
||||||
// .filter(|&f| hovered && self.is_find && f.has_matched())
|
|
||||||
// .and_then(|finder| finder.matched_idx(f.url()))
|
|
||||||
// {
|
|
||||||
// let len = active.finder().unwrap().matched().len();
|
|
||||||
// spans.push(Span::styled(
|
|
||||||
// format!(
|
|
||||||
// " [{}/{}]",
|
|
||||||
// if idx > 99 { ">99".to_string() } else { (idx + 1).to_string() },
|
|
||||||
// if len > 99 { ">99".to_string() } else { len.to_string() }
|
|
||||||
// ),
|
|
||||||
// // TODO: to be configured by THEME?
|
|
||||||
// Style::new().fg(Color::Rgb(255, 255, 50)).add_modifier(Modifier::ITALIC),
|
|
||||||
// ));
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// ListItem::new(Line::from(spans)).style(style)
|
|
||||||
// })
|
|
||||||
// .collect();
|
|
||||||
|
|
||||||
// List::new(items).render(area, buf);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -91,7 +91,7 @@ impl Finder {
|
||||||
|
|
||||||
/// Explode the name into three parts: head, body, tail.
|
/// Explode the name into three parts: head, body, tail.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn highlighted(&self, name: &OsStr) -> Vec<Range<usize>> {
|
pub fn highlighted(&self, name: &OsStr) -> Option<Vec<Range<usize>>> {
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
let found = self.query.find(name.to_string_lossy().as_bytes()).map(|m| m.range());
|
let found = self.query.find(name.to_string_lossy().as_bytes()).map(|m| m.range());
|
||||||
|
|
||||||
|
|
@ -101,7 +101,7 @@ impl Finder {
|
||||||
self.query.find(name.as_bytes()).map(|m| m.range())
|
self.query.find(name.as_bytes()).map(|m| m.range())
|
||||||
};
|
};
|
||||||
|
|
||||||
found.map(|r| vec![r]).unwrap_or_default()
|
found.map(|r| vec![r])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -109,17 +109,11 @@ impl Finder {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn matched(&self) -> &BTreeMap<Url, u8> { &self.matched }
|
pub fn matched(&self) -> &BTreeMap<Url, u8> { &self.matched }
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn has_matched(&self) -> bool { !self.matched.is_empty() }
|
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn matched_idx(&self, url: &Url) -> Option<u8> {
|
pub fn matched_idx(&self, url: &Url) -> Option<u8> {
|
||||||
if let Some((_, &idx)) = self.matched.iter().find(|(u, _)| *u == url) {
|
if let Some((_, &idx)) = self.matched.iter().find(|(u, _)| *u == url) {
|
||||||
return Some(idx);
|
return Some(idx);
|
||||||
}
|
}
|
||||||
if url.file_name().map(|n| self.matches(n)) == Some(true) {
|
|
||||||
return Some(100);
|
|
||||||
}
|
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -57,6 +57,33 @@ function Folder:markers(area, markers)
|
||||||
return elements
|
return elements
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function Folder:highlighted_name(file)
|
||||||
|
-- Complete prefix when searching across directories
|
||||||
|
local prefix = file:prefix() or ""
|
||||||
|
if prefix ~= "" then
|
||||||
|
prefix = prefix .. "/"
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Range highlighting for filenames
|
||||||
|
local highlights = file:highlights()
|
||||||
|
local spans = ui.highlight_ranges(prefix .. file.name, highlights)
|
||||||
|
|
||||||
|
-- Show symlink target
|
||||||
|
if MANAGER.show_symlink and file.link_to ~= nil then
|
||||||
|
spans[#spans + 1] = ui.Span(" -> " .. tostring(file.link_to)):italic()
|
||||||
|
end
|
||||||
|
|
||||||
|
if highlights == nil or not file:is_hovered() then
|
||||||
|
return spans
|
||||||
|
end
|
||||||
|
|
||||||
|
local found = file:found()
|
||||||
|
if found ~= nil then
|
||||||
|
spans[#spans + 1] = ui.Span(string.format(" [%d/%d]", found[1] + 1, found[2])):fg("#ffff32"):italic()
|
||||||
|
end
|
||||||
|
return spans
|
||||||
|
end
|
||||||
|
|
||||||
function Folder:parent(area)
|
function Folder:parent(area)
|
||||||
local folder = self:by_kind(self.Kind.Parent)
|
local folder = self:by_kind(self.Kind.Parent)
|
||||||
if folder == nil then
|
if folder == nil then
|
||||||
|
|
@ -66,7 +93,7 @@ function Folder:parent(area)
|
||||||
local items = {}
|
local items = {}
|
||||||
for _, f in ipairs(folder.window) do
|
for _, f in ipairs(folder.window) do
|
||||||
local item = ui.ListItem(" " .. f:icon() .. " " .. f.name .. " ")
|
local item = ui.ListItem(" " .. f:icon() .. " " .. f.name .. " ")
|
||||||
if f.hovered then
|
if f:is_hovered() then
|
||||||
item = item:style(THEME.files.hovered)
|
item = item:style(THEME.files.hovered)
|
||||||
else
|
else
|
||||||
item = item:style(f:style())
|
item = item:style(f:style())
|
||||||
|
|
@ -82,18 +109,11 @@ function Folder:current(area)
|
||||||
local markers = {}
|
local markers = {}
|
||||||
local items = {}
|
local items = {}
|
||||||
for i, f in ipairs(self:by_kind(self.Kind.Current).window) do
|
for i, f in ipairs(self:by_kind(self.Kind.Current).window) do
|
||||||
local name = ui.highlight_ranges(f.name, f:highlights())
|
local name = self:highlighted_name(f)
|
||||||
|
|
||||||
-- Show symlink target
|
|
||||||
if MANAGER.show_symlink then
|
|
||||||
if f.link_to ~= nil then
|
|
||||||
name[#name + 1] = ui.Span(" -> " .. tostring(f.link_to)):italic()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Highlight hovered file
|
-- Highlight hovered file
|
||||||
local item = ui.ListItem(ui.Line { ui.Span(" " .. f:icon() .. " "), table.unpack(name) })
|
local item = ui.ListItem(ui.Line { ui.Span(" " .. f:icon() .. " "), table.unpack(name) })
|
||||||
if f.hovered then
|
if f:is_hovered() then
|
||||||
item = item:style(THEME.files.hovered)
|
item = item:style(THEME.files.hovered)
|
||||||
else
|
else
|
||||||
item = item:style(f:style())
|
item = item:style(f:style())
|
||||||
|
|
@ -101,10 +121,10 @@ function Folder:current(area)
|
||||||
items[#items + 1] = item
|
items[#items + 1] = item
|
||||||
|
|
||||||
-- Mark yanked/selected files
|
-- Mark yanked/selected files
|
||||||
local yanked = f:yanked()
|
local yanked = f:is_yanked()
|
||||||
if yanked ~= 0 then
|
if yanked ~= 0 then
|
||||||
markers[#markers + 1] = { i, yanked }
|
markers[#markers + 1] = { i, yanked }
|
||||||
elseif f:selected() then
|
elseif f:is_selected() then
|
||||||
markers[#markers + 1] = { i, 3 }
|
markers[#markers + 1] = { i, 3 }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
@ -121,7 +141,7 @@ function Folder:preview(area)
|
||||||
local items = {}
|
local items = {}
|
||||||
for _, f in ipairs(folder.window) do
|
for _, f in ipairs(folder.window) do
|
||||||
local item = ui.ListItem(" " .. f:icon() .. " " .. f.name .. " ")
|
local item = ui.ListItem(" " .. f:icon() .. " " .. f.name .. " ")
|
||||||
if f.hovered then
|
if f:is_hovered() then
|
||||||
item = item:style(THEME.preview.hovered)
|
item = item:style(THEME.preview.hovered)
|
||||||
else
|
else
|
||||||
item = item:style(f:style())
|
item = item:style(f:style())
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
use core::Ctx;
|
use core::Ctx;
|
||||||
|
|
||||||
use config::{MANAGER, THEME};
|
use config::MANAGER;
|
||||||
use mlua::{AnyUserData, MetaMethod, UserDataFields, UserDataMethods, Value};
|
use mlua::{AnyUserData, MetaMethod, UserDataFields, UserDataMethods, Value};
|
||||||
|
|
||||||
use super::{Range, Url};
|
use super::Url;
|
||||||
use crate::{layout::Style, LUA};
|
use crate::LUA;
|
||||||
|
|
||||||
pub struct Active<'a, 'b> {
|
pub struct Active<'a, 'b> {
|
||||||
scope: &'b mlua::Scope<'a, 'a>,
|
scope: &'b mlua::Scope<'a, 'a>,
|
||||||
|
|
@ -99,80 +99,8 @@ impl<'a, 'b> Active<'a, 'b> {
|
||||||
) -> mlua::Result<AnyUserData<'a>> {
|
) -> mlua::Result<AnyUserData<'a>> {
|
||||||
let ud = self.scope.create_any_userdata_ref(inner)?;
|
let ud = self.scope.create_any_userdata_ref(inner)?;
|
||||||
ud.set_named_user_value("idx", idx)?;
|
ud.set_named_user_value("idx", idx)?;
|
||||||
|
ud.set_named_user_value("folder", self.scope.create_any_userdata_ref(folder)?)?;
|
||||||
ud.set_named_user_value(
|
ud.set_named_user_value("manager", self.scope.create_any_userdata_ref(&self.cx.manager)?)?;
|
||||||
"icon",
|
|
||||||
self.scope.create_function(|_, ()| {
|
|
||||||
Ok(
|
|
||||||
THEME
|
|
||||||
.icons
|
|
||||||
.iter()
|
|
||||||
.find(|&x| x.name.match_path(inner.url(), Some(inner.is_dir())))
|
|
||||||
.map(|x| x.display.to_string()),
|
|
||||||
)
|
|
||||||
})?,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
ud.set_named_user_value(
|
|
||||||
"style",
|
|
||||||
self.scope.create_function(|_, ()| {
|
|
||||||
let mime = self.cx.manager.mimetype.get(inner.url());
|
|
||||||
Ok(
|
|
||||||
THEME
|
|
||||||
.filetypes
|
|
||||||
.iter()
|
|
||||||
.find(|&x| x.matches(inner.url(), mime, inner.is_dir()))
|
|
||||||
.map(|x| Style::from(x.style)),
|
|
||||||
)
|
|
||||||
})?,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
ud.set_named_user_value(
|
|
||||||
"hovered",
|
|
||||||
matches!(&folder.hovered, Some(f) if f.url() == inner.url()),
|
|
||||||
)?;
|
|
||||||
|
|
||||||
ud.set_named_user_value(
|
|
||||||
"yanked",
|
|
||||||
self.scope.create_function(|_, ()| {
|
|
||||||
let (cut, urls) = self.cx.manager.yanked();
|
|
||||||
Ok(if !urls.contains(inner.url()) {
|
|
||||||
0u8
|
|
||||||
} else if *cut {
|
|
||||||
2u8
|
|
||||||
} else {
|
|
||||||
1u8
|
|
||||||
})
|
|
||||||
})?,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
ud.set_named_user_value(
|
|
||||||
"selected",
|
|
||||||
self.scope.create_function(|_, me: AnyUserData| {
|
|
||||||
let is_visual = self.inner.mode.is_visual();
|
|
||||||
let selected = folder.files.is_selected(inner.url());
|
|
||||||
Ok(if !is_visual {
|
|
||||||
selected
|
|
||||||
} else {
|
|
||||||
let idx: usize = me.named_user_value("idx")?;
|
|
||||||
self.inner.mode.pending(folder.offset() + idx, selected)
|
|
||||||
})
|
|
||||||
})?,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
ud.set_named_user_value(
|
|
||||||
"highlights",
|
|
||||||
self.scope.create_function(|_, ()| {
|
|
||||||
let Some(finder) = self.inner.finder() else {
|
|
||||||
return Ok(None);
|
|
||||||
};
|
|
||||||
Ok(
|
|
||||||
inner
|
|
||||||
.name()
|
|
||||||
.map(|n| finder.highlighted(n).into_iter().map(Range::from).collect::<Vec<_>>()),
|
|
||||||
)
|
|
||||||
})?,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
Ok(ud)
|
Ok(ud)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
use mlua::{AnyUserData, Function, IntoLua, MetaMethod, UserData, UserDataFields, UserDataMethods, Value};
|
use config::THEME;
|
||||||
|
use mlua::{AnyUserData, IntoLua, MetaMethod, UserData, UserDataFields, UserDataMethods, UserDataRef};
|
||||||
|
|
||||||
use super::Url;
|
use super::{Range, Url};
|
||||||
use crate::{layout::Style, LUA};
|
use crate::{layout::Style, LUA};
|
||||||
|
|
||||||
pub struct File(core::files::File);
|
pub struct File(core::files::File);
|
||||||
|
|
@ -46,36 +47,115 @@ impl Files {
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
LUA.register_userdata_type::<core::files::File>(|reg| {
|
LUA.register_userdata_type::<core::files::File>(|reg| {
|
||||||
reg.add_field_method_get("name", |_, me| {
|
|
||||||
Ok(me.url().file_name().map(|n| n.to_string_lossy().to_string()))
|
|
||||||
});
|
|
||||||
reg.add_function("icon", |_, me: AnyUserData| {
|
|
||||||
me.named_user_value::<Function>("icon")?.call::<_, String>(())
|
|
||||||
});
|
|
||||||
reg.add_function("style", |_, me: AnyUserData| {
|
|
||||||
me.named_user_value::<Function>("style")?.call::<_, Style>(())
|
|
||||||
});
|
|
||||||
reg.add_field_function_get("hovered", |_, me| me.named_user_value::<bool>("hovered"));
|
|
||||||
reg.add_function("yanked", |_, me: AnyUserData| {
|
|
||||||
me.named_user_value::<Function>("yanked")?.call::<_, u8>(me)
|
|
||||||
});
|
|
||||||
reg.add_function("selected", |_, me: AnyUserData| {
|
|
||||||
me.named_user_value::<Function>("selected")?.call::<_, bool>(me)
|
|
||||||
});
|
|
||||||
reg.add_function("highlights", |_, me: AnyUserData| {
|
|
||||||
me.named_user_value::<Function>("highlights")?.call::<_, Value>(())
|
|
||||||
});
|
|
||||||
|
|
||||||
reg.add_field_method_get("url", |_, me| Ok(Url::from(me.url())));
|
reg.add_field_method_get("url", |_, me| Ok(Url::from(me.url())));
|
||||||
reg.add_field_method_get("length", |_, me| Ok(me.length()));
|
reg.add_field_method_get("length", |_, me| Ok(me.length()));
|
||||||
reg.add_field_method_get("link_to", |_, me| Ok(me.link_to().map(Url::from)));
|
reg.add_field_method_get("link_to", |_, me| Ok(me.link_to().map(Url::from)));
|
||||||
reg.add_field_method_get("is_link", |_, me| Ok(me.is_link()));
|
reg.add_field_method_get("is_link", |_, me| Ok(me.is_link()));
|
||||||
reg.add_field_method_get("is_hidden", |_, me| Ok(me.is_hidden()));
|
reg.add_field_method_get("is_hidden", |_, me| Ok(me.is_hidden()));
|
||||||
|
|
||||||
// Meta
|
reg.add_field_method_get("name", |_, me| {
|
||||||
|
Ok(me.url().file_name().map(|n| n.to_string_lossy().to_string()))
|
||||||
|
});
|
||||||
reg.add_field_method_get("permissions", |_, me| {
|
reg.add_field_method_get("permissions", |_, me| {
|
||||||
Ok(shared::permissions(me.meta().permissions()))
|
Ok(shared::permissions(me.meta().permissions()))
|
||||||
});
|
});
|
||||||
|
|
||||||
|
reg.add_function("prefix", |_, me: AnyUserData| {
|
||||||
|
let folder = me.named_user_value::<UserDataRef<core::manager::Folder>>("folder")?;
|
||||||
|
if !folder.cwd.is_search() {
|
||||||
|
return Ok(None);
|
||||||
|
}
|
||||||
|
|
||||||
|
let file = me.borrow::<core::files::File>()?;
|
||||||
|
let mut p = file.url().strip_prefix(&folder.cwd).unwrap_or(file.url()).components();
|
||||||
|
p.next_back();
|
||||||
|
Ok(Some(p.as_path().to_string_lossy().to_string()))
|
||||||
|
});
|
||||||
|
|
||||||
|
reg.add_method("icon", |_, me, ()| {
|
||||||
|
Ok(
|
||||||
|
THEME
|
||||||
|
.icons
|
||||||
|
.iter()
|
||||||
|
.find(|&x| x.name.match_path(me.url(), Some(me.is_dir())))
|
||||||
|
.map(|x| x.display.to_string()),
|
||||||
|
)
|
||||||
|
});
|
||||||
|
|
||||||
|
reg.add_function("style", |_, me: AnyUserData| {
|
||||||
|
let manager = me.named_user_value::<UserDataRef<core::manager::Manager>>("manager")?;
|
||||||
|
let file = me.borrow::<core::files::File>()?;
|
||||||
|
let mime = manager.mimetype.get(file.url());
|
||||||
|
Ok(
|
||||||
|
THEME
|
||||||
|
.filetypes
|
||||||
|
.iter()
|
||||||
|
.find(|&x| x.matches(file.url(), mime, file.is_dir()))
|
||||||
|
.map(|x| Style::from(x.style)),
|
||||||
|
)
|
||||||
|
});
|
||||||
|
|
||||||
|
reg.add_function("is_hovered", |_, me: AnyUserData| {
|
||||||
|
let folder = me.named_user_value::<UserDataRef<core::manager::Folder>>("folder")?;
|
||||||
|
let file = me.borrow::<core::files::File>()?;
|
||||||
|
Ok(matches!(&folder.hovered, Some(f) if f.url() == file.url()))
|
||||||
|
});
|
||||||
|
|
||||||
|
reg.add_function("is_yanked", |_, me: AnyUserData| {
|
||||||
|
let manager = me.named_user_value::<UserDataRef<core::manager::Manager>>("manager")?;
|
||||||
|
let file = me.borrow::<core::files::File>()?;
|
||||||
|
Ok(if !manager.yanked().1.contains(file.url()) {
|
||||||
|
0u8
|
||||||
|
} else if manager.yanked().0 {
|
||||||
|
2u8
|
||||||
|
} else {
|
||||||
|
1u8
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
reg.add_function("is_selected", |_, me: AnyUserData| {
|
||||||
|
let manager = me.named_user_value::<UserDataRef<core::manager::Manager>>("manager")?;
|
||||||
|
let folder = me.named_user_value::<UserDataRef<core::manager::Folder>>("folder")?;
|
||||||
|
let file = me.borrow::<core::files::File>()?;
|
||||||
|
|
||||||
|
let selected = folder.files.is_selected(file.url());
|
||||||
|
Ok(if !manager.active().mode.is_visual() {
|
||||||
|
selected
|
||||||
|
} else {
|
||||||
|
let idx: usize = me.named_user_value("idx")?;
|
||||||
|
manager.active().mode.pending(folder.offset() + idx, selected)
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
reg.add_function("found", |lua, me: AnyUserData| {
|
||||||
|
let manager = me.named_user_value::<UserDataRef<core::manager::Manager>>("manager")?;
|
||||||
|
let Some(finder) = manager.active().finder() else {
|
||||||
|
return Ok(None);
|
||||||
|
};
|
||||||
|
|
||||||
|
let file = me.borrow::<core::files::File>()?;
|
||||||
|
if let Some(idx) = finder.matched_idx(file.url()) {
|
||||||
|
return Some(
|
||||||
|
lua.create_sequence_from([idx.into_lua(lua)?, finder.matched().len().into_lua(lua)?]),
|
||||||
|
)
|
||||||
|
.transpose();
|
||||||
|
}
|
||||||
|
Ok(None)
|
||||||
|
});
|
||||||
|
|
||||||
|
reg.add_function("highlights", |_, me: AnyUserData| {
|
||||||
|
let manager = me.named_user_value::<UserDataRef<core::manager::Manager>>("manager")?;
|
||||||
|
let Some(finder) = manager.active().finder() else {
|
||||||
|
return Ok(None);
|
||||||
|
};
|
||||||
|
|
||||||
|
let file = me.borrow::<core::files::File>()?;
|
||||||
|
let Some(h) = file.name().and_then(|n| finder.highlighted(n)) else {
|
||||||
|
return Ok(None);
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(Some(h.into_iter().map(Range::from).collect::<Vec<_>>()))
|
||||||
|
});
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
use std::{borrow::Cow, env, ffi::OsStr, fmt::Display, path::{Component, Path, PathBuf}};
|
use std::{borrow::Cow, env, path::{Component, Path, PathBuf}};
|
||||||
|
|
||||||
use tokio::fs;
|
use tokio::fs;
|
||||||
|
|
||||||
|
|
@ -43,39 +43,6 @@ pub fn expand_url(mut u: Url) -> Url {
|
||||||
u
|
u
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ShortPath<'a> {
|
|
||||||
pub prefix: &'a Path,
|
|
||||||
pub name: &'a OsStr,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Display for ShortPath<'_> {
|
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
||||||
if self.prefix == Path::new("") {
|
|
||||||
return write!(f, "{}", self.name.to_string_lossy());
|
|
||||||
}
|
|
||||||
write!(f, "{}/{}", self.prefix.display(), self.name.to_string_lossy())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn short_path<'a>(p: &'a Path, base: &Path) -> ShortPath<'a> {
|
|
||||||
let p = p.strip_prefix(base).unwrap_or(p);
|
|
||||||
let mut parts = p.components();
|
|
||||||
let name = parts.next_back().and_then(|p| match p {
|
|
||||||
Component::Normal(p) => Some(p),
|
|
||||||
_ => None,
|
|
||||||
});
|
|
||||||
ShortPath { prefix: parts.as_path(), name: name.unwrap_or_default() }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn readable_path(p: &Path) -> String {
|
|
||||||
if let Some(home) = env::var_os("HOME") {
|
|
||||||
if let Ok(p) = p.strip_prefix(home) {
|
|
||||||
return format!("~/{}", p.display());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
p.display().to_string()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn unique_path(mut p: Url) -> Url {
|
pub async fn unique_path(mut p: Url) -> Url {
|
||||||
let Some(name) = p.file_name().map(|n| n.to_owned()) else {
|
let Some(name) = p.file_name().map(|n| n.to_owned()) else {
|
||||||
return p;
|
return p;
|
||||||
|
|
@ -91,7 +58,7 @@ pub async fn unique_path(mut p: Url) -> Url {
|
||||||
p
|
p
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parmaters
|
// Parameters
|
||||||
// * `path`: The absolute path(contains no `/./`) to get relative path.
|
// * `path`: The absolute path(contains no `/./`) to get relative path.
|
||||||
// * `root`: The absolute path(contains no `/./`) to be compared.
|
// * `root`: The absolute path(contains no `/./`) to be compared.
|
||||||
//
|
//
|
||||||
|
|
@ -138,12 +105,10 @@ pub fn path_relative_to<'a>(path: &'a Path, root: &Path) -> Cow<'a, Path> {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn optional_bool(s: &str) -> Option<bool> {
|
pub fn optional_bool(s: &str) -> Option<bool> {
|
||||||
if s == "true" {
|
match s {
|
||||||
Some(true)
|
"true" => Some(true),
|
||||||
} else if s == "false" {
|
"false" => Some(false),
|
||||||
Some(false)
|
_ => None,
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue