mirror of
https://github.com/sxyazi/yazi.git
synced 2025-01-02 13:50:15 +03:00
feat: long text scrolling
This commit is contained in:
parent
820ddf2d4c
commit
b6ea235b5e
46
Cargo.lock
generated
46
Cargo.lock
generated
@ -71,13 +71,13 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "async-trait"
|
||||
version = "0.1.71"
|
||||
version = "0.1.72"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a564d521dd56509c4c47480d00b80ee55f7e385ae48db5744c67ad50c92d2ebf"
|
||||
checksum = "cc6dde6e4ed435a4c1ee4e73592f5ba9da2151af10076cc04858746af9352d09"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.26",
|
||||
"syn 2.0.27",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -538,7 +538,7 @@ checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.26",
|
||||
"syn 2.0.27",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1098,9 +1098,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.15"
|
||||
version = "0.2.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd"
|
||||
checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
@ -1219,7 +1219,7 @@ checksum = "ec2e072ecce94ec471b13398d5402c188e76ac03cf74dd1a975161b23a3f6d9c"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.26",
|
||||
"syn 2.0.27",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1511,22 +1511,22 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.173"
|
||||
version = "1.0.174"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e91f70896d6720bc714a4a57d22fc91f1db634680e65c8efe13323f1fa38d53f"
|
||||
checksum = "3b88756493a5bd5e5395d53baa70b194b05764ab85b59e43e4b8f4e1192fa9b1"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.173"
|
||||
version = "1.0.174"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a6250dde8342e0232232be9ca3db7aa40aceb5a3e5dd9bddbc00d99a007cde49"
|
||||
checksum = "6e5c3a298c7f978e53536f95a63bdc4c4a64550582f31a0359a9afda6aede62e"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.26",
|
||||
"syn 2.0.27",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1653,9 +1653,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.26"
|
||||
version = "2.0.27"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "45c3457aacde3c65315de5031ec191ce46604304d2446e803d71ade03308d970"
|
||||
checksum = "b60f673f44a8255b9c8c657daf66a596d435f2da81a555b06dc644d080ba45e0"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@ -1693,22 +1693,22 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.43"
|
||||
version = "1.0.44"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a35fc5b8971143ca348fa6df4f024d4d55264f3468c71ad1c2f365b0a4d58c42"
|
||||
checksum = "611040a08a0439f8248d1990b111c95baa9c704c805fa1f62104b39655fd7f90"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "1.0.43"
|
||||
version = "1.0.44"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "463fe12d7993d3b327787537ce8dd4dfa058de32fc2b195ef3cde03dc4771e8f"
|
||||
checksum = "090198534930841fab3a5d1bb637cde49e339654e606195f8d9c76eeb081dc96"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.26",
|
||||
"syn 2.0.27",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1813,7 +1813,7 @@ checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.26",
|
||||
"syn 2.0.27",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1967,7 +1967,7 @@ checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.26",
|
||||
"syn 2.0.27",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2127,7 +2127,7 @@ dependencies = [
|
||||
"once_cell",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.26",
|
||||
"syn 2.0.27",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
@ -2149,7 +2149,7 @@ checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.26",
|
||||
"syn 2.0.27",
|
||||
"wasm-bindgen-backend",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
@ -1,23 +1,24 @@
|
||||
use anyhow::{anyhow, Result};
|
||||
use ratatui::layout::Rect;
|
||||
use tokio::sync::oneshot::Sender;
|
||||
use unicode_width::UnicodeWidthStr;
|
||||
use unicode_width::{UnicodeWidthChar, UnicodeWidthStr};
|
||||
|
||||
use super::InputSnap;
|
||||
use crate::{core::{external, Position}, misc::CharKind};
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Input {
|
||||
title: String,
|
||||
value: String,
|
||||
position: (u16, u16),
|
||||
title: String,
|
||||
pub(crate) value: String,
|
||||
position: (u16, u16),
|
||||
|
||||
op: InputOp,
|
||||
start: Option<usize>,
|
||||
pub(crate) op: InputOp,
|
||||
pub(crate) start: Option<usize>,
|
||||
|
||||
mode: InputMode,
|
||||
offset: usize,
|
||||
cursor: usize,
|
||||
callback: Option<Sender<Result<String>>>,
|
||||
pub(crate) mode: InputMode,
|
||||
pub(crate) offset: usize,
|
||||
pub(crate) cursor: usize,
|
||||
callback: Option<Sender<Result<String>>>,
|
||||
|
||||
pub visible: bool,
|
||||
}
|
||||
@ -60,7 +61,7 @@ impl Input {
|
||||
};
|
||||
|
||||
self.cursor = self.count();
|
||||
self.offset = self.value.width().saturating_sub(50);
|
||||
self.offset = self.cursor.saturating_sub(50 - 2 /* Border width */);
|
||||
self.callback = Some(tx);
|
||||
self.visible = true;
|
||||
}
|
||||
@ -129,8 +130,8 @@ impl Input {
|
||||
|
||||
if self.cursor < self.offset {
|
||||
self.offset = self.cursor;
|
||||
} else if self.cursor > self.offset + 50 {
|
||||
self.offset = self.cursor.saturating_sub(50);
|
||||
} else if self.cursor >= self.offset + 50 - 2 {
|
||||
self.offset = self.cursor.saturating_sub(50 - 2 - self.mode.delta());
|
||||
}
|
||||
b
|
||||
}
|
||||
@ -271,24 +272,20 @@ impl Input {
|
||||
}
|
||||
|
||||
fn handle_op(&mut self, cursor: usize, include: bool) -> bool {
|
||||
let old = self.cursor;
|
||||
let snap = self.snap();
|
||||
let range = if self.op == InputOp::None { None } else { self.range(cursor, include) };
|
||||
|
||||
let b = match self.op {
|
||||
match self.op {
|
||||
InputOp::None => {
|
||||
self.cursor = cursor;
|
||||
false
|
||||
}
|
||||
InputOp::Delete(insert) => {
|
||||
let range = range.unwrap();
|
||||
let old_mode = self.mode;
|
||||
|
||||
let (start, end) = (self.idx(range.0), self.idx(range.1));
|
||||
|
||||
self.value.drain(start.unwrap()..end.unwrap());
|
||||
self.mode = if insert { InputMode::Insert } else { InputMode::Normal };
|
||||
self.cursor = range.0;
|
||||
|
||||
start != end || self.mode != old_mode
|
||||
}
|
||||
InputOp::Yank => {
|
||||
let range = range.unwrap();
|
||||
@ -298,13 +295,12 @@ impl Input {
|
||||
futures::executor::block_on(async {
|
||||
external::clipboard_set(yanked).await.ok();
|
||||
});
|
||||
start != end
|
||||
}
|
||||
};
|
||||
|
||||
self.op = InputOp::None;
|
||||
self.cursor = self.count().saturating_sub(self.mode.delta()).min(self.cursor);
|
||||
b || self.cursor != old
|
||||
snap != self.snap()
|
||||
}
|
||||
}
|
||||
|
||||
@ -313,28 +309,24 @@ impl Input {
|
||||
pub fn title(&self) -> String { self.title.clone() }
|
||||
|
||||
#[inline]
|
||||
pub fn value(&self) -> String { self.value.clone() }
|
||||
pub fn value(&self) -> &str {
|
||||
let win = self.window();
|
||||
&self.value[self.idx(win.0).unwrap()..self.idx(win.1).unwrap()]
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn mode(&self) -> InputMode { self.mode }
|
||||
|
||||
#[inline]
|
||||
pub fn area(&self) -> Rect {
|
||||
Rect { x: self.position.0, y: self.position.1 + 2, width: 50, height: 3 }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn mode(&self) -> InputMode { self.mode }
|
||||
|
||||
#[inline]
|
||||
pub fn cursor(&self) -> (u16, u16) {
|
||||
let width = self
|
||||
.value
|
||||
.chars()
|
||||
.enumerate()
|
||||
.take_while(|(i, _)| *i < self.cursor)
|
||||
.map(|(_, c)| c)
|
||||
.collect::<String>()
|
||||
.width() as u16;
|
||||
|
||||
let area = self.area();
|
||||
let width = self.value[self.offset..self.idx(self.cursor).unwrap()].width() as u16;
|
||||
|
||||
(area.x + width + 1, area.y + 1)
|
||||
}
|
||||
|
||||
@ -346,10 +338,14 @@ impl Input {
|
||||
let start = self.start.unwrap();
|
||||
let (start, end) =
|
||||
if start < self.cursor { (start, self.cursor) } else { (self.cursor + 1, start + 1) };
|
||||
|
||||
let win = self.window();
|
||||
let (start, end) = (start.max(win.0), end.min(win.1));
|
||||
let (start, end) = (self.idx(start).unwrap(), self.idx(end).unwrap());
|
||||
|
||||
let offset = self.idx(self.offset).unwrap();
|
||||
Some(Rect {
|
||||
x: self.position.0 + 1 + self.value[..start].width() as u16,
|
||||
x: self.position.0 + 1 + self.value[offset..start].width() as u16,
|
||||
y: self.position.1 + 3,
|
||||
width: self.value[start..end].width() as u16,
|
||||
height: 1,
|
||||
@ -377,4 +373,23 @@ impl Input {
|
||||
.map(|s| if s <= cursor { (s, cursor) } else { (cursor, s) })
|
||||
.map(|(s, e)| (s, e + include as usize))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn window(&self) -> (usize, usize) {
|
||||
let mut len = 0;
|
||||
let v = self
|
||||
.value
|
||||
.chars()
|
||||
.enumerate()
|
||||
.skip(self.offset)
|
||||
.map_while(|(i, c)| {
|
||||
len += c.width().unwrap_or(0);
|
||||
if len > 50 - 2/*Border width*/ { None } else { Some(i) }
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
(v.first().copied().unwrap_or(0), v.last().map(|l| l + 1).unwrap_or(0))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn snap(&self) -> InputSnap { InputSnap::from(self) }
|
||||
}
|
||||
|
@ -1,3 +1,5 @@
|
||||
mod input;
|
||||
mod snap;
|
||||
|
||||
pub use input::*;
|
||||
pub use snap::*;
|
||||
|
28
src/core/input/snap.rs
Normal file
28
src/core/input/snap.rs
Normal file
@ -0,0 +1,28 @@
|
||||
use super::{Input, InputMode, InputOp};
|
||||
|
||||
#[derive(Default, PartialEq, Eq)]
|
||||
pub struct InputSnap {
|
||||
value: String,
|
||||
|
||||
op: InputOp,
|
||||
start: Option<usize>,
|
||||
|
||||
mode: InputMode,
|
||||
offset: usize,
|
||||
cursor: usize,
|
||||
}
|
||||
|
||||
impl From<&Input> for InputSnap {
|
||||
fn from(input: &Input) -> Self {
|
||||
Self {
|
||||
value: input.value.clone(),
|
||||
|
||||
op: input.op,
|
||||
start: input.start,
|
||||
|
||||
mode: input.mode,
|
||||
offset: input.offset,
|
||||
cursor: input.cursor,
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user