Skip to content

Commit

Permalink
..
Browse files Browse the repository at this point in the history
  • Loading branch information
sxyazi committed Oct 6, 2023
1 parent 61c633e commit a3d92bf
Show file tree
Hide file tree
Showing 15 changed files with 272 additions and 92 deletions.
2 changes: 1 addition & 1 deletion app/src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ impl App {
fn dispatch_render(&mut self) {
if let Some(term) = &mut self.term {
let _ = term.draw(|f| {
plugin::scope(&self.cx, || {
plugin::scope(&self.cx, |_| {
f.render_widget(Root::new(&self.cx), f.size());
});

Expand Down
24 changes: 1 addition & 23 deletions app/src/manager/folder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,36 +16,14 @@ impl Folder {
}

impl Folder {
// fn highlighted_item<'b>(&'b self, file: &'b File) -> Vec<Span> {
// let short = short_path(file.url(), &self.folder.cwd);
//
// let v = self.is_find.then_some(()).and_then(|_| {
// let finder = self.cx.manager.active().finder()?;
// let (head, body, tail) = finder.explode(short.name)?;
//
// // TODO: to be configured by THEME?
// let style = Style::new().fg(Color::Rgb(255, 255,
// 50)).add_modifier(Modifier::ITALIC); Some(vec![
// Span::raw(short.prefix.join(head.as_ref()).display().to_string()),
// Span::styled(body, style),
// Span::raw(tail),
// ])
// });
//
// v.unwrap_or_else(|| vec![Span::raw(format!("{}", short))])
// }
}

impl Widget for Folder {
fn render(self, area: Rect, buf: &mut Buffer) {
let x = plugin::Folder { kind: self.kind as u8 }.render(area);
let x = plugin::Folder { kind: self.kind as u8 }.render(area, buf);
if x.is_err() {
info!("{:?}", x);
return;
}

for x in x.unwrap() {
x.render(buf);
}

// let items: Vec<_> = window
Expand Down
6 changes: 1 addition & 5 deletions app/src/status/layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,10 @@ pub(crate) struct Layout;

impl Widget for Layout {
fn render(self, area: Rect, buf: &mut Buffer) {
let x = plugin::Status::render(area);
let x = plugin::Status.render(area, buf);
if x.is_err() {
info!("{:?}", x);
return;
}

for x in x.unwrap() {
x.render(buf);
}
}
}
20 changes: 12 additions & 8 deletions core/src/manager/finder.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::{collections::BTreeMap, ffi::OsStr};
use std::{collections::BTreeMap, ffi::OsStr, ops::Range};

use anyhow::Result;
use regex::bytes::{Regex, RegexBuilder};
Expand Down Expand Up @@ -91,13 +91,17 @@ impl Finder {

/// Explode the name into three parts: head, body, tail.
#[inline]
pub fn explode(&self, name: &[u8]) -> Option<(String, String, String)> {
let range = self.query.find(name).map(|m| m.range())?;
Some((
String::from_utf8_lossy(&name[..range.start]).to_string(),
String::from_utf8_lossy(&name[range.start..range.end]).to_string(),
String::from_utf8_lossy(&name[range.end..]).to_string(),
))
pub fn highlighted(&self, name: &OsStr) -> Vec<Range<usize>> {
#[cfg(target_os = "windows")]
let found = self.query.find(name.to_string_lossy().as_bytes());

#[cfg(not(target_os = "windows"))]
let found = {
use std::os::unix::ffi::OsStrExt;
self.query.find(name.as_bytes())
};

found.map(|m| vec![m.range()]).unwrap_or_default()
}
}

Expand Down
70 changes: 31 additions & 39 deletions plugin/preset/components/folder.lua
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,6 @@ function Folder:by_kind(kind)
end
end

function Folder:window(kind) return (self:by_kind(kind) or {}).window end

function Folder:hovered(kind) return (self:by_kind(kind) or {}).hovered end

function Folder:markers(area, markers)
if #markers == 0 then
return {}
Expand Down Expand Up @@ -51,79 +47,75 @@ function Folder:markers(area, markers)
end

function Folder:parent(area)
local window = self:window(self.Kind.Parent)
if window == nil then
local folder = self:by_kind(self.Kind.Parent)
if folder == nil then
return {}
end

local hovered = (self:hovered(self.Kind.Parent) or {}).url
local lines = {}
for _, f in ipairs(window) do
local line = ui.Line { ui.Span(" " .. f:icon() .. " " .. f.name .. " ") }
if f.url == hovered then
line = line:style(THEME.files.hovered)
local items = {}
for _, f in ipairs(folder.window) do
local item = ui.ListItem(" " .. f:icon() .. " " .. f.name .. " ")
if f.hovered then
item = item:style(THEME.files.hovered)
else
line = line:style(f:style())
item = item:style(f:style())
end

lines[#lines + 1] = line
items[#items + 1] = item
end

return { ui.Paragraph(area, lines) }
return { ui.List(area, items) }
end

function Folder:current(area)
local hovered = (self:hovered(self.Kind.Current) or {}).url
local markers = {}
local lines = {}
for i, f in ipairs(self:window(self.Kind.Current)) do
local name = f.name
local items = {}
for i, f in ipairs(self:by_kind(self.Kind.Current).window) do
local name = ui.highlight_ranges(f.name, f:highlights())

-- Show symlink target
if MANAGER.show_symlink then
local link_to = f.link_to
if link_to ~= nil then
name = name .. " -> " .. tostring(link_to)
if f.link_to ~= nil then
name[#name + 1] = ui.Span(" -> " .. tostring(f.link_to)):italic()
end
end

-- Highlight hovered file
local line = ui.Line { ui.Span(" " .. f:icon() .. " " .. name .. " ") }
if f.url == hovered then
line = line:style(THEME.files.hovered)
local item = ui.ListItem(ui.Line { ui.Span(" " .. f:icon() .. " "), table.unpack(name) })
if f.hovered then
item = item:style(THEME.files.hovered)
else
line = line:style(f:style())
item = item:style(f:style())
end
lines[#lines + 1] = line
items[#items + 1] = item

-- Mark selected/yanked files
if f:selected() then
markers[#markers + 1] = { i, 1 }
end
end

return { ui.Paragraph(area, lines), table.unpack(self:markers(area, markers)) }
return { ui.List(area, items), table.unpack(self:markers(area, markers)) }
end

function Folder:preview(area)
local window = self:window(self.Kind.Preview)
if window == nil then
local folder = self:by_kind(self.Kind.Preview)
if folder == nil then
return {}
end

local hovered = (self:hovered(self.Kind.Preview) or {}).url
local lines = {}
for _, f in ipairs(window) do
local line = ui.Line { ui.Span(" " .. f:icon() .. " " .. f.name .. " ") }
if f.url == hovered then
line = line:style(THEME.preview.hovered)
local items = {}
for _, f in ipairs(folder.window) do
local item = ui.ListItem(" " .. f:icon() .. " " .. f.name .. " ")
if f.hovered then
item = item:style(THEME.preview.hovered)
else
line = line:style(f:style())
item = item:style(f:style())
end
lines[#lines + 1] = line
items[#items + 1] = item
end

return { ui.Paragraph(area, lines) }
return { ui.List(area, items) }
end

function Folder:render(area, args)
Expand Down
21 changes: 21 additions & 0 deletions plugin/preset/ui.lua
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,24 @@ ui = {
VERTICAL = true,
},
}

function ui.highlight_ranges(s, ranges)
if ranges == nil or #ranges == 0 then
return { ui.Span(s) }
end

local spans = {}
local last = 0
for _, r in ipairs(ranges) do
if r[1] > last then
spans[#spans + 1] = ui.Span(s:sub(last + 1, r[1]))
end
-- TODO: use a customable style
spans[#spans + 1] = ui.Span(s:sub(r[1] + 1, r[2])):fg("yellow"):italic()
last = r[2]
end
if last < #s then
spans[#spans + 1] = ui.Span(s:sub(last + 1))
end
return spans
end
20 changes: 19 additions & 1 deletion plugin/src/bindings/shared.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,23 @@
use mlua::{MetaMethod, UserData, UserDataRef};
use mlua::{IntoLua, MetaMethod, UserData, UserDataRef};

// --- Range
pub struct Range<T>(std::ops::Range<T>);

impl<T> From<std::ops::Range<T>> for Range<T> {
fn from(value: std::ops::Range<T>) -> Self { Self(value) }
}

impl<'lua, T> IntoLua<'lua> for Range<T>
where
T: IntoLua<'lua>,
{
fn into_lua(self, lua: &'lua mlua::Lua) -> mlua::Result<mlua::Value> {
let tbl = lua.create_sequence_from([self.0.start, self.0.end])?;
tbl.into_lua(lua)
}
}

// --- Url
pub struct Url(shared::Url);

impl From<&shared::Url> for Url {
Expand Down
25 changes: 24 additions & 1 deletion plugin/src/bindings/tab.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use core::Ctx;
use config::{MANAGER, THEME};
use mlua::{AnyUserData, Function, IntoLua, MetaMethod, UserData, UserDataFields, UserDataMethods, Value};

use super::Url;
use super::{Range, Url};
use crate::{layout::Style, LUA};

struct File(core::files::File);
Expand Down Expand Up @@ -89,9 +89,13 @@ impl<'a, 'b> Tab<'a, 'b> {
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("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("length", |_, me| Ok(me.length()));
Expand Down Expand Up @@ -203,6 +207,11 @@ impl<'a, 'b> Tab<'a, 'b> {
})?,
)?;

ud.set_named_user_value(
"hovered",
matches!(&folder.hovered, Some(f) if f.url() == inner.url()),
)?;

ud.set_named_user_value(
"selected",
self.scope.create_function(|_, me: AnyUserData| {
Expand All @@ -217,6 +226,20 @@ impl<'a, 'b> Tab<'a, 'b> {
})?,
)?;

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)
}

Expand Down
42 changes: 34 additions & 8 deletions plugin/src/components.rs
Original file line number Diff line number Diff line change
@@ -1,30 +1,56 @@
use mlua::{Result, Table, TableExt};
use ratatui::layout;
use mlua::{AnyUserData, Table, TableExt};

use crate::{layout::{Paragraph, Rect}, GLOBALS, LUA};
use crate::{layout::{List, Paragraph, Rect}, GLOBALS, LUA};

#[inline]
fn layout(values: Vec<AnyUserData>, buf: &mut ratatui::prelude::Buffer) -> mlua::Result<()> {
for value in values {
if let Ok(c) = value.take::<Paragraph>() {
c.render(buf)
} else if let Ok(c) = value.take::<List>() {
c.render(buf)
}
}
Ok(())
}

// --- Status
pub struct Status;

impl Status {
pub fn render(area: layout::Rect) -> Result<Vec<Paragraph>> {
pub fn render(
self,
area: ratatui::layout::Rect,
buf: &mut ratatui::prelude::Buffer,
) -> mlua::Result<()> {
let comp: Table = GLOBALS.get("Status")?;
comp.call_method::<_, _>("render", Rect(area))
let values: Vec<AnyUserData> = comp.call_method::<_, _>("render", Rect(area))?;

layout(values, buf)
}
}

// --- Folder
pub struct Folder {
pub kind: u8,
}

impl Folder {
fn args(&self) -> Result<Table> {
fn args(&self) -> mlua::Result<Table> {
let tbl = LUA.create_table()?;
tbl.set("kind", self.kind)?;
Ok(tbl)
}

pub fn render(self, area: layout::Rect) -> Result<Vec<Paragraph>> {
pub fn render(
self,
area: ratatui::layout::Rect,
buf: &mut ratatui::prelude::Buffer,
) -> mlua::Result<()> {
let comp: Table = GLOBALS.get("Folder")?;
comp.call_method::<_, _>("render", (Rect(area), self.args()?))
let values: Vec<AnyUserData> =
comp.call_method::<_, _>("render", (Rect(area), self.args()?))?;

layout(values, buf)
}
}
Loading

0 comments on commit a3d92bf

Please sign in to comment.