mirror of
https://github.com/sxyazi/yazi.git
synced 2026-07-21 23:01:05 +00:00
feat: new ya.id("app") to get YAZI_ID in plugins (#2503)
This commit is contained in:
parent
570c6d308b
commit
db0300c902
23 changed files with 102 additions and 76 deletions
12
Cargo.lock
generated
12
Cargo.lock
generated
|
|
@ -389,9 +389,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "clap_complete"
|
||||
version = "4.5.46"
|
||||
version = "4.5.47"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f5c5508ea23c5366f77e53f5a0070e5a84e51687ec3ef9e0464c86dc8d13ce98"
|
||||
checksum = "c06f5378ea264ad4f82bbc826628b5aad714a75abf6ece087e923010eb937fb6"
|
||||
dependencies = [
|
||||
"clap",
|
||||
]
|
||||
|
|
@ -3564,16 +3564,16 @@ dependencies = [
|
|||
"yazi-dds",
|
||||
"yazi-fs",
|
||||
"yazi-macro",
|
||||
"yazi-prebuild",
|
||||
"yazi-prebuilt",
|
||||
"yazi-proxy",
|
||||
"yazi-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "yazi-prebuild"
|
||||
version = "0.1.2"
|
||||
name = "yazi-prebuilt"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f4b6c8e12e39ac0f79fa96f36e5b88e0da8d230691abd729eec709b43c74f632"
|
||||
checksum = "33232d9116df6415ddfcdf72701b1b7439ce87f240a14723e8dd5d17e7ed5f98"
|
||||
|
||||
[[package]]
|
||||
name = "yazi-proxy"
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
{"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","prebuild","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"],"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"],"flagWords":[]}
|
||||
|
|
@ -21,8 +21,11 @@ regex = { workspace = true }
|
|||
serde = { workspace = true }
|
||||
|
||||
[build-dependencies]
|
||||
yazi-shared = { path = "../yazi-shared", version = "25.3.7" }
|
||||
|
||||
# External dependencies
|
||||
clap = { workspace = true }
|
||||
clap_complete = "4.5.46"
|
||||
clap_complete = "4.5.47"
|
||||
clap_complete_fig = "4.5.2"
|
||||
clap_complete_nushell = "4.5.5"
|
||||
vergen-gitcl = { version = "1.0.5", features = [ "build", "rustc" ] }
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
use std::path::PathBuf;
|
||||
|
||||
use clap::{Parser, command};
|
||||
use yazi_shared::Id;
|
||||
|
||||
#[derive(Debug, Default, Parser)]
|
||||
#[command(name = "yazi")]
|
||||
|
|
@ -22,7 +23,7 @@ pub struct Args {
|
|||
|
||||
/// Use the specified client ID, must be a globally unique number
|
||||
#[arg(long)]
|
||||
pub client_id: Option<u64>,
|
||||
pub client_id: Option<Id>,
|
||||
/// Report the specified local events to stdout
|
||||
#[arg(long)]
|
||||
pub local_events: Option<String>,
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ yazi-shared = { path = "../yazi-shared", version = "25.3.7" }
|
|||
# External build dependencies
|
||||
anyhow = { workspace = true }
|
||||
clap = { workspace = true }
|
||||
clap_complete = "4.5.46"
|
||||
clap_complete = "4.5.47"
|
||||
clap_complete_fig = "4.5.2"
|
||||
clap_complete_nushell = "4.5.5"
|
||||
serde_json = { workspace = true }
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ pub struct Input {
|
|||
}
|
||||
|
||||
impl Input {
|
||||
pub const fn border(&self) -> u16 { 1 }
|
||||
pub const fn border(&self) -> u16 { 2 }
|
||||
}
|
||||
|
||||
impl FromStr for Input {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
use anyhow::{Result, bail};
|
||||
use mlua::{ExternalResult, IntoLua, Lua, Value};
|
||||
use serde::Serialize;
|
||||
use yazi_shared::Id;
|
||||
|
||||
use super::{BodyBulk, BodyBye, BodyCd, BodyCustom, BodyDelete, BodyHey, BodyHi, BodyHover, BodyLoad, BodyMount, BodyMove, BodyRename, BodyTab, BodyTrash, BodyYank};
|
||||
use crate::Payload;
|
||||
|
|
@ -107,12 +108,12 @@ impl<'a> Body<'a> {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
pub fn with_receiver(self, receiver: u64) -> Payload<'a> {
|
||||
pub fn with_receiver(self, receiver: Id) -> Payload<'a> {
|
||||
Payload::new(self).with_receiver(receiver)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn with_sender(self, sender: u64) -> Payload<'a> { Payload::new(self).with_sender(sender) }
|
||||
pub fn with_sender(self, sender: Id) -> Payload<'a> { Payload::new(self).with_sender(sender) }
|
||||
}
|
||||
|
||||
impl IntoLua for Body<'static> {
|
||||
|
|
|
|||
|
|
@ -2,19 +2,20 @@ use std::{borrow::Cow, collections::HashMap};
|
|||
|
||||
use mlua::{ExternalResult, IntoLua, Lua, Value};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use yazi_shared::Id;
|
||||
|
||||
use super::{Body, BodyHi};
|
||||
use crate::Peer;
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct BodyHey {
|
||||
pub peers: HashMap<u64, Peer>,
|
||||
pub peers: HashMap<Id, Peer>,
|
||||
pub version: Cow<'static, str>,
|
||||
}
|
||||
|
||||
impl BodyHey {
|
||||
#[inline]
|
||||
pub fn owned(peers: HashMap<u64, Peer>) -> Body<'static> {
|
||||
pub fn owned(peers: HashMap<Id, Peer>) -> Body<'static> {
|
||||
Self { peers, version: BodyHi::version().into() }.into()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,19 +5,19 @@ use parking_lot::RwLock;
|
|||
use serde::{Deserialize, Serialize};
|
||||
use tokio::{io::AsyncWriteExt, select, sync::mpsc, task::JoinHandle, time};
|
||||
use tracing::error;
|
||||
use yazi_shared::RoCell;
|
||||
use yazi_shared::{Id, RoCell};
|
||||
|
||||
use crate::{ClientReader, ClientWriter, Payload, Pubsub, Server, Stream, body::{Body, BodyBye, BodyHi}};
|
||||
|
||||
pub(super) static ID: RoCell<u64> = RoCell::new();
|
||||
pub(super) static PEERS: RoCell<RwLock<HashMap<u64, Peer>>> = RoCell::new();
|
||||
pub static ID: RoCell<Id> = RoCell::new();
|
||||
pub(super) static PEERS: RoCell<RwLock<HashMap<Id, Peer>>> = RoCell::new();
|
||||
|
||||
pub(super) static QUEUE_TX: RoCell<mpsc::UnboundedSender<String>> = RoCell::new();
|
||||
pub(super) static QUEUE_RX: RoCell<mpsc::UnboundedReceiver<String>> = RoCell::new();
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Client {
|
||||
pub(super) id: u64,
|
||||
pub(super) id: Id,
|
||||
pub(super) tx: mpsc::UnboundedSender<String>,
|
||||
pub(super) abilities: HashSet<String>,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ pub fn init() {
|
|||
let (tx, rx) = tokio::sync::mpsc::unbounded_channel();
|
||||
|
||||
// Client
|
||||
ID.init(yazi_boot::ARGS.client_id.unwrap_or(yazi_shared::timestamp_us()));
|
||||
ID.init(yazi_boot::ARGS.client_id.unwrap_or(yazi_shared::Id::unique()));
|
||||
PEERS.with(<_>::default);
|
||||
QUEUE_TX.init(tx);
|
||||
QUEUE_RX.init(rx);
|
||||
|
|
|
|||
|
|
@ -3,19 +3,19 @@ use std::{fmt::Display, io::Write, str::FromStr};
|
|||
use anyhow::{Result, anyhow};
|
||||
use yazi_boot::BOOT;
|
||||
use yazi_macro::emit;
|
||||
use yazi_shared::event::Cmd;
|
||||
use yazi_shared::{Id, event::Cmd};
|
||||
|
||||
use crate::{ID, body::Body};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Payload<'a> {
|
||||
pub receiver: u64,
|
||||
pub sender: u64,
|
||||
pub receiver: Id,
|
||||
pub sender: Id,
|
||||
pub body: Body<'a>,
|
||||
}
|
||||
|
||||
impl<'a> Payload<'a> {
|
||||
pub(super) fn new(body: Body<'a>) -> Self { Self { receiver: 0, sender: *ID, body } }
|
||||
pub(super) fn new(body: Body<'a>) -> Self { Self { receiver: Id(0), sender: *ID, body } }
|
||||
|
||||
pub(super) fn flush(&self) { writeln!(std::io::stdout(), "{self}").ok(); }
|
||||
|
||||
|
|
@ -33,12 +33,12 @@ impl<'a> Payload<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
pub(super) fn with_receiver(mut self, receiver: u64) -> Self {
|
||||
pub(super) fn with_receiver(mut self, receiver: Id) -> Self {
|
||||
self.receiver = receiver;
|
||||
self
|
||||
}
|
||||
|
||||
pub(super) fn with_sender(mut self, sender: u64) -> Self {
|
||||
pub(super) fn with_sender(mut self, sender: Id) -> Self {
|
||||
self.sender = sender;
|
||||
self
|
||||
}
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ impl Pubsub {
|
|||
|
||||
pub fn pub_(body: Body<'static>) { body.with_receiver(*ID).emit(); }
|
||||
|
||||
pub fn pub_to(receiver: u64, body: Body<'static>) {
|
||||
pub fn pub_to(receiver: Id, body: Body<'static>) {
|
||||
if receiver == *ID {
|
||||
return Self::pub_(body);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,11 +3,11 @@ use std::{collections::HashMap, str::FromStr, time::Duration};
|
|||
use anyhow::Result;
|
||||
use parking_lot::RwLock;
|
||||
use tokio::{io::{AsyncBufReadExt, AsyncWriteExt, BufReader}, select, sync::mpsc::{self, UnboundedReceiver}, task::JoinHandle, time};
|
||||
use yazi_shared::RoCell;
|
||||
use yazi_shared::{Id, RoCell};
|
||||
|
||||
use crate::{Client, ClientWriter, Payload, Peer, STATE, Stream, body::{Body, BodyBye, BodyHey}};
|
||||
|
||||
pub(super) static CLIENTS: RoCell<RwLock<HashMap<u64, Client>>> = RoCell::new();
|
||||
pub(super) static CLIENTS: RoCell<RwLock<HashMap<Id, Client>>> = RoCell::new();
|
||||
|
||||
pub(super) struct Server;
|
||||
|
||||
|
|
@ -87,7 +87,7 @@ impl Server {
|
|||
}))
|
||||
}
|
||||
|
||||
fn handle_hi(s: String, id: &mut Option<u64>, tx: mpsc::UnboundedSender<String>) {
|
||||
fn handle_hi(s: String, id: &mut Option<Id>, tx: mpsc::UnboundedSender<String>) {
|
||||
let Ok(payload) = Payload::from_str(&s) else { return };
|
||||
let Body::Hi(hi) = payload.body else { return };
|
||||
|
||||
|
|
@ -108,7 +108,7 @@ impl Server {
|
|||
Self::handle_hey(&clients);
|
||||
}
|
||||
|
||||
fn handle_hey(clients: &HashMap<u64, Client>) {
|
||||
fn handle_hey(clients: &HashMap<Id, Client>) {
|
||||
let payload = format!(
|
||||
"{}\n",
|
||||
Payload::new(BodyHey::owned(
|
||||
|
|
@ -118,7 +118,7 @@ impl Server {
|
|||
clients.values().for_each(|c| _ = c.tx.send(payload.clone()));
|
||||
}
|
||||
|
||||
async fn handle_bye(id: u64, mut rx: UnboundedReceiver<String>, mut writer: ClientWriter) {
|
||||
async fn handle_bye(id: Id, mut rx: UnboundedReceiver<String>, mut writer: ClientWriter) {
|
||||
while let Ok(payload) = rx.try_recv() {
|
||||
if writer.write_all(payload.as_bytes()).await.is_err() {
|
||||
break;
|
||||
|
|
@ -126,7 +126,7 @@ impl Server {
|
|||
}
|
||||
|
||||
_ = writer
|
||||
.write_all(BodyBye::owned().with_receiver(id).with_sender(0).to_string().as_bytes())
|
||||
.write_all(BodyBye::owned().with_receiver(id).with_sender(Id(0)).to_string().as_bytes())
|
||||
.await;
|
||||
|
||||
writer.flush().await.ok();
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ tokio-util = { workspace = true }
|
|||
tracing = { workspace = true }
|
||||
twox-hash = { workspace = true }
|
||||
unicode-width = { workspace = true }
|
||||
yazi-prebuild = "0.1.2"
|
||||
yazi-prebuilt = "0.1.0"
|
||||
|
||||
[target."cfg(unix)".dependencies]
|
||||
uzers = { workspace = true }
|
||||
|
|
|
|||
4
yazi-plugin/src/external/highlighter.rs
vendored
4
yazi-plugin/src/external/highlighter.rs
vendored
|
|
@ -23,9 +23,9 @@ impl Highlighter {
|
|||
let theme = std::fs::File::open(&THEME.mgr.syntect_theme)
|
||||
.map_err(LoadingError::Io)
|
||||
.and_then(|f| ThemeSet::load_from_reader(&mut std::io::BufReader::new(f)))
|
||||
.or_else(|_| ThemeSet::load_from_reader(&mut Cursor::new(yazi_prebuild::ansi_theme())));
|
||||
.or_else(|_| ThemeSet::load_from_reader(&mut Cursor::new(yazi_prebuilt::ansi_theme())));
|
||||
|
||||
let syntaxes = dumps::from_uncompressed_data(yazi_prebuild::syntaxes());
|
||||
let syntaxes = dumps::from_uncompressed_data(yazi_prebuilt::syntaxes());
|
||||
|
||||
(theme.unwrap(), syntaxes.unwrap())
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
use std::ops::Deref;
|
||||
|
||||
use mlua::{FromLua, UserData};
|
||||
use mlua::{ExternalError, ExternalResult, FromLua, Lua, UserData, Value};
|
||||
|
||||
#[derive(Clone, Copy, FromLua)]
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct Id(pub yazi_shared::Id);
|
||||
|
||||
impl Deref for Id {
|
||||
|
|
@ -12,4 +12,18 @@ impl Deref for Id {
|
|||
fn deref(&self) -> &Self::Target { &self.0 }
|
||||
}
|
||||
|
||||
impl UserData for Id {}
|
||||
impl FromLua for Id {
|
||||
fn from_lua(value: Value, _: &Lua) -> mlua::Result<Self> {
|
||||
Ok(match value {
|
||||
Value::Integer(i) => Self(i.try_into().into_lua_err()?),
|
||||
Value::UserData(ud) => *ud.borrow::<Self>()?,
|
||||
_ => Err("expected integer or userdata".into_lua_err())?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl UserData for Id {
|
||||
fn add_fields<F: mlua::UserDataFields<Self>>(fields: &mut F) {
|
||||
fields.add_field_method_get("value", |_, me: &Self| Ok(me.0.get()));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use mlua::{ExternalResult, Function, Lua, Value};
|
||||
use yazi_dds::body::Body;
|
||||
|
||||
use crate::runtime::RtRef;
|
||||
use crate::{Id, runtime::RtRef};
|
||||
|
||||
pub struct Pubsub;
|
||||
|
||||
|
|
@ -14,8 +14,8 @@ impl Pubsub {
|
|||
}
|
||||
|
||||
pub(super) fn pub_to(lua: &Lua) -> mlua::Result<Function> {
|
||||
lua.create_function(|_, (receiver, kind, value): (u64, mlua::String, Value)| {
|
||||
yazi_dds::Pubsub::pub_to(receiver, Body::from_lua(&kind.to_str()?, value)?);
|
||||
lua.create_function(|_, (receiver, kind, value): (Id, mlua::String, Value)| {
|
||||
yazi_dds::Pubsub::pub_to(*receiver, Body::from_lua(&kind.to_str()?, value)?);
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ impl Utils {
|
|||
pub(super) fn id(lua: &Lua) -> mlua::Result<Function> {
|
||||
lua.create_function(|_, type_: mlua::String| {
|
||||
Ok(Id(match type_.as_bytes().as_ref() {
|
||||
b"app" => *yazi_dds::ID,
|
||||
b"ft" => yazi_fs::FILES_TICKET.next(),
|
||||
_ => Err("Invalid id type".into_lua_err())?,
|
||||
}))
|
||||
|
|
|
|||
|
|
@ -1,13 +1,15 @@
|
|||
use std::{fmt::Display, str::FromStr, sync::atomic::{AtomicUsize, Ordering}};
|
||||
use std::{fmt::Display, str::FromStr, sync::atomic::{AtomicU64, Ordering}};
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Clone, Copy, Debug, Default, Hash, Eq, PartialEq, Serialize, Deserialize)]
|
||||
pub struct Id(usize);
|
||||
pub struct Id(pub u64);
|
||||
|
||||
impl Id {
|
||||
#[inline]
|
||||
pub fn get(&self) -> usize { self.0 }
|
||||
pub const fn get(&self) -> u64 { self.0 }
|
||||
|
||||
pub fn unique() -> Self { Self(crate::timestamp_us()) }
|
||||
}
|
||||
|
||||
impl Display for Id {
|
||||
|
|
@ -15,25 +17,29 @@ impl Display for Id {
|
|||
}
|
||||
|
||||
impl FromStr for Id {
|
||||
type Err = <usize as FromStr>::Err;
|
||||
type Err = <u64 as FromStr>::Err;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> { s.parse().map(Self) }
|
||||
}
|
||||
|
||||
impl TryFrom<i64> for Id {
|
||||
type Error = <usize as TryFrom<i64>>::Error;
|
||||
type Error = <u64 as TryFrom<i64>>::Error;
|
||||
|
||||
fn try_from(value: i64) -> Result<Self, Self::Error> { usize::try_from(value).map(Self) }
|
||||
fn try_from(value: i64) -> Result<Self, Self::Error> { u64::try_from(value).map(Self) }
|
||||
}
|
||||
|
||||
impl PartialEq<u64> for Id {
|
||||
fn eq(&self, other: &u64) -> bool { self.0 == *other }
|
||||
}
|
||||
|
||||
// --- Ids
|
||||
pub struct Ids {
|
||||
next: AtomicUsize,
|
||||
next: AtomicU64,
|
||||
}
|
||||
|
||||
impl Ids {
|
||||
#[inline]
|
||||
pub const fn new() -> Self { Self { next: AtomicUsize::new(1) } }
|
||||
pub const fn new() -> Self { Self { next: AtomicU64::new(1) } }
|
||||
|
||||
#[inline]
|
||||
pub fn next(&self) -> Id {
|
||||
|
|
|
|||
|
|
@ -42,8 +42,8 @@ impl Input {
|
|||
let delta = snap.mode.delta();
|
||||
let s = snap.slice(snap.offset..snap.cursor + delta);
|
||||
if s.width() >= limit {
|
||||
let s = s.chars().rev().collect::<String>();
|
||||
snap.offset = snap.cursor - InputSnap::find_window(&s, 0, limit).end.saturating_sub(delta);
|
||||
let range = InputSnap::find_window(s.chars().rev(), 0, limit);
|
||||
snap.offset = snap.cursor - range.end.saturating_sub(delta);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,19 +22,19 @@ impl InputSnap {
|
|||
|
||||
op: Default::default(),
|
||||
|
||||
mode: Default::default(),
|
||||
mode: Default::default(),
|
||||
offset: usize::MAX,
|
||||
cursor: usize::MAX,
|
||||
};
|
||||
snap.reset(limit);
|
||||
snap.resize(limit);
|
||||
snap
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(super) fn reset(&mut self, limit: usize) {
|
||||
pub(super) fn resize(&mut self, limit: usize) {
|
||||
let range = Self::find_window(self.value.chars().rev(), 0, limit);
|
||||
self.cursor = self.cursor.min(self.count().saturating_sub(self.mode.delta()));
|
||||
self.offset =
|
||||
self.offset.min(self.cursor.saturating_sub(Self::find_window(&self.rev(), 0, limit).end));
|
||||
self.offset = self.offset.min(self.cursor.saturating_sub(range.end));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -61,30 +61,29 @@ impl InputSnap {
|
|||
&self.value[s.unwrap()..e.unwrap()]
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(super) fn rev(&self) -> String { self.value.chars().rev().collect::<String>() }
|
||||
|
||||
#[inline]
|
||||
pub(super) fn window(&self, limit: usize) -> Range<usize> {
|
||||
Self::find_window(&self.value, self.offset, limit)
|
||||
Self::find_window(self.value.chars(), self.offset, limit)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(super) fn find_window(s: &str, offset: usize, limit: usize) -> Range<usize> {
|
||||
pub(super) fn find_window<T>(it: T, offset: usize, limit: usize) -> Range<usize>
|
||||
where
|
||||
T: Iterator<Item = char>,
|
||||
{
|
||||
let mut width = 0;
|
||||
let v: Vec<_> = s
|
||||
.chars()
|
||||
.enumerate()
|
||||
.skip(offset)
|
||||
.map_while(|(i, c)| {
|
||||
width += c.width().unwrap_or(0);
|
||||
if width < limit { Some(i) } else { None }
|
||||
})
|
||||
.collect();
|
||||
let mut range = None;
|
||||
|
||||
if v.is_empty() {
|
||||
return 0..0;
|
||||
for (i, c) in it.enumerate().skip(offset) {
|
||||
width += c.width().unwrap_or(0);
|
||||
if width > limit {
|
||||
break;
|
||||
}
|
||||
match range {
|
||||
None => range = Some(i..i + 1),
|
||||
Some(ref mut r) => r.end = i + 1,
|
||||
}
|
||||
}
|
||||
*v.first().unwrap()..v.last().unwrap() + 1
|
||||
range.unwrap_or(0..0)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ impl InputSnaps {
|
|||
let value = mem::take(&mut self.versions[self.idx].value);
|
||||
self.versions[self.idx] = self.current.clone();
|
||||
self.versions[self.idx].value = value;
|
||||
self.versions[self.idx].reset(limit);
|
||||
self.versions[self.idx].resize(limit);
|
||||
|
||||
// If the *current* value is the same as the *last* version
|
||||
if self.versions[self.idx].value == self.current.value {
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ impl Widget for &Input {
|
|||
height: area.height.min(1),
|
||||
},
|
||||
THEME.input.selected,
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue