feat: better file hover state (#269)

This commit is contained in:
三咲雅 · Misaki Masa 2023-10-14 23:12:32 +08:00 committed by GitHub
parent 0b0901823d
commit b840dcccd5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 204 additions and 114 deletions

View File

@ -130,12 +130,10 @@ impl App {
manager.refresh(); manager.refresh();
} }
Event::Files(op) => { Event::Files(op) => {
let calc = matches!(op, FilesOp::Full(..) | FilesOp::Part(..)); let calc = !matches!(op, FilesOp::Size(..) | FilesOp::IOErr(_));
let b = match op { let b = match op {
FilesOp::Full(..) => manager.update_read(op),
FilesOp::Part(..) => manager.update_read(op),
FilesOp::Size(..) => manager.update_read(op),
FilesOp::IOErr(..) => manager.update_ioerr(op), FilesOp::IOErr(..) => manager.update_ioerr(op),
_ => manager.update_read(op),
}; };
if b { if b {
emit!(Render); emit!(Render);
@ -156,8 +154,8 @@ impl App {
emit!(Peek); emit!(Peek);
} }
} }
Event::Hover(file) => { Event::Hover(url) => {
if manager.update_hover(file) { if manager.current_mut().repos(url) {
emit!(Render); emit!(Render);
} }
emit!(Peek); emit!(Peek);

View File

@ -6,7 +6,7 @@ use crossterm::event::KeyEvent;
use shared::{InputError, RoCell, Url}; use shared::{InputError, RoCell, Url};
use tokio::sync::{mpsc::{self, UnboundedSender}, oneshot}; use tokio::sync::{mpsc::{self, UnboundedSender}, oneshot};
use super::{files::{File, FilesOp}, input::InputOpt, select::SelectOpt}; use super::{files::FilesOp, input::InputOpt, select::SelectOpt};
use crate::{manager::PreviewLock, tasks::TasksProgress}; use crate::{manager::PreviewLock, tasks::TasksProgress};
static TX: RoCell<UnboundedSender<Event>> = RoCell::new(); static TX: RoCell<UnboundedSender<Event>> = RoCell::new();
@ -26,7 +26,7 @@ pub enum Event {
Files(FilesOp), Files(FilesOp),
Pages(usize), Pages(usize),
Mimetype(BTreeMap<Url, String>), Mimetype(BTreeMap<Url, String>),
Hover(Option<File>), Hover(Option<Url>),
Peek(Option<(usize, Url)>), Peek(Option<(usize, Url)>),
Preview(PreviewLock), Preview(PreviewLock),

View File

@ -1,4 +1,4 @@
use std::{borrow::Cow, ffi::OsStr, fs::Metadata}; use std::{borrow::Cow, collections::BTreeMap, ffi::OsStr, fs::Metadata};
use anyhow::Result; use anyhow::Result;
use shared::Url; use shared::Url;
@ -34,6 +34,13 @@ impl File {
let is_hidden = url.file_name().map(|s| s.to_string_lossy().starts_with('.')).unwrap_or(false); let is_hidden = url.file_name().map(|s| s.to_string_lossy().starts_with('.')).unwrap_or(false);
Self { url, meta, length, link_to, is_link, is_hidden } Self { url, meta, length, link_to, is_link, is_hidden }
} }
#[inline]
pub fn into_map(self) -> BTreeMap<Url, File> {
let mut map = BTreeMap::new();
map.insert(self.url.clone(), self);
map
}
} }
impl File { impl File {

View File

@ -173,6 +173,84 @@ impl Files {
} }
true true
} }
pub fn update_creating(&mut self, mut todo: BTreeMap<Url, File>) -> bool {
if !self.show_hidden {
todo.retain(|_, f| !f.is_hidden);
}
let b = self.update_replacing(&mut todo);
if todo.is_empty() {
return b;
}
self.items.extend(todo.into_values());
self.sorter.sort(&mut self.items, &self.sizes);
self.version += 1;
true
}
pub fn update_deleting(&mut self, mut todo: BTreeSet<Url>) -> bool {
let mut removed = Vec::with_capacity(todo.len());
macro_rules! go {
($name:expr) => {
removed.clear();
for i in 0..$name.len() {
if todo.remove(&$name[i].url) {
removed.push(i);
if todo.is_empty() {
break;
}
}
}
for i in (0..removed.len()).rev() {
$name.remove(removed[i]);
}
};
}
let mut b = false;
if !todo.is_empty() {
go!(self.items);
b |= !removed.is_empty();
}
if !todo.is_empty() {
go!(self.hidden);
b |= !removed.is_empty();
}
b
}
pub fn update_replacing(&mut self, todo: &mut BTreeMap<Url, File>) -> bool {
if todo.is_empty() {
return false;
}
macro_rules! go {
($name:expr) => {
for i in 0..$name.len() {
if let Some(f) = todo.remove(&$name[i].url) {
$name[i] = f;
if todo.is_empty() {
self.version += 1;
return true;
}
}
}
};
}
let old = todo.len();
go!(self.items);
go!(self.hidden);
if old != todo.len() {
self.version += 1;
return true;
}
false
}
} }
impl Files { impl Files {

View File

@ -1,4 +1,4 @@
use std::{collections::BTreeMap, sync::atomic::{AtomicU64, Ordering}}; use std::{collections::{BTreeMap, BTreeSet}, sync::atomic::{AtomicU64, Ordering}};
use shared::Url; use shared::Url;
@ -13,6 +13,10 @@ pub enum FilesOp {
Part(Url, u64, Vec<File>), Part(Url, u64, Vec<File>),
Size(Url, BTreeMap<Url, u64>), Size(Url, BTreeMap<Url, u64>),
IOErr(Url), IOErr(Url),
Creating(Url, BTreeMap<Url, File>),
Deleting(Url, BTreeSet<Url>),
Replacing(Url, BTreeMap<Url, File>),
} }
impl FilesOp { impl FilesOp {
@ -23,6 +27,10 @@ impl FilesOp {
Self::Part(url, ..) => url, Self::Part(url, ..) => url,
Self::Size(url, _) => url, Self::Size(url, _) => url,
Self::IOErr(url) => url, Self::IOErr(url) => url,
Self::Creating(url, _) => url,
Self::Deleting(url, _) => url,
Self::Replacing(url, _) => url,
} }
} }

View File

@ -9,11 +9,10 @@ pub struct Folder {
pub cwd: Url, pub cwd: Url,
pub files: Files, pub files: Files,
offset: usize, pub offset: usize,
cursor: usize, pub cursor: usize,
pub page: usize, pub page: usize,
pub hovered: Option<File>,
} }
impl From<Url> for Folder { impl From<Url> for Folder {
@ -30,19 +29,23 @@ impl Folder {
FilesOp::Full(_, items) => self.files.update_full(items), FilesOp::Full(_, items) => self.files.update_full(items),
FilesOp::Part(_, ticket, items) => self.files.update_part(ticket, items), FilesOp::Part(_, ticket, items) => self.files.update_part(ticket, items),
FilesOp::Size(_, items) => self.files.update_size(items), FilesOp::Size(_, items) => self.files.update_size(items),
FilesOp::Creating(_, items) => self.files.update_creating(items),
FilesOp::Deleting(_, items) => self.files.update_deleting(items),
FilesOp::Replacing(_, mut items) => self.files.update_replacing(&mut items),
_ => unreachable!(), _ => unreachable!(),
}; };
if !b { if !b {
return false; return false;
} }
let max = self.files.len().saturating_sub(1); let old = self.page;
self.offset = self.offset.min(max); self.prev(Default::default());
self.cursor = self.cursor.min(max);
self.set_page(true); if self.page == old {
emit!(Pages(self.page)); // Force update
}
self.hover_repos();
self.hovered = self.files.duplicate(self.cursor);
true true
} }
@ -59,35 +62,34 @@ impl Folder {
} }
pub fn next(&mut self, step: Step) -> bool { pub fn next(&mut self, step: Step) -> bool {
let old = (self.cursor, self.offset);
let len = self.files.len(); let len = self.files.len();
if len == 0 {
return false;
}
let old = self.cursor;
let limit = MANAGER.layout.folder_height(); let limit = MANAGER.layout.folder_height();
self.cursor = step.add(self.cursor, || limit).min(len - 1); self.cursor = step.add(self.cursor, || limit).min(len.saturating_sub(1));
self.hovered = self.files.duplicate(self.cursor); self.offset = if self.cursor >= (self.offset + limit).min(len).saturating_sub(5) {
len.saturating_sub(limit).min(self.offset + self.cursor - old.0)
} else {
self.offset.min(len.saturating_sub(1))
};
self.set_page(false); self.set_page(false);
old != (self.cursor, self.offset)
if self.cursor >= (self.offset + limit).min(len).saturating_sub(5) {
self.offset = len.saturating_sub(limit).min(self.offset + self.cursor - old);
}
old != self.cursor
} }
pub fn prev(&mut self, step: Step) -> bool { pub fn prev(&mut self, step: Step) -> bool {
let old = self.cursor; let old = (self.cursor, self.offset);
self.cursor = step.add(self.cursor, || MANAGER.layout.folder_height()); let max = self.files.len().saturating_sub(1);
self.hovered = self.files.duplicate(self.cursor);
self.cursor = step.add(self.cursor, || MANAGER.layout.folder_height()).min(max);
self.offset = if self.cursor < self.offset + 5 {
self.offset.saturating_sub(old.0 - self.cursor)
} else {
self.offset.min(max)
};
self.set_page(false); self.set_page(false);
old != (self.cursor, self.offset)
if self.cursor < self.offset + 5 {
self.offset = self.offset.saturating_sub(old - self.cursor);
}
old != self.cursor
} }
pub fn hover(&mut self, url: &Url) -> bool { pub fn hover(&mut self, url: &Url) -> bool {
@ -100,26 +102,14 @@ impl Folder {
} }
#[inline] #[inline]
pub fn hover_repos(&mut self) -> bool { pub fn repos(&mut self, url: Option<impl AsRef<Url>>) -> bool {
self.hover(&self.hovered.as_ref().map(|h| h.url_owned()).unwrap_or_default()) if let Some(u) = url { self.hover(u.as_ref()) } else { self.prev(Default::default()) }
}
pub fn hover_force(&mut self, file: File) -> bool {
if self.hover(file.url()) {
return true;
}
self.hovered = Some(file);
false
} }
} }
impl Folder { impl Folder {
#[inline] #[inline]
pub fn offset(&self) -> usize { self.offset } pub fn hovered(&self) -> Option<&File> { self.files.get(self.cursor) }
#[inline]
pub fn cursor(&self) -> usize { self.cursor }
pub fn paginate(&self) -> &[File] { pub fn paginate(&self) -> &[File] {
let len = self.files.len(); let len = self.files.len();

View File

@ -42,10 +42,9 @@ impl Manager {
let mut to_watch = BTreeSet::new(); let mut to_watch = BTreeSet::new();
for tab in self.tabs.iter() { for tab in self.tabs.iter() {
to_watch.insert(&tab.current.cwd); to_watch.insert(&tab.current.cwd);
if let Some(ref h) = tab.current.hovered { match tab.current.hovered() {
if h.is_dir() { Some(h) if h.is_dir() => _ = to_watch.insert(h.url()),
to_watch.insert(h.url()); _ => {}
}
} }
if let Some(ref p) = tab.parent { if let Some(ref p) = tab.parent {
to_watch.insert(&p.cwd); to_watch.insert(&p.cwd);
@ -65,7 +64,7 @@ impl Manager {
} }
if hovered.is_dir() { if hovered.is_dir() {
let position = self.active().history(url).map(|f| (f.offset(), f.files.len())); let position = self.active().history(url).map(|f| (f.offset, f.files.len()));
self.active_mut().preview.folder(url, position, sequent); self.active_mut().preview.folder(url, position, sequent);
return false; return false;
} }
@ -200,9 +199,11 @@ impl Manager {
fs::File::create(&path).await?; fs::File::create(&path).await?;
} }
let child = path.components().take(cwd.components().count() + 1).collect::<PathBuf>(); let child =
if let Ok(file) = File::from(Url::from(child)).await { Url::from(path.components().take(cwd.components().count() + 1).collect::<PathBuf>());
emit!(Hover(file)); if let Ok(f) = File::from(child.clone()).await {
emit!(Files(FilesOp::Creating(cwd, f.into_map())));
emit!(Hover(child));
emit!(Refresh); emit!(Refresh);
} }
Ok::<(), Error>(()) Ok::<(), Error>(())
@ -219,6 +220,21 @@ impl Manager {
return false; return false;
}; };
async fn rename_and_hover(old: Url, new: Url) -> Result<()> {
fs::rename(&old, &new).await?;
if old.parent() != new.parent() {
return Ok(());
}
let parent = old.parent_url().unwrap();
emit!(Files(FilesOp::Deleting(parent, BTreeSet::from([old]))));
let file = File::from(new.clone()).await?;
emit!(Files(FilesOp::Creating(file.parent().unwrap(), file.into_map())));
emit!(Hover(new));
Ok(())
}
tokio::spawn(async move { tokio::spawn(async move {
let mut result = emit!(Input( let mut result = emit!(Input(
InputOpt::hovered("Rename:").with_value(hovered.file_name().unwrap().to_string_lossy()) InputOpt::hovered("Rename:").with_value(hovered.file_name().unwrap().to_string_lossy())
@ -230,14 +246,14 @@ impl Manager {
let new = hovered.parent().unwrap().join(name); let new = hovered.parent().unwrap().join(name);
if force || fs::symlink_metadata(&new).await.is_err() { if force || fs::symlink_metadata(&new).await.is_err() {
fs::rename(&hovered, new).await.ok(); rename_and_hover(hovered, Url::from(new)).await.ok();
return; return;
} }
let mut result = emit!(Input(InputOpt::hovered("Overwrite an existing file? (y/N)"))); let mut result = emit!(Input(InputOpt::hovered("Overwrite an existing file? (y/N)")));
if let Some(Ok(choice)) = result.recv().await { if let Some(Ok(choice)) = result.recv().await {
if choice == "y" || choice == "Y" { if choice == "y" || choice == "Y" {
fs::rename(&hovered, new).await.ok(); rename_and_hover(hovered, Url::from(new)).await.ok();
} }
}; };
}); });
@ -404,11 +420,6 @@ impl Manager {
self.mimetype.extend(mimes); self.mimetype.extend(mimes);
true true
} }
#[inline]
pub fn update_hover(&mut self, file: Option<File>) -> bool {
file.map(|f| self.current_mut().hover_force(f)) == Some(true)
}
} }
impl Manager { impl Manager {
@ -437,7 +448,7 @@ impl Manager {
pub fn parent(&self) -> Option<&Folder> { self.tabs.active().parent.as_ref() } pub fn parent(&self) -> Option<&Folder> { self.tabs.active().parent.as_ref() }
#[inline] #[inline]
pub fn hovered(&self) -> Option<&File> { self.tabs.active().current.hovered.as_ref() } pub fn hovered(&self) -> Option<&File> { self.tabs.active().current.hovered() }
#[inline] #[inline]
pub fn selected(&self) -> Vec<&File> { self.tabs.active().selected() } pub fn selected(&self) -> Vec<&File> { self.tabs.active().selected() }

View File

@ -77,7 +77,7 @@ impl Tab {
// Visual selection // Visual selection
if let Some((start, items)) = self.mode.visual_mut() { if let Some((start, items)) = self.mode.visual_mut() {
let after = self.current.cursor(); let after = self.current.cursor;
items.clear(); items.clear();
for i in start.min(after)..=after.max(start) { for i in start.min(after)..=after.max(start) {
@ -97,14 +97,15 @@ impl Tab {
let mut hovered = None; let mut hovered = None;
if !file.is_dir() { if !file.is_dir() {
hovered = Some(file); hovered = Some(file.url_owned());
target = target.parent_url().unwrap(); target = target.parent_url().unwrap();
emit!(Files(FilesOp::Creating(target.clone(), file.into_map())));
} }
// Already in target // Already in target
if self.current.cwd == target { if self.current.cwd == target {
if hovered.map(|h| self.current.hover_force(h)) == Some(true) { if let Some(h) = hovered {
emit!(Hover); emit!(Hover(h));
} }
return false; return false;
} }
@ -128,7 +129,7 @@ impl Tab {
// Hover the file // Hover the file
if let Some(h) = hovered { if let Some(h) = hovered {
self.current.hover_force(h); emit!(Hover(h));
} }
// Backstack // Backstack
@ -153,15 +154,12 @@ impl Tab {
} }
pub fn enter(&mut self) -> bool { pub fn enter(&mut self) -> bool {
let Some(hovered) = self.current.hovered.clone() else { let Some(hovered) = self.current.hovered().filter(|h| h.is_dir()).map(|h| h.url_owned()) else {
return false; return false;
}; };
if !hovered.is_dir() {
return false;
}
// Current // Current
let rep = self.history_new(hovered.url()); let rep = self.history_new(&hovered);
let rep = mem::replace(&mut self.current, rep); let rep = mem::replace(&mut self.current, rep);
if rep.cwd.is_regular() { if rep.cwd.is_regular() {
self.history.insert(rep.cwd.clone(), rep); self.history.insert(rep.cwd.clone(), rep);
@ -171,10 +169,10 @@ impl Tab {
if let Some(rep) = self.parent.take() { if let Some(rep) = self.parent.take() {
self.history.insert(rep.cwd.clone(), rep); self.history.insert(rep.cwd.clone(), rep);
} }
self.parent = Some(self.history_new(&hovered.parent().unwrap())); self.parent = Some(self.history_new(&hovered.parent_url().unwrap()));
// Backstack // Backstack
self.backstack.push(hovered.url_owned()); self.backstack.push(hovered);
emit!(Refresh); emit!(Refresh);
true true
@ -183,8 +181,7 @@ impl Tab {
pub fn leave(&mut self) -> bool { pub fn leave(&mut self) -> bool {
let current = self let current = self
.current .current
.hovered .hovered()
.as_ref()
.and_then(|h| h.parent()) .and_then(|h| h.parent())
.filter(|p| *p != self.current.cwd) .filter(|p| *p != self.current.cwd)
.or_else(|| self.current.cwd.parent_url()); .or_else(|| self.current.cwd.parent_url());
@ -230,8 +227,8 @@ impl Tab {
} }
pub fn select(&mut self, state: Option<bool>) -> bool { pub fn select(&mut self, state: Option<bool>) -> bool {
if let Some(ref hovered) = self.current.hovered { if let Some(u) = self.current.hovered().map(|h| h.url_owned()) {
return self.current.files.select(hovered.url(), state); return self.current.files.select(&u, state);
} }
false false
} }
@ -239,7 +236,7 @@ impl Tab {
pub fn select_all(&mut self, state: Option<bool>) -> bool { self.current.files.select_all(state) } pub fn select_all(&mut self, state: Option<bool>) -> bool { self.current.files.select_all(state) }
pub fn visual_mode(&mut self, unset: bool) -> bool { pub fn visual_mode(&mut self, unset: bool) -> bool {
let idx = self.current.cursor(); let idx = self.current.cursor;
if unset { if unset {
self.mode = Mode::Unset(idx, BTreeSet::from([idx])); self.mode = Mode::Unset(idx, BTreeSet::from([idx]));
@ -276,9 +273,9 @@ impl Tab {
}; };
let step = if prev { let step = if prev {
finder.prev(&self.current.files, self.current.cursor(), true) finder.prev(&self.current.files, self.current.cursor, true)
} else { } else {
finder.next(&self.current.files, self.current.cursor(), true) finder.next(&self.current.files, self.current.cursor, true)
}; };
if let Some(step) = step { if let Some(step) = step {
@ -318,9 +315,9 @@ impl Tab {
let b = finder.catchup(&self.current.files); let b = finder.catchup(&self.current.files);
let step = if prev { let step = if prev {
finder.prev(&self.current.files, self.current.cursor(), false) finder.prev(&self.current.files, self.current.cursor, false)
} else { } else {
finder.next(&self.current.files, self.current.cursor(), false) finder.next(&self.current.files, self.current.cursor, false)
}; };
b | step.is_some_and(|s| self.arrow(s.into())) b | step.is_some_and(|s| self.arrow(s.into()))
@ -427,7 +424,7 @@ impl Tab {
} }
pub fn update_peek(&mut self, max: usize, url: Url) -> bool { pub fn update_peek(&mut self, max: usize, url: Url) -> bool {
let Some(ref hovered) = self.current.hovered else { let Some(hovered) = self.current.hovered() else {
return false; return false;
}; };
@ -439,7 +436,7 @@ impl Tab {
} }
pub fn update_preview(&mut self, lock: PreviewLock) -> bool { pub fn update_preview(&mut self, lock: PreviewLock) -> bool {
let Some(hovered) = self.current.hovered.as_ref().map(|h| h.url()) else { let Some(hovered) = self.current.hovered().map(|h| h.url()) else {
return self.preview_reset(); return self.preview_reset();
}; };
@ -463,7 +460,7 @@ impl Tab {
let selected = self.current.files.selected(&pending, self.mode.is_unset()); let selected = self.current.files.selected(&pending, self.mode.is_unset());
if selected.is_empty() { if selected.is_empty() {
self.current.hovered.as_ref().map(|h| vec![h]).unwrap_or_default() self.current.hovered().map(|h| vec![h]).unwrap_or_default()
} else { } else {
selected selected
} }
@ -513,26 +510,27 @@ impl Tab {
} }
self.show_hidden = state; self.show_hidden = state;
self.apply_files_attrs(false) if self.apply_files_attrs(false) {
emit!(Peek);
return true;
}
false
} }
pub fn apply_files_attrs(&mut self, only_hovered: bool) -> bool { pub fn apply_files_attrs(&mut self, just_preview: bool) -> bool {
let mut b = false; let mut b = false;
if let Some(f) = self if let Some(f) =
.current self.current.hovered().filter(|h| h.is_dir()).and_then(|h| self.history.get_mut(h.url()))
.hovered
.as_ref()
.filter(|h| h.is_dir())
.and_then(|h| self.history.get_mut(h.url()))
{ {
b |= f.files.set_show_hidden(self.show_hidden); b |= f.files.set_show_hidden(self.show_hidden);
b |= f.files.set_sorter(self.sorter); b |= f.files.set_sorter(self.sorter);
} }
if only_hovered { if just_preview {
return b; return b;
} }
let hovered = self.current.hovered().map(|h| h.url_owned());
b |= self.current.files.set_show_hidden(self.show_hidden); b |= self.current.files.set_show_hidden(self.show_hidden);
b |= self.current.files.set_sorter(self.sorter); b |= self.current.files.set_sorter(self.sorter);
@ -541,7 +539,7 @@ impl Tab {
b |= parent.files.set_sorter(self.sorter); b |= parent.files.set_sorter(self.sorter);
} }
self.current.hover_repos(); self.current.repos(hovered);
b b
} }
} }

View File

@ -1 +1 @@
{"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","metatable","natsort","backstack","luajit","Succ","Succ","cand"],"language":"en","version":"0.2","flagWords":[]} {"version":"0.2","language":"en","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","metatable","natsort","backstack","luajit","Succ","Succ","cand","fileencoding","foldmethod","lightgreen","darkgray","lightred","lightyellow","lightcyan"]}

View File

@ -26,8 +26,8 @@ impl<'a, 'b> Active<'a, 'b> {
LUA.register_userdata_type::<core::manager::Folder>(|reg| { LUA.register_userdata_type::<core::manager::Folder>(|reg| {
reg.add_field_method_get("cwd", |_, me| Ok(Url::from(&me.cwd))); reg.add_field_method_get("cwd", |_, me| Ok(Url::from(&me.cwd)));
reg.add_field_method_get("offset", |_, me| Ok(me.offset())); reg.add_field_method_get("offset", |_, me| Ok(me.offset));
reg.add_field_method_get("cursor", |_, me| Ok(me.cursor())); reg.add_field_method_get("cursor", |_, me| Ok(me.cursor));
reg.add_field_function_get("window", |_, me| me.named_user_value::<Value>("window")); reg.add_field_function_get("window", |_, me| me.named_user_value::<Value>("window"));
reg.add_field_function_get("files", |_, me| me.named_user_value::<AnyUserData>("files")); reg.add_field_function_get("files", |_, me| me.named_user_value::<AnyUserData>("files"));
@ -63,7 +63,7 @@ impl<'a, 'b> Active<'a, 'b> {
inner: &'a core::manager::Folder, inner: &'a core::manager::Folder,
window: Option<(usize, usize)>, window: Option<(usize, usize)>,
) -> mlua::Result<AnyUserData<'a>> { ) -> mlua::Result<AnyUserData<'a>> {
let window = window.unwrap_or_else(|| (inner.offset(), MANAGER.layout.folder_height())); let window = window.unwrap_or_else(|| (inner.offset, MANAGER.layout.folder_height()));
let ud = self.scope.create_any_userdata_ref(inner)?; let ud = self.scope.create_any_userdata_ref(inner)?;
ud.set_named_user_value( ud.set_named_user_value(
@ -81,7 +81,7 @@ impl<'a, 'b> Active<'a, 'b> {
// TODO: remove this // TODO: remove this
ud.set_named_user_value( ud.set_named_user_value(
"hovered", "hovered",
inner.hovered.as_ref().and_then(|h| self.file(999, h, inner).ok()), inner.hovered().and_then(|h| self.file(999, h, inner).ok()),
)?; )?;
Ok(ud) Ok(ud)
@ -116,7 +116,7 @@ impl<'a, 'b> Active<'a, 'b> {
.as_ref() .as_ref()
.filter(|l| l.is_folder()) .filter(|l| l.is_folder())
.and_then(|l| tab.history(&l.url)) .and_then(|l| tab.history(&l.url))
.and_then(|f| self.folder(f, Some((f.offset(), MANAGER.layout.preview_height()))).ok()), .and_then(|f| self.folder(f, Some((f.offset, MANAGER.layout.preview_height()))).ok()),
)?; )?;
Ok(ud) Ok(ud)

View File

@ -104,7 +104,7 @@ impl Files {
reg.add_function("is_hovered", |_, me: AnyUserData| { reg.add_function("is_hovered", |_, me: AnyUserData| {
let folder = me.named_user_value::<UserDataRef<core::manager::Folder>>("folder")?; let folder = me.named_user_value::<UserDataRef<core::manager::Folder>>("folder")?;
let file = me.borrow::<core::files::File>()?; let file = me.borrow::<core::files::File>()?;
Ok(matches!(&folder.hovered, Some(f) if f.url() == file.url())) Ok(matches!(folder.hovered(), Some(f) if f.url() == file.url()))
}); });
reg.add_function("is_yanked", |_, me: AnyUserData| { reg.add_function("is_yanked", |_, me: AnyUserData| {
@ -129,7 +129,7 @@ impl Files {
selected selected
} else { } else {
let idx: usize = me.named_user_value("idx")?; let idx: usize = me.named_user_value("idx")?;
manager.active().mode.pending(folder.offset() + idx, selected) manager.active().mode.pending(folder.offset + idx, selected)
}) })
}); });