diff --git a/Cargo.lock b/Cargo.lock index 860102fe..d508b0a9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -375,9 +375,9 @@ dependencies = [ [[package]] name = "bitvec" -version = "1.0.1" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" +checksum = "ddcec3d12c579d40898fe0a9a358a803c23e9c52ca3c425707f81c9436211837" dependencies = [ "funty", "radium", @@ -519,9 +519,9 @@ checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495" [[package]] name = "bytes" -version = "1.11.1" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" +checksum = "8ae3f5d315924270530207e2a68396c3cc547f6dca3fbdca317cfb1a51edb593" [[package]] name = "castaway" @@ -1393,9 +1393,9 @@ dependencies = [ [[package]] name = "generic-array" -version = "0.14.7" +version = "0.14.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +checksum = "4bb6743198531e02858aeaea5398fcc883e71851fcbcb5a2f773e2fb6cb1edf2" dependencies = [ "typenum", "version_check", @@ -1407,7 +1407,7 @@ version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2e55f16dcf0e9c00efbe2e655ffe45fc98e7066b52bc92f8a79e64060a79351" dependencies = [ - "generic-array 0.14.7", + "generic-array 0.14.9", "rustversion", "typenum", ] diff --git a/cspell.json b/cspell.json index 99144de9..0685a4f8 100644 --- a/cspell.json +++ b/cspell.json @@ -1 +1 @@ -{"words":["Punct","KEYMAP","splitn","crossterm","YAZI","peekable","ratatui","syntect","pbpaste","pbcopy","oneshot","Posix","Lsar","XADDOS","zoxide","cands","Deque","precache","imageops","IFBLK","IFCHR","IFDIR","IFIFO","IFLNK","IFMT","IFSOCK","IRGRP","IROTH","IRUSR","ISGID","ISUID","ISVTX","IWGRP","IWOTH","IWUSR","IXGRP","IXOTH","IXUSR","libc","winsize","TIOCGWINSZ","xpixel","ypixel","ioerr","appender","Catppuccin","macchiato","gitmodules","Dotfiles","bashprofile","vimrc","flac","webp","exiftool","mediainfo","ripgrep","indexmap","indexmap","unwatch","canonicalize","serde","fsevent","Ueberzug","iterm","wezterm","sixel","chafa","ueberzugpp","Konsole","Überzug","pkgs","pdftoppm","poppler","singlefile","jpegopt","EXIF","rustfmt","mktemp","nanos","xclip","xsel","natord","Mintty","nixos","nixpkgs","SIGTSTP","SIGCONT","SIGCONT","mlua","nonstatic","userdata","metatable","natsort","backstack","luajit","Succ","Succ","cand","fileencoding","foldmethod","lightgreen","darkgray","lightred","lightyellow","lightcyan","nushell","msvc","aarch","linemode","sxyazi","rsplit","ZELLIJ","bitflags","bitflags","USERPROFILE","Neovim","vergen","gitcl","Renderable","preloaders","prec","Upserting","prio","Ghostty","Catmull","Lanczos","cmds","unyank","scrolloff","headsup","unsub","uzers","scopeguard","SPDLOG","globset","filetime","magick","magick","prefetcher","Prework","prefetchers","PREWORKERS","conds","translit","rxvt","Urxvt","realpath","realname","REPARSE","hardlink","hardlinking","nlink","nlink","linemodes","SIGSTOP","sevenzip","rsplitn","replacen","DECSET","DECRQM","repeek","cwds","tcsi","Hyprland","Wayfire","SWAYSOCK","btime","nsec","codegen","gethostname","fchmod","fdfind","Rustc","rustc","ffprobe","vframes","luma","obase","outln","errln","tmtheme","twox","cfgs","fstype","objc","rdev","runloop","exfat","rclone","DECRQSS","DECSCUSR","libvterm","Uninit","lockin","rposition","resvg","foldhash","tilded","futs","chdir","hashbrown","JEMALLOC","RUSTFLAGS","RDONLY","GETPATH","fcntl","casefold","inodes","Splatable","casefied","thiserror","memchr","memmem","russh","deadpool","keepalive","nodelay","publickey","deadpool","initing","treelize","TOCTOU","fellback","watchee","Textlike","sstr","pointee","writef","wakeup","nonblocking","sigwinch","timespec","termios","tcgetattr","tcsetattr","tcgetwinsize","rustix","codepoint","codepoints","Raterm","mimetypes","Mimelist","renderables","redrawer"],"language":"en","version":"0.2","flagWords":[]} \ No newline at end of file +{"flagWords":[],"version":"0.2","language":"en","words":["Punct","KEYMAP","splitn","crossterm","YAZI","peekable","ratatui","syntect","pbpaste","pbcopy","oneshot","Posix","Lsar","XADDOS","zoxide","cands","Deque","precache","imageops","IFBLK","IFCHR","IFDIR","IFIFO","IFLNK","IFMT","IFSOCK","IRGRP","IROTH","IRUSR","ISGID","ISUID","ISVTX","IWGRP","IWOTH","IWUSR","IXGRP","IXOTH","IXUSR","libc","winsize","TIOCGWINSZ","xpixel","ypixel","ioerr","appender","Catppuccin","macchiato","gitmodules","Dotfiles","bashprofile","vimrc","flac","webp","exiftool","mediainfo","ripgrep","indexmap","indexmap","unwatch","canonicalize","serde","fsevent","Ueberzug","iterm","wezterm","sixel","chafa","ueberzugpp","Konsole","Überzug","pkgs","pdftoppm","poppler","singlefile","jpegopt","EXIF","rustfmt","mktemp","nanos","xclip","xsel","natord","Mintty","nixos","nixpkgs","SIGTSTP","SIGCONT","SIGCONT","mlua","nonstatic","userdata","metatable","natsort","backstack","luajit","Succ","Succ","cand","fileencoding","foldmethod","lightgreen","darkgray","lightred","lightyellow","lightcyan","nushell","msvc","aarch","linemode","sxyazi","rsplit","ZELLIJ","bitflags","bitflags","USERPROFILE","Neovim","vergen","gitcl","Renderable","preloaders","prec","Upserting","prio","Ghostty","Catmull","Lanczos","cmds","unyank","scrolloff","headsup","unsub","uzers","scopeguard","SPDLOG","globset","filetime","magick","magick","prefetcher","Prework","prefetchers","PREWORKERS","conds","translit","rxvt","Urxvt","realpath","realname","REPARSE","hardlink","hardlinking","nlink","nlink","linemodes","SIGSTOP","sevenzip","rsplitn","replacen","DECSET","DECRQM","repeek","cwds","tcsi","Hyprland","Wayfire","SWAYSOCK","btime","nsec","codegen","gethostname","fchmod","fdfind","Rustc","rustc","ffprobe","vframes","luma","obase","outln","errln","tmtheme","twox","cfgs","fstype","objc","rdev","runloop","exfat","rclone","DECRQSS","DECSCUSR","libvterm","Uninit","lockin","rposition","resvg","foldhash","tilded","futs","chdir","hashbrown","JEMALLOC","RUSTFLAGS","RDONLY","GETPATH","fcntl","casefold","inodes","Splatable","casefied","thiserror","memchr","memmem","russh","deadpool","keepalive","nodelay","publickey","deadpool","initing","treelize","TOCTOU","fellback","watchee","Textlike","sstr","pointee","writef","wakeup","nonblocking","sigwinch","timespec","termios","tcgetattr","tcsetattr","tcgetwinsize","rustix","codepoint","codepoints","Raterm","mimetypes","Mimelist","renderables","redrawer","Padable"]} \ No newline at end of file diff --git a/yazi-actor/src/input/close.rs b/yazi-actor/src/input/close.rs index 2bc5cd3e..19ae12e7 100644 --- a/yazi-actor/src/input/close.rs +++ b/yazi-actor/src/input/close.rs @@ -25,7 +25,7 @@ impl Actor for Close { } drop(guard); - cx.input.main_visible = false; + cx.input.main.visible = false; act!(cmp:close, cx)?; succ!(render!()); diff --git a/yazi-actor/src/input/show.rs b/yazi-actor/src/input/show.rs index 1c16fbf6..29f700ad 100644 --- a/yazi-actor/src/input/show.rs +++ b/yazi-actor/src/input/show.rs @@ -1,5 +1,7 @@ +use std::ops::DerefMut; + use anyhow::Result; -use ratatui_widgets::block::Padding; +use ratatui_core::layout::Margin; use yazi_config::{THEME, YAZI}; use yazi_macro::{act, render, succ}; use yazi_parser::input::ShowForm; @@ -17,15 +19,16 @@ impl Actor for Show { fn act(cx: &mut Ctx, Self::Form { mut opt }: Self::Form) -> Result { act!(input:close, cx)?; + let area = cx.mgr.area(opt.position); let input = &mut cx.input; - input.main_visible = true; - input.main_title = opt.title.clone(); - input.main_position = opt.position; + input.main.visible = true; + input.main.title = opt.title.clone(); + input.main.position = opt.position; opt.styles = (&THEME.input).into(); opt.blinking = YAZI.input.cursor_blink; - opt.position = opt.position.padding(Padding::uniform(1)); - input.main = yazi_widgets::input::Input::new(opt)?; + *input.main.deref_mut() = yazi_widgets::input::Input::new(opt)?; + input.main.repos(area.inner(Margin::new(1, 1))); succ!(render!()); } diff --git a/yazi-actor/src/lives/input_alt.rs b/yazi-actor/src/lives/input_alt.rs index 8ef49f55..92c24208 100644 --- a/yazi-actor/src/lives/input_alt.rs +++ b/yazi-actor/src/lives/input_alt.rs @@ -1,21 +1,20 @@ -use std::{ops::Deref, sync::Arc}; +use std::ops::Deref; use mlua::{AnyUserData, UserData, UserDataFields}; -use parking_lot::Mutex; use yazi_shim::mlua::UserDataFieldsExt; use super::{Lives, PtrCell}; -pub(super) struct InputAlt(PtrCell>>); +pub(super) struct InputAlt(PtrCell); impl Deref for InputAlt { - type Target = Arc>; + type Target = yazi_core::input::InputAlt; fn deref(&self) -> &Self::Target { &self.0 } } impl InputAlt { - pub(super) fn make(inner: &Arc>) -> mlua::Result { + pub(super) fn make(inner: &yazi_core::input::InputAlt) -> mlua::Result { Lives::scoped_userdata(Self(inner.into())) } } diff --git a/yazi-binding/src/elements/area.rs b/yazi-binding/src/elements/area.rs index 62fed8dd..2badbecb 100644 --- a/yazi-binding/src/elements/area.rs +++ b/yazi-binding/src/elements/area.rs @@ -1,8 +1,9 @@ use std::fmt::Debug; use mlua::{AnyUserData, ExternalError, FromLua, IntoLua, Lua, Value}; +use yazi_shim::ratatui::Padable; -use super::{Pos, Rect}; +use super::Rect; use crate::position::Position; const EXPECTED: &str = "expected a Pos or Rect"; @@ -10,7 +11,7 @@ const EXPECTED: &str = "expected a Pos or Rect"; #[derive(Clone, Copy)] pub enum Area { Rect(Rect), - Pos(Pos), + Pos(Position), } impl Default for Area { @@ -26,6 +27,15 @@ impl Debug for Area { } } +impl From for Position { + fn from(value: Area) -> Self { + match value { + Area::Rect(rect) => Self::from(*rect), + Area::Pos(pos) => pos, + } + } +} + impl Area { pub fn size(self) -> ratatui_core::layout::Size { match self { @@ -34,13 +44,10 @@ impl Area { } } - pub fn inner(self, padding: ratatui_widgets::block::Padding) -> Self { + pub fn padding(self, padding: ratatui_widgets::block::Padding) -> Self { match self { - Self::Rect(rect) => Self::Rect(rect.pad(padding.into())), - Self::Pos(mut pos) => { - pos.pad += padding; - Self::Pos(pos) - } + Self::Rect(rect) => Self::Rect(rect.padding(padding).into()), + Self::Pos(pos) => Self::Pos(pos.padding(padding)), } } @@ -50,7 +57,7 @@ impl Area { ) -> ratatui_core::layout::Rect { match self { Self::Rect(rect) => *rect, - Self::Pos(pos) => *Rect(f(*pos)).pad(pos.pad), + Self::Pos(pos) => f(pos), } } } @@ -73,7 +80,7 @@ impl TryFrom<&AnyUserData> for Area { fn try_from(value: &AnyUserData) -> Result { Ok(if let Ok(rect) = value.borrow::() { Self::Rect(*rect) - } else if let Ok(pos) = value.borrow::() { + } else if let Ok(pos) = value.borrow::() { Self::Pos(*pos) } else { return Err(EXPECTED.into_lua_err()); diff --git a/yazi-binding/src/elements/mod.rs b/yazi-binding/src/elements/mod.rs index fa027fe9..004b09ce 100644 --- a/yazi-binding/src/elements/mod.rs +++ b/yazi-binding/src/elements/mod.rs @@ -1 +1 @@ -yazi_macro::mod_flat!(align area bar border cell color constraint edge fill gauge layout line list pad pos rect row span spatial table text wrap); +yazi_macro::mod_flat!(align area bar border cell color constraint edge fill gauge layout line list pad rect row span spatial table text wrap); diff --git a/yazi-binding/src/elements/pad.rs b/yazi-binding/src/elements/pad.rs index c2e53070..cd4b0376 100644 --- a/yazi-binding/src/elements/pad.rs +++ b/yazi-binding/src/elements/pad.rs @@ -12,7 +12,11 @@ impl Deref for Pad { } impl From for Pad { - fn from(pad: ratatui_widgets::block::Padding) -> Self { Self(pad) } + fn from(value: ratatui_widgets::block::Padding) -> Self { Self(value) } +} + +impl From for ratatui_widgets::block::Padding { + fn from(value: Pad) -> Self { value.0 } } impl Pad { diff --git a/yazi-binding/src/elements/rect.rs b/yazi-binding/src/elements/rect.rs index 8d48516c..c39015a0 100644 --- a/yazi-binding/src/elements/rect.rs +++ b/yazi-binding/src/elements/rect.rs @@ -1,6 +1,7 @@ use std::ops::Deref; use mlua::{FromLua, IntoLua, Lua, MetaMethod, Table, UserData, UserDataFields, UserDataMethods, Value}; +use yazi_shim::ratatui::Padable; use super::Pad; @@ -44,16 +45,6 @@ impl Rect { rect.into_lua(lua) } - pub(super) fn pad(self, pad: Pad) -> Self { - let mut r = *self; - r.x = r.x.saturating_add(pad.left); - r.y = r.y.saturating_add(pad.top); - - r.width = r.width.saturating_sub(pad.left + pad.right); - r.height = r.height.saturating_sub(pad.top + pad.bottom); - Self(r) - } - fn patch(self, t: Table) -> mlua::Result { Ok(Self(ratatui_core::layout::Rect { x: t.raw_get::>("x")?.unwrap_or(self.x), @@ -83,7 +74,7 @@ impl UserData for Rect { } fn add_methods>(methods: &mut M) { - methods.add_method("pad", |_, me, pad: Pad| Ok(me.pad(pad))); + methods.add_method("pad", |_, me, pad: Pad| Ok(Self(me.padding(pad)))); methods.add_method("contains", |_, me, Self(rect)| Ok(me.contains(rect.into()))); methods.add_meta_method(MetaMethod::Call, |_, me, t: Table| me.patch(t)); diff --git a/yazi-binding/src/elements/pos.rs b/yazi-binding/src/position/lua.rs similarity index 61% rename from yazi-binding/src/elements/pos.rs rename to yazi-binding/src/position/lua.rs index ac74de16..d2ce2de2 100644 --- a/yazi-binding/src/elements/pos.rs +++ b/yazi-binding/src/position/lua.rs @@ -1,35 +1,13 @@ -use std::{ops::Deref, str::FromStr}; +use std::str::FromStr; use mlua::{AnyUserData, ExternalError, ExternalResult, FromLua, IntoLua, Lua, MetaMethod, Table, UserData, UserDataFields, UserDataMethods, Value}; use yazi_shim::strum::IntoStr; -use super::Pad; -use crate::position::{Offset, Origin, Position}; +use crate::{elements::Pad, position::{Offset, Origin, Position}}; const EXPECTED: &str = "expected a Pos"; -#[derive(Clone, Copy, Default)] -pub struct Pos { - inner: Position, - - pub(super) pad: Pad, -} - -impl Deref for Pos { - type Target = Position; - - fn deref(&self) -> &Self::Target { &self.inner } -} - -impl From for Pos { - fn from(value: Position) -> Self { Self { inner: value, ..Default::default() } } -} - -impl From for Position { - fn from(value: Pos) -> Self { value.inner } -} - -impl TryFrom<&AnyUserData> for Pos { +impl TryFrom<&AnyUserData> for Position { type Error = mlua::Error; fn try_from(ud: &AnyUserData) -> Result { @@ -37,23 +15,24 @@ impl TryFrom<&AnyUserData> for Pos { } } -impl TryFrom for Pos { +impl TryFrom
for Position { type Error = mlua::Error; fn try_from(t: Table) -> Result { Ok(Self::from(Position { - origin: Origin::from_str(&t.raw_get::(1)?.to_str()?).into_lua_err()?, - offset: Offset { + origin: Origin::from_str(&t.raw_get::(1)?.to_str()?).into_lua_err()?, + offset: Offset { x: t.raw_get("x").unwrap_or_default(), y: t.raw_get("y").unwrap_or_default(), width: t.raw_get("w").unwrap_or_default(), height: t.raw_get("h").unwrap_or_default(), }, + padding: Default::default(), })) } } -impl FromLua for Pos { +impl FromLua for Position { fn from_lua(value: Value, _: &Lua) -> mlua::Result { match value { Value::Table(tbl) => Self::try_from(tbl), @@ -63,23 +42,18 @@ impl FromLua for Pos { } } -impl Pos { +impl Position { pub fn compose(lua: &Lua) -> mlua::Result { let new = lua.create_function(|_, (_, t): (Table, Table)| Self::try_from(t))?; - let position = lua.create_table()?; - position.set_metatable(Some(lua.create_table_from([(MetaMethod::Call.name(), new)])?))?; + let pos = lua.create_table()?; + pos.set_metatable(Some(lua.create_table_from([(MetaMethod::Call.name(), new)])?))?; - position.into_lua(lua) - } - - pub fn with_height(mut self, height: u16) -> Self { - self.inner.height = height; - self + pos.into_lua(lua) } } -impl UserData for Pos { +impl UserData for Position { fn add_fields>(fields: &mut F) { // TODO: cache fields.add_field_method_get("1", |_, me| Ok(me.origin.into_str())); @@ -91,7 +65,7 @@ impl UserData for Pos { fn add_methods>(methods: &mut M) { methods.add_function("pad", |_, (ud, pad): (AnyUserData, Pad)| { - ud.borrow_mut::()?.pad = pad; + ud.borrow_mut::()?.padding = pad.into(); Ok(ud) }); } diff --git a/yazi-binding/src/position/mod.rs b/yazi-binding/src/position/mod.rs index eef64651..75e14b31 100644 --- a/yazi-binding/src/position/mod.rs +++ b/yazi-binding/src/position/mod.rs @@ -1 +1 @@ -yazi_macro::mod_flat!(offset origin position); +yazi_macro::mod_flat!(lua offset origin position); diff --git a/yazi-binding/src/position/offset.rs b/yazi-binding/src/position/offset.rs index 23c4be2c..4cea9d6b 100644 --- a/yazi-binding/src/position/offset.rs +++ b/yazi-binding/src/position/offset.rs @@ -10,6 +10,17 @@ pub struct Offset { pub height: u16, } +impl From for Offset { + fn from(value: ratatui_core::layout::Rect) -> Self { + Self { + x: value.x as i16, + y: value.y as i16, + width: value.width, + height: value.height, + } + } +} + impl TryFrom<[i16; 4]> for Offset { type Error = anyhow::Error; @@ -32,8 +43,3 @@ impl TryFrom<[i16; 4]> for Offset { }) } } - -impl Offset { - #[inline] - pub fn line() -> Self { Self { x: 0, y: 0, width: u16::MAX, height: 1 } } -} diff --git a/yazi-binding/src/position/position.rs b/yazi-binding/src/position/position.rs index bd25fda7..2c649cce 100644 --- a/yazi-binding/src/position/position.rs +++ b/yazi-binding/src/position/position.rs @@ -2,13 +2,15 @@ use std::ops::{Deref, DerefMut}; use ratatui_core::layout::Rect; use ratatui_widgets::block::Padding; +use yazi_shim::ratatui::Padable; use super::{Offset, Origin}; #[derive(Clone, Copy, Debug, Default)] pub struct Position { - pub origin: Origin, - pub offset: Offset, + pub origin: Origin, + pub offset: Offset, + pub padding: Padding, } impl Deref for Position { @@ -21,8 +23,23 @@ impl DerefMut for Position { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.offset } } +impl From for Position { + fn from(value: Rect) -> Self { Self::new(Origin::TopLeft, value.into()) } +} + impl Position { - pub const fn new(origin: Origin, offset: Offset) -> Self { Self { origin, offset } } + pub const fn new(origin: Origin, offset: Offset) -> Self { + Self { origin, offset, padding: Padding::ZERO } + } + + pub const fn hovered(offset: Offset) -> Self { + Self { origin: Origin::Hovered, offset, padding: Padding::ZERO } + } + + pub fn with_height(mut self, height: u16) -> Self { + self.height = height; + self + } pub fn rect(&self, (cols, rows): (u16, u16)) -> Rect { use Origin::*; @@ -52,10 +69,11 @@ impl Position { width: width.min(cols.saturating_sub(new_x)), height: height.min(rows.saturating_sub(new_y)), } + .padding(self.padding) } - pub fn sticky((cols, rows): (u16, u16), base: Rect, offset: Offset) -> Rect { - let Offset { x, y, width, height } = offset; + pub fn sticky(self, base: Rect, (cols, rows): (u16, u16)) -> Rect { + let Offset { x, y, width, height } = self.offset; let above = base.y.saturating_add(base.height).saturating_add(height).saturating_add_signed(y) > rows; @@ -73,31 +91,15 @@ impl Position { width: width.min(cols.saturating_sub(new_x)), height: height.min(rows.saturating_sub(new_y)), } + .padding(self.padding) } - pub fn padding(mut self, padding: Padding) -> Self { - use Origin::*; - let h_reduction = padding.left + padding.right; - let v_reduction = padding.top + padding.bottom; - - self.x = self.x.saturating_add_unsigned(padding.left); - self.y = self.y.saturating_add_unsigned(padding.top); - - self.width = self.width.saturating_sub(h_reduction); - self.height = self.height.saturating_sub(v_reduction); - - self.x = self.x.saturating_sub_unsigned(match self.origin { - TopCenter | BottomCenter | Center => h_reduction / 2, - TopRight | BottomRight => h_reduction, - _ => 0, - }); - - self.y = self.y.saturating_sub_unsigned(match self.origin { - BottomLeft | BottomCenter | BottomRight => v_reduction, - Center => v_reduction / 2, - _ => 0, - }); - + pub fn padding(mut self, padding: impl Into) -> Self { + let p = padding.into(); + self.padding.left = self.padding.left.saturating_add(p.left); + self.padding.right = self.padding.right.saturating_add(p.right); + self.padding.top = self.padding.top.saturating_add(p.top); + self.padding.bottom = self.padding.bottom.saturating_add(p.bottom); self } } diff --git a/yazi-core/src/core.rs b/yazi-core/src/core.rs index 07585ae7..3cd29787 100644 --- a/yazi-core/src/core.rs +++ b/yazi-core/src/core.rs @@ -34,8 +34,8 @@ 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.main_position).inner(Margin::new(1, 1)), - InputGuard::Alt(alt) => self.mgr.area(alt.pos), + InputGuard::Main(_) => self.mgr.area(self.input.position()?).inner(Margin::new(1, 1)), + InputGuard::Alt(_) => self.mgr.area(self.input.position()?), }; return Some((Position { x: x + guard.cursor(), y }, guard.cursor_shape())); } diff --git a/yazi-core/src/input/input.rs b/yazi-core/src/input/input.rs index f9ebec52..d7f4e628 100644 --- a/yazi-core/src/input/input.rs +++ b/yazi-core/src/input/input.rs @@ -1,40 +1,83 @@ -use std::sync::Arc; +use std::{ops::{Deref, DerefMut}, sync::Arc}; use parking_lot::Mutex; -use yazi_binding::position::Position; +use yazi_binding::{elements::Spatial, position::Position}; use crate::input::{InputGuard, InputMutGuard}; #[derive(Default)] pub struct Input { - pub main: yazi_widgets::input::Input, - pub alt: Option>>, - - pub main_visible: bool, - pub main_title: String, - pub main_position: Position, + pub main: InputMain, + pub alt: Option, } impl Input { - pub fn focus(&self) -> bool { self.main_visible || self.alt.is_some() } + pub fn focus(&self) -> bool { self.main.visible || self.alt.is_some() } + + pub fn position(&self) -> Option { + if self.main.visible { + Some(self.main.position) + } else if let Some(alt) = &self.alt { + Some(alt.position) + } else { + None + } + } pub fn lock(&self) -> Option> { - if self.main_visible { - Some(InputGuard::Main(&self.main)) + if self.main.visible { + Some(InputGuard::Main(&self.main.inner)) } else if let Some(alt) = &self.alt { - Some(InputGuard::Alt(alt.lock())) + Some(InputGuard::Alt(alt.inner.lock())) } else { None } } pub fn lock_mut(&mut self) -> Option> { - if self.main_visible { - Some(InputMutGuard::Main(&mut self.main)) + if self.main.visible { + Some(InputMutGuard::Main(&mut self.main.inner)) } else if let Some(alt) = &self.alt { - Some(InputMutGuard::Alt(alt.lock())) + Some(InputMutGuard::Alt(alt.inner.lock())) } else { None } } } + +// --- InputMain +#[derive(Default)] +pub struct InputMain { + inner: yazi_widgets::input::Input, + pub visible: bool, + pub title: String, + pub position: Position, +} + +impl Deref for InputMain { + type Target = yazi_widgets::input::Input; + + fn deref(&self) -> &Self::Target { &self.inner } +} + +impl DerefMut for InputMain { + fn deref_mut(&mut self) -> &mut Self::Target { &mut self.inner } +} + +// --- InputAlt +pub struct InputAlt { + inner: Arc>, + position: Position, +} + +impl Deref for InputAlt { + type Target = Arc>; + + fn deref(&self) -> &Self::Target { &self.inner } +} + +impl From<&yazi_widgets::input::InputArc> for InputAlt { + fn from(value: &yazi_widgets::input::InputArc) -> Self { + Self { inner: value.deref().clone(), position: value.area().into() } + } +} diff --git a/yazi-core/src/tab/tab.rs b/yazi-core/src/tab/tab.rs index 6924707b..8dd15cf3 100644 --- a/yazi-core/src/tab/tab.rs +++ b/yazi-core/src/tab/tab.rs @@ -93,7 +93,7 @@ impl Tab { pub fn hovered_rect_based(&self, pos: Position) -> Rect { let area = TERM.dimension().area(); if let Some(r) = self.hovered_rect() { - Position::sticky(area, r, pos.offset) + pos.sticky(r, area) } else { Position::new(Origin::TopCenter, pos.offset).rect(area) } diff --git a/yazi-fm/src/cmp/cmp.rs b/yazi-fm/src/cmp/cmp.rs index d4560456..49711759 100644 --- a/yazi-fm/src/cmp/cmp.rs +++ b/yazi-fm/src/cmp/cmp.rs @@ -39,13 +39,14 @@ impl Widget for Cmp<'_> { }) .collect(); - let input_area = self.core.mgr.area(self.core.input.main_position); - let mut area = Position::sticky(TERM.dimension().area(), input_area, Offset { + let input_area = self.core.mgr.area(self.core.input.main.position); + let mut area = Position::hovered(Offset { x: 1, y: 0, width: input_area.width.saturating_sub(2), height: items.len() as u16 + 2, - }); + }) + .sticky(input_area, TERM.dimension().area()); if area.y > input_area.y { area.y = area.y.saturating_sub(1); diff --git a/yazi-fm/src/input/input.rs b/yazi-fm/src/input/input.rs index 236a97dd..c2edf160 100644 --- a/yazi-fm/src/input/input.rs +++ b/yazi-fm/src/input/input.rs @@ -15,13 +15,13 @@ impl Widget for Input<'_> { fn render(self, _: Rect, buf: &mut Buffer) { let input = &self.core.input; - let outer = self.core.mgr.area(input.main_position); + let outer = self.core.mgr.area(input.main.position); yazi_widgets::clear::Clear::default().render(outer, buf); Block::bordered() .border_type(BorderType::Rounded) .border_style(THEME.input.border.get()) - .title(Line::styled(&input.main_title, THEME.input.title.get())) + .title(Line::styled(&input.main.title, THEME.input.title.get())) .render(outer, buf); input.main.render(outer.inner(Margin::new(1, 1)), buf); diff --git a/yazi-fm/src/root.rs b/yazi-fm/src/root.rs index 9f884c69..ef4e76a5 100644 --- a/yazi-fm/src/root.rs +++ b/yazi-fm/src/root.rs @@ -42,7 +42,7 @@ impl Widget for Root<'_> { pick::Pick::new(self.core).render(area, buf); } - if self.core.input.main_visible { + if self.core.input.main.visible { input::Input::new(self.core).render(area, buf); } diff --git a/yazi-plugin/src/ui/ui.rs b/yazi-plugin/src/ui/ui.rs index aed21ae0..c8a8c010 100644 --- a/yazi-plugin/src/ui/ui.rs +++ b/yazi-plugin/src/ui/ui.rs @@ -1,5 +1,5 @@ use mlua::{IntoLua, Lua, Value}; -use yazi_binding::{Composer, ComposerGet, ComposerSet, elements::{Align, Bar, Border, Color, Constraint, Edge, Fill, Gauge, Layout, Line, List, Pad, Pos, Rect, Row, Span, Table, Text, Wrap}, style::Style}; +use yazi_binding::{Composer, ComposerGet, ComposerSet, elements::{Align, Bar, Border, Color, Constraint, Edge, Fill, Gauge, Layout, Line, List, Pad, Rect, Row, Span, Table, Text, Wrap}, position::Position, style::Style}; use yazi_config::THEME; use yazi_widgets::{clear::Clear, input::InputArc}; @@ -21,7 +21,7 @@ pub fn compose() -> Composer { b"Line" => Line::compose(lua)?, b"List" => List::compose(lua)?, b"Pad" => Pad::compose(lua)?, - b"Pos" => Pos::compose(lua)?, + b"Pos" => Position::compose(lua)?, b"Rect" => Rect::compose(lua)?, b"Row" => Row::compose(lua)?, b"Span" => Span::compose(lua)?, diff --git a/yazi-plugin/src/utils/layer.rs b/yazi-plugin/src/utils/layer.rs index 06cf0177..f425342f 100644 --- a/yazi-plugin/src/utils/layer.rs +++ b/yazi-plugin/src/utils/layer.rs @@ -2,7 +2,7 @@ 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, Pos, Text}, runtime}; +use yazi_binding::{elements::{Line, Text}, runtime}; use yazi_config::{Platform, keymap::{Chord, ChordArc}, popup::ConfirmCfg}; use yazi_core::notify::MessageOpt; use yazi_macro::relay; @@ -79,7 +79,7 @@ impl Utils { } let result = ConfirmProxy::show(ConfirmCfg { - position: t.raw_get::("pos")?.into(), + position: t.raw_get("pos")?, title: t.raw_get::("title")?.into(), body: t.raw_get::>("body")?.unwrap_or_default().into(), list: Default::default(), // TODO diff --git a/yazi-plugin/src/utils/spot.rs b/yazi-plugin/src/utils/spot.rs index 8a5e1cdc..085ea509 100644 --- a/yazi-plugin/src/utils/spot.rs +++ b/yazi-plugin/src/utils/spot.rs @@ -14,7 +14,7 @@ impl Utils { let mut table = yazi_binding::elements::Table::try_from(&table)?; let area = table.area(); - table.set_area(area.inner(ratatui_widgets::block::Padding::uniform(1))); + table.set_area(area.padding(ratatui_widgets::block::Padding::uniform(1))); lock.data = vec![ Renderable::Clear(Default::default()).with_area(area), diff --git a/yazi-shim/src/ratatui/mod.rs b/yazi-shim/src/ratatui/mod.rs index ae7fd6e5..ecda8dca 100644 --- a/yazi-shim/src/ratatui/mod.rs +++ b/yazi-shim/src/ratatui/mod.rs @@ -1 +1 @@ -yazi_macro::mod_flat!(line span wrapper); +yazi_macro::mod_flat!(line padding span wrapper); diff --git a/yazi-shim/src/ratatui/padding.rs b/yazi-shim/src/ratatui/padding.rs new file mode 100644 index 00000000..afe8969e --- /dev/null +++ b/yazi-shim/src/ratatui/padding.rs @@ -0,0 +1,20 @@ +use ratatui_widgets::block::Padding; + +pub trait Padable { + fn padding(self, pad: impl Into) -> Self; +} + +impl Padable for ratatui_core::layout::Rect { + fn padding(self, padding: impl Into) -> Self { + let p = padding.into(); + let horizontal = p.left.saturating_add(p.right); + let vertical = p.top.saturating_add(p.bottom); + + Self { + x: self.x.saturating_add(p.left), + y: self.y.saturating_add(p.top), + width: self.width.saturating_sub(horizontal), + height: self.height.saturating_sub(vertical), + } + } +} diff --git a/yazi-tty/src/lua.rs b/yazi-tty/src/lua.rs index 5814267e..70ae40ca 100644 --- a/yazi-tty/src/lua.rs +++ b/yazi-tty/src/lua.rs @@ -11,6 +11,11 @@ impl Tty { let mut w = self.writer(); let result = match kind { + b"Print" => { + write!(w, "{}", t.raw_get::(1)?) + } + + // DnD b"AgreeDrag" => { let it = t.raw_get::
("mimes")?.sequence_iter::(lua).flatten(); write!(w, "{}", match &*t.raw_get::("type")? { @@ -48,6 +53,7 @@ impl Tty { b"move" => write!(w, "{}", FinishDrop::Move), _ => return Err("invalid FinishDrop type".into_lua_err()), }, + _ => return Err("invalid sequence kind".into_lua_err()), }; diff --git a/yazi-widgets/src/input/actor/casefy.rs b/yazi-widgets/src/input/actor/casefy.rs index 72494c71..3db1ce00 100644 --- a/yazi-widgets/src/input/actor/casefy.rs +++ b/yazi-widgets/src/input/actor/casefy.rs @@ -22,7 +22,7 @@ impl Input { snap.value.replace_range(start..end, &casefied); snap.op = InputOp::None; snap.cursor = range.start; - self.snaps.tag(self.pos.width as usize).then(|| self.flush_type()); + self.snaps.tag(self.size.width as usize).then(|| self.flush_type()); act!(r#move, self)?; succ!(render!()); diff --git a/yazi-widgets/src/input/actor/escape.rs b/yazi-widgets/src/input/actor/escape.rs index d9e45d77..e083571a 100644 --- a/yazi-widgets/src/input/actor/escape.rs +++ b/yazi-widgets/src/input/actor/escape.rs @@ -19,7 +19,7 @@ impl Input { snap.mode = InputMode::Normal; } } - self.snaps.tag(self.pos.width as usize); + self.snaps.tag(self.size.width as usize); succ!(); } } diff --git a/yazi-widgets/src/input/actor/move.rs b/yazi-widgets/src/input/actor/move.rs index d3958f42..0e9545cc 100644 --- a/yazi-widgets/src/input/actor/move.rs +++ b/yazi-widgets/src/input/actor/move.rs @@ -15,7 +15,7 @@ impl Input { render!(self.handle_op(opt.step.add(&snap.value, snap.cursor), false)); let n_cur = self.snap().cursor; - let (limit, snap) = (self.pos.width as usize, self.snap_mut()); + let (limit, snap) = (self.size.width as usize, self.snap_mut()); if snap.value.is_empty() { succ!(snap.offset = 0); } diff --git a/yazi-widgets/src/input/actor/replace.rs b/yazi-widgets/src/input/actor/replace.rs index 84cad48f..39a47d4f 100644 --- a/yazi-widgets/src/input/actor/replace.rs +++ b/yazi-widgets/src/input/actor/replace.rs @@ -29,7 +29,7 @@ impl Input { (Some(_), Some((len, _))) => snap.value.replace_range(start..start + len, &s), } - self.snaps.tag(self.pos.width as usize).then(|| self.flush_type()); + self.snaps.tag(self.size.width as usize).then(|| self.flush_type()); succ!(render!()); } } diff --git a/yazi-widgets/src/input/input.rs b/yazi-widgets/src/input/input.rs index a4d145be..b4f9591e 100644 --- a/yazi-widgets/src/input/input.rs +++ b/yazi-widgets/src/input/input.rs @@ -1,7 +1,7 @@ use std::{borrow::Cow, ops::Range}; use anyhow::Result; -use yazi_binding::position::Position; +use ratatui_core::layout::{Rect, Size}; use yazi_macro::act; use yazi_shared::id::Ids; use yazi_shim::path::CROSS_SEPARATOR; @@ -12,7 +12,7 @@ use crate::{CLIPBOARD, input::{InputCallback, InputEvent, InputOpt, InputStyles} #[derive(Debug, Default)] pub struct Input { - pub pos: Position, + pub size: Size, pub snaps: InputSnaps, pub styles: InputStyles, pub obscure: bool, @@ -26,10 +26,8 @@ pub struct Input { impl Input { pub fn new(opt: InputOpt) -> Result { - let limit = opt.position.width as usize; let mut input = Self { - pos: opt.position, - snaps: InputSnaps::new(opt.value, opt.obscure, limit), + snaps: InputSnaps::new(opt.value, opt.obscure), styles: opt.styles, obscure: opt.obscure, blinking: opt.blinking, @@ -48,9 +46,13 @@ impl Input { Ok(input) } - pub fn repos(&mut self, pos: Position) { - self.pos = pos; - self.snap_mut().resize(pos.width as usize); + pub fn repos(&mut self, area: Rect) { + let size = area.into(); + + if self.size != size { + self.size = size; + self.snap_mut().resize(size.width as usize); + } } pub(super) fn handle_op(&mut self, cursor: usize, include: bool) -> bool { @@ -89,7 +91,7 @@ impl Input { return false; } if !matches!(old.op, InputOp::None | InputOp::Select(_)) { - self.snaps.tag(self.pos.width as usize).then(|| self.flush_type()); + self.snaps.tag(self.size.width as usize).then(|| self.flush_type()); } true } @@ -118,9 +120,9 @@ impl Input { pub fn display(&self) -> Cow<'_, str> { if self.obscure { - "•".repeat(self.snap().window(self.pos.width as usize).len()).into() + "•".repeat(self.snap().window(self.size.width as usize).len()).into() } else { - self.snap().slice(self.snap().window(self.pos.width as usize)).into() + self.snap().slice(self.snap().window(self.size.width as usize)).into() } } @@ -149,7 +151,7 @@ impl Input { let (start, end) = if start < snap.cursor { (start, snap.cursor) } else { (snap.cursor + 1, start + 1) }; - let win = snap.window(self.pos.width as usize); + let win = snap.window(self.size.width as usize); let Range { start, end } = start.max(win.start)..end.min(win.end); let s = snap.width(snap.offset..start); diff --git a/yazi-widgets/src/input/input_arc.rs b/yazi-widgets/src/input/input_arc.rs index 1876bee6..b5efbb20 100644 --- a/yazi-widgets/src/input/input_arc.rs +++ b/yazi-widgets/src/input/input_arc.rs @@ -1,17 +1,24 @@ -use std::sync::Arc; +use std::{ops::Deref, sync::Arc}; use mlua::{AnyUserData, IntoLua, Lua, MetaMethod, Table, UserData, UserDataMethods, Value}; use parking_lot::Mutex; use ratatui_core::widgets::Widget; -use yazi_binding::{elements::{Area, Spatial}, impl_area_method, position::{Offset, Origin, Position}}; +use yazi_binding::{elements::{Area, Spatial}, impl_area_method}; use crate::input::{Input, InputOpt, InputStyles}; #[derive(Clone, Debug, Default)] pub struct InputArc { - pub focus: bool, - + area: Area, inner: Arc>, + + pub focus: bool, +} + +impl Deref for InputArc { + type Target = Arc>; + + fn deref(&self) -> &Self::Target { &self.inner } } impl InputArc { @@ -47,22 +54,9 @@ impl TryFrom<&AnyUserData> for InputArc { } impl Spatial for InputArc { - fn area(&self) -> Area { self.inner.lock().pos.into() } + fn area(&self) -> Area { self.area } - fn set_area(&mut self, area: Area) { - self.inner.lock().repos(match area { - Area::Rect(rect) => Position { - origin: Origin::TopLeft, - offset: Offset { - x: rect.x as i16, - y: rect.y as i16, - width: rect.width, - height: rect.height, - }, - }, - Area::Pos(pos) => pos.into(), - }); - } + fn set_area(&mut self, area: Area) { self.area = area; } } impl Widget for &InputArc { @@ -70,7 +64,9 @@ impl Widget for &InputArc { where Self: Sized, { - self.inner.lock().render(rect, buf) + let mut guard = self.inner.lock(); + guard.repos(rect); + guard.render(rect, buf) } } diff --git a/yazi-widgets/src/input/option.rs b/yazi-widgets/src/input/option.rs index 1b64f55d..3cb3c1c5 100644 --- a/yazi-widgets/src/input/option.rs +++ b/yazi-widgets/src/input/option.rs @@ -1,5 +1,5 @@ use mlua::{ExternalError, FromLua, Lua, Table, Value}; -use yazi_binding::{elements::Pos, position::Position}; +use yazi_binding::position::Position; use yazi_macro::impl_data_any; use crate::input::{InputCallback, InputStyles}; @@ -48,7 +48,7 @@ impl TryFrom<&Table> for InputOpt { cursor: None, obscure: t.raw_get("obscure")?, blinking: false, - position: t.raw_get::("pos")?.with_height(3).into(), + position: t.raw_get::("pos").unwrap_or_default().with_height(3), realtime: t.raw_get("realtime")?, completion: false, cb: None, diff --git a/yazi-widgets/src/input/snap.rs b/yazi-widgets/src/input/snap.rs index 112988b5..03954be9 100644 --- a/yazi-widgets/src/input/snap.rs +++ b/yazi-widgets/src/input/snap.rs @@ -18,7 +18,7 @@ pub struct InputSnap { } impl InputSnap { - pub(super) fn new(value: String, obscure: bool, limit: usize) -> Self { + pub(super) fn new(value: String, obscure: bool) -> Self { let mut snap = Self { value, @@ -30,7 +30,7 @@ impl InputSnap { offset: 0, cursor: usize::MAX, }; - snap.resize(limit); + snap.resize(0); snap } diff --git a/yazi-widgets/src/input/snaps.rs b/yazi-widgets/src/input/snaps.rs index 780ee383..b14cf7fa 100644 --- a/yazi-widgets/src/input/snaps.rs +++ b/yazi-widgets/src/input/snaps.rs @@ -13,15 +13,15 @@ impl Default for InputSnaps { fn default() -> Self { Self { idx: 0, - versions: vec![InputSnap::new(String::new(), false, 0)], - current: InputSnap::new(String::new(), false, 0), + versions: vec![InputSnap::new(String::new(), false)], + current: InputSnap::new(String::new(), false), } } } impl InputSnaps { - pub fn new(value: String, obscure: bool, limit: usize) -> Self { - let current = InputSnap::new(value, obscure, limit); + pub fn new(value: String, obscure: bool) -> Self { + let current = InputSnap::new(value, obscure); Self { idx: 0, versions: vec![current.clone()], current } }