mirror of
https://github.com/sxyazi/yazi.git
synced 2026-07-21 14:51:03 +00:00
fix: ignore NumLock state when comparing keybindings (#4071)
This commit is contained in:
parent
0ba1811af3
commit
4f45ddb514
40 changed files with 139 additions and 116 deletions
23
Cargo.lock
generated
23
Cargo.lock
generated
|
|
@ -543,9 +543,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.2.64"
|
||||
version = "1.2.65"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dad887fd958be91b5098c0248def011f4523ab786cd411be668777e55063501f"
|
||||
checksum = "e228eec9be7c17ccb640b59b36a5cd805ea2a564a4c5e162c2f659fea30d3b96"
|
||||
dependencies = [
|
||||
"find-msvc-tools",
|
||||
"jobserver",
|
||||
|
|
@ -2880,14 +2880,14 @@ checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69"
|
|||
|
||||
[[package]]
|
||||
name = "ratatui-core"
|
||||
version = "0.1.1"
|
||||
source = "git+https://github.com/yazi-rs/ratatui.git?rev=a1c4922a242861d755163ae85d7e41b85ed277d2#a1c4922a242861d755163ae85d7e41b85ed277d2"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cbb175c433c8e28a809d1f5773a2ae96e68c0ce40db865cbab1020bf33ae479c"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"compact_str",
|
||||
"critical-section",
|
||||
"hashbrown 0.17.1",
|
||||
"indoc",
|
||||
"itertools",
|
||||
"kasuari",
|
||||
"lru",
|
||||
|
|
@ -2902,8 +2902,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "ratatui-widgets"
|
||||
version = "0.3.1"
|
||||
source = "git+https://github.com/yazi-rs/ratatui.git?rev=a1c4922a242861d755163ae85d7e41b85ed277d2#a1c4922a242861d755163ae85d7e41b85ed277d2"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "66e3d19bcc9130ca376277d93b60767ff121ace3be06f5f95f81dd68956407d1"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"hashbrown 0.17.1",
|
||||
|
|
@ -4705,10 +4706,8 @@ dependencies = [
|
|||
"indexmap 2.14.0",
|
||||
"libc",
|
||||
"mlua",
|
||||
"parking_lot",
|
||||
"paste",
|
||||
"ratatui-core",
|
||||
"ratatui-widgets",
|
||||
"scopeguard",
|
||||
"tokio",
|
||||
"tokio-stream",
|
||||
|
|
@ -4867,7 +4866,6 @@ dependencies = [
|
|||
"regex",
|
||||
"serde",
|
||||
"serde_with",
|
||||
"tokio",
|
||||
"toml",
|
||||
"tracing",
|
||||
"yazi-binding",
|
||||
|
|
@ -5343,11 +5341,13 @@ dependencies = [
|
|||
"mlua",
|
||||
"parking_lot",
|
||||
"russh",
|
||||
"serde",
|
||||
"tokio",
|
||||
"toml",
|
||||
"tracing",
|
||||
"typed-path",
|
||||
"yazi-binding",
|
||||
"yazi-config",
|
||||
"yazi-codegen",
|
||||
"yazi-fs",
|
||||
"yazi-macro",
|
||||
"yazi-sftp",
|
||||
|
|
@ -5396,6 +5396,7 @@ dependencies = [
|
|||
"tracing",
|
||||
"unicode-width",
|
||||
"yazi-binding",
|
||||
"yazi-dds",
|
||||
"yazi-macro",
|
||||
"yazi-shared",
|
||||
"yazi-shim",
|
||||
|
|
|
|||
|
|
@ -62,8 +62,8 @@ parking_lot = "0.12.5"
|
|||
paste = "1.0.15"
|
||||
percent-encoding = "2.3.2"
|
||||
rand = { version = "0.10.1", default-features = false, features = [ "std", "sys_rng" ] }
|
||||
ratatui-core = { version = "0.1.1", default-features = false, features = [ "std", "layout-cache", "serde", "underline-color" ] }
|
||||
ratatui-widgets = { version = "0.3.1", default-features = false, features = [ "std", "unstable-rendered-line-info" ] }
|
||||
ratatui-core = { version = "0.1.2", default-features = false, features = [ "std", "layout-cache", "serde", "underline-color" ] }
|
||||
ratatui-widgets = { version = "0.3.2", default-features = false, features = [ "std", "unstable-rendered-line-info" ] }
|
||||
regex = "1.12.4"
|
||||
russh = { version = "0.61.2", default-features = false, features = [ "ring", "rsa" ] }
|
||||
scopeguard = "1.2.0"
|
||||
|
|
@ -93,7 +93,3 @@ module_inception = "allow"
|
|||
option_map_unit_fn = "allow"
|
||||
unit_arg = "allow"
|
||||
use_self = "warn"
|
||||
|
||||
[patch.crates-io]
|
||||
ratatui-core = { git = "https://github.com/yazi-rs/ratatui.git", package = "ratatui-core", rev = "a1c4922a242861d755163ae85d7e41b85ed277d2" }
|
||||
ratatui-widgets = { git = "https://github.com/yazi-rs/ratatui.git", package = "ratatui-widgets", rev = "a1c4922a242861d755163ae85d7e41b85ed277d2" }
|
||||
|
|
|
|||
|
|
@ -28,10 +28,6 @@ rustPlatform.buildRustPackage (finalAttrs: {
|
|||
|
||||
cargoLock = {
|
||||
lockFile = "${src}/Cargo.lock";
|
||||
outputHashes = {
|
||||
"ratatui-core-0.1.1" = "sha256-wkEOgwAhW0ObtPDlJmOOoY5qf9c/P79ktN4b43jtcGw=";
|
||||
"ratatui-widgets-0.3.1" = "sha256-wkEOgwAhW0ObtPDlJmOOoY5qf9c/P79ktN4b43jtcGw=";
|
||||
};
|
||||
};
|
||||
|
||||
env = {
|
||||
|
|
|
|||
|
|
@ -46,10 +46,8 @@ futures = { workspace = true }
|
|||
hashbrown = { workspace = true }
|
||||
indexmap = { workspace = true }
|
||||
mlua = { workspace = true }
|
||||
parking_lot = { workspace = true }
|
||||
paste = { workspace = true }
|
||||
ratatui-core = { workspace = true }
|
||||
ratatui-widgets = { workspace = true }
|
||||
scopeguard = { workspace = true }
|
||||
tokio = { workspace = true }
|
||||
tokio-stream = { workspace = true }
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
use std::ops::DerefMut;
|
||||
|
||||
use anyhow::Result;
|
||||
use ratatui_core::layout::Margin;
|
||||
use yazi_config::{THEME, YAZI};
|
||||
use yazi_macro::{act, render, succ};
|
||||
use yazi_parser::input::ShowForm;
|
||||
use yazi_shared::data::Data;
|
||||
use yazi_shim::ratatui::Padable;
|
||||
|
||||
use crate::{Actor, Ctx};
|
||||
|
||||
|
|
@ -19,7 +19,7 @@ impl Actor for Show {
|
|||
fn act(cx: &mut Ctx, Self::Form { mut opt }: Self::Form) -> Result<Data> {
|
||||
act!(input:close, cx)?;
|
||||
|
||||
let area = cx.mgr.area(opt.position);
|
||||
let area = cx.mgr.area(opt.position).padding(cx.input.padding());
|
||||
let input = &mut cx.input;
|
||||
input.main.visible = true;
|
||||
input.main.title = opt.title.clone();
|
||||
|
|
@ -28,7 +28,7 @@ impl Actor for Show {
|
|||
opt.styles = (&THEME.input).into();
|
||||
opt.blinking = YAZI.input.cursor_blink;
|
||||
*input.main.deref_mut() = yazi_widgets::input::Input::new(opt)?;
|
||||
input.main.repos(area.inner(Margin::new(1, 1)));
|
||||
input.main.repos(area);
|
||||
|
||||
succ!(render!());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ impl From<ratatui_core::layout::Rect> for Area {
|
|||
}
|
||||
|
||||
impl From<Position> for Area {
|
||||
fn from(value: Position) -> Self { Self::Pos(value.into()) }
|
||||
fn from(value: Position) -> Self { Self::Pos(value) }
|
||||
}
|
||||
|
||||
impl TryFrom<&AnyUserData> for Area {
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ impl TryFrom<Table> for Position {
|
|||
type Error = mlua::Error;
|
||||
|
||||
fn try_from(t: Table) -> Result<Self, Self::Error> {
|
||||
Ok(Self::from(Position {
|
||||
Ok(Self {
|
||||
origin: Origin::from_str(&t.raw_get::<mlua::String>(1)?.to_str()?).into_lua_err()?,
|
||||
offset: Offset {
|
||||
x: t.raw_get("x").unwrap_or_default(),
|
||||
|
|
@ -28,7 +28,7 @@ impl TryFrom<Table> for Position {
|
|||
height: t.raw_get("h").unwrap_or_default(),
|
||||
},
|
||||
padding: Default::default(),
|
||||
}))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -37,6 +37,5 @@ ratatui-widgets = { workspace = true }
|
|||
regex = { workspace = true }
|
||||
serde = { workspace = true }
|
||||
serde_with = { workspace = true }
|
||||
tokio = { workspace = true }
|
||||
toml = { workspace = true }
|
||||
tracing = { workspace = true }
|
||||
|
|
|
|||
|
|
@ -7,9 +7,8 @@ use serde_with::{DeserializeAs, DisplayFromStr, OneOrMany};
|
|||
use yazi_binding::Iter;
|
||||
use yazi_codegen::DeserializeOver2;
|
||||
use yazi_shared::{Layer, event::{Actions, deserialize_actions}, id::Id};
|
||||
use yazi_term::event::KeyEvent;
|
||||
|
||||
use super::ids::chord_id;
|
||||
use super::{Key, ids::chord_id};
|
||||
use crate::{Mixable, Platform, keymap::{ChordArc, Chords}};
|
||||
|
||||
static RE: OnceLock<Regex> = OnceLock::new();
|
||||
|
|
@ -19,7 +18,7 @@ pub struct Chord<const L: u8 = { Layer::Null as u8 }> {
|
|||
#[serde(skip, default = "chord_id")]
|
||||
pub id: Id,
|
||||
#[serde(deserialize_with = "deserialize_on")]
|
||||
pub on: Vec<KeyEvent>,
|
||||
pub on: Vec<Key>,
|
||||
#[serde(deserialize_with = "deserialize_actions::<L, _>")]
|
||||
pub run: Actions,
|
||||
#[serde(default)]
|
||||
|
|
@ -84,11 +83,11 @@ impl<const L: u8> Mixable for Chord<L> {
|
|||
fn filter(&self) -> bool { self.r#for.matches() && !self.noop() }
|
||||
}
|
||||
|
||||
fn deserialize_on<'de, D>(deserializer: D) -> Result<Vec<KeyEvent>, D::Error>
|
||||
fn deserialize_on<'de, D>(deserializer: D) -> Result<Vec<Key>, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
let keys: Vec<KeyEvent> = OneOrMany::<DisplayFromStr>::deserialize_as(deserializer)?;
|
||||
let keys: Vec<Key> = OneOrMany::<DisplayFromStr>::deserialize_as(deserializer)?;
|
||||
if keys.is_empty() {
|
||||
return Err(de::Error::custom("'on' cannot be empty"));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,44 @@
|
|||
use std::{fmt::{Display, Write}, str::FromStr};
|
||||
|
||||
use anyhow::bail;
|
||||
use mlua::{IntoLua, Lua, LuaSerdeExt, Value};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use yazi_shim::mlua::SER_OPT;
|
||||
use yazi_term::event::{KeyCode, KeyEvent, Modifiers};
|
||||
|
||||
use crate::event::{KeyCode, KeyEvent, Modifiers};
|
||||
#[derive(Clone, Copy, Debug, Default, Deserialize, Eq, Hash, PartialEq, Serialize)]
|
||||
pub struct Key {
|
||||
#[serde(flatten)]
|
||||
pub code: KeyCode,
|
||||
pub shift: bool,
|
||||
pub ctrl: bool,
|
||||
pub alt: bool,
|
||||
#[serde(rename = "super")]
|
||||
pub super_: bool,
|
||||
}
|
||||
|
||||
impl FromStr for KeyEvent {
|
||||
impl Key {
|
||||
pub fn plain(&self) -> Option<char> {
|
||||
match self.code {
|
||||
KeyCode::Char(c) if !self.ctrl && !self.alt && !self.super_ => Some(c),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<KeyEvent> for Key {
|
||||
fn from(value: KeyEvent) -> Self {
|
||||
Self {
|
||||
code: value.code,
|
||||
shift: value.modifiers.contains(Modifiers::SHIFT),
|
||||
ctrl: value.modifiers.contains(Modifiers::CONTROL),
|
||||
alt: value.modifiers.contains(Modifiers::ALT),
|
||||
super_: value.modifiers.contains(Modifiers::SUPER),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for Key {
|
||||
type Err = anyhow::Error;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
|
|
@ -12,19 +46,20 @@ impl FromStr for KeyEvent {
|
|||
bail!("empty key")
|
||||
}
|
||||
|
||||
let mut key = Self::default();
|
||||
if !s.starts_with('<') || !s.ends_with('>') {
|
||||
let c = s.chars().next().unwrap();
|
||||
return Ok(Self::new(KeyCode::Char(c), Modifiers::for_char(c)));
|
||||
key.code = KeyCode::Char(s.chars().next().unwrap());
|
||||
key.shift = matches!(key.code, KeyCode::Char(c) if c.is_ascii_uppercase());
|
||||
return Ok(key);
|
||||
}
|
||||
|
||||
let mut key: Self = KeyCode::Null.into();
|
||||
let mut it = s[1..s.len() - 1].split_inclusive('-').peekable();
|
||||
while let Some(next) = it.next() {
|
||||
match next.to_ascii_lowercase().as_str() {
|
||||
"s-" => key.modifiers |= Modifiers::SHIFT,
|
||||
"c-" => key.modifiers |= Modifiers::CONTROL,
|
||||
"a-" => key.modifiers |= Modifiers::ALT,
|
||||
"d-" => key.modifiers |= Modifiers::SUPER,
|
||||
"s-" => key.shift = true,
|
||||
"c-" => key.ctrl = true,
|
||||
"a-" => key.alt = true,
|
||||
"d-" => key.super_ = true,
|
||||
|
||||
"space" => key.code = KeyCode::Char(' '),
|
||||
"backspace" => key.code = KeyCode::Backspace,
|
||||
|
|
@ -64,12 +99,8 @@ impl FromStr for KeyEvent {
|
|||
_ => match next {
|
||||
s if it.peek().is_none() => {
|
||||
let c = s.chars().next().unwrap();
|
||||
key.modifiers |= Modifiers::for_char(c);
|
||||
key.code = KeyCode::Char(if key.modifiers.contains(Modifiers::SHIFT) {
|
||||
c.to_ascii_uppercase()
|
||||
} else {
|
||||
c
|
||||
});
|
||||
key.shift |= c.is_ascii_uppercase();
|
||||
key.code = KeyCode::Char(if key.shift { c.to_ascii_uppercase() } else { c });
|
||||
}
|
||||
s => bail!("unknown key: {s}"),
|
||||
},
|
||||
|
|
@ -83,23 +114,23 @@ impl FromStr for KeyEvent {
|
|||
}
|
||||
}
|
||||
|
||||
impl Display for KeyEvent {
|
||||
impl Display for Key {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
if let Some(c) = self.plain() {
|
||||
return if c == ' ' { write!(f, "<Space>") } else { f.write_char(c) };
|
||||
}
|
||||
|
||||
write!(f, "<")?;
|
||||
if self.modifiers.contains(Modifiers::SUPER) {
|
||||
if self.super_ {
|
||||
write!(f, "D-")?;
|
||||
}
|
||||
if self.modifiers.contains(Modifiers::CONTROL) {
|
||||
if self.ctrl {
|
||||
write!(f, "C-")?;
|
||||
}
|
||||
if self.modifiers.contains(Modifiers::ALT) {
|
||||
if self.alt {
|
||||
write!(f, "A-")?;
|
||||
}
|
||||
if self.modifiers.contains(Modifiers::SHIFT) && !matches!(self.code, KeyCode::Char(_)) {
|
||||
if self.shift && !matches!(self.code, KeyCode::Char(_)) {
|
||||
write!(f, "S-")?;
|
||||
}
|
||||
|
||||
|
|
@ -149,3 +180,7 @@ impl Display for KeyEvent {
|
|||
write!(f, "{code}>")
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoLua for Key {
|
||||
fn into_lua(self, lua: &Lua) -> mlua::Result<Value> { lua.to_value_with(&self, SER_OPT) }
|
||||
}
|
||||
|
|
@ -1 +1 @@
|
|||
yazi_macro::mod_flat!(chord chord_arc chords ids keymap section);
|
||||
yazi_macro::mod_flat!(chord chord_arc chords ids key keymap section);
|
||||
|
|
|
|||
|
|
@ -6,9 +6,8 @@ use serde::Deserialize;
|
|||
use yazi_codegen::DeserializeOver2;
|
||||
use yazi_shared::Layer;
|
||||
use yazi_shim::{mlua::UserDataFieldsExt, toml::DeserializeOverHook};
|
||||
use yazi_term::event::KeyEvent;
|
||||
|
||||
use super::{Chord, Chords, chords::layer_default};
|
||||
use super::{Key, Chord, Chords, chords::layer_default};
|
||||
use crate::{keymap::ChordArc, mix};
|
||||
|
||||
#[derive(Default, Deserialize, DeserializeOver2)]
|
||||
|
|
@ -37,7 +36,7 @@ impl<const L: u8> KeymapSection<L> {
|
|||
impl<const L: u8> DeserializeOverHook for KeymapSection<L> {
|
||||
fn deserialize_over_hook(self) -> Result<Self, toml::de::Error> {
|
||||
#[inline]
|
||||
fn on<const L: u8>(Chord { on, .. }: &Chord<L>) -> [KeyEvent; 2] {
|
||||
fn on<const L: u8>(Chord { on, .. }: &Chord<L>) -> [Key; 2] {
|
||||
[on.first().copied().unwrap_or_default(), on.get(1).copied().unwrap_or_default()]
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
yazi_macro::mod_pub!(keymap mgr open opener plugin popup preview tasks theme vfs which);
|
||||
yazi_macro::mod_pub!(keymap mgr open opener plugin popup preview tasks theme which);
|
||||
|
||||
yazi_macro::mod_flat!(icon inject layout mixing pattern platform preset priority selectable selector utils yazi);
|
||||
yazi_macro::mod_flat!(icon inject layout mixing pattern platform preset priority selectable selector yazi);
|
||||
|
||||
use std::io::{Read, Write};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use crate::{Yazi, keymap::Keymap, theme::Theme, vfs::Vfs};
|
||||
use crate::{Yazi, keymap::Keymap, theme::Theme};
|
||||
|
||||
pub(crate) struct Preset;
|
||||
|
||||
|
|
@ -18,8 +18,4 @@ impl Preset {
|
|||
yazi_macro::theme_preset!("dark")
|
||||
})
|
||||
}
|
||||
|
||||
pub(super) fn vfs() -> Result<Vfs, toml::de::Error> {
|
||||
toml::from_str(&yazi_macro::config_preset!("vfs"))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,12 +3,11 @@ use std::path::PathBuf;
|
|||
use anyhow::{Context, Result};
|
||||
use serde::{Deserialize, Deserializer, Serialize};
|
||||
use yazi_codegen::DeserializeOver2;
|
||||
use yazi_fs::{Xdg, create_owned_dir_blocking};
|
||||
use yazi_fs::{Xdg, create_owned_dir_blocking, path::sanitize_path};
|
||||
use yazi_shared::timestamp_us;
|
||||
use yazi_shim::{SStr, toml::DeserializeOverHook};
|
||||
|
||||
use super::PreviewWrap;
|
||||
use crate::normalize_path;
|
||||
|
||||
#[derive(Debug, Deserialize, DeserializeOver2, Serialize)]
|
||||
pub struct Preview {
|
||||
|
|
@ -65,7 +64,7 @@ where
|
|||
if path.as_os_str().is_empty() {
|
||||
Ok(Xdg::temp_dir().to_owned())
|
||||
} else {
|
||||
normalize_path(path).ok_or_else(|| {
|
||||
sanitize_path(path).ok_or_else(|| {
|
||||
serde::de::Error::custom("cache_dir must be either empty or an absolute path.")
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,11 +5,10 @@ use arc_swap::ArcSwap;
|
|||
use serde::{Deserialize, Deserializer, de};
|
||||
use yazi_binding::style::StyleFlat;
|
||||
use yazi_codegen::{DeserializeOver, DeserializeOver1, DeserializeOver2, Overlay};
|
||||
use yazi_fs::{Xdg, ok_or_not_found};
|
||||
use yazi_fs::{Xdg, ok_or_not_found, path::sanitize_path};
|
||||
use yazi_shim::{arc_swap::IntoPointee, cell::SyncCell};
|
||||
|
||||
use super::{Custom, Filetype, Flavor, Icon};
|
||||
use crate::normalize_path;
|
||||
|
||||
#[derive(Deserialize, DeserializeOver, DeserializeOver1, Overlay)]
|
||||
pub struct Theme {
|
||||
|
|
@ -274,7 +273,7 @@ where
|
|||
{
|
||||
let mut path = PathBuf::deserialize(deserializer)?;
|
||||
if !path.as_os_str().is_empty() {
|
||||
path = normalize_path(path).ok_or_else(|| {
|
||||
path = sanitize_path(path).ok_or_else(|| {
|
||||
de::Error::custom("syntect_theme must be either empty or an absolute path.")
|
||||
})?;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
use ratatui_core::layout::{Margin, Position, Rect};
|
||||
use ratatui_core::layout::{Position, Rect};
|
||||
use yazi_shared::Layer;
|
||||
use yazi_shim::ratatui::Padable;
|
||||
use yazi_tty::sequence::SetCursorStyle;
|
||||
|
||||
use crate::{cmp::Cmp, confirm::Confirm, help::Help, input::{Input, InputGuard}, mgr::Mgr, notify::Notify, pick::Pick, tab::{Folder, Tab}, tasks::Tasks, which::Which};
|
||||
|
|
@ -34,7 +35,7 @@ impl Core {
|
|||
pub fn cursor(&self) -> Option<(Position, SetCursorStyle)> {
|
||||
if let Some(guard) = self.input.lock() {
|
||||
let Rect { x, y, .. } = match &guard {
|
||||
InputGuard::Main(_) => self.mgr.area(self.input.position()?).inner(Margin::new(1, 1)),
|
||||
InputGuard::Main(_) => self.mgr.area(self.input.position()?).padding(self.input.padding()),
|
||||
InputGuard::Alt(_) => self.mgr.area(self.input.position()?),
|
||||
};
|
||||
return Some((Position { x: x + guard.cursor(), y }, guard.cursor_shape()));
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
use std::{ops::{Deref, DerefMut}, sync::Arc};
|
||||
|
||||
use parking_lot::Mutex;
|
||||
use ratatui_widgets::block::Padding;
|
||||
use yazi_binding::{elements::Spatial, position::Position};
|
||||
|
||||
use crate::input::{InputGuard, InputMutGuard};
|
||||
|
|
@ -14,6 +15,8 @@ pub struct Input {
|
|||
impl Input {
|
||||
pub fn focus(&self) -> bool { self.main.visible || self.alt.is_some() }
|
||||
|
||||
pub fn padding(&self) -> Padding { Padding::new(1, 1, 1, 1) }
|
||||
|
||||
pub fn position(&self) -> Option<Position> {
|
||||
if self.main.visible {
|
||||
Some(self.main.position)
|
||||
|
|
|
|||
|
|
@ -1,9 +1,8 @@
|
|||
use mlua::{ExternalError, FromLua, IntoLua, Lua, Table, Value};
|
||||
use tokio::sync::mpsc;
|
||||
use yazi_config::{KEYMAP, keymap::ChordArc};
|
||||
use yazi_config::{KEYMAP, keymap::{ChordArc, Key}};
|
||||
use yazi_macro::impl_data_any;
|
||||
use yazi_shared::{Layer, event::ActionCow};
|
||||
use yazi_term::event::KeyEvent;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct WhichOpt {
|
||||
|
|
@ -32,8 +31,8 @@ impl TryFrom<ActionCow> for WhichOpt {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<(Layer, KeyEvent)> for WhichOpt {
|
||||
fn from((layer, key): (Layer, KeyEvent)) -> Self {
|
||||
impl From<(Layer, Key)> for WhichOpt {
|
||||
fn from((layer, key): (Layer, Key)) -> Self {
|
||||
Self {
|
||||
tx: None,
|
||||
cands: KEYMAP
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
use tokio::sync::mpsc;
|
||||
use yazi_config::keymap::ChordArc;
|
||||
use yazi_config::keymap::{ChordArc, Key};
|
||||
use yazi_macro::{emit, render_and};
|
||||
use yazi_term::event::KeyEvent;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Which {
|
||||
|
|
@ -15,7 +14,7 @@ pub struct Which {
|
|||
}
|
||||
|
||||
impl Which {
|
||||
pub fn r#type(&mut self, key: KeyEvent) -> bool {
|
||||
pub fn r#type(&mut self, key: Key) -> bool {
|
||||
self.cands.retain(|c| c.on.len() > self.times && c.on[self.times] == key);
|
||||
self.times += 1;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use anyhow::Result;
|
||||
use yazi_actor::Ctx;
|
||||
use yazi_config::{KEYMAP, keymap::Chord};
|
||||
use yazi_config::{KEYMAP, keymap::{Chord, Key}};
|
||||
use yazi_macro::act;
|
||||
use yazi_shared::Layer;
|
||||
use yazi_term::event::KeyEvent;
|
||||
|
|
@ -29,6 +29,7 @@ impl<'a> Router<'a> {
|
|||
}
|
||||
|
||||
let layer = core.layer();
|
||||
let key = Key::from(key);
|
||||
Ok(match layer {
|
||||
L::Null | L::App | L::Notify => unreachable!(),
|
||||
L::Mgr | L::Tasks | L::Spot | L::Pick | L::Input | L::Confirm | L::Help => {
|
||||
|
|
@ -39,7 +40,7 @@ impl<'a> Router<'a> {
|
|||
})
|
||||
}
|
||||
|
||||
fn matches(&mut self, layer: Layer, key: KeyEvent) -> bool {
|
||||
fn matches(&mut self, layer: Layer, key: Key) -> bool {
|
||||
for chord in &*KEYMAP.chords(layer) {
|
||||
let Chord { on, .. } = chord.as_ref();
|
||||
if on.is_empty() || on[0] != key {
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
yazi_macro::mod_flat!(clean expand path percent relative);
|
||||
yazi_macro::mod_flat!(clean expand normalize path percent relative);
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
use std::path::PathBuf;
|
||||
|
||||
use yazi_fs::path::{clean_url, expand_url};
|
||||
use yazi_shared::url::UrlBuf;
|
||||
|
||||
pub(crate) fn normalize_path(path: PathBuf) -> Option<PathBuf> {
|
||||
use crate::path::{clean_url, expand_url};
|
||||
|
||||
pub fn sanitize_path(path: PathBuf) -> Option<PathBuf> {
|
||||
clean_url(yazi_fs::provider::local::try_absolute(expand_url(UrlBuf::from(path)))?)
|
||||
.into_loc()
|
||||
.into_os()
|
||||
|
|
@ -6,7 +6,7 @@ macro_rules! config_preset {
|
|||
std::borrow::Cow::from(
|
||||
std::fs::read_to_string(concat!(
|
||||
env!("CARGO_MANIFEST_DIR"),
|
||||
"/preset/",
|
||||
"/../yazi-config/preset/",
|
||||
$name,
|
||||
"-default.toml"
|
||||
))
|
||||
|
|
@ -17,7 +17,7 @@ macro_rules! config_preset {
|
|||
{
|
||||
std::borrow::Cow::from(include_str!(concat!(
|
||||
env!("CARGO_MANIFEST_DIR"),
|
||||
"/preset/",
|
||||
"/../yazi-config/preset/",
|
||||
$name,
|
||||
"-default.toml"
|
||||
)))
|
||||
|
|
|
|||
|
|
@ -1,15 +1,15 @@
|
|||
use mlua::{FromLua, IntoLua, Lua, Value};
|
||||
use yazi_config::keymap::Key;
|
||||
use yazi_core::which::WhichOpt;
|
||||
use yazi_shared::{Layer, event::ActionCow};
|
||||
use yazi_term::event::KeyEvent;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct ActivateForm {
|
||||
pub opt: WhichOpt,
|
||||
}
|
||||
|
||||
impl From<(Layer, KeyEvent)> for ActivateForm {
|
||||
fn from(value: (Layer, KeyEvent)) -> Self { Self { opt: value.into() } }
|
||||
impl From<(Layer, Key)> for ActivateForm {
|
||||
fn from(value: (Layer, Key)) -> Self { Self { opt: value.into() } }
|
||||
}
|
||||
|
||||
impl TryFrom<ActionCow> for ActivateForm {
|
||||
|
|
|
|||
|
|
@ -3,12 +3,11 @@ use std::{str::FromStr, time::Duration};
|
|||
use mlua::{ExternalError, ExternalResult, Function, IntoLuaMulti, Lua, Table, Value};
|
||||
use tokio_stream::wrappers::UnboundedReceiverStream;
|
||||
use yazi_binding::{elements::{Line, Text}, runtime};
|
||||
use yazi_config::{Platform, keymap::{Chord, ChordArc}, popup::ConfirmCfg};
|
||||
use yazi_config::{Platform, keymap::{Chord, ChordArc, Key}, popup::ConfirmCfg};
|
||||
use yazi_core::notify::MessageOpt;
|
||||
use yazi_macro::relay;
|
||||
use yazi_proxy::{ConfirmProxy, InputProxy, NotifyProxy, WhichProxy};
|
||||
use yazi_shared::{Debounce, Layer};
|
||||
use yazi_term::event::KeyEvent;
|
||||
use yazi_widgets::input::{InputOpt, InputStream};
|
||||
|
||||
use super::Utils;
|
||||
|
|
@ -93,15 +92,15 @@ impl Utils {
|
|||
lua.create_function(|_, opt: MessageOpt| Ok(NotifyProxy::push(opt)))
|
||||
}
|
||||
|
||||
fn parse_keys(value: Value) -> mlua::Result<Vec<KeyEvent>> {
|
||||
fn parse_keys(value: Value) -> mlua::Result<Vec<Key>> {
|
||||
Ok(match value {
|
||||
Value::String(s) => {
|
||||
vec![KeyEvent::from_str(&s.to_str()?).into_lua_err()?]
|
||||
vec![Key::from_str(&s.to_str()?).into_lua_err()?]
|
||||
}
|
||||
Value::Table(t) => {
|
||||
let mut v = Vec::with_capacity(10);
|
||||
for s in t.sequence_values::<mlua::String>() {
|
||||
v.push(KeyEvent::from_str(&s?.to_str()?).into_lua_err()?);
|
||||
v.push(Key::from_str(&s?.to_str()?).into_lua_err()?);
|
||||
}
|
||||
v
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
yazi_macro::mod_flat!(conversion dnd event keyboard lua modifiers mouse);
|
||||
yazi_macro::mod_flat!(dnd event keyboard lua modifiers mouse);
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ workspace = true
|
|||
|
||||
[dependencies]
|
||||
yazi-binding = { path = "../yazi-binding", version = "26.5.6" }
|
||||
yazi-config = { path = "../yazi-config", version = "26.5.6" }
|
||||
yazi-codegen = { path = "../yazi-codegen", version = "26.5.6" }
|
||||
yazi-fs = { path = "../yazi-fs", version = "26.5.6" }
|
||||
yazi-macro = { path = "../yazi-macro", version = "26.5.6" }
|
||||
yazi-sftp = { path = "../yazi-sftp", version = "26.5.6" }
|
||||
|
|
@ -31,6 +31,8 @@ hashbrown = { workspace = true }
|
|||
mlua = { workspace = true }
|
||||
parking_lot = { workspace = true }
|
||||
russh = { workspace = true }
|
||||
serde = { workspace = true }
|
||||
tokio = { workspace = true }
|
||||
toml = { workspace = true }
|
||||
tracing = { workspace = true }
|
||||
typed-path = { workspace = true }
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::vfs::ServiceSftp;
|
||||
use crate::config::ServiceSftp;
|
||||
|
||||
#[derive(Deserialize, Serialize)]
|
||||
#[serde(tag = "type", rename_all = "kebab-case")]
|
||||
|
|
@ -6,7 +6,7 @@ use serde::{Deserialize, Deserializer, Serialize, de, de::{MapAccess, Visitor}};
|
|||
use yazi_codegen::DeserializeOver;
|
||||
use yazi_shim::toml::DeserializeOverWith;
|
||||
|
||||
use crate::vfs::Service;
|
||||
use crate::config::Service;
|
||||
|
||||
#[derive(Serialize, Deserialize, DeserializeOver)]
|
||||
pub struct Services(HashMap<String, Service>);
|
||||
|
|
@ -1,8 +1,7 @@
|
|||
use std::{env, path::PathBuf};
|
||||
|
||||
use serde::{Deserialize, Deserializer, Serialize, de};
|
||||
|
||||
use crate::normalize_path;
|
||||
use yazi_fs::path::sanitize_path;
|
||||
|
||||
#[derive(Deserialize, Eq, Hash, PartialEq, Serialize)]
|
||||
pub struct ServiceSftp {
|
||||
|
|
@ -27,7 +26,7 @@ where
|
|||
{
|
||||
let mut path = PathBuf::deserialize(deserializer)?;
|
||||
if !path.as_os_str().is_empty() {
|
||||
path = normalize_path(path)
|
||||
path = sanitize_path(path)
|
||||
.ok_or_else(|| de::Error::custom("path must be either empty or an absolute path"))?;
|
||||
}
|
||||
|
||||
|
|
@ -46,7 +45,7 @@ where
|
|||
if path.as_os_str().is_empty() {
|
||||
Ok(default_identity_agent())
|
||||
} else {
|
||||
normalize_path(path)
|
||||
sanitize_path(path)
|
||||
.ok_or_else(|| de::Error::custom("identity_agent must be either empty or an absolute path"))
|
||||
}
|
||||
}
|
||||
|
|
@ -8,7 +8,7 @@ use yazi_fs::{Xdg, ok_or_not_found};
|
|||
use yazi_shim::toml::DeserializeOver;
|
||||
|
||||
use super::Service;
|
||||
use crate::{Preset, vfs::Services};
|
||||
use crate::config::Services;
|
||||
|
||||
#[derive(Deserialize, Serialize, DeserializeOver, DeserializeOver1)]
|
||||
pub struct Vfs {
|
||||
|
|
@ -21,7 +21,8 @@ impl Vfs {
|
|||
|
||||
async fn init() -> io::Result<Vfs> {
|
||||
tokio::task::spawn_blocking(|| -> anyhow::Result<Vfs> {
|
||||
Ok(Preset::vfs()?.deserialize_over(&Vfs::read()?)?)
|
||||
let vfs: Vfs = toml::from_str(&yazi_macro::config_preset!("vfs"))?;
|
||||
Ok(vfs.deserialize_over(&Vfs::read()?)?)
|
||||
})
|
||||
.await?
|
||||
.map_err(io::Error::other)
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
yazi_macro::mod_pub!(provider);
|
||||
yazi_macro::mod_pub!(config provider);
|
||||
|
||||
yazi_macro::mod_flat!(cha file files fns op);
|
||||
|
||||
|
|
|
|||
|
|
@ -2,9 +2,10 @@ use std::{io, sync::Arc, time::{Duration, SystemTime}};
|
|||
|
||||
use chrono::DateTime;
|
||||
use russh::keys::{PrivateKeyWithHashAlg, agent::AgentIdentity};
|
||||
use yazi_config::vfs::ServiceSftp;
|
||||
use yazi_fs::provider::local::Local;
|
||||
|
||||
use crate::config::ServiceSftp;
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub(super) struct Conn {
|
||||
pub(super) name: &'static str,
|
||||
|
|
|
|||
|
|
@ -1,11 +1,10 @@
|
|||
use std::io;
|
||||
|
||||
use yazi_config::vfs::{ServiceSftp, Vfs};
|
||||
use yazi_fs::provider::{Attrs, FileBuilder};
|
||||
use yazi_sftp::fs::Flags;
|
||||
use yazi_shared::url::{AsUrl, Url};
|
||||
|
||||
use crate::provider::sftp::Conn;
|
||||
use crate::{config::{ServiceSftp, Vfs}, provider::sftp::Conn};
|
||||
|
||||
#[derive(Clone, Copy, Default)]
|
||||
pub struct Gate(crate::provider::Gate);
|
||||
|
|
|
|||
|
|
@ -2,10 +2,7 @@ yazi_macro::mod_flat!(absolute conn gate metadata read_dir sftp);
|
|||
|
||||
static CONN: yazi_shim::cell::RoCell<
|
||||
parking_lot::Mutex<
|
||||
hashbrown::HashMap<
|
||||
&'static yazi_config::vfs::ServiceSftp,
|
||||
&'static deadpool::managed::Pool<Conn>,
|
||||
>,
|
||||
hashbrown::HashMap<&'static crate::config::ServiceSftp, &'static deadpool::managed::Pool<Conn>>,
|
||||
>,
|
||||
> = yazi_shim::cell::RoCell::new();
|
||||
|
||||
|
|
|
|||
|
|
@ -1,13 +1,12 @@
|
|||
use std::{io, sync::Arc};
|
||||
|
||||
use tokio::{io::{AsyncWriteExt, BufReader, BufWriter}, sync::mpsc::Receiver};
|
||||
use yazi_config::vfs::{ServiceSftp, Vfs};
|
||||
use yazi_fs::{cha::ChaMode, provider::{Capabilities, DirReader, FileHolder, Provider}};
|
||||
use yazi_sftp::fs::{Attrs, Flags};
|
||||
use yazi_shared::{loc::LocBuf, path::{AsPath, PathBufDyn}, pool::InternStr, scheme::SchemeKind, strand::AsStrand, url::{Url, UrlBuf, UrlCow, UrlLike}};
|
||||
|
||||
use super::Cha;
|
||||
use crate::provider::sftp::Conn;
|
||||
use crate::{config::{ServiceSftp, Vfs}, provider::sftp::Conn};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Sftp<'a> {
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ vendored-lua = [ "mlua/vendored" ]
|
|||
|
||||
[dependencies]
|
||||
yazi-binding = { path = "../yazi-binding", version = "26.5.6" }
|
||||
yazi-dds = { path = "../yazi-dds", version = "26.5.6" }
|
||||
yazi-macro = { path = "../yazi-macro", version = "26.5.6" }
|
||||
yazi-shared = { path = "../yazi-shared", version = "26.5.6" }
|
||||
yazi-shim = { path = "../yazi-shim", version = "26.5.6" }
|
||||
|
|
|
|||
|
|
@ -4,6 +4,9 @@ use mlua::{AnyUserData, IntoLua, Lua, MetaMethod, Table, UserData, UserDataMetho
|
|||
use parking_lot::Mutex;
|
||||
use ratatui_core::widgets::Widget;
|
||||
use yazi_binding::{elements::{Area, Spatial}, impl_area_method};
|
||||
use yazi_dds::Pubsub;
|
||||
use yazi_macro::err;
|
||||
use yazi_shim::strum::IntoStr;
|
||||
|
||||
use crate::input::{Input, InputOpt, InputStyles};
|
||||
|
||||
|
|
@ -26,6 +29,7 @@ impl InputArc {
|
|||
let new = lua.create_function(move |_, (_, mut opt): (Table, InputOpt)| {
|
||||
opt.styles.normal = opt.styles.normal.or(styles.normal);
|
||||
opt.styles.selected = opt.styles.selected.or(styles.selected);
|
||||
opt = opt.with_cb(|e| err!(Pubsub::pub_after_input((&e).into_str(), e.value())));
|
||||
Ok(Self::from(Input::new(opt)?))
|
||||
})?;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue