From ac6b077bd251a201ff78fe34f536f9bc3eb3f4d2 Mon Sep 17 00:00:00 2001 From: sxyazi Date: Mon, 10 Jul 2023 16:01:48 +0800 Subject: [PATCH] refactor: separate file logic from the folder module --- src/config/mod.rs | 2 +- src/core/adapter/mod.rs | 4 +- src/core/event.rs | 9 +- src/core/external/fd.rs | 7 +- src/core/external/rg.rs | 7 +- src/core/files/file.rs | 35 ++++++++ src/core/files/files.rs | 134 ++++++++++++++++++++++++++++ src/core/files/mod.rs | 5 ++ src/core/manager/folder.rs | 168 ++++++++---------------------------- src/core/manager/manager.rs | 30 +++---- src/core/manager/preview.rs | 8 +- src/core/manager/tab.rs | 41 ++++++++- src/core/manager/watcher.rs | 5 +- src/core/mod.rs | 13 ++- src/misc/buffer.rs | 5 +- src/ui/app.rs | 4 +- src/ui/context.rs | 2 +- src/ui/dispatcher.rs | 2 +- src/ui/input.rs | 2 +- src/ui/manager/folder.rs | 4 +- src/ui/manager/layout.rs | 2 +- src/ui/manager/preview.rs | 2 +- src/ui/tasks/layout.rs | 2 +- 23 files changed, 303 insertions(+), 190 deletions(-) create mode 100644 src/core/files/file.rs create mode 100644 src/core/files/files.rs create mode 100644 src/core/files/mod.rs diff --git a/src/config/mod.rs b/src/config/mod.rs index 54890891..c630013a 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -7,7 +7,7 @@ mod pattern; pub mod preview; pub mod theme; -pub use pattern::*; +pub(crate) use pattern::*; pub static KEYMAP: Lazy = Lazy::new(|| keymap::Keymap::new()); pub static MANAGER: Lazy = Lazy::new(|| manager::Manager::new()); diff --git a/src/core/adapter/mod.rs b/src/core/adapter/mod.rs index 2823cb39..092bf152 100644 --- a/src/core/adapter/mod.rs +++ b/src/core/adapter/mod.rs @@ -1 +1,3 @@ -pub mod kitty; +mod kitty; + +pub use kitty::*; diff --git a/src/core/event.rs b/src/core/event.rs index 4c1f1886..15345422 100644 --- a/src/core/event.rs +++ b/src/core/event.rs @@ -2,10 +2,9 @@ use std::path::PathBuf; use anyhow::Result; use crossterm::event::KeyEvent; -use indexmap::IndexMap; use tokio::sync::{mpsc::Sender, oneshot}; -use super::{FolderItem, InputOpt, PreviewData}; +use super::{files::FilesOp, input::InputOpt, manager::PreviewData}; static mut TX: Option> = None; @@ -17,7 +16,7 @@ pub enum Event { Resize(u16, u16), Refresh, - Files(PathBuf, IndexMap), + Files(FilesOp), Hover, Mimetype(PathBuf, String), Preview(PathBuf, PreviewData), @@ -67,8 +66,8 @@ macro_rules! emit { $crate::core::Event::Resize($cols, $rows).emit(); }; - (Files($path:expr, $items:expr)) => { - $crate::core::Event::Files($path, $items).emit(); + (Files($op:expr)) => { + $crate::core::Event::Files($op).emit(); }; (Mimetype($path:expr, $mime:expr)) => { $crate::core::Event::Mimetype($path, $mime).emit(); diff --git a/src/core/external/fd.rs b/src/core/external/fd.rs index 7e8f4d7f..31cd0d36 100644 --- a/src/core/external/fd.rs +++ b/src/core/external/fd.rs @@ -12,7 +12,7 @@ pub struct FdOpt { pub subject: String, } -pub fn fd(opt: FdOpt) -> Result<(JoinHandle<()>, UnboundedReceiver>)> { +pub fn fd(opt: FdOpt) -> Result<(JoinHandle<()>, UnboundedReceiver>)> { let mut child = Command::new("fd") .arg("--base-directory") .arg(&opt.cwd) @@ -30,7 +30,10 @@ pub fn fd(opt: FdOpt) -> Result<(JoinHandle<()>, UnboundedReceiver>) let handle = tokio::spawn(async move { while let Ok(Some(line)) = it.next_line().await { - buf.push(line); + let path = PathBuf::from(line); + if path.components().count() > 1 { + buf.push(path); + } } child.wait().await.ok(); }); diff --git a/src/core/external/rg.rs b/src/core/external/rg.rs index 2fc7459f..50f2cee3 100644 --- a/src/core/external/rg.rs +++ b/src/core/external/rg.rs @@ -11,7 +11,7 @@ pub struct RgOpt { pub subject: String, } -pub async fn rg(opt: RgOpt) -> Result<(JoinHandle<()>, UnboundedReceiver>)> { +pub fn rg(opt: RgOpt) -> Result<(JoinHandle<()>, UnboundedReceiver>)> { let mut child = Command::new("rg") .current_dir(&opt.cwd) .args(&["--color=never", "--files-with-matches", "--smart-case"]) @@ -28,7 +28,10 @@ pub async fn rg(opt: RgOpt) -> Result<(JoinHandle<()>, UnboundedReceiver 1 { + buf.push(path); + } } child.wait().await.ok(); }); diff --git a/src/core/files/file.rs b/src/core/files/file.rs new file mode 100644 index 00000000..c50525cb --- /dev/null +++ b/src/core/files/file.rs @@ -0,0 +1,35 @@ +use std::{fs::Metadata, path::{Path, PathBuf}}; + +use anyhow::Result; +use tokio::fs; + +#[derive(Clone)] +pub struct File { + pub name: String, + pub path: PathBuf, + pub meta: Metadata, + pub length: Option, + pub is_link: bool, + pub is_hidden: bool, + pub is_selected: bool, +} + +impl File { + #[inline] + pub async fn from(path: &Path) -> Result { + let meta = fs::metadata(path).await?; + Ok(Self::from_meta(path, meta).await) + } + + pub async fn from_meta(path: &Path, mut meta: Metadata) -> File { + let is_link = meta.is_symlink(); + if is_link { + meta = fs::metadata(&path).await.unwrap_or(meta); + } + + let name = path.file_name().map(|n| n.to_string_lossy().to_string()).unwrap_or_default(); + let length = if meta.is_dir() { None } else { Some(meta.len()) }; + let is_hidden = name.starts_with('.'); + File { name, path: path.to_path_buf(), meta, length, is_link, is_hidden, is_selected: false } + } +} diff --git a/src/core/files/files.rs b/src/core/files/files.rs new file mode 100644 index 00000000..8e836249 --- /dev/null +++ b/src/core/files/files.rs @@ -0,0 +1,134 @@ +use std::{ops::{Deref, DerefMut}, path::{Path, PathBuf}}; + +use indexmap::IndexMap; +use tokio::fs; + +use super::File; +use crate::{config::{manager::SortBy, MANAGER}, emit}; + +#[derive(Default)] +pub struct Files { + items: IndexMap, + sort: FilesSort, + pub show_hidden: bool, +} + +impl Files { + pub async fn from(paths: Vec) -> IndexMap { + let mut items = IndexMap::new(); + for path in paths { + if let Ok(file) = File::from(&path).await { + items.insert(path, file); + } + } + items + } + + pub async fn read(path: &Path) { + let mut iter = match fs::read_dir(path).await { + Ok(it) => it, + Err(_) => return, + }; + + let mut items = IndexMap::new(); + while let Ok(Some(item)) = iter.next_entry().await { + if let Ok(meta) = item.metadata().await { + let path = item.path(); + let file = File::from_meta(&path, meta).await; + items.insert(path, file); + } + } + emit!(Files(FilesOp::Update(path.to_path_buf(), items))); + } + + pub fn sort(&mut self) { + fn cmp(a: T, b: T, reverse: bool) -> std::cmp::Ordering { + if reverse { b.cmp(&a) } else { a.cmp(&b) } + } + + let reverse = self.sort.reverse; + match self.sort.by { + SortBy::Alphabetical => self.items.sort_by(|_, a, _, b| cmp(&a.name, &b.name, reverse)), + SortBy::Created => self.items.sort_by(|_, a, _, b| { + if let (Ok(a), Ok(b)) = (a.meta.created(), b.meta.created()) { + return cmp(a, b, reverse); + } + std::cmp::Ordering::Equal + }), + SortBy::Modified => self.items.sort_by(|_, a, _, b| { + if let (Ok(a), Ok(b)) = (a.meta.modified(), b.meta.modified()) { + return cmp(a, b, reverse); + } + std::cmp::Ordering::Equal + }), + SortBy::Size => { + self.items.sort_by(|_, a, _, b| cmp(a.length.unwrap_or(0), b.length.unwrap_or(0), reverse)) + } + } + } + + pub fn update(&mut self, mut items: IndexMap) -> bool { + if !self.show_hidden { + items.retain(|_, item| !item.is_hidden); + } + + for (path, item) in &mut items { + if let Some(old) = self.items.get(path) { + item.length = old.length; + item.is_selected = old.is_selected; + } + } + + self.items = items; + self.sort(); + true + } + + pub fn append(&mut self, items: IndexMap) -> bool { + for (path, mut item) in items.into_iter() { + if let Some(old) = self.items.get(&path) { + item.length = old.length; + item.is_selected = old.is_selected; + } + self.items.insert(path, item); + } + + self.sort(); + true + } +} + +impl Deref for Files { + type Target = IndexMap; + + fn deref(&self) -> &Self::Target { &self.items } +} + +impl DerefMut for Files { + fn deref_mut(&mut self) -> &mut Self::Target { &mut self.items } +} + +struct FilesSort { + pub by: SortBy, + pub reverse: bool, +} + +impl Default for FilesSort { + fn default() -> Self { Self { by: MANAGER.sort_by, reverse: MANAGER.sort_reverse } } +} + +pub enum FilesOp { + Update(PathBuf, IndexMap), + Append(PathBuf, IndexMap), +} + +impl FilesOp { + #[inline] + pub fn path(&self) -> PathBuf { + match self { + Self::Update(path, _) => path, + Self::Append(path, _) => path, + } + .clone() + } +} diff --git a/src/core/files/mod.rs b/src/core/files/mod.rs new file mode 100644 index 00000000..35de6151 --- /dev/null +++ b/src/core/files/mod.rs @@ -0,0 +1,5 @@ +mod file; +mod files; + +pub use file::*; +pub use files::*; diff --git a/src/core/manager/folder.rs b/src/core/manager/folder.rs index 2cde399f..fb6f6dea 100644 --- a/src/core/manager/folder.rs +++ b/src/core/manager/folder.rs @@ -1,142 +1,48 @@ -use std::{fs::Metadata, path::{Path, PathBuf}, usize}; +use std::{path::{Path, PathBuf}, usize}; -use indexmap::{map::Slice, IndexMap}; +use indexmap::map::Slice; use ratatui::layout::Rect; -use tokio::fs; use super::{ALL_RATIO, CURRENT_RATIO, DIR_PADDING, PARENT_RATIO}; -use crate::{config::{manager::SortBy, MANAGER}, emit, misc::tty_size}; +use crate::{core::files::{File, Files, FilesOp}, emit, misc::tty_size}; #[derive(Default)] pub struct Folder { - pub cwd: PathBuf, - items: IndexMap, - offset: usize, - cursor: usize, + pub cwd: PathBuf, + pub files: Files, + offset: usize, + cursor: usize, - sort: FolderSort, - show_hidden: bool, pub in_search: bool, } -#[derive(Clone)] -pub struct FolderItem { - pub name: String, - pub path: PathBuf, - pub meta: Metadata, - pub length: Option, - pub is_link: bool, - pub is_hidden: bool, - pub is_selected: bool, -} - -struct FolderSort { - pub by: SortBy, - pub reverse: bool, -} - -impl Default for FolderSort { - fn default() -> Self { Self { by: MANAGER.sort_by, reverse: MANAGER.sort_reverse } } -} - impl Folder { - pub fn new(cwd: &Path) -> Self { - Self { cwd: cwd.to_path_buf(), show_hidden: MANAGER.show_hidden, ..Default::default() } - } + pub fn new(cwd: &Path) -> Self { Self { cwd: cwd.to_path_buf(), ..Default::default() } } pub fn new_search(cwd: &Path) -> Self { - Self { - cwd: cwd.to_path_buf(), - show_hidden: MANAGER.show_hidden, - in_search: true, - ..Default::default() + Self { cwd: cwd.to_path_buf(), in_search: true, ..Default::default() } + } + + pub fn update(&mut self, op: FilesOp) -> bool { + let b = match op { + FilesOp::Update(_, items) => self.files.update(items), + FilesOp::Append(_, items) => self.files.append(items), + }; + if !b { + return false; } + + let len = self.files.len(); + self.cursor = self.cursor.min(len.saturating_sub(1)); + self.offset = self.offset.min(len); + true } #[inline] pub fn limit() -> usize { tty_size().ws_row.saturating_sub(DIR_PADDING) as usize } - pub async fn read(path: &Path) { - let mut iter = match fs::read_dir(path).await { - Ok(it) => it, - Err(_) => return, - }; - - let mut items = IndexMap::new(); - while let Ok(Some(item)) = iter.next_entry().await { - let mut meta = if let Ok(meta) = item.metadata().await { meta } else { continue }; - let is_link = meta.is_symlink(); - if is_link { - meta = fs::metadata(&path).await.unwrap_or(meta); - } - - let path = item.path(); - let name = item.file_name().to_string_lossy().to_string(); - - let length = if meta.is_dir() { None } else { Some(meta.len()) }; - let is_hidden = name.starts_with('.'); - - items.insert(path.clone(), FolderItem { - name, - path, - meta, - length, - is_link, - is_hidden, - is_selected: false, - }); - } - emit!(Files(path.to_path_buf(), items)); - } - - pub fn sort(&mut self) { - fn cmp(a: T, b: T, reverse: bool) -> std::cmp::Ordering { - if reverse { b.cmp(&a) } else { a.cmp(&b) } - } - - let reverse = self.sort.reverse; - match self.sort.by { - SortBy::Alphabetical => self.items.sort_by(|_, a, _, b| cmp(&a.name, &b.name, reverse)), - SortBy::Created => self.items.sort_by(|_, a, _, b| { - if let (Ok(a), Ok(b)) = (a.meta.created(), b.meta.created()) { - return cmp(a, b, reverse); - } - std::cmp::Ordering::Equal - }), - SortBy::Modified => self.items.sort_by(|_, a, _, b| { - if let (Ok(a), Ok(b)) = (a.meta.modified(), b.meta.modified()) { - return cmp(a, b, reverse); - } - std::cmp::Ordering::Equal - }), - SortBy::Size => { - self.items.sort_by(|_, a, _, b| cmp(a.length.unwrap_or(0), b.length.unwrap_or(0), reverse)) - } - } - } - - pub fn update(&mut self, mut items: IndexMap) -> bool { - if !self.show_hidden { - items.retain(|_, item| !item.is_hidden); - } - - for (path, item) in &mut items { - if let Some(old) = self.items.get(path) { - item.length = old.length; - item.is_selected = old.is_selected; - } - } - - let len = items.len(); - self.items = items; - self.cursor = self.cursor.min(len.saturating_sub(1)); - self.offset = self.offset.min(len); - self.sort(); - true - } - pub fn next(&mut self, step: usize) -> bool { - let len = self.items.len(); + let len = self.files.len(); if len == 0 { return false; } @@ -164,30 +70,30 @@ impl Folder { } pub fn hidden(&mut self, show: Option) -> bool { - if show.is_none() || self.show_hidden != show.unwrap() { - self.show_hidden = !self.show_hidden; + if show.is_none() || self.files.show_hidden != show.unwrap() { + self.files.show_hidden = !self.files.show_hidden; emit!(Refresh); } false } - pub fn paginate(&self) -> &Slice { - let end = (self.offset + Self::limit()).min(self.items.len()); - self.items.get_range(self.offset..end).unwrap() + pub fn paginate(&self) -> &Slice { + let end = (self.offset + Self::limit()).min(self.files.len()); + self.files.get_range(self.offset..end).unwrap() } pub fn select(&mut self, idx: Option, state: Option) -> bool { - let len = self.items.len(); + let len = self.files.len(); let mut apply = |idx: usize, state: Option| -> bool { if state.is_none() { - self.items[idx].is_selected = !self.items[idx].is_selected; + self.files[idx].is_selected = !self.files[idx].is_selected; return true; } let state = state.unwrap(); - if state != self.items[idx].is_selected { - self.items[idx].is_selected = state; + if state != self.files[idx].is_selected { + self.files[idx].is_selected = state; return true; } @@ -213,7 +119,7 @@ impl Folder { pub fn selected(&self) -> Option> { let v = self - .items + .files .iter() .filter(|(_, item)| item.is_selected) .map(|(path, _)| path.clone()) @@ -234,9 +140,7 @@ impl Folder { impl Folder { #[inline] - pub fn hovered(&self) -> Option<&FolderItem> { - self.items.get_index(self.cursor).map(|(_, item)| item) - } + pub fn hovered(&self) -> Option<&File> { self.files.get_index(self.cursor).map(|(_, item)| item) } #[inline] pub fn cursor(&self) -> usize { self.cursor } @@ -246,7 +150,7 @@ impl Folder { #[inline] pub fn position(&self, path: &Path) -> Option { - self.items.iter().position(|(p, _)| p == path) + self.files.iter().position(|(p, _)| p == path) } #[inline] diff --git a/src/core/manager/manager.rs b/src/core/manager/manager.rs index b471b344..bc28ea73 100644 --- a/src/core/manager/manager.rs +++ b/src/core/manager/manager.rs @@ -1,12 +1,9 @@ use std::{collections::{BTreeSet, HashMap, HashSet}, path::PathBuf}; -use indexmap::IndexMap; -use ratatui::layout::Rect; use tokio::fs; -use tracing::trace; -use super::{FolderItem, PreviewData, Tab, Tabs, Watcher}; -use crate::{core::{Folder, Input, InputOpt, Precache}, emit}; +use super::{PreviewData, Tab, Tabs, Watcher}; +use crate::{core::{files::{File, FilesOp}, input::{Input, InputOpt}, manager::Folder, tasks::Precache}, emit}; pub struct Manager { tabs: Tabs, @@ -169,25 +166,20 @@ impl Manager { files.into_iter().map(|p| self.mimetype.get(p).cloned()).collect() } - pub fn update_files(&mut self, path: PathBuf, items: IndexMap) -> bool { + pub fn update_files(&mut self, op: FilesOp) -> bool { + let path = op.path(); let cwd = self.current().cwd.clone(); + let hovered = self.hovered().map(|h| h.path.clone()); - - let mut b = if cwd == path && !self.current().in_search { - self.current_mut().update(items) + let folder = if cwd == path && !self.current().in_search { + self.current_mut() } else if matches!(self.parent(), Some(p) if p.cwd == path) { - self.active_mut().parent.as_mut().unwrap().update(items) + self.active_mut().parent.as_mut().unwrap() } else { - self - .active_mut() - .history - .entry(path.clone()) - .or_insert_with(|| Folder::new(&path)) - .update(items); - - matches!(self.hovered(), Some(h) if h.path == path) + self.active_mut().history.entry(path.to_path_buf()).or_insert_with(|| Folder::new(&path)) }; + let mut b = folder.update(op) || matches!(self.hovered(), Some(h) if h.path == path); b |= self.active_mut().parent.as_mut().map_or(false, |p| p.hover(&cwd)); b |= hovered.as_ref().map_or(false, |h| self.current_mut().hover(h)); @@ -248,5 +240,5 @@ impl Manager { pub fn parent(&self) -> &Option { &self.tabs.active().parent } #[inline] - pub fn hovered(&self) -> Option<&FolderItem> { self.tabs.active().current.hovered() } + pub fn hovered(&self) -> Option<&File> { self.tabs.active().current.hovered() } } diff --git a/src/core/manager/preview.rs b/src/core/manager/preview.rs index 96b3747d..0f5e4e68 100644 --- a/src/core/manager/preview.rs +++ b/src/core/manager/preview.rs @@ -1,14 +1,12 @@ use std::{fs::File, io::BufReader, path::{Path, PathBuf}, sync::OnceLock}; -use adapter::kitty::Kitty; use anyhow::{anyhow, Context, Result}; use image::imageops::FilterType; -use ratatui::layout::Rect; use syntect::{easy::HighlightLines, highlighting::{Theme, ThemeSet}, parsing::SyntaxSet, util::as_24_bit_terminal_escaped}; use tokio::{fs, task::JoinHandle}; -use super::{Folder, ALL_RATIO, PREVIEW_BORDER, PREVIEW_PADDING, PREVIEW_RATIO}; -use crate::{config::{PREVIEW, THEME}, core::{adapter, Precache}, emit, misc::{first_n_lines, tty_ratio, tty_size}}; +use super::{ALL_RATIO, PREVIEW_BORDER, PREVIEW_PADDING, PREVIEW_RATIO}; +use crate::{config::{PREVIEW, THEME}, core::{adapter::Kitty, files::Files, tasks::Precache}, emit, misc::{first_n_lines, tty_ratio, tty_size}}; static SYNTECT_SYNTAX: OnceLock = OnceLock::new(); static SYNTECT_THEME: OnceLock = OnceLock::new(); @@ -76,7 +74,7 @@ impl Preview { } pub async fn folder(path: &Path) -> Result { - Folder::read(&path).await; + Files::read(&path).await; Ok(PreviewData::Folder) } diff --git a/src/core/manager/tab.rs b/src/core/manager/tab.rs index 434810ac..b4298ab9 100644 --- a/src/core/manager/tab.rs +++ b/src/core/manager/tab.rs @@ -1,11 +1,15 @@ use std::{collections::BTreeMap, mem, path::{Path, PathBuf}}; +use anyhow::Result; +use tokio::task::JoinHandle; + use super::{Folder, Mode, Preview}; -use crate::emit; +use crate::{core::{external, files::{Files, FilesOp}, input::{Input, InputOpt}}, emit}; pub struct Tab { pub(super) current: Folder, pub(super) parent: Option, + search: Option>>, pub(super) mode: Mode, @@ -18,6 +22,7 @@ impl Tab { Self { current: Folder::new(path), parent: path.parent().map(|p| Folder::new(p)), + search: None, mode: Default::default(), @@ -124,6 +129,40 @@ impl Tab { pub fn forward(&mut self) -> bool { todo!() } + pub fn search(&mut self, grep: bool) -> bool { + if let Some(handle) = self.search.take() { + handle.abort(); + } + + let cwd = self.current.cwd.clone(); + let hidden = self.current.files.show_hidden; + + let pos = Input::top_position(); + self.search = Some(tokio::spawn(async move { + let subject = emit!(Input(InputOpt { + title: "Find:".to_string(), + value: "".to_string(), + position: pos, + })) + .await?; + + let (handle, mut buf) = if grep { + external::rg(external::RgOpt { cwd: cwd.clone(), hidden, subject })? + } else { + external::fd(external::FdOpt { cwd: cwd.clone(), hidden, regex: false, subject })? + }; + + while let Some(chunk) = buf.recv().await { + if chunk.is_empty() { + break; + } + emit!(Files(FilesOp::Append(cwd.clone(), Files::from(chunk).await))); + } + Ok(handle.await?) + })); + false + } + pub fn select(&mut self, state: Option) -> bool { let idx = Some(self.current.cursor()); self.current.select(idx, state) diff --git a/src/core/manager/watcher.rs b/src/core/manager/watcher.rs index 16249c97..5de97a40 100644 --- a/src/core/manager/watcher.rs +++ b/src/core/manager/watcher.rs @@ -3,8 +3,7 @@ use std::{collections::BTreeSet, path::{Path, PathBuf}}; use notify::{RecommendedWatcher, Watcher as _Watcher}; use tokio::sync::mpsc::{self, Sender}; -use super::Folder; -use crate::emit; +use crate::core::files::Files; pub struct Watcher { tx: Sender, @@ -54,7 +53,7 @@ impl Watcher { tokio::spawn(async move { while let Some(path) = rx.recv().await { - Folder::read(&path).await; + Files::read(&path).await; } }); diff --git a/src/core/mod.rs b/src/core/mod.rs index dddee82c..c43538ba 100644 --- a/src/core/mod.rs +++ b/src/core/mod.rs @@ -1,12 +1,9 @@ -mod adapter; +pub mod adapter; mod event; pub mod external; -mod input; -mod manager; -mod tasks; +pub mod files; +pub mod input; +pub mod manager; +pub mod tasks; -pub use adapter::*; pub use event::*; -pub use input::*; -pub use manager::*; -pub use tasks::*; diff --git a/src/misc/buffer.rs b/src/misc/buffer.rs index d7ddae62..5b8674f9 100644 --- a/src/misc/buffer.rs +++ b/src/misc/buffer.rs @@ -31,5 +31,8 @@ impl DelayedBuffer { } impl Drop for DelayedBuffer { - fn drop(&mut self) { self.flush(); } + fn drop(&mut self) { + self.flush(); + self.tx.send(vec![]).ok(); + } } diff --git a/src/ui/app.rs b/src/ui/app.rs index f6711422..a6e3d6c0 100644 --- a/src/ui/app.rs +++ b/src/ui/app.rs @@ -74,8 +74,8 @@ impl App { Event::Refresh => { manager.refresh(); } - Event::Files(path, files) => { - if manager.update_files(path, files) { + Event::Files(op) => { + if manager.update_files(op) { emit!(Render); } } diff --git a/src/ui/context.rs b/src/ui/context.rs index 14fc55c9..e2bee6c9 100644 --- a/src/ui/context.rs +++ b/src/ui/context.rs @@ -1,4 +1,4 @@ -use crate::core::{Input, Manager, Tasks}; +use crate::core::{input::Input, manager::Manager, tasks::Tasks}; pub struct Ctx { pub cursor: Option<(u16, u16)>, diff --git a/src/ui/dispatcher.rs b/src/ui/dispatcher.rs index f91c83a8..fdb33571 100644 --- a/src/ui/dispatcher.rs +++ b/src/ui/dispatcher.rs @@ -1,7 +1,7 @@ use crossterm::event::KeyCode; use super::Ctx; -use crate::{config::{keymap::{Exec, Key, Single}, KEYMAP}, core::InputMode, emit, misc::optinal_bool}; +use crate::{config::{keymap::{Exec, Key, Single}, KEYMAP}, core::input::InputMode, emit, misc::optinal_bool}; pub struct Executor; diff --git a/src/ui/input.rs b/src/ui/input.rs index fb6b3c2c..8b872e78 100644 --- a/src/ui/input.rs +++ b/src/ui/input.rs @@ -1,7 +1,7 @@ use ratatui::{buffer::Buffer, layout::Rect, style::{Color, Style}, text::Line, widgets::{Block, BorderType, Borders, Clear, Paragraph, Widget}}; use super::{Ctx, Term}; -use crate::core::InputMode; +use crate::core::input::InputMode; pub struct Input<'a> { cx: &'a Ctx, diff --git a/src/ui/manager/folder.rs b/src/ui/manager/folder.rs index c4b1843e..445daefa 100644 --- a/src/ui/manager/folder.rs +++ b/src/ui/manager/folder.rs @@ -3,13 +3,13 @@ use ratatui::{buffer::Buffer, layout::Rect, style::{Color, Modifier, Style}, wid use crate::{config::THEME, core}; pub struct Folder<'a> { - folder: &'a core::Folder, + folder: &'a core::manager::Folder, is_preview: bool, is_selection: bool, } impl<'a> Folder<'a> { - pub fn new(folder: &'a core::Folder) -> Self { + pub fn new(folder: &'a core::manager::Folder) -> Self { Self { folder, is_preview: false, is_selection: false } } diff --git a/src/ui/manager/layout.rs b/src/ui/manager/layout.rs index b9f7199a..55f65f05 100644 --- a/src/ui/manager/layout.rs +++ b/src/ui/manager/layout.rs @@ -1,7 +1,7 @@ use ratatui::{buffer::Buffer, layout::{self, Constraint, Direction, Rect}, widgets::{Block, Borders, Widget}}; use super::{Folder, Preview}; -use crate::{core::{Mode, ALL_RATIO, CURRENT_RATIO, PARENT_RATIO, PREVIEW_RATIO}, ui::Ctx}; +use crate::{core::manager::{Mode, ALL_RATIO, CURRENT_RATIO, PARENT_RATIO, PREVIEW_RATIO}, ui::Ctx}; pub struct Layout<'a> { cx: &'a Ctx, diff --git a/src/ui/manager/preview.rs b/src/ui/manager/preview.rs index 2e5e906b..9a729dd8 100644 --- a/src/ui/manager/preview.rs +++ b/src/ui/manager/preview.rs @@ -4,7 +4,7 @@ use ansi_to_tui::IntoText; use ratatui::{buffer::Buffer, layout::Rect, widgets::{Paragraph, Widget}}; use super::Folder; -use crate::{core::{kitty::Kitty, PreviewData}, ui::{Ctx, Term}}; +use crate::{core::{adapter::Kitty, manager::PreviewData}, ui::{Ctx, Term}}; pub struct Preview<'a> { cx: &'a Ctx, diff --git a/src/ui/tasks/layout.rs b/src/ui/tasks/layout.rs index 55a18c43..98007e7b 100644 --- a/src/ui/tasks/layout.rs +++ b/src/ui/tasks/layout.rs @@ -1,7 +1,7 @@ use ratatui::{buffer::Buffer, layout::{self, Alignment, Constraint, Direction, Rect}, style::{Color, Modifier, Style}, widgets::{Block, BorderType, Borders, List, ListItem, Padding, Widget}}; use super::Clear; -use crate::{core::TASKS_PERCENT, ui::Ctx}; +use crate::{core::tasks::TASKS_PERCENT, ui::Ctx}; pub struct Layout<'a> { cx: &'a Ctx,