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 shift_char_keymap
This commit is contained in:
commit
3ee8ef8547
10 changed files with 93 additions and 23 deletions
|
|
@ -81,6 +81,9 @@ rules = [
|
|||
|
||||
# { mime = "application/json", use = "text" },
|
||||
{ name = "*.json", use = "text" },
|
||||
|
||||
# Multiple openers for a single rule
|
||||
{ name = "*.html", use = [ "browser", "text" ] },
|
||||
]
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
mod open;
|
||||
mod opener;
|
||||
mod rule;
|
||||
|
||||
pub use open::*;
|
||||
pub use opener::*;
|
||||
use rule::*;
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ use serde::{Deserialize, Deserializer};
|
|||
use shared::MIME_DIR;
|
||||
|
||||
use super::Opener;
|
||||
use crate::{Pattern, MERGED_YAZI};
|
||||
use crate::{open::OpenRule, MERGED_YAZI};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Open {
|
||||
|
|
@ -13,20 +13,12 @@ pub struct Open {
|
|||
rules: Vec<OpenRule>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct OpenRule {
|
||||
name: Option<Pattern>,
|
||||
mime: Option<Pattern>,
|
||||
#[serde(rename = "use")]
|
||||
use_: String,
|
||||
}
|
||||
|
||||
impl Default for Open {
|
||||
fn default() -> Self { toml::from_str(&MERGED_YAZI).unwrap() }
|
||||
}
|
||||
|
||||
impl Open {
|
||||
pub fn openers<P, M>(&self, path: P, mime: M) -> Option<&IndexSet<Opener>>
|
||||
pub fn openers<P, M>(&self, path: P, mime: M) -> Option<IndexSet<&Opener>>
|
||||
where
|
||||
P: AsRef<Path>,
|
||||
M: AsRef<str>,
|
||||
|
|
@ -36,7 +28,14 @@ impl Open {
|
|||
if rule.mime.as_ref().map_or(false, |m| m.matches(&mime))
|
||||
|| rule.name.as_ref().map_or(false, |n| n.match_path(&path, is_folder))
|
||||
{
|
||||
self.openers.get(&rule.use_)
|
||||
let openers = rule
|
||||
.use_
|
||||
.iter()
|
||||
.filter_map(|use_| self.openers.get(use_))
|
||||
.flatten()
|
||||
.collect::<IndexSet<_>>();
|
||||
|
||||
if openers.is_empty() { None } else { Some(openers) }
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
|
@ -49,12 +48,12 @@ impl Open {
|
|||
P: AsRef<Path>,
|
||||
M: AsRef<str>,
|
||||
{
|
||||
self.openers(path, mime).and_then(|o| o.iter().find(|o| o.block))
|
||||
self.openers(path, mime).and_then(|o| o.into_iter().find(|o| o.block))
|
||||
}
|
||||
|
||||
pub fn common_openers(&self, targets: &[(impl AsRef<Path>, impl AsRef<str>)]) -> Vec<&Opener> {
|
||||
let grouped = targets.iter().filter_map(|(p, m)| self.openers(p, m)).collect::<Vec<_>>();
|
||||
let flat = grouped.iter().flat_map(|&g| g).collect::<IndexSet<_>>();
|
||||
let grouped: Vec<_> = targets.iter().filter_map(|(p, m)| self.openers(p, m)).collect();
|
||||
let flat: IndexSet<_> = grouped.iter().flatten().copied().collect();
|
||||
flat.into_iter().filter(|&o| grouped.iter().all(|g| g.contains(o))).collect()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
58
config/src/open/rule.rs
Normal file
58
config/src/open/rule.rs
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
use std::fmt;
|
||||
|
||||
use serde::{de::{self, Visitor}, Deserialize, Deserializer};
|
||||
|
||||
use crate::pattern::Pattern;
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub(super) struct OpenRule {
|
||||
pub(super) name: Option<Pattern>,
|
||||
pub(super) mime: Option<Pattern>,
|
||||
#[serde(rename = "use")]
|
||||
#[serde(deserialize_with = "OpenRule::deserialize")]
|
||||
pub(super) use_: Vec<String>,
|
||||
}
|
||||
|
||||
impl OpenRule {
|
||||
fn deserialize<'de, D>(deserializer: D) -> Result<Vec<String>, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
struct UseVisitor;
|
||||
|
||||
impl<'de> Visitor<'de> for UseVisitor {
|
||||
type Value = Vec<String>;
|
||||
|
||||
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
formatter.write_str("a string, or array of strings")
|
||||
}
|
||||
|
||||
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
|
||||
where
|
||||
A: de::SeqAccess<'de>,
|
||||
{
|
||||
let mut uses = Vec::new();
|
||||
while let Some(use_) = seq.next_element::<String>()? {
|
||||
uses.push(use_);
|
||||
}
|
||||
Ok(uses)
|
||||
}
|
||||
|
||||
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
Ok(vec![value.to_owned()])
|
||||
}
|
||||
|
||||
fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
Ok(vec![v])
|
||||
}
|
||||
}
|
||||
|
||||
deserializer.deserialize_any(UseVisitor)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
use std::{cmp::Ordering, collections::BTreeMap, mem, ops::Deref};
|
||||
use std::{cmp::Ordering, collections::BTreeMap, mem};
|
||||
|
||||
use config::{manager::SortBy, MANAGER};
|
||||
use shared::Url;
|
||||
|
|
|
|||
|
|
@ -362,14 +362,13 @@ impl Manager {
|
|||
|
||||
if url == self.cwd() {
|
||||
self.current_mut().update(op);
|
||||
} else if matches!(self.parent(), Some(p) if &p.cwd == url) {
|
||||
self.active_mut().parent.as_mut().unwrap().update(op);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
self.active_mut().leave();
|
||||
true
|
||||
} else if matches!(self.parent(), Some(p) if &p.cwd == url) {
|
||||
self.active_mut().parent.as_mut().unwrap().update(op)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update_mimetype(&mut self, mut mimes: BTreeMap<Url, String>, tasks: &Tasks) -> bool {
|
||||
|
|
|
|||
|
|
@ -33,7 +33,11 @@ impl Tabs {
|
|||
}
|
||||
|
||||
pub fn switch(&mut self, idx: isize, rel: bool) -> bool {
|
||||
let idx = if rel { self.absolute(idx) } else { idx as usize };
|
||||
let idx = if rel {
|
||||
(self.idx as isize + idx).rem_euclid(self.items.len() as isize) as usize
|
||||
} else {
|
||||
idx as usize
|
||||
};
|
||||
|
||||
if idx == self.idx || idx >= self.items.len() {
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -134,7 +134,7 @@ impl Tasks {
|
|||
pub fn file_open(&self, targets: &[(impl AsRef<Path>, impl AsRef<str>)]) -> bool {
|
||||
let mut openers = BTreeMap::new();
|
||||
for (path, mime) in targets {
|
||||
if let Some(opener) = OPEN.openers(path, mime).and_then(|o| o.first()) {
|
||||
if let Some(opener) = OPEN.openers(path, mime).and_then(|o| o.first().copied()) {
|
||||
openers.entry(opener).or_insert_with(Vec::new).push(path.as_ref().as_os_str());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,10 @@ pub fn expand_path(p: impl AsRef<Path>) -> PathBuf {
|
|||
return PathBuf::from_iter([&home, p.as_os_str()]);
|
||||
}
|
||||
}
|
||||
p.to_path_buf()
|
||||
if p.is_absolute() {
|
||||
return p.to_path_buf();
|
||||
}
|
||||
env::current_dir().map_or_else(|_| p.to_path_buf(), |c| c.join(p))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
|
|
|||
|
|
@ -99,6 +99,8 @@ pub fn file_mode(mode: u32) -> String {
|
|||
|
||||
#[cfg(target_os = "macos")]
|
||||
let m = mode as u16;
|
||||
#[cfg(target_os = "freebsd")]
|
||||
let m = mode as u16;
|
||||
#[cfg(target_os = "linux")]
|
||||
let m = mode;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue