mirror of
https://github.com/sxyazi/yazi.git
synced 2026-07-21 23:01:05 +00:00
fix: use a unique Id for each tab (#1826)
This commit is contained in:
parent
35d781e240
commit
e8c1d625ac
24 changed files with 143 additions and 82 deletions
|
|
@ -2,21 +2,18 @@ use std::{collections::HashSet, path::PathBuf};
|
|||
|
||||
use yazi_dds::Pubsub;
|
||||
use yazi_macro::render;
|
||||
use yazi_shared::{event::{Cmd, Data}, fs::{Url, Urn}};
|
||||
use yazi_shared::{Id, event::{Cmd, Data}, fs::{Url, Urn}};
|
||||
|
||||
use crate::manager::Manager;
|
||||
|
||||
struct Opt {
|
||||
url: Option<Url>,
|
||||
tab: Option<usize>,
|
||||
tab: Option<Id>,
|
||||
}
|
||||
|
||||
impl From<Cmd> for Opt {
|
||||
fn from(mut c: Cmd) -> Self {
|
||||
Self {
|
||||
url: c.take_first().and_then(Data::into_url),
|
||||
tab: c.get("tab").and_then(Data::as_usize),
|
||||
}
|
||||
Self { url: c.take_first().and_then(Data::into_url), tab: c.get("tab").and_then(Data::as_id) }
|
||||
}
|
||||
}
|
||||
impl From<Option<Url>> for Opt {
|
||||
|
|
@ -49,10 +46,10 @@ impl Manager {
|
|||
self.watcher.watch(to_watch);
|
||||
|
||||
// Publish through DDS
|
||||
Pubsub::pub_from_hover(self.active().idx, self.hovered().map(|h| &h.url));
|
||||
Pubsub::pub_from_hover(self.active().id, self.hovered().map(|h| &h.url));
|
||||
}
|
||||
|
||||
fn hover_do(&mut self, url: Url, tab: Option<usize>) {
|
||||
fn hover_do(&mut self, url: Url, tab: Option<Id>) {
|
||||
// Hover on the file
|
||||
if let Ok(p) = url.strip_prefix(&self.current_or(tab).url).map(PathBuf::from) {
|
||||
render!(self.current_or_mut(tab).repos(Some(Urn::new(&p))));
|
||||
|
|
|
|||
|
|
@ -30,7 +30,6 @@ impl Tabs {
|
|||
self.set_idx(self.absolute(1));
|
||||
}
|
||||
|
||||
self.reorder();
|
||||
render!();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,8 +36,7 @@ impl Tabs {
|
|||
return;
|
||||
}
|
||||
|
||||
let mut tab = Tab { idx: self.cursor + 1, ..Default::default() };
|
||||
|
||||
let mut tab = Tab::default();
|
||||
if !opt.current {
|
||||
tab.cd(opt.url);
|
||||
} else if let Some(h) = self.active().hovered() {
|
||||
|
|
@ -52,7 +51,6 @@ impl Tabs {
|
|||
|
||||
self.items.insert(self.cursor + 1, tab);
|
||||
self.set_idx(self.cursor + 1);
|
||||
self.reorder();
|
||||
render!();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,7 +21,6 @@ impl Tabs {
|
|||
|
||||
self.items.swap(self.cursor, idx);
|
||||
self.set_idx(idx);
|
||||
self.reorder();
|
||||
render!();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@ impl Manager {
|
|||
return;
|
||||
}
|
||||
|
||||
ManagerProxy::hover(None, tab.idx); // Re-hover in next loop
|
||||
ManagerProxy::hover(None, tab.id); // Re-hover in next loop
|
||||
ManagerProxy::update_paged(); // Update for paged files in next loop
|
||||
if calc {
|
||||
tasks.prework_sorted(&tab.current.files);
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ use ratatui::layout::Rect;
|
|||
use yazi_adapter::Dimension;
|
||||
use yazi_config::popup::{Origin, Position};
|
||||
use yazi_fs::Folder;
|
||||
use yazi_shared::fs::{File, Url};
|
||||
use yazi_shared::{Id, fs::{File, Url}};
|
||||
|
||||
use super::{Mimetype, Tabs, Watcher, Yanked};
|
||||
use crate::tab::Tab;
|
||||
|
|
@ -48,10 +48,10 @@ impl Manager {
|
|||
pub fn active_mut(&mut self) -> &mut Tab { self.tabs.active_mut() }
|
||||
|
||||
#[inline]
|
||||
pub fn active_or(&self, idx: Option<usize>) -> &Tab { self.tabs.active_or(idx) }
|
||||
pub fn active_or(&self, id: Option<Id>) -> &Tab { self.tabs.active_or(id) }
|
||||
|
||||
#[inline]
|
||||
pub fn active_or_mut(&mut self, idx: Option<usize>) -> &mut Tab { self.tabs.active_or_mut(idx) }
|
||||
pub fn active_or_mut(&mut self, id: Option<Id>) -> &mut Tab { self.tabs.active_or_mut(id) }
|
||||
|
||||
#[inline]
|
||||
pub fn current(&self) -> &Folder { &self.active().current }
|
||||
|
|
@ -60,10 +60,10 @@ impl Manager {
|
|||
pub fn current_mut(&mut self) -> &mut Folder { &mut self.active_mut().current }
|
||||
|
||||
#[inline]
|
||||
pub fn current_or(&self, idx: Option<usize>) -> &Folder { &self.active_or(idx).current }
|
||||
pub fn current_or(&self, idx: Option<Id>) -> &Folder { &self.active_or(idx).current }
|
||||
|
||||
#[inline]
|
||||
pub fn current_or_mut(&mut self, idx: Option<usize>) -> &mut Folder {
|
||||
pub fn current_or_mut(&mut self, idx: Option<Id>) -> &mut Folder {
|
||||
&mut self.active_or_mut(idx).current
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ use std::ops::{Deref, DerefMut};
|
|||
use yazi_boot::BOOT;
|
||||
use yazi_dds::Pubsub;
|
||||
use yazi_proxy::ManagerProxy;
|
||||
use yazi_shared::fs::Url;
|
||||
use yazi_shared::{Id, fs::Url};
|
||||
|
||||
use crate::tab::Tab;
|
||||
|
||||
|
|
@ -16,7 +16,6 @@ impl Tabs {
|
|||
pub fn make() -> Self {
|
||||
let mut tabs =
|
||||
Self { cursor: 0, items: (0..BOOT.cwds.len()).map(|_| Tab::default()).collect() };
|
||||
tabs.reorder();
|
||||
|
||||
for (i, tab) in tabs.iter_mut().enumerate() {
|
||||
let file = &BOOT.files[i];
|
||||
|
|
@ -37,11 +36,6 @@ impl Tabs {
|
|||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(super) fn reorder(&mut self) {
|
||||
self.items.iter_mut().enumerate().for_each(|(i, tab)| tab.idx = i);
|
||||
}
|
||||
|
||||
pub(super) fn set_idx(&mut self, idx: usize) {
|
||||
// Reset the preview of the last active tab
|
||||
if let Some(active) = self.items.get_mut(self.cursor) {
|
||||
|
|
@ -63,16 +57,16 @@ impl Tabs {
|
|||
pub(super) fn active_mut(&mut self) -> &mut Tab { &mut self.items[self.cursor] }
|
||||
|
||||
#[inline]
|
||||
pub fn active_or(&self, idx: Option<usize>) -> &Tab {
|
||||
idx.and_then(|i| self.items.get(i)).unwrap_or(&self.items[self.cursor])
|
||||
pub fn active_or(&self, id: Option<Id>) -> &Tab {
|
||||
id.and_then(|id| self.iter().find(|&t| t.id == id)).unwrap_or(self.active())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(super) fn active_or_mut(&mut self, idx: Option<usize>) -> &mut Tab {
|
||||
if let Some(i) = idx.filter(|&i| i < self.items.len()) {
|
||||
pub(super) fn active_or_mut(&mut self, id: Option<Id>) -> &mut Tab {
|
||||
if let Some(i) = id.and_then(|id| self.iter().position(|t| t.id == id)) {
|
||||
&mut self.items[i]
|
||||
} else {
|
||||
&mut self.items[self.cursor]
|
||||
self.active_mut()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ impl Tab {
|
|||
}
|
||||
}
|
||||
|
||||
ManagerProxy::hover(None, self.idx);
|
||||
ManagerProxy::hover(None, self.id);
|
||||
render!();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ impl Tab {
|
|||
self.backstack.push(opt.target.clone());
|
||||
}
|
||||
|
||||
Pubsub::pub_from_cd(self.idx, self.cwd());
|
||||
Pubsub::pub_from_cd(self.id, self.cwd());
|
||||
ManagerProxy::refresh();
|
||||
render!();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ impl Tab {
|
|||
|
||||
self.current.repos(hovered.as_ref().map(|u| u.as_urn()));
|
||||
if self.hovered().map(|f| f.urn()) != hovered.as_ref().map(|u| u.as_urn()) {
|
||||
ManagerProxy::hover(None, self.idx);
|
||||
ManagerProxy::hover(None, self.id);
|
||||
}
|
||||
|
||||
render!();
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ impl Tab {
|
|||
self.apply_files_attrs();
|
||||
|
||||
if hovered.as_ref() != self.hovered().map(|f| &f.url) {
|
||||
ManagerProxy::hover(hovered, self.idx);
|
||||
ManagerProxy::hover(hovered, self.id);
|
||||
} else if self.hovered().is_some_and(|f| f.is_dir()) {
|
||||
ManagerProxy::peek(true);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,6 +30,6 @@ impl Tab {
|
|||
|
||||
self.cd(parent.clone());
|
||||
FilesOp::Creating(parent, vec![File::from_dummy(opt.target.clone(), None)]).emit();
|
||||
ManagerProxy::hover(Some(opt.target), self.idx);
|
||||
ManagerProxy::hover(Some(opt.target), self.id);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,14 +7,13 @@ use yazi_adapter::Dimension;
|
|||
use yazi_config::{LAYOUT, popup::{Origin, Position}};
|
||||
use yazi_fs::{Folder, FolderStage};
|
||||
use yazi_macro::render;
|
||||
use yazi_shared::fs::{File, Url};
|
||||
use yazi_shared::{Id, Ids, fs::{File, Url}};
|
||||
|
||||
use super::{Backstack, Config, Finder, History, Mode, Preview};
|
||||
use crate::tab::Selected;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Tab {
|
||||
pub idx: usize,
|
||||
pub id: Id,
|
||||
pub mode: Mode,
|
||||
pub conf: Config,
|
||||
pub current: Folder,
|
||||
|
|
@ -29,6 +28,28 @@ pub struct Tab {
|
|||
pub search: Option<JoinHandle<Result<()>>>,
|
||||
}
|
||||
|
||||
impl Default for Tab {
|
||||
fn default() -> Self {
|
||||
static IDS: Ids = Ids::new();
|
||||
|
||||
Self {
|
||||
id: IDS.next(),
|
||||
mode: Default::default(),
|
||||
conf: Default::default(),
|
||||
current: Default::default(),
|
||||
parent: Default::default(),
|
||||
|
||||
backstack: Default::default(),
|
||||
history: Default::default(),
|
||||
selected: Default::default(),
|
||||
|
||||
preview: Default::default(),
|
||||
finder: Default::default(),
|
||||
search: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Tab {
|
||||
pub fn shutdown(&mut self) {
|
||||
if let Some(handle) = self.search.take() {
|
||||
|
|
|
|||
|
|
@ -2,13 +2,13 @@ use std::borrow::Cow;
|
|||
|
||||
use mlua::{IntoLua, Lua, Value};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use yazi_shared::fs::Url;
|
||||
use yazi_shared::{Id, fs::Url};
|
||||
|
||||
use super::Body;
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct BodyCd<'a> {
|
||||
pub tab: usize,
|
||||
pub tab: Id,
|
||||
pub url: Cow<'a, Url>,
|
||||
#[serde(skip)]
|
||||
dummy: bool,
|
||||
|
|
@ -16,14 +16,14 @@ pub struct BodyCd<'a> {
|
|||
|
||||
impl<'a> BodyCd<'a> {
|
||||
#[inline]
|
||||
pub fn borrowed(tab: usize, url: &'a Url) -> Body<'a> {
|
||||
pub fn borrowed(tab: Id, url: &'a Url) -> Body<'a> {
|
||||
Self { tab, url: Cow::Borrowed(url), dummy: false }.into()
|
||||
}
|
||||
}
|
||||
|
||||
impl BodyCd<'static> {
|
||||
#[inline]
|
||||
pub fn dummy(tab: usize) -> Body<'static> {
|
||||
pub fn dummy(tab: Id) -> Body<'static> {
|
||||
Self { tab, url: Default::default(), dummy: true }.into()
|
||||
}
|
||||
}
|
||||
|
|
@ -36,11 +36,11 @@ impl IntoLua<'_> for BodyCd<'static> {
|
|||
fn into_lua(self, lua: &Lua) -> mlua::Result<Value> {
|
||||
if let Some(Cow::Owned(url)) = Some(self.url).filter(|_| !self.dummy) {
|
||||
lua.create_table_from([
|
||||
("tab", self.tab.into_lua(lua)?),
|
||||
("tab", self.tab.get().into_lua(lua)?),
|
||||
("url", lua.create_any_userdata(url)?.into_lua(lua)?),
|
||||
])?
|
||||
} else {
|
||||
lua.create_table_from([("tab", self.tab)])?
|
||||
lua.create_table_from([("tab", self.tab.get())])?
|
||||
}
|
||||
.into_lua(lua)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,26 +2,26 @@ use std::borrow::Cow;
|
|||
|
||||
use mlua::{IntoLua, Lua, Value};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use yazi_shared::fs::Url;
|
||||
use yazi_shared::{Id, fs::Url};
|
||||
|
||||
use super::Body;
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct BodyHover<'a> {
|
||||
pub tab: usize,
|
||||
pub tab: Id,
|
||||
pub url: Option<Cow<'a, Url>>,
|
||||
}
|
||||
|
||||
impl<'a> BodyHover<'a> {
|
||||
#[inline]
|
||||
pub fn borrowed(tab: usize, url: Option<&'a Url>) -> Body<'a> {
|
||||
pub fn borrowed(tab: Id, url: Option<&'a Url>) -> Body<'a> {
|
||||
Self { tab, url: url.map(Cow::Borrowed) }.into()
|
||||
}
|
||||
}
|
||||
|
||||
impl BodyHover<'static> {
|
||||
#[inline]
|
||||
pub fn dummy(tab: usize) -> Body<'static> { Self { tab, url: None }.into() }
|
||||
pub fn dummy(tab: Id) -> Body<'static> { Self { tab, url: None }.into() }
|
||||
}
|
||||
|
||||
impl<'a> From<BodyHover<'a>> for Body<'a> {
|
||||
|
|
@ -32,11 +32,11 @@ impl IntoLua<'_> for BodyHover<'static> {
|
|||
fn into_lua(self, lua: &Lua) -> mlua::Result<Value> {
|
||||
if let Some(Cow::Owned(url)) = self.url {
|
||||
lua.create_table_from([
|
||||
("tab", self.tab.into_lua(lua)?),
|
||||
("tab", self.tab.get().into_lua(lua)?),
|
||||
("url", lua.create_any_userdata(url)?.into_lua(lua)?),
|
||||
])?
|
||||
} else {
|
||||
lua.create_table_from([("tab", self.tab)])?
|
||||
lua.create_table_from([("tab", self.tab.get())])?
|
||||
}
|
||||
.into_lua(lua)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ use std::collections::{HashMap, HashSet};
|
|||
use mlua::Function;
|
||||
use parking_lot::RwLock;
|
||||
use yazi_boot::BOOT;
|
||||
use yazi_shared::{RoCell, fs::Url};
|
||||
use yazi_shared::{Id, RoCell, fs::Url};
|
||||
|
||||
use crate::{Client, ID, PEERS, body::{Body, BodyBulk, BodyCd, BodyDelete, BodyHi, BodyHover, BodyMove, BodyMoveItem, BodyRename, BodyTab, BodyTrash, BodyYank}};
|
||||
|
||||
|
|
@ -88,7 +88,7 @@ impl Pubsub {
|
|||
true
|
||||
}
|
||||
|
||||
pub fn pub_from_cd(tab: usize, url: &Url) {
|
||||
pub fn pub_from_cd(tab: Id, url: &Url) {
|
||||
if LOCAL.read().contains_key("cd") {
|
||||
Self::pub_(BodyCd::dummy(tab));
|
||||
}
|
||||
|
|
@ -100,7 +100,7 @@ impl Pubsub {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn pub_from_hover(tab: usize, url: Option<&Url>) {
|
||||
pub fn pub_from_hover(tab: Id, url: Option<&Url>) {
|
||||
if LOCAL.read().contains_key("hover") {
|
||||
Self::pub_(BodyHover::dummy(tab));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ impl Tab {
|
|||
|
||||
pub(super) fn register(lua: &Lua) -> mlua::Result<()> {
|
||||
lua.register_userdata_type::<Self>(|reg| {
|
||||
reg.add_field_method_get("idx", |_, me| Ok(me.idx + 1));
|
||||
reg.add_field_method_get("id", |_, me| Ok(me.id.get()));
|
||||
reg.add_method("name", |lua, me, ()| {
|
||||
lua.create_string(me.current.url.name().as_encoded_bytes())
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,15 +1,15 @@
|
|||
use std::{collections::{HashMap, HashSet}, mem, ops::Deref, sync::atomic::Ordering};
|
||||
use std::{collections::{HashMap, HashSet}, mem, ops::Deref};
|
||||
|
||||
use tokio::{fs::{self, DirEntry}, select, sync::mpsc::{self, UnboundedReceiver}};
|
||||
use yazi_config::{MANAGER, manager::SortBy};
|
||||
use yazi_shared::fs::{Cha, FILES_TICKET, File, FilesOp, Url, Urn, UrnBuf, maybe_exists};
|
||||
use yazi_shared::{Id, fs::{Cha, FILES_TICKET, File, FilesOp, Url, Urn, UrnBuf, maybe_exists}};
|
||||
|
||||
use super::{FilesSorter, Filter};
|
||||
|
||||
pub struct Files {
|
||||
hidden: Vec<File>,
|
||||
items: Vec<File>,
|
||||
ticket: u64,
|
||||
ticket: Id,
|
||||
version: u64,
|
||||
pub revision: u64,
|
||||
|
||||
|
|
@ -118,7 +118,7 @@ impl Files {
|
|||
|
||||
impl Files {
|
||||
pub fn update_full(&mut self, files: Vec<File>) {
|
||||
self.ticket = FILES_TICKET.fetch_add(1, Ordering::Relaxed);
|
||||
self.ticket = FILES_TICKET.next();
|
||||
|
||||
(self.hidden, self.items) = self.split_files(files);
|
||||
if !self.items.is_empty() {
|
||||
|
|
@ -126,7 +126,7 @@ impl Files {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn update_part(&mut self, files: Vec<File>, ticket: u64) {
|
||||
pub fn update_part(&mut self, files: Vec<File>, ticket: Id) {
|
||||
if !files.is_empty() {
|
||||
if ticket != self.ticket {
|
||||
return;
|
||||
|
|
@ -162,7 +162,7 @@ impl Files {
|
|||
}
|
||||
|
||||
pub fn update_ioerr(&mut self) {
|
||||
self.ticket = FILES_TICKET.fetch_add(1, Ordering::Relaxed);
|
||||
self.ticket = FILES_TICKET.next();
|
||||
self.hidden.clear();
|
||||
self.items.clear();
|
||||
}
|
||||
|
|
@ -349,7 +349,7 @@ impl Files {
|
|||
|
||||
// --- Ticket
|
||||
#[inline]
|
||||
pub fn ticket(&self) -> u64 { self.ticket }
|
||||
pub fn ticket(&self) -> Id { self.ticket }
|
||||
|
||||
// --- Sorter
|
||||
#[inline]
|
||||
|
|
|
|||
14
yazi-plugin/src/external/highlighter.rs
vendored
14
yazi-plugin/src/external/highlighter.rs
vendored
|
|
@ -1,13 +1,13 @@
|
|||
use std::{borrow::Cow, io::Cursor, mem, path::{Path, PathBuf}, sync::atomic::{AtomicUsize, Ordering}};
|
||||
use std::{borrow::Cow, io::Cursor, mem, path::{Path, PathBuf}};
|
||||
|
||||
use anyhow::{Result, anyhow};
|
||||
use ratatui::{layout::Rect, text::{Line, Span, Text}};
|
||||
use syntect::{LoadingError, dumps, easy::HighlightLines, highlighting::{self, Theme, ThemeSet}, parsing::{SyntaxReference, SyntaxSet}};
|
||||
use tokio::{fs::File, io::{AsyncBufReadExt, BufReader}, sync::OnceCell};
|
||||
use yazi_config::{PREVIEW, THEME, preview::PreviewWrap};
|
||||
use yazi_shared::{errors::PeekError, replace_to_printable};
|
||||
use yazi_shared::{Ids, errors::PeekError, replace_to_printable};
|
||||
|
||||
static INCR: AtomicUsize = AtomicUsize::new(0);
|
||||
static INCR: Ids = Ids::new();
|
||||
static SYNTECT: OnceCell<(Theme, SyntaxSet)> = OnceCell::const_new();
|
||||
|
||||
pub struct Highlighter {
|
||||
|
|
@ -39,7 +39,7 @@ impl Highlighter {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
pub fn abort() { INCR.fetch_add(1, Ordering::Relaxed); }
|
||||
pub fn abort() { INCR.next(); }
|
||||
|
||||
pub async fn highlight(&self, skip: usize, area: Rect) -> Result<Text<'static>, PeekError> {
|
||||
let mut reader = BufReader::new(File::open(&self.path).await?);
|
||||
|
|
@ -104,13 +104,13 @@ impl Highlighter {
|
|||
after: Vec<String>,
|
||||
syntax: &'static SyntaxReference,
|
||||
) -> Result<Text<'static>, PeekError> {
|
||||
let ticket = INCR.load(Ordering::Relaxed);
|
||||
let ticket = INCR.current();
|
||||
let (theme, syntaxes) = Self::init().await;
|
||||
|
||||
tokio::task::spawn_blocking(move || {
|
||||
let mut h = HighlightLines::new(syntax, theme);
|
||||
for line in before {
|
||||
if ticket != INCR.load(Ordering::Relaxed) {
|
||||
if ticket != INCR.current() {
|
||||
return Err("Highlighting cancelled".into());
|
||||
}
|
||||
h.highlight_line(&line, syntaxes).map_err(|e| anyhow!(e))?;
|
||||
|
|
@ -119,7 +119,7 @@ impl Highlighter {
|
|||
let indent = PREVIEW.indent();
|
||||
let mut lines = Vec::with_capacity(after.len());
|
||||
for line in after {
|
||||
if ticket != INCR.load(Ordering::Relaxed) {
|
||||
if ticket != INCR.current() {
|
||||
return Err("Highlighting cancelled".into());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use yazi_macro::emit;
|
||||
use yazi_shared::{Layer, event::Cmd, fs::Url};
|
||||
use yazi_shared::{Id, Layer, event::Cmd, fs::Url};
|
||||
|
||||
use crate::options::OpenDoOpt;
|
||||
|
||||
|
|
@ -12,7 +12,7 @@ impl ManagerProxy {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
pub fn hover(url: Option<Url>, tab: usize) {
|
||||
pub fn hover(url: Option<Url>, tab: Id) {
|
||||
emit!(Call(
|
||||
Cmd::args("hover", &url.map_or_else(Vec::new, |u| vec![u])).with("tab", tab),
|
||||
Layer::Manager
|
||||
|
|
|
|||
|
|
@ -143,3 +143,5 @@ impl_integer_as!(isize, as_isize);
|
|||
impl_integer_as!(i16, as_i16);
|
||||
|
||||
impl_number_as!(f64, as_f64);
|
||||
|
||||
impl_integer_as!(crate::Id, as_id);
|
||||
|
|
|
|||
|
|
@ -1,15 +1,15 @@
|
|||
use std::{collections::{HashMap, HashSet}, sync::atomic::{AtomicU64, Ordering}};
|
||||
use std::collections::{HashMap, HashSet};
|
||||
|
||||
use super::{Cha, File, UrnBuf};
|
||||
use crate::{Layer, event::Cmd, fs::Url};
|
||||
use crate::{Id, Ids, Layer, event::Cmd, fs::Url};
|
||||
|
||||
pub static FILES_TICKET: AtomicU64 = AtomicU64::new(0);
|
||||
pub static FILES_TICKET: Ids = Ids::new();
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum FilesOp {
|
||||
Full(Url, Vec<File>, Cha),
|
||||
Part(Url, Vec<File>, u64),
|
||||
Done(Url, Cha, u64),
|
||||
Part(Url, Vec<File>, Id),
|
||||
Done(Url, Cha, Id),
|
||||
Size(Url, HashMap<UrnBuf, u64>),
|
||||
IOErr(Url, std::io::ErrorKind),
|
||||
|
||||
|
|
@ -41,8 +41,8 @@ impl FilesOp {
|
|||
crate::event::Event::Call(Cmd::new("update_files").with_any("op", self), Layer::Manager).emit();
|
||||
}
|
||||
|
||||
pub fn prepare(cwd: &Url) -> u64 {
|
||||
let ticket = FILES_TICKET.fetch_add(1, Ordering::Relaxed);
|
||||
pub fn prepare(cwd: &Url) -> Id {
|
||||
let ticket = FILES_TICKET.next();
|
||||
Self::Part(cwd.clone(), vec![], ticket).emit();
|
||||
ticket
|
||||
}
|
||||
|
|
|
|||
54
yazi-shared/src/id.rs
Normal file
54
yazi-shared/src/id.rs
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
use std::{fmt::Display, str::FromStr, sync::atomic::{AtomicUsize, Ordering}};
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Clone, Copy, Debug, Default, Hash, Eq, PartialEq, Serialize, Deserialize)]
|
||||
pub struct Id(usize);
|
||||
|
||||
impl Id {
|
||||
#[inline]
|
||||
pub fn get(&self) -> usize { self.0 }
|
||||
}
|
||||
|
||||
impl Display for Id {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { self.0.fmt(f) }
|
||||
}
|
||||
|
||||
impl FromStr for Id {
|
||||
type Err = <usize 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;
|
||||
|
||||
fn try_from(value: i64) -> Result<Self, Self::Error> { usize::try_from(value).map(Self) }
|
||||
}
|
||||
|
||||
// --- Ids
|
||||
pub struct Ids {
|
||||
next: AtomicUsize,
|
||||
}
|
||||
|
||||
impl Ids {
|
||||
#[inline]
|
||||
pub const fn new() -> Self { Self { next: AtomicUsize::new(1) } }
|
||||
|
||||
#[inline]
|
||||
pub fn next(&self) -> Id {
|
||||
loop {
|
||||
let old = self.next.fetch_add(1, Ordering::Relaxed);
|
||||
if old != 0 {
|
||||
return Id(old);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn current(&self) -> Id { Id(self.next.load(Ordering::Relaxed)) }
|
||||
}
|
||||
|
||||
impl Default for Ids {
|
||||
fn default() -> Self { Self::new() }
|
||||
}
|
||||
|
|
@ -2,10 +2,7 @@
|
|||
|
||||
yazi_macro::mod_pub!(errors event fs shell theme translit);
|
||||
|
||||
yazi_macro::mod_flat!(
|
||||
chars condition debounce env layer natsort number os rand ro_cell terminal throttle
|
||||
time xdg
|
||||
);
|
||||
yazi_macro::mod_flat!(chars condition debounce env id layer natsort number os rand ro_cell terminal throttle time xdg);
|
||||
|
||||
pub fn init() {
|
||||
#[cfg(unix)]
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue