mirror of
https://github.com/sxyazi/yazi.git
synced 2026-07-25 08:41:05 +00:00
..
This commit is contained in:
parent
6f66eee596
commit
c09f054655
6 changed files with 52 additions and 76 deletions
|
|
@ -1,28 +1,27 @@
|
||||||
use std::{collections::{BTreeMap, BTreeSet}, ops::Range, path::{Path, PathBuf}};
|
use std::{collections::{BTreeMap, BTreeSet}, mem, ops::Deref, path::{Path, PathBuf}};
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use config::MANAGER;
|
use config::MANAGER;
|
||||||
use tokio::fs;
|
use tokio::fs;
|
||||||
|
|
||||||
use super::{File, FilesSorter, NonHiddenFiles};
|
use super::{File, FilesSorter};
|
||||||
|
|
||||||
pub struct Files {
|
pub struct Files {
|
||||||
items: Vec<File>,
|
items: Vec<File>,
|
||||||
length: usize,
|
hidden: Vec<File>,
|
||||||
|
|
||||||
sizes: BTreeMap<PathBuf, u64>,
|
sizes: BTreeMap<PathBuf, u64>,
|
||||||
selected: BTreeSet<PathBuf>,
|
selected: BTreeSet<PathBuf>,
|
||||||
|
|
||||||
pub sorter: FilesSorter,
|
pub sorter: FilesSorter,
|
||||||
// TODO: XXX
|
show_hidden: bool,
|
||||||
pub show_hidden: bool,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Files {
|
impl Default for Files {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
items: Default::default(),
|
items: Default::default(),
|
||||||
length: Default::default(),
|
hidden: Default::default(),
|
||||||
|
|
||||||
sizes: Default::default(),
|
sizes: Default::default(),
|
||||||
selected: Default::default(),
|
selected: Default::default(),
|
||||||
|
|
@ -33,6 +32,12 @@ impl Default for Files {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Deref for Files {
|
||||||
|
type Target = Vec<File>;
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target { &self.items }
|
||||||
|
}
|
||||||
|
|
||||||
impl Files {
|
impl Files {
|
||||||
pub async fn read(paths: &[impl AsRef<Path>]) -> Vec<File> {
|
pub async fn read(paths: &[impl AsRef<Path>]) -> Vec<File> {
|
||||||
let mut items = Vec::with_capacity(paths.len());
|
let mut items = Vec::with_capacity(paths.len());
|
||||||
|
|
@ -54,7 +59,9 @@ impl Files {
|
||||||
}
|
}
|
||||||
Ok(items)
|
Ok(items)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Files {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn select(&mut self, path: &Path, state: Option<bool>) -> bool {
|
pub fn select(&mut self, path: &Path, state: Option<bool>) -> bool {
|
||||||
let old = self.selected.contains(path);
|
let old = self.selected.contains(path);
|
||||||
|
|
@ -104,21 +111,31 @@ impl Files {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn set_show_hidden(&mut self, state: bool) -> bool {
|
pub fn set_show_hidden(&mut self, state: Option<bool>) -> bool {
|
||||||
if self.show_hidden == state {
|
let state = state.unwrap_or(!self.show_hidden);
|
||||||
|
if state == self.show_hidden {
|
||||||
|
return false;
|
||||||
|
} else if state && self.hidden.is_empty() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.length =
|
if state {
|
||||||
if state { self.items.len() } else { self.items.iter().filter(|f| !f.is_hidden).count() };
|
self.items.append(&mut self.hidden);
|
||||||
|
self.sorter.sort(&mut self.items);
|
||||||
|
} else {
|
||||||
|
let items = mem::take(&mut self.items);
|
||||||
|
(self.hidden, self.items) = items.into_iter().partition(|f| f.is_hidden);
|
||||||
|
}
|
||||||
|
|
||||||
self.show_hidden = state;
|
self.show_hidden = state;
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update_read(&mut self, mut items: Vec<File>) -> bool {
|
pub fn update_read(&mut self, mut items: Vec<File>) -> bool {
|
||||||
|
if !self.show_hidden {
|
||||||
|
(self.hidden, items) = items.into_iter().partition(|f| f.is_hidden);
|
||||||
|
}
|
||||||
self.sorter.sort(&mut items);
|
self.sorter.sort(&mut items);
|
||||||
self.length =
|
|
||||||
if self.show_hidden { items.len() } else { items.iter().filter(|f| !f.is_hidden).count() };
|
|
||||||
self.items = items;
|
self.items = items;
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
@ -131,15 +148,16 @@ impl Files {
|
||||||
|
|
||||||
pub fn update_search(&mut self, items: Vec<File>) -> bool {
|
pub fn update_search(&mut self, items: Vec<File>) -> bool {
|
||||||
if !items.is_empty() {
|
if !items.is_empty() {
|
||||||
self.length = items.len();
|
let (hidden, items): (Vec<_>, Vec<_>) = items.into_iter().partition(|f| f.is_hidden);
|
||||||
self.items.extend(items);
|
self.items.extend(items);
|
||||||
|
self.hidden.extend(hidden);
|
||||||
self.sorter.sort(&mut self.items);
|
self.sorter.sort(&mut self.items);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if !self.items.is_empty() {
|
if !self.items.is_empty() {
|
||||||
self.length = 0;
|
|
||||||
self.items.clear();
|
self.items.clear();
|
||||||
|
self.hidden.clear();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -148,23 +166,7 @@ impl Files {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Files {
|
impl Files {
|
||||||
#[inline]
|
pub fn pick(&self, indices: &BTreeSet<usize>) -> Vec<&File> {
|
||||||
pub fn len(&self) -> usize { self.length }
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn iter<'a>(&'a self) -> Box<dyn Iterator<Item = &'a File> + 'a> {
|
|
||||||
if self.show_hidden {
|
|
||||||
return Box::new(self.items.iter());
|
|
||||||
}
|
|
||||||
Box::new(NonHiddenFiles::new(&self.items, self.length))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn range(&self, range: Range<usize>) -> Vec<&File> {
|
|
||||||
self.iter().skip(range.start).take(range.end - range.start).collect()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn pick<'a>(&'a self, indices: &BTreeSet<usize>) -> Vec<&'a File> {
|
|
||||||
let mut items = Vec::with_capacity(indices.len());
|
let mut items = Vec::with_capacity(indices.len());
|
||||||
for (i, item) in self.iter().enumerate() {
|
for (i, item) in self.iter().enumerate() {
|
||||||
if indices.contains(&i) {
|
if indices.contains(&i) {
|
||||||
|
|
@ -185,7 +187,9 @@ impl Files {
|
||||||
return Default::default();
|
return Default::default();
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut items = Vec::with_capacity(self.selected.len() + pending.len());
|
let mut items =
|
||||||
|
Vec::with_capacity(self.selected.len() + if !unset { pending.len() } else { 0 });
|
||||||
|
|
||||||
for (i, item) in self.iter().enumerate() {
|
for (i, item) in self.iter().enumerate() {
|
||||||
let b = self.selected.contains(&item.path);
|
let b = self.selected.contains(&item.path);
|
||||||
if !unset && (b || pending.contains(&i)) {
|
if !unset && (b || pending.contains(&i)) {
|
||||||
|
|
@ -208,3 +212,8 @@ impl Files {
|
||||||
self.iter().any(|f| self.selected.contains(&f.path))
|
self.iter().any(|f| self.selected.contains(&f.path))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Files {
|
||||||
|
#[inline]
|
||||||
|
pub fn show_hidden(&self) -> bool { self.show_hidden }
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,29 +0,0 @@
|
||||||
use super::File;
|
|
||||||
|
|
||||||
pub struct NonHiddenFiles<'a> {
|
|
||||||
items: &'a Vec<File>,
|
|
||||||
|
|
||||||
cur: usize,
|
|
||||||
max: usize,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> NonHiddenFiles<'a> {
|
|
||||||
pub fn new(items: &'a Vec<File>, max: usize) -> Self { Self { items, cur: 0, max } }
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> Iterator for NonHiddenFiles<'a> {
|
|
||||||
type Item = &'a File;
|
|
||||||
|
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
|
||||||
while self.cur < self.items.len() {
|
|
||||||
let item = &self.items[self.cur];
|
|
||||||
self.cur += 1;
|
|
||||||
if !item.is_hidden {
|
|
||||||
return Some(&item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None
|
|
||||||
}
|
|
||||||
|
|
||||||
fn size_hint(&self) -> (usize, Option<usize>) { (self.max, Some(self.max)) }
|
|
||||||
}
|
|
||||||
|
|
@ -1,11 +1,9 @@
|
||||||
mod file;
|
mod file;
|
||||||
mod files;
|
mod files;
|
||||||
mod iterator;
|
|
||||||
mod op;
|
mod op;
|
||||||
mod sorter;
|
mod sorter;
|
||||||
|
|
||||||
pub use file::*;
|
pub use file::*;
|
||||||
pub use files::*;
|
pub use files::*;
|
||||||
pub use iterator::*;
|
|
||||||
pub use op::*;
|
pub use op::*;
|
||||||
pub use sorter::*;
|
pub use sorter::*;
|
||||||
|
|
|
||||||
|
|
@ -93,25 +93,23 @@ impl Folder {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn hidden(&mut self, show: Option<bool>) -> bool {
|
pub fn hidden(&mut self, show: Option<bool>) -> bool {
|
||||||
if show.is_none() || self.files.show_hidden != show.unwrap() {
|
if self.files.set_show_hidden(show) {
|
||||||
self.files.show_hidden = !self.files.show_hidden;
|
|
||||||
emit!(Refresh);
|
emit!(Refresh);
|
||||||
}
|
}
|
||||||
|
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn window(&self) -> Vec<&File> {
|
pub fn window(&self) -> &[File] {
|
||||||
let end = (self.offset + MANAGER.layout.folder_height()).min(self.files.len());
|
let end = (self.offset + MANAGER.layout.folder_height()).min(self.files.len());
|
||||||
self.files.range(self.offset..end)
|
&self.files[self.offset..end]
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn window_for(&self, offset: usize) -> Vec<&File> {
|
pub fn window_for(&self, offset: usize) -> &[File] {
|
||||||
let start = offset.min(self.files.len().saturating_sub(1));
|
let start = offset.min(self.files.len().saturating_sub(1));
|
||||||
let end = (offset + MANAGER.layout.folder_height()).min(self.files.len());
|
let end = (offset + MANAGER.layout.folder_height()).min(self.files.len());
|
||||||
self.files.range(start..end)
|
&self.files[start..end]
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn hover(&mut self, path: &Path) -> bool {
|
pub fn hover(&mut self, path: &Path) -> bool {
|
||||||
|
|
@ -136,13 +134,13 @@ impl Folder {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn cursor(&self) -> usize { self.cursor }
|
pub fn cursor(&self) -> usize { self.cursor }
|
||||||
|
|
||||||
pub fn paginate(&self) -> Vec<&File> {
|
pub fn paginate(&self) -> &[File] {
|
||||||
let len = self.files.len();
|
let len = self.files.len();
|
||||||
let limit = MANAGER.layout.folder_height();
|
let limit = MANAGER.layout.folder_height();
|
||||||
|
|
||||||
let start = (self.page * limit).min(len.saturating_sub(1));
|
let start = (self.page * limit).min(len.saturating_sub(1));
|
||||||
let end = (start + limit).min(len);
|
let end = (start + limit).min(len);
|
||||||
self.files.range(start..end)
|
&self.files[start..end]
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn rect_current(&self, path: &Path) -> Option<Rect> {
|
pub fn rect_current(&self, path: &Path) -> Option<Rect> {
|
||||||
|
|
|
||||||
|
|
@ -230,7 +230,7 @@ impl Tab {
|
||||||
}
|
}
|
||||||
|
|
||||||
let cwd = self.current.cwd.clone();
|
let cwd = self.current.cwd.clone();
|
||||||
let hidden = self.current.files.show_hidden;
|
let hidden = self.current.files.show_hidden();
|
||||||
|
|
||||||
self.search = Some(tokio::spawn(async move {
|
self.search = Some(tokio::spawn(async move {
|
||||||
let subject = emit!(Input(InputOpt::top("Search:"))).await?;
|
let subject = emit!(Input(InputOpt::top("Search:"))).await?;
|
||||||
|
|
|
||||||
|
|
@ -227,9 +227,9 @@ impl Tasks {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn precache_mime(&self, targets: Vec<&File>, mimetype: &HashMap<PathBuf, String>) -> bool {
|
pub fn precache_mime(&self, targets: &[File], mimetype: &HashMap<PathBuf, String>) -> bool {
|
||||||
let targets = targets
|
let targets = targets
|
||||||
.into_iter()
|
.iter()
|
||||||
.filter(|f| f.meta.is_file() && !mimetype.contains_key(&f.path))
|
.filter(|f| f.meta.is_file() && !mimetype.contains_key(&f.path))
|
||||||
.map(|f| f.path.clone())
|
.map(|f| f.path.clone())
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue