mirror of
https://github.com/sxyazi/yazi.git
synced 2026-07-25 08:41:05 +00:00
Merge branch 'main' of https://github.com/sxyazi/yazi into plain_text_log
This commit is contained in:
commit
37786a2eac
10 changed files with 67 additions and 25 deletions
|
|
@ -151,6 +151,7 @@ impl Executor {
|
|||
let b = cx.manager.active_mut().set_sorter(FilesSorter {
|
||||
by: SortBy::try_from(exec.args.get(0).cloned().unwrap_or_default())
|
||||
.unwrap_or_default(),
|
||||
sensitive: exec.named.contains_key("sensitive"),
|
||||
reverse: exec.named.contains_key("reverse"),
|
||||
dir_first: exec.named.contains_key("dir_first"),
|
||||
});
|
||||
|
|
|
|||
|
|
@ -19,11 +19,11 @@ impl<'a> Widget for Layout<'a> {
|
|||
.constraints([Constraint::Percentage(50), Constraint::Percentage(50)].as_ref())
|
||||
.split(area);
|
||||
|
||||
let current = &self.cx.manager.current();
|
||||
let location = if current.cwd.is_search() {
|
||||
format!("{} (search)", readable_path(¤t.cwd))
|
||||
let cwd = &self.cx.manager.current().cwd;
|
||||
let location = if cwd.is_search() {
|
||||
format!("{} (search: {})", readable_path(cwd), cwd.frag().unwrap())
|
||||
} else {
|
||||
readable_path(¤t.cwd)
|
||||
readable_path(cwd)
|
||||
};
|
||||
|
||||
Paragraph::new(location).style(Style::new().fg(Color::Cyan)).render(chunks[0], buf);
|
||||
|
|
|
|||
|
|
@ -14,6 +14,11 @@
|
|||
- `"natural"`: Sort naturally, e.g. `1.md` < `2.md` < `10.md`
|
||||
- `"size"`: Sort by file size
|
||||
|
||||
- sort_sensitive: Sort case-sensitively
|
||||
|
||||
- `true`: Case-sensitive
|
||||
- `false`: Case-insensitive
|
||||
|
||||
- sort_reverse: Display files in reverse order
|
||||
|
||||
- `true`: Reverse order
|
||||
|
|
@ -81,8 +86,8 @@ rules = [
|
|||
|
||||
Available rule parameters are as follows:
|
||||
|
||||
- name: Glob expression for matching the file name
|
||||
- mime: Glob expression for matching the MIME type
|
||||
- name: Glob expression for matching the file name. Case insensitive by default, add `\s` to the beginning to make it sensitive.
|
||||
- mime: Glob expression for matching the MIME type. Case insensitive by default, add `\s` to the beginning to make it sensitive.
|
||||
- use: Opener name corresponding to the names in the opener section.
|
||||
|
||||
## tasks
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
[manager]
|
||||
layout = [ 1, 4, 3 ]
|
||||
sort_by = "modified"
|
||||
sort_sensitive = false
|
||||
sort_reverse = true
|
||||
sort_dir_first = true
|
||||
show_hidden = false
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ pub struct Manager {
|
|||
|
||||
// Sorting
|
||||
pub sort_by: SortBy,
|
||||
pub sort_sensitive: bool,
|
||||
pub sort_reverse: bool,
|
||||
pub sort_dir_first: bool,
|
||||
|
||||
|
|
|
|||
|
|
@ -1,18 +1,26 @@
|
|||
use std::path::Path;
|
||||
|
||||
use glob::MatchOptions;
|
||||
use serde::Deserialize;
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(try_from = "String")]
|
||||
pub struct Pattern {
|
||||
inner: glob::Pattern,
|
||||
sensitive: bool,
|
||||
is_folder: bool,
|
||||
full_path: bool,
|
||||
}
|
||||
|
||||
impl Pattern {
|
||||
#[inline]
|
||||
pub fn matches(&self, str: impl AsRef<str>) -> bool { self.inner.matches(str.as_ref()) }
|
||||
pub fn matches(&self, str: impl AsRef<str>) -> bool {
|
||||
self.inner.matches_with(str.as_ref(), MatchOptions {
|
||||
case_sensitive: self.sensitive,
|
||||
require_literal_separator: false,
|
||||
require_literal_leading_dot: false,
|
||||
})
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn match_path(&self, path: impl AsRef<Path>, is_folder: Option<bool>) -> bool {
|
||||
|
|
@ -20,7 +28,7 @@ impl Pattern {
|
|||
let s = if self.full_path {
|
||||
path.to_str()
|
||||
} else {
|
||||
path.file_name().and_then(|n| n.to_str()).or(path.to_str())
|
||||
path.file_name().and_then(|n| n.to_str()).or_else(|| path.to_str())
|
||||
};
|
||||
is_folder.map_or(true, |f| f == self.is_folder) && s.map_or(false, |s| self.matches(s))
|
||||
}
|
||||
|
|
@ -30,11 +38,13 @@ impl TryFrom<&str> for Pattern {
|
|||
type Error = anyhow::Error;
|
||||
|
||||
fn try_from(s: &str) -> Result<Self, Self::Error> {
|
||||
let new = s.trim_end_matches('/');
|
||||
let a = s.trim_start_matches("\\s");
|
||||
let b = a.trim_end_matches('/');
|
||||
Ok(Self {
|
||||
inner: glob::Pattern::new(new)?,
|
||||
is_folder: new.len() < s.len(),
|
||||
full_path: new.contains('/'),
|
||||
inner: glob::Pattern::new(b)?,
|
||||
sensitive: a.len() < s.len(),
|
||||
is_folder: b.len() < a.len(),
|
||||
full_path: b.contains('/'),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use std::{cmp::Ordering, collections::BTreeMap, mem};
|
||||
use std::{cmp::Ordering, collections::BTreeMap, mem, ops::Deref};
|
||||
|
||||
use config::{manager::SortBy, MANAGER};
|
||||
use shared::Url;
|
||||
|
|
@ -8,6 +8,7 @@ use super::File;
|
|||
#[derive(Clone, Copy, PartialEq)]
|
||||
pub struct FilesSorter {
|
||||
pub by: SortBy,
|
||||
pub sensitive: bool,
|
||||
pub reverse: bool,
|
||||
pub dir_first: bool,
|
||||
}
|
||||
|
|
@ -16,6 +17,7 @@ impl Default for FilesSorter {
|
|||
fn default() -> Self {
|
||||
Self {
|
||||
by: MANAGER.sort_by,
|
||||
sensitive: MANAGER.sort_sensitive,
|
||||
reverse: MANAGER.sort_reverse,
|
||||
dir_first: MANAGER.sort_dir_first,
|
||||
}
|
||||
|
|
@ -29,9 +31,17 @@ impl FilesSorter {
|
|||
}
|
||||
|
||||
match self.by {
|
||||
SortBy::Alphabetical => {
|
||||
items.sort_unstable_by(|a, b| self.cmp(&*a.url, &*b.url, self.promote(a, b)))
|
||||
SortBy::Alphabetical => items.sort_unstable_by(|a, b| {
|
||||
if self.sensitive {
|
||||
return self.cmp(&*a.url, &*b.url, self.promote(a, b));
|
||||
}
|
||||
|
||||
self.cmp(
|
||||
a.url.as_os_str().to_ascii_lowercase(),
|
||||
b.url.as_os_str().to_ascii_lowercase(),
|
||||
self.promote(a, b),
|
||||
)
|
||||
}),
|
||||
SortBy::Created => items.sort_unstable_by(|a, b| {
|
||||
if let (Ok(aa), Ok(bb)) = (a.meta.created(), b.meta.created()) {
|
||||
return self.cmp(aa, bb, self.promote(a, b));
|
||||
|
|
@ -65,12 +75,16 @@ impl FilesSorter {
|
|||
indices.sort_unstable_by(|&a, &b| {
|
||||
let promote = self.promote(entities[a].1, entities[b].1);
|
||||
if promote != Ordering::Equal {
|
||||
promote
|
||||
} else if self.reverse {
|
||||
natord::compare(&entities[b].0, &entities[a].0)
|
||||
} else {
|
||||
natord::compare(&entities[a].0, &entities[b].0)
|
||||
return promote;
|
||||
}
|
||||
|
||||
let ordering = if self.sensitive {
|
||||
natord::compare(&entities[a].0, &entities[b].0)
|
||||
} else {
|
||||
natord::compare_ignore_case(&entities[a].0, &entities[b].0)
|
||||
};
|
||||
|
||||
if self.reverse { ordering.reverse() } else { ordering }
|
||||
});
|
||||
|
||||
let dummy = File {
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ use std::{io::BufRead, path::Path, sync::atomic::{AtomicUsize, Ordering}};
|
|||
use adaptor::ADAPTOR;
|
||||
use anyhow::anyhow;
|
||||
use config::{MANAGER, PREVIEW};
|
||||
use futures::TryFutureExt;
|
||||
use shared::{MimeKind, PeekError};
|
||||
use syntect::{easy::HighlightFile, util::as_24_bit_terminal_escaped};
|
||||
use tokio::fs;
|
||||
|
|
@ -69,7 +70,9 @@ impl Provider {
|
|||
}
|
||||
|
||||
pub(super) async fn json(path: &Path, skip: usize) -> Result<String, PeekError> {
|
||||
external::jq(path, skip, MANAGER.layout.preview_height()).await
|
||||
external::jq(path, skip, MANAGER.layout.preview_height())
|
||||
.or_else(|_| Provider::highlight(path, skip))
|
||||
.await
|
||||
}
|
||||
|
||||
pub(super) async fn archive(path: &Path, skip: usize) -> Result<String, PeekError> {
|
||||
|
|
|
|||
|
|
@ -289,7 +289,7 @@ impl Tab {
|
|||
handle.abort();
|
||||
}
|
||||
|
||||
let cwd = self.current.cwd.to_search();
|
||||
let mut cwd = self.current.cwd.clone();
|
||||
let hidden = self.show_hidden;
|
||||
|
||||
self.search = Some(tokio::spawn(async move {
|
||||
|
|
@ -297,6 +297,7 @@ impl Tab {
|
|||
bail!("canceled")
|
||||
};
|
||||
|
||||
cwd = cwd.into_search(subject.clone());
|
||||
let rx = if grep {
|
||||
external::rg(external::RgOpt { cwd: cwd.clone(), hidden, subject })
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ use std::{ffi::{OsStr, OsString}, fmt::{Debug, Formatter}, ops::{Deref, DerefMut
|
|||
pub struct Url {
|
||||
scheme: UrlScheme,
|
||||
path: PathBuf,
|
||||
frag: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
|
||||
|
|
@ -114,11 +115,12 @@ impl Url {
|
|||
pub fn is_search(&self) -> bool { self.scheme == UrlScheme::Search }
|
||||
|
||||
#[inline]
|
||||
pub fn to_search(&self) -> Self { self.clone().into_search() }
|
||||
pub fn to_search(&self, frag: String) -> Self { self.clone().into_search(frag) }
|
||||
|
||||
#[inline]
|
||||
pub fn into_search(mut self) -> Self {
|
||||
pub fn into_search(mut self, frag: String) -> Self {
|
||||
self.scheme = UrlScheme::Search;
|
||||
self.frag = Some(frag);
|
||||
self
|
||||
}
|
||||
|
||||
|
|
@ -137,4 +139,8 @@ impl Url {
|
|||
// --- Path
|
||||
#[inline]
|
||||
pub fn set_path(&mut self, path: PathBuf) { self.path = path; }
|
||||
|
||||
// --- Frag
|
||||
#[inline]
|
||||
pub fn frag(&self) -> Option<&str> { self.frag.as_deref() }
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue