mirror of
https://github.com/sxyazi/yazi.git
synced 2026-07-25 08:41:05 +00:00
feat: platform-specific key binding (#2526)
This commit is contained in:
parent
83f4deecfe
commit
e138364102
10 changed files with 57 additions and 43 deletions
|
|
@ -1,4 +1,4 @@
|
||||||
use anyhow::{Context, Result};
|
use anyhow::{Context, Result, bail};
|
||||||
use tokio::fs;
|
use tokio::fs;
|
||||||
use twox_hash::XxHash3_128;
|
use twox_hash::XxHash3_128;
|
||||||
use yazi_fs::ok_or_not_found;
|
use yazi_fs::ok_or_not_found;
|
||||||
|
|
@ -22,18 +22,21 @@ impl Dependency {
|
||||||
&["LICENSE", "README.md", "main.lua"][..]
|
&["LICENSE", "README.md", "main.lua"][..]
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut hasher = XxHash3_128::new();
|
let mut h = XxHash3_128::new();
|
||||||
for file in files {
|
for &file in files {
|
||||||
hasher.write(file.as_bytes());
|
h.write(file.as_bytes());
|
||||||
hasher.write(b"VpvFw9Atb7cWGOdqhZCra634CcJJRlsRl72RbZeV0vpG1\0");
|
h.write(b"VpvFw9Atb7cWGOdqhZCra634CcJJRlsRl72RbZeV0vpG1\0");
|
||||||
hasher.write(&ok_or_not_found(fs::read(dir.join(file)).await)?);
|
h.write(&ok_or_not_found(fs::read(dir.join(file)).await)?);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut assets = vec![];
|
let mut assets = vec![];
|
||||||
match fs::read_dir(dir.join("assets")).await {
|
match fs::read_dir(dir.join("assets")).await {
|
||||||
Ok(mut it) => {
|
Ok(mut it) => {
|
||||||
while let Some(entry) = it.next_entry().await? {
|
while let Some(entry) = it.next_entry().await? {
|
||||||
assets.push((entry.file_name(), fs::read(entry.path()).await?));
|
let Ok(name) = entry.file_name().into_string() else {
|
||||||
|
bail!("asset path is not valid UTF-8: {}", entry.path().display());
|
||||||
|
};
|
||||||
|
assets.push((name, fs::read(entry.path()).await?));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(e) if e.kind() == std::io::ErrorKind::NotFound => {}
|
Err(e) if e.kind() == std::io::ErrorKind::NotFound => {}
|
||||||
|
|
@ -42,11 +45,11 @@ impl Dependency {
|
||||||
|
|
||||||
assets.sort_unstable_by(|(a, _), (b, _)| a.cmp(b));
|
assets.sort_unstable_by(|(a, _), (b, _)| a.cmp(b));
|
||||||
for (name, data) in assets {
|
for (name, data) in assets {
|
||||||
hasher.write(name.as_encoded_bytes());
|
h.write(name.as_bytes());
|
||||||
hasher.write(b"pQU2in0xcsu97Y77Nuq2LnT8mczMlFj22idcYRmMrglqU\0");
|
h.write(b"pQU2in0xcsu97Y77Nuq2LnT8mczMlFj22idcYRmMrglqU\0");
|
||||||
hasher.write(&data);
|
h.write(&data);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(format!("{:x}", hasher.finish_128()))
|
Ok(format!("{:x}", h.finish_128()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
use std::{borrow::Cow, hash::{Hash, Hasher}, sync::OnceLock};
|
use std::{borrow::Cow, hash::{Hash, Hasher}, sync::OnceLock};
|
||||||
|
|
||||||
|
use anyhow::Result;
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use yazi_shared::{Layer, event::Cmd};
|
use yazi_shared::{Layer, event::Cmd};
|
||||||
|
|
@ -15,6 +16,8 @@ pub struct Chord {
|
||||||
#[serde(deserialize_with = "super::deserialize_run")]
|
#[serde(deserialize_with = "super::deserialize_run")]
|
||||||
pub run: Vec<Cmd>,
|
pub run: Vec<Cmd>,
|
||||||
pub desc: Option<String>,
|
pub desc: Option<String>,
|
||||||
|
#[serde(rename = "for")]
|
||||||
|
pub for_: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PartialEq for Chord {
|
impl PartialEq for Chord {
|
||||||
|
|
@ -53,14 +56,15 @@ impl Chord {
|
||||||
pub(super) fn noop(&self) -> bool {
|
pub(super) fn noop(&self) -> bool {
|
||||||
self.run.len() == 1 && self.run[0].name == "noop" && self.run[0].args.is_empty()
|
self.run.len() == 1 && self.run[0].name == "noop" && self.run[0].args.is_empty()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
impl Chord {
|
||||||
pub(super) fn with_layer(mut self, layer: Layer) -> Self {
|
pub(super) fn reshape(mut self, layer: Layer) -> Result<Self> {
|
||||||
for c in &mut self.run {
|
for cmd in &mut self.run {
|
||||||
if c.layer == Default::default() {
|
if cmd.layer == Default::default() {
|
||||||
c.layer = layer;
|
cmd.layer = layer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self
|
Ok(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ where
|
||||||
where
|
where
|
||||||
A: de::SeqAccess<'de>,
|
A: de::SeqAccess<'de>,
|
||||||
{
|
{
|
||||||
let mut cmds = vec![];
|
let mut cmds = Vec::with_capacity(seq.size_hint().unwrap_or(0));
|
||||||
while let Some(value) = &seq.next_element::<String>()? {
|
while let Some(value) = &seq.next_element::<String>()? {
|
||||||
cmds.push(Key::from_str(value).map_err(de::Error::custom)?);
|
cmds.push(Key::from_str(value).map_err(de::Error::custom)?);
|
||||||
}
|
}
|
||||||
|
|
@ -61,7 +61,7 @@ where
|
||||||
where
|
where
|
||||||
A: de::SeqAccess<'de>,
|
A: de::SeqAccess<'de>,
|
||||||
{
|
{
|
||||||
let mut cmds = vec![];
|
let mut cmds = Vec::with_capacity(seq.size_hint().unwrap_or(0));
|
||||||
while let Some(value) = &seq.next_element::<String>()? {
|
while let Some(value) = &seq.next_element::<String>()? {
|
||||||
cmds.push(Cmd::from_str(value).map_err(de::Error::custom)?);
|
cmds.push(Cmd::from_str(value).map_err(de::Error::custom)?);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,19 +3,19 @@ use serde::Deserialize;
|
||||||
use yazi_codegen::DeserializeOver1;
|
use yazi_codegen::DeserializeOver1;
|
||||||
use yazi_shared::Layer;
|
use yazi_shared::Layer;
|
||||||
|
|
||||||
use super::{Chord, KeymapRule};
|
use super::{Chord, KeymapRules};
|
||||||
|
|
||||||
#[derive(Deserialize, DeserializeOver1)]
|
#[derive(Deserialize, DeserializeOver1)]
|
||||||
pub struct Keymap {
|
pub struct Keymap {
|
||||||
#[serde(rename = "manager")]
|
#[serde(rename = "manager")]
|
||||||
pub mgr: KeymapRule,
|
pub mgr: KeymapRules,
|
||||||
pub tasks: KeymapRule,
|
pub tasks: KeymapRules,
|
||||||
pub spot: KeymapRule,
|
pub spot: KeymapRules,
|
||||||
pub pick: KeymapRule,
|
pub pick: KeymapRules,
|
||||||
pub input: KeymapRule,
|
pub input: KeymapRules,
|
||||||
pub confirm: KeymapRule,
|
pub confirm: KeymapRules,
|
||||||
pub help: KeymapRule,
|
pub help: KeymapRules,
|
||||||
pub cmp: KeymapRule,
|
pub cmp: KeymapRules,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Keymap {
|
impl Keymap {
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
yazi_macro::mod_flat!(chord cow deserializers key keymap rule);
|
yazi_macro::mod_flat!(chord cow deserializers key keymap rules);
|
||||||
|
|
|
||||||
|
|
@ -6,10 +6,10 @@ use yazi_codegen::DeserializeOver2;
|
||||||
use yazi_shared::Layer;
|
use yazi_shared::Layer;
|
||||||
|
|
||||||
use super::Chord;
|
use super::Chord;
|
||||||
use crate::{Preset, keymap::Key};
|
use crate::{Preset, check_for, keymap::Key};
|
||||||
|
|
||||||
#[derive(Default, Deserialize, DeserializeOver2)]
|
#[derive(Default, Deserialize, DeserializeOver2)]
|
||||||
pub struct KeymapRule {
|
pub struct KeymapRules {
|
||||||
pub keymap: Vec<Chord>,
|
pub keymap: Vec<Chord>,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
prepend_keymap: Vec<Chord>,
|
prepend_keymap: Vec<Chord>,
|
||||||
|
|
@ -17,13 +17,13 @@ pub struct KeymapRule {
|
||||||
append_keymap: Vec<Chord>,
|
append_keymap: Vec<Chord>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Deref for KeymapRule {
|
impl Deref for KeymapRules {
|
||||||
type Target = Vec<Chord>;
|
type Target = Vec<Chord>;
|
||||||
|
|
||||||
fn deref(&self) -> &Self::Target { &self.keymap }
|
fn deref(&self) -> &Self::Target { &self.keymap }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl KeymapRule {
|
impl KeymapRules {
|
||||||
pub(crate) fn reshape(self, layer: Layer) -> Result<Self> {
|
pub(crate) fn reshape(self, layer: Layer) -> Result<Self> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn on(Chord { on, .. }: &Chord) -> [Key; 2] {
|
fn on(Chord { on, .. }: &Chord) -> [Key; 2] {
|
||||||
|
|
@ -38,9 +38,10 @@ impl KeymapRule {
|
||||||
self.keymap.into_iter().filter(|v| !a_seen.contains(&on(v))),
|
self.keymap.into_iter().filter(|v| !a_seen.contains(&on(v))),
|
||||||
self.append_keymap.into_iter().filter(|v| !b_seen.contains(&on(v))),
|
self.append_keymap.into_iter().filter(|v| !b_seen.contains(&on(v))),
|
||||||
)
|
)
|
||||||
.filter(|chord| !chord.noop())
|
.map(|mut chord| (chord.for_.take(), chord))
|
||||||
.map(|chord| chord.with_layer(layer))
|
.filter(|(for_, chord)| !chord.noop() && check_for(for_.as_deref()))
|
||||||
.collect();
|
.map(|(_, chord)| chord.reshape(layer))
|
||||||
|
.collect::<Result<_>>()?;
|
||||||
|
|
||||||
Ok(Self { keymap, ..Default::default() })
|
Ok(Self { keymap, ..Default::default() })
|
||||||
}
|
}
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
yazi_macro::mod_pub!(keymap mgr open opener plugin popup preview tasks theme which);
|
yazi_macro::mod_pub!(keymap mgr open opener plugin popup preview tasks theme which);
|
||||||
|
|
||||||
yazi_macro::mod_flat!(layout pattern preset priority yazi);
|
yazi_macro::mod_flat!(layout pattern platform preset priority yazi);
|
||||||
|
|
||||||
use std::io::{Read, Write};
|
use std::io::{Read, Write};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ use indexmap::IndexSet;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
|
||||||
use super::OpenerRule;
|
use super::OpenerRule;
|
||||||
|
use crate::check_for;
|
||||||
|
|
||||||
#[derive(Debug, Deserialize)]
|
#[derive(Debug, Deserialize)]
|
||||||
pub struct Opener(HashMap<String, Vec<OpenerRule>>);
|
pub struct Opener(HashMap<String, Vec<OpenerRule>>);
|
||||||
|
|
@ -44,12 +45,7 @@ impl Opener {
|
||||||
*rules = mem::take(rules)
|
*rules = mem::take(rules)
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|mut r| (r.for_.take(), r))
|
.map(|mut r| (r.for_.take(), r))
|
||||||
.filter(|(for_, _)| match for_.as_ref().map(|s| s.as_str()) {
|
.filter(|(for_, _)| check_for(for_.as_deref()))
|
||||||
Some("unix") if cfg!(unix) => true,
|
|
||||||
Some(os) if os == std::env::consts::OS => true,
|
|
||||||
Some(_) => false,
|
|
||||||
None => true,
|
|
||||||
})
|
|
||||||
.map(|(_, r)| r.reshape())
|
.map(|(_, r)| r.reshape())
|
||||||
.collect::<Result<IndexSet<_>>>()?
|
.collect::<Result<IndexSet<_>>>()?
|
||||||
.into_iter()
|
.into_iter()
|
||||||
|
|
|
||||||
9
yazi-config/src/platform.rs
Normal file
9
yazi-config/src/platform.rs
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
#[inline]
|
||||||
|
pub(crate) fn check_for(for_: Option<&str>) -> bool {
|
||||||
|
match for_.as_ref().map(|s| s.as_ref()) {
|
||||||
|
Some("unix") if cfg!(unix) => true,
|
||||||
|
Some(os) if os == std::env::consts::OS => true,
|
||||||
|
Some(_) => false,
|
||||||
|
None => true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -23,6 +23,7 @@ impl Utils {
|
||||||
on: Self::parse_keys(cand.raw_get("on")?)?,
|
on: Self::parse_keys(cand.raw_get("on")?)?,
|
||||||
run: vec![Cmd::args("which:callback", &[i]).with_any("tx", tx.clone())],
|
run: vec![Cmd::args("which:callback", &[i]).with_any("tx", tx.clone())],
|
||||||
desc: cand.raw_get("desc").ok(),
|
desc: cand.raw_get("desc").ok(),
|
||||||
|
for_: None,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue