diff --git a/Cargo.lock b/Cargo.lock index 4e84b565..e5d37558 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2554,9 +2554,7 @@ name = "yazi-core" version = "0.1.5" dependencies = [ "anyhow", - "async-channel", "bitflags 2.4.1", - "clipboard-win", "crossterm", "futures", "indexmap", @@ -2566,16 +2564,15 @@ dependencies = [ "ratatui", "regex", "serde", - "serde_json", "syntect", "tokio", "tokio-stream", "tracing", - "trash", "unicode-width", "yazi-adaptor", "yazi-config", "yazi-prebuild", + "yazi-scheduler", "yazi-shared", ] @@ -2625,6 +2622,27 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "394457709d77af570fcb3c0ef878336213b4e9c8f298eccde728aecd602aa7e0" +[[package]] +name = "yazi-scheduler" +version = "0.1.5" +dependencies = [ + "anyhow", + "async-channel", + "clipboard-win", + "futures", + "libc", + "parking_lot", + "regex", + "serde", + "serde_json", + "tokio", + "tracing", + "trash", + "yazi-adaptor", + "yazi-config", + "yazi-shared", +] + [[package]] name = "yazi-shared" version = "0.1.5" diff --git a/yazi-core/Cargo.toml b/yazi-core/Cargo.toml index d034d6b7..92069d80 100644 --- a/yazi-core/Cargo.toml +++ b/yazi-core/Cargo.toml @@ -9,13 +9,13 @@ homepage = "https://yazi-rs.github.io" repository = "https://github.com/sxyazi/yazi" [dependencies] -yazi-adaptor = { path = "../yazi-adaptor", version = "0.1.5" } -yazi-config = { path = "../yazi-config", version = "0.1.5" } -yazi-shared = { path = "../yazi-shared", version = "0.1.5" } +yazi-adaptor = { path = "../yazi-adaptor", version = "0.1.5" } +yazi-config = { path = "../yazi-config", version = "0.1.5" } +yazi-scheduler = { path = "../yazi-scheduler", version = "0.1.5" } +yazi-shared = { path = "../yazi-shared", version = "0.1.5" } # External dependencies anyhow = "^1" -async-channel = "^1" bitflags = "^2" crossterm = "^0" futures = "^0" @@ -26,16 +26,11 @@ parking_lot = "^0" ratatui = "^0" regex = "^1" serde = "^1" -serde_json = "^1" syntect = { version = "^5", default-features = false, features = [ "parsing", "default-themes", "plist-load", "regex-onig" ] } tokio = { version = "^1", features = [ "parking_lot", "macros", "rt-multi-thread", "sync", "time", "fs", "process", "io-std", "io-util" ] } tokio-stream = "^0" -trash = "^3" unicode-width = "^0" yazi-prebuild = "^0" # Logging tracing = { version = "^0", features = [ "max_level_debug", "release_max_level_warn" ] } - -[target."cfg(windows)".dependencies] -clipboard-win = "^4" diff --git a/yazi-core/src/context.rs b/yazi-core/src/context.rs index b1b6d82c..373666f6 100644 --- a/yazi-core/src/context.rs +++ b/yazi-core/src/context.rs @@ -1,7 +1,5 @@ use ratatui::prelude::Rect; -use tokio::sync::oneshot; use yazi_config::popup::{Origin, Position}; -use yazi_shared::{emit, event::Exec, Layer}; use crate::{completion::Completion, help::Help, input::Input, manager::Manager, select::Select, tasks::Tasks, which::Which}; @@ -29,19 +27,10 @@ impl Ctx { } #[inline] - pub async fn stop() { - let (tx, rx) = oneshot::channel::<()>(); - emit!(Call(Exec::call("stop", vec!["true".to_string()]).with_data(Some(tx)).vec(), Layer::App)); - rx.await.ok(); - } + pub async fn stop() { yazi_scheduler::Scheduler::app_stop().await } #[inline] - pub fn resume() { - emit!(Call( - Exec::call("stop", vec!["false".to_string()]).with_data(None::>).vec(), - Layer::App - )); - } + pub fn resume() { yazi_scheduler::Scheduler::app_resume() } pub fn area(&self, position: &Position) -> Rect { if position.origin != Origin::Hovered { diff --git a/yazi-core/src/files/files.rs b/yazi-core/src/files/files.rs index ff79e141..f5e3b426 100644 --- a/yazi-core/src/files/files.rs +++ b/yazi-core/src/files/files.rs @@ -3,7 +3,7 @@ use std::{collections::{BTreeMap, BTreeSet}, mem, ops::Deref, sync::atomic::Orde use anyhow::Result; use tokio::{fs, select, sync::mpsc::{self, UnboundedReceiver}}; use yazi_config::{manager::SortBy, MANAGER}; -use yazi_shared::{files::{File, FILES_TICKET}, fs::Url}; +use yazi_shared::fs::{File, Url, FILES_TICKET}; use super::FilesSorter; diff --git a/yazi-core/src/files/sorter.rs b/yazi-core/src/files/sorter.rs index 840896e7..bdf620ba 100644 --- a/yazi-core/src/files/sorter.rs +++ b/yazi-core/src/files/sorter.rs @@ -1,7 +1,7 @@ use std::{cmp::Ordering, collections::BTreeMap, mem}; use yazi_config::manager::SortBy; -use yazi_shared::{files::File, fs::Url, natsort}; +use yazi_shared::{fs::File, fs::Url, natsort}; #[derive(Clone, Copy, Default, PartialEq)] pub struct FilesSorter { diff --git a/yazi-core/src/input/commands/paste.rs b/yazi-core/src/input/commands/paste.rs index 47783b01..98ec4d91 100644 --- a/yazi-core/src/input/commands/paste.rs +++ b/yazi-core/src/input/commands/paste.rs @@ -1,6 +1,7 @@ +use yazi_scheduler::external; use yazi_shared::event::Exec; -use crate::{external, input::{op::InputOp, Input}}; +use crate::input::{op::InputOp, Input}; pub struct Opt { before: bool, diff --git a/yazi-core/src/input/input.rs b/yazi-core/src/input/input.rs index 07fae677..2f23e697 100644 --- a/yazi-core/src/input/input.rs +++ b/yazi-core/src/input/input.rs @@ -3,10 +3,10 @@ use std::ops::Range; use tokio::sync::mpsc::UnboundedSender; use unicode_width::UnicodeWidthStr; use yazi_config::{popup::Position, INPUT}; +use yazi_scheduler::external; use yazi_shared::InputError; use super::{mode::InputMode, op::InputOp, InputSnap, InputSnaps}; -use crate::external; #[derive(Default)] pub struct Input { diff --git a/yazi-core/src/lib.rs b/yazi-core/src/lib.rs index ef525620..08b17e4d 100644 --- a/yazi-core/src/lib.rs +++ b/yazi-core/src/lib.rs @@ -6,10 +6,8 @@ clippy::unit_arg )] -mod blocker; pub mod completion; mod context; -pub mod external; pub mod files; pub mod help; mod highlighter; @@ -22,9 +20,8 @@ pub mod tab; pub mod tasks; pub mod which; -pub use blocker::*; pub use context::*; pub use highlighter::*; pub use step::*; -pub fn init() { init_blocker(); } +pub fn init() { yazi_scheduler::init(); } diff --git a/yazi-core/src/manager/commands/create.rs b/yazi-core/src/manager/commands/create.rs index 890dd79c..7320fd5d 100644 --- a/yazi-core/src/manager/commands/create.rs +++ b/yazi-core/src/manager/commands/create.rs @@ -2,7 +2,7 @@ use std::path::{PathBuf, MAIN_SEPARATOR}; use tokio::fs; use yazi_config::popup::InputCfg; -use yazi_shared::{emit, event::Exec, files::{File, FilesOp}, fs::Url}; +use yazi_shared::{emit, event::Exec, fs::{File, FilesOp}, fs::Url}; use crate::{input::Input, manager::Manager}; diff --git a/yazi-core/src/manager/commands/open.rs b/yazi-core/src/manager/commands/open.rs index db801322..029c6eb6 100644 --- a/yazi-core/src/manager/commands/open.rs +++ b/yazi-core/src/manager/commands/open.rs @@ -1,9 +1,10 @@ use std::ffi::OsString; use yazi_config::{popup::SelectCfg, OPEN}; +use yazi_scheduler::external; use yazi_shared::{event::Exec, MIME_DIR}; -use crate::{external, manager::Manager, select::Select, tasks::Tasks}; +use crate::{manager::Manager, select::Select, tasks::Tasks}; pub struct Opt { interactive: bool, diff --git a/yazi-core/src/manager/commands/rename.rs b/yazi-core/src/manager/commands/rename.rs index 60a7a904..b820754f 100644 --- a/yazi-core/src/manager/commands/rename.rs +++ b/yazi-core/src/manager/commands/rename.rs @@ -3,9 +3,10 @@ use std::{collections::BTreeMap, ffi::OsStr, io::{stdout, BufWriter, Write}, pat use anyhow::{anyhow, bail, Result}; use tokio::{fs::{self, OpenOptions}, io::{stdin, AsyncReadExt, AsyncWriteExt}}; use yazi_config::{popup::InputCfg, OPEN, PREVIEW}; -use yazi_shared::{emit, event::Exec, files::{File, FilesOp}, fs::{max_common_root, Url}, term::Term, Defer}; +use yazi_scheduler::{external::{self, ShellOpt}, BLOCKER}; +use yazi_shared::{emit, event::Exec, fs::{max_common_root, File, FilesOp, Url}, term::Term, Defer}; -use crate::{external::{self, ShellOpt}, input::Input, manager::Manager, Ctx, BLOCKER}; +use crate::{input::Input, manager::Manager, Ctx}; pub struct Opt { force: bool, diff --git a/yazi-core/src/manager/manager.rs b/yazi-core/src/manager/manager.rs index 269042a5..4cc0c7a5 100644 --- a/yazi-core/src/manager/manager.rs +++ b/yazi-core/src/manager/manager.rs @@ -1,6 +1,6 @@ use std::collections::{BTreeMap, HashMap, HashSet}; -use yazi_shared::{files::{File, FilesOp}, fs::Url}; +use yazi_shared::{fs::{File, FilesOp}, fs::Url}; use super::{Tabs, Watcher}; use crate::{tab::{Folder, Tab}, tasks::Tasks}; diff --git a/yazi-core/src/manager/watcher.rs b/yazi-core/src/manager/watcher.rs index 785b2e2b..ac62a0c9 100644 --- a/yazi-core/src/manager/watcher.rs +++ b/yazi-core/src/manager/watcher.rs @@ -5,9 +5,10 @@ use notify::{event::{MetadataKind, ModifyKind}, EventKind, RecommendedWatcher, R use parking_lot::RwLock; use tokio::{fs, pin, sync::mpsc::{self, UnboundedReceiver}}; use tokio_stream::{wrappers::UnboundedReceiverStream, StreamExt}; -use yazi_shared::{emit, files::{File, FilesOp}, fs::Url}; +use yazi_scheduler::external; +use yazi_shared::{emit, fs::{File, FilesOp, Url}}; -use crate::{external, files::Files}; +use crate::files::Files; pub struct Watcher { watcher: RecommendedWatcher, diff --git a/yazi-core/src/preview/preview.rs b/yazi-core/src/preview/preview.rs index 32804d57..81ec6e01 100644 --- a/yazi-core/src/preview/preview.rs +++ b/yazi-core/src/preview/preview.rs @@ -4,7 +4,7 @@ use tokio::{pin, task::JoinHandle}; use tokio_stream::{wrappers::UnboundedReceiverStream, StreamExt}; use yazi_adaptor::ADAPTOR; use yazi_config::MANAGER; -use yazi_shared::{emit, event::{PreviewData, PreviewLock}, files::FilesOp, fs::{Cha, Url}, MimeKind, PeekError}; +use yazi_shared::{emit, event::{PreviewData, PreviewLock}, fs::{Cha, FilesOp, Url}, MimeKind, PeekError}; use super::Provider; use crate::{files::Files, manager::Manager, Highlighter}; diff --git a/yazi-core/src/preview/provider.rs b/yazi-core/src/preview/provider.rs index 9fa4adfc..09e0df68 100644 --- a/yazi-core/src/preview/provider.rs +++ b/yazi-core/src/preview/provider.rs @@ -3,9 +3,10 @@ use std::path::Path; use tokio::fs; use yazi_adaptor::ADAPTOR; use yazi_config::{MANAGER, PREVIEW}; +use yazi_scheduler::external; use yazi_shared::{event::PreviewData, MimeKind, PeekError}; -use crate::{external, Highlighter}; +use crate::Highlighter; pub(super) struct Provider; diff --git a/yazi-core/src/tab/commands/copy.rs b/yazi-core/src/tab/commands/copy.rs index 805619fa..15d5622d 100644 --- a/yazi-core/src/tab/commands/copy.rs +++ b/yazi-core/src/tab/commands/copy.rs @@ -1,8 +1,9 @@ use std::ffi::{OsStr, OsString}; +use yazi_scheduler::external; use yazi_shared::event::Exec; -use crate::{external, tab::Tab}; +use crate::tab::Tab; pub struct Opt<'a> { type_: &'a str, diff --git a/yazi-core/src/tab/commands/jump.rs b/yazi-core/src/tab/commands/jump.rs index 3cb3e69d..0700daf0 100644 --- a/yazi-core/src/tab/commands/jump.rs +++ b/yazi-core/src/tab/commands/jump.rs @@ -1,6 +1,7 @@ +use yazi_scheduler::{external::{self, FzfOpt, ZoxideOpt}, BLOCKER}; use yazi_shared::{event::Exec, fs::ends_with_slash, Defer}; -use crate::{external::{self, FzfOpt, ZoxideOpt}, tab::Tab, Ctx, BLOCKER}; +use crate::{tab::Tab, Ctx}; pub struct Opt { type_: OptType, diff --git a/yazi-core/src/tab/commands/reveal.rs b/yazi-core/src/tab/commands/reveal.rs index 4c7bda76..129c67a6 100644 --- a/yazi-core/src/tab/commands/reveal.rs +++ b/yazi-core/src/tab/commands/reveal.rs @@ -1,4 +1,4 @@ -use yazi_shared::{emit, event::Exec, files::{File, FilesOp}, fs::{expand_path, Url}, Layer}; +use yazi_shared::{emit, event::Exec, fs::{File, FilesOp}, fs::{expand_path, Url}, Layer}; use crate::{manager::Manager, tab::Tab}; diff --git a/yazi-core/src/tab/commands/search.rs b/yazi-core/src/tab/commands/search.rs index 49b51471..69e2176f 100644 --- a/yazi-core/src/tab/commands/search.rs +++ b/yazi-core/src/tab/commands/search.rs @@ -4,9 +4,10 @@ use anyhow::bail; use tokio::pin; use tokio_stream::{wrappers::UnboundedReceiverStream, StreamExt}; use yazi_config::popup::InputCfg; -use yazi_shared::{emit, event::Exec, files::FilesOp}; +use yazi_scheduler::external; +use yazi_shared::{emit, event::Exec, fs::FilesOp}; -use crate::{external, input::Input, manager::Manager, tab::Tab}; +use crate::{input::Input, manager::Manager, tab::Tab}; pub struct Opt { pub type_: OptType, diff --git a/yazi-core/src/tab/folder.rs b/yazi-core/src/tab/folder.rs index 623b907d..832fb63f 100644 --- a/yazi-core/src/tab/folder.rs +++ b/yazi-core/src/tab/folder.rs @@ -1,6 +1,6 @@ use ratatui::layout::Rect; use yazi_config::MANAGER; -use yazi_shared::{emit, files::{File, FilesOp}, fs::Url}; +use yazi_shared::{emit, fs::{File, FilesOp}, fs::Url}; use crate::{files::Files, Step}; diff --git a/yazi-core/src/tab/tab.rs b/yazi-core/src/tab/tab.rs index d1ddd9dc..72adf988 100644 --- a/yazi-core/src/tab/tab.rs +++ b/yazi-core/src/tab/tab.rs @@ -2,7 +2,7 @@ use std::{borrow::Cow, collections::BTreeMap}; use anyhow::Result; use tokio::task::JoinHandle; -use yazi_shared::{event::PreviewLock, files::File, fs::Url}; +use yazi_shared::{event::PreviewLock, fs::File, fs::Url}; use super::{Backstack, Config, Finder, Folder, Mode}; use crate::preview::Preview; diff --git a/yazi-core/src/tasks/commands/inspect.rs b/yazi-core/src/tasks/commands/inspect.rs index 349dabff..e93f5479 100644 --- a/yazi-core/src/tasks/commands/inspect.rs +++ b/yazi-core/src/tasks/commands/inspect.rs @@ -2,9 +2,10 @@ use std::io::{stdout, Write}; use crossterm::terminal::{disable_raw_mode, enable_raw_mode}; use tokio::{io::{stdin, AsyncReadExt}, select, sync::mpsc, time}; +use yazi_scheduler::BLOCKER; use yazi_shared::{event::Exec, term::Term, Defer}; -use crate::{tasks::Tasks, Ctx, BLOCKER}; +use crate::{tasks::Tasks, Ctx}; pub struct Opt; diff --git a/yazi-core/src/tasks/mod.rs b/yazi-core/src/tasks/mod.rs index 79983611..32ea75be 100644 --- a/yazi-core/src/tasks/mod.rs +++ b/yazi-core/src/tasks/mod.rs @@ -1,13 +1,8 @@ mod commands; -mod running; -mod scheduler; -mod task; +mod progress; mod tasks; -mod workers; -use running::*; -use scheduler::*; -use task::*; +pub use progress::*; pub use tasks::*; pub const TASKS_PADDING: u16 = 2; diff --git a/yazi-core/src/tasks/progress.rs b/yazi-core/src/tasks/progress.rs new file mode 100644 index 00000000..f14eabd6 --- /dev/null +++ b/yazi-core/src/tasks/progress.rs @@ -0,0 +1,31 @@ +use serde::Serialize; +use yazi_scheduler::Running; + +#[derive(Clone, Copy, Default, Eq, PartialEq, Serialize)] +pub struct TasksProgress { + pub total: u32, + pub succ: u32, + pub fail: u32, + + pub found: u64, + pub processed: u64, +} + +impl From<&Running> for TasksProgress { + fn from(running: &Running) -> Self { + let mut progress = Self::default(); + if running.is_empty() { + return progress; + } + + for task in running.values() { + progress.total += task.total; + progress.succ += task.succ; + progress.fail += task.fail; + + progress.found += task.found; + progress.processed += task.processed; + } + progress + } +} diff --git a/yazi-core/src/tasks/tasks.rs b/yazi-core/src/tasks/tasks.rs index 0c573463..d993254c 100644 --- a/yazi-core/src/tasks/tasks.rs +++ b/yazi-core/src/tasks/tasks.rs @@ -1,11 +1,12 @@ -use std::{collections::{BTreeMap, HashMap, HashSet}, ffi::OsStr, path::Path, sync::Arc}; +use std::{collections::{BTreeMap, HashMap, HashSet}, ffi::OsStr, path::Path, sync::Arc, time::Duration}; -use serde::Serialize; +use tokio::time::sleep; use tracing::debug; use yazi_config::{manager::SortBy, open::Opener, popup::InputCfg, OPEN}; -use yazi_shared::{files::File, fs::Url, term::Term, MimeKind}; +use yazi_scheduler::{Scheduler, TaskSummary}; +use yazi_shared::{fs::{File, Url}, term::Term, MimeKind}; -use super::{running::Running, task::TaskSummary, Scheduler, TASKS_PADDING, TASKS_PERCENT}; +use super::{TasksProgress, TASKS_PADDING, TASKS_PERCENT}; use crate::{files::Files, input::Input}; pub struct Tasks { @@ -18,12 +19,28 @@ pub struct Tasks { impl Tasks { pub fn start() -> Self { - Self { + let tasks = Self { scheduler: Arc::new(Scheduler::start()), visible: false, cursor: 0, progress: Default::default(), - } + }; + + let running = tasks.scheduler.running.clone(); + tokio::spawn(async move { + let mut last = TasksProgress::default(); + loop { + sleep(Duration::from_millis(500)).await; + + let new = TasksProgress::from(&*running.read()); + if last != new { + last = new; + Tasks::_update(new); + } + } + }); + + tasks } #[inline] @@ -209,32 +226,3 @@ impl Tasks { #[inline] pub fn len(&self) -> usize { self.scheduler.running.read().len() } } - -#[derive(Clone, Copy, Default, Eq, PartialEq, Serialize)] -pub struct TasksProgress { - pub total: u32, - pub succ: u32, - pub fail: u32, - - pub found: u64, - pub processed: u64, -} - -impl From<&Running> for TasksProgress { - fn from(running: &Running) -> Self { - let mut progress = Self::default(); - if running.is_empty() { - return progress; - } - - for task in running.values() { - progress.total += task.total; - progress.succ += task.succ; - progress.fail += task.fail; - - progress.found += task.found; - progress.processed += task.processed; - } - progress - } -} diff --git a/yazi-fm/src/app/app.rs b/yazi-fm/src/app/app.rs index 29c6b32b..c8107b03 100644 --- a/yazi-fm/src/app/app.rs +++ b/yazi-fm/src/app/app.rs @@ -5,7 +5,7 @@ use crossterm::event::KeyEvent; use ratatui::{backend::Backend, prelude::Rect}; use yazi_config::{keymap::Key, BOOT}; use yazi_core::{input::InputMode, preview::COLLISION, Ctx}; -use yazi_shared::{emit, event::{Event, Exec}, files::FilesOp, term::Term, Layer}; +use yazi_shared::{emit, event::{Event, Exec}, fs::FilesOp, term::Term, Layer}; use crate::{Executor, Logs, Panic, Root, Signals}; diff --git a/yazi-plugin/src/bindings/active.rs b/yazi-plugin/src/bindings/active.rs index c0d3246f..9075cf26 100644 --- a/yazi-plugin/src/bindings/active.rs +++ b/yazi-plugin/src/bindings/active.rs @@ -104,7 +104,7 @@ impl<'a, 'b> Active<'a, 'b> { fn file( &self, idx: usize, - inner: &'a yazi_shared::files::File, + inner: &'a yazi_shared::fs::File, folder: &'a yazi_core::tab::Folder, ) -> mlua::Result> { let ud = self.scope.create_any_userdata_ref(inner)?; diff --git a/yazi-plugin/src/bindings/files.rs b/yazi-plugin/src/bindings/files.rs index 0962183b..18327ffd 100644 --- a/yazi-plugin/src/bindings/files.rs +++ b/yazi-plugin/src/bindings/files.rs @@ -6,10 +6,10 @@ use yazi_config::THEME; use super::{Range, Url}; use crate::{layout::Style, LUA}; -pub struct File(yazi_shared::files::File); +pub struct File(yazi_shared::fs::File); -impl From<&yazi_shared::files::File> for File { - fn from(value: &yazi_shared::files::File) -> Self { Self(value.clone()) } +impl From<&yazi_shared::fs::File> for File { + fn from(value: &yazi_shared::fs::File) -> Self { Self(value.clone()) } } impl UserData for File { @@ -47,7 +47,7 @@ impl Files { }); })?; - LUA.register_userdata_type::(|reg| { + LUA.register_userdata_type::(|reg| { reg.add_field_method_get("url", |_, me| Ok(Url::from(&me.url))); reg.add_field_method_get("link_to", |_, me| Ok(me.link_to().map(Url::from))); reg.add_field_method_get("is_link", |_, me| Ok(me.is_link())); @@ -87,7 +87,7 @@ impl Files { Ok(me.url.file_name().map(|n| n.to_string_lossy().to_string())) }); reg.add_function("size", |_, me: AnyUserData| { - let file = me.borrow::()?; + let file = me.borrow::()?; if !file.is_dir() { return Ok(Some(file.len)); } @@ -97,7 +97,7 @@ impl Files { }); reg.add_function("mime", |_, me: AnyUserData| { let manager = me.named_user_value::>("manager")?; - let file = me.borrow::()?; + let file = me.borrow::()?; Ok(manager.mimetype.get(&file.url).cloned()) }); reg.add_function("prefix", |_, me: AnyUserData| { @@ -106,7 +106,7 @@ impl Files { return Ok(None); } - let file = me.borrow::()?; + let file = me.borrow::()?; let mut p = file.url.strip_prefix(&folder.cwd).unwrap_or(&file.url).components(); p.next_back(); Ok(Some(p.as_path().to_string_lossy().to_string())) @@ -122,7 +122,7 @@ impl Files { }); reg.add_function("style", |_, me: AnyUserData| { let manager = me.named_user_value::>("manager")?; - let file = me.borrow::()?; + let file = me.borrow::()?; let mime = manager.mimetype.get(&file.url); Ok( THEME @@ -134,12 +134,12 @@ impl Files { }); reg.add_function("is_hovered", |_, me: AnyUserData| { let folder = me.named_user_value::>("folder")?; - let file = me.borrow::()?; + let file = me.borrow::()?; Ok(matches!(folder.hovered(), Some(f) if f.url == file.url)) }); reg.add_function("is_yanked", |_, me: AnyUserData| { let manager = me.named_user_value::>("manager")?; - let file = me.borrow::()?; + let file = me.borrow::()?; Ok(if !manager.yanked.1.contains(&file.url) { 0u8 } else if manager.yanked.0 { @@ -151,7 +151,7 @@ impl Files { reg.add_function("is_selected", |_, me: AnyUserData| { let manager = me.named_user_value::>("manager")?; let folder = me.named_user_value::>("folder")?; - let file = me.borrow::()?; + let file = me.borrow::()?; let selected = folder.files.is_selected(&file.url); Ok(if !manager.active().mode.is_visual() { @@ -167,7 +167,7 @@ impl Files { return Ok(None); }; - let file = me.borrow::()?; + let file = me.borrow::()?; if let Some(idx) = finder.matched_idx(&file.url) { return Some( lua.create_sequence_from([idx.into_lua(lua)?, finder.matched().len().into_lua(lua)?]), @@ -182,7 +182,7 @@ impl Files { return Ok(None); }; - let file = me.borrow::()?; + let file = me.borrow::()?; let Some(h) = file.name().and_then(|n| finder.highlighted(n)) else { return Ok(None); }; diff --git a/yazi-scheduler/Cargo.toml b/yazi-scheduler/Cargo.toml new file mode 100644 index 00000000..2ee172d9 --- /dev/null +++ b/yazi-scheduler/Cargo.toml @@ -0,0 +1,32 @@ +[package] +name = "yazi-scheduler" +version = "0.1.5" +edition = "2021" +license = "MIT" +authors = [ "sxyazi " ] +description = "Yazi task scheduler" +homepage = "https://yazi-rs.github.io" +repository = "https://github.com/sxyazi/yazi" + +[dependencies] +yazi-adaptor = { path = "../yazi-adaptor", version = "0.1.5" } +yazi-config = { path = "../yazi-config", version = "0.1.5" } +yazi-shared = { path = "../yazi-shared", version = "0.1.5" } + +# External dependencies +anyhow = "^1" +async-channel = "^1" +futures = "^0" +libc = "^0" +parking_lot = "^0" +regex = "^1" +serde = "^1" +serde_json = "^1" +tokio = { version = "^1", features = [ "parking_lot", "rt-multi-thread" ] } +trash = "^3" + +# Logging +tracing = { version = "^0", features = [ "max_level_debug", "release_max_level_warn" ] } + +[target."cfg(windows)".dependencies] +clipboard-win = "^4" diff --git a/yazi-core/src/blocker.rs b/yazi-scheduler/src/blocker.rs similarity index 100% rename from yazi-core/src/blocker.rs rename to yazi-scheduler/src/blocker.rs diff --git a/yazi-core/src/external/clipboard.rs b/yazi-scheduler/src/external/clipboard.rs similarity index 100% rename from yazi-core/src/external/clipboard.rs rename to yazi-scheduler/src/external/clipboard.rs diff --git a/yazi-core/src/external/fd.rs b/yazi-scheduler/src/external/fd.rs similarity index 96% rename from yazi-core/src/external/fd.rs rename to yazi-scheduler/src/external/fd.rs index f299af76..55f7d72f 100644 --- a/yazi-core/src/external/fd.rs +++ b/yazi-scheduler/src/external/fd.rs @@ -2,7 +2,7 @@ use std::process::Stdio; use anyhow::Result; use tokio::{io::{AsyncBufReadExt, BufReader}, process::Command, sync::mpsc::{self, UnboundedReceiver}}; -use yazi_shared::{files::File, fs::Url}; +use yazi_shared::fs::{File, Url}; pub struct FdOpt { pub cwd: Url, diff --git a/yazi-core/src/external/ffmpegthumbnailer.rs b/yazi-scheduler/src/external/ffmpegthumbnailer.rs similarity index 100% rename from yazi-core/src/external/ffmpegthumbnailer.rs rename to yazi-scheduler/src/external/ffmpegthumbnailer.rs diff --git a/yazi-core/src/external/file.rs b/yazi-scheduler/src/external/file.rs similarity index 100% rename from yazi-core/src/external/file.rs rename to yazi-scheduler/src/external/file.rs diff --git a/yazi-core/src/external/fzf.rs b/yazi-scheduler/src/external/fzf.rs similarity index 100% rename from yazi-core/src/external/fzf.rs rename to yazi-scheduler/src/external/fzf.rs diff --git a/yazi-core/src/external/jq.rs b/yazi-scheduler/src/external/jq.rs similarity index 100% rename from yazi-core/src/external/jq.rs rename to yazi-scheduler/src/external/jq.rs diff --git a/yazi-core/src/external/lsar.rs b/yazi-scheduler/src/external/lsar.rs similarity index 100% rename from yazi-core/src/external/lsar.rs rename to yazi-scheduler/src/external/lsar.rs diff --git a/yazi-core/src/external/mod.rs b/yazi-scheduler/src/external/mod.rs similarity index 100% rename from yazi-core/src/external/mod.rs rename to yazi-scheduler/src/external/mod.rs diff --git a/yazi-core/src/external/pdftoppm.rs b/yazi-scheduler/src/external/pdftoppm.rs similarity index 100% rename from yazi-core/src/external/pdftoppm.rs rename to yazi-scheduler/src/external/pdftoppm.rs diff --git a/yazi-core/src/external/rg.rs b/yazi-scheduler/src/external/rg.rs similarity index 95% rename from yazi-core/src/external/rg.rs rename to yazi-scheduler/src/external/rg.rs index c240b66d..3367f53c 100644 --- a/yazi-core/src/external/rg.rs +++ b/yazi-scheduler/src/external/rg.rs @@ -2,7 +2,7 @@ use std::process::Stdio; use anyhow::Result; use tokio::{io::{AsyncBufReadExt, BufReader}, process::Command, sync::mpsc::{self, UnboundedReceiver}}; -use yazi_shared::{files::File, fs::Url}; +use yazi_shared::fs::{File, Url}; pub struct RgOpt { pub cwd: Url, diff --git a/yazi-core/src/external/shell.rs b/yazi-scheduler/src/external/shell.rs similarity index 100% rename from yazi-core/src/external/shell.rs rename to yazi-scheduler/src/external/shell.rs diff --git a/yazi-core/src/external/unar.rs b/yazi-scheduler/src/external/unar.rs similarity index 100% rename from yazi-core/src/external/unar.rs rename to yazi-scheduler/src/external/unar.rs diff --git a/yazi-core/src/external/zoxide.rs b/yazi-scheduler/src/external/zoxide.rs similarity index 100% rename from yazi-core/src/external/zoxide.rs rename to yazi-scheduler/src/external/zoxide.rs diff --git a/yazi-scheduler/src/lib.rs b/yazi-scheduler/src/lib.rs new file mode 100644 index 00000000..ed2f4695 --- /dev/null +++ b/yazi-scheduler/src/lib.rs @@ -0,0 +1,15 @@ +#![allow(clippy::unit_arg)] + +mod blocker; +pub mod external; +mod running; +mod scheduler; +mod task; +pub mod workers; + +pub use blocker::*; +pub use running::*; +pub use scheduler::*; +pub use task::*; + +pub fn init() { init_blocker(); } diff --git a/yazi-core/src/tasks/running.rs b/yazi-scheduler/src/running.rs similarity index 69% rename from yazi-core/src/tasks/running.rs rename to yazi-scheduler/src/running.rs index 882aa31d..d353a970 100644 --- a/yazi-core/src/tasks/running.rs +++ b/yazi-scheduler/src/running.rs @@ -5,7 +5,7 @@ use futures::future::BoxFuture; use super::{Task, TaskStage}; #[derive(Default)] -pub(super) struct Running { +pub struct Running { incr: usize, pub(super) hooks: @@ -21,25 +21,25 @@ impl Running { } #[inline] - pub(super) fn get(&self, id: usize) -> Option<&Task> { self.all.get(&id) } + pub fn get(&self, id: usize) -> Option<&Task> { self.all.get(&id) } #[inline] - pub(super) fn get_mut(&mut self, id: usize) -> Option<&mut Task> { self.all.get_mut(&id) } + pub fn get_mut(&mut self, id: usize) -> Option<&mut Task> { self.all.get_mut(&id) } #[inline] - pub(super) fn get_id(&self, idx: usize) -> Option { self.values().nth(idx).map(|t| t.id) } + pub fn get_id(&self, idx: usize) -> Option { self.values().nth(idx).map(|t| t.id) } #[inline] - pub(super) fn len(&self) -> usize { self.all.len() } + pub fn len(&self) -> usize { self.all.len() } #[inline] pub(super) fn exists(&self, id: usize) -> bool { self.all.contains_key(&id) } #[inline] - pub(super) fn values(&self) -> impl Iterator { self.all.values() } + pub fn values(&self) -> impl Iterator { self.all.values() } #[inline] - pub(super) fn is_empty(&self) -> bool { self.all.is_empty() } + pub fn is_empty(&self) -> bool { self.all.is_empty() } pub(super) fn try_remove( &mut self, diff --git a/yazi-core/src/tasks/scheduler.rs b/yazi-scheduler/src/scheduler.rs similarity index 84% rename from yazi-core/src/tasks/scheduler.rs rename to yazi-scheduler/src/scheduler.rs index 0309892f..55faa5a5 100644 --- a/yazi-core/src/tasks/scheduler.rs +++ b/yazi-scheduler/src/scheduler.rs @@ -2,25 +2,25 @@ use std::{ffi::OsStr, sync::Arc, time::Duration}; use futures::{future::BoxFuture, FutureExt}; use parking_lot::RwLock; -use tokio::{fs, select, sync::{mpsc::{self, UnboundedReceiver}, oneshot}, time::sleep}; +use tokio::{fs, select, sync::{mpsc::{self, UnboundedReceiver}, oneshot}}; use yazi_config::{open::Opener, TASKS}; -use yazi_shared::{fs::{unique_path, Url}, Throttle}; +use yazi_shared::{emit, event::Exec, fs::{unique_path, Url}, Layer, Throttle}; -use super::{workers::{File, FileOpDelete, FileOpLink, FileOpPaste, FileOpTrash, Precache, PrecacheOpMime, PrecacheOpSize, Process, ProcessOpOpen}, Running, TaskOp, TaskStage, TasksProgress}; -use crate::tasks::Tasks; +use super::{Running, TaskOp, TaskStage}; +use crate::workers::{File, FileOpDelete, FileOpLink, FileOpPaste, FileOpTrash, Precache, PrecacheOpMime, PrecacheOpSize, Process, ProcessOpOpen}; pub struct Scheduler { file: Arc, precache: Arc, process: Arc, - todo: async_channel::Sender>, - prog: mpsc::UnboundedSender, - pub(super) running: Arc>, + todo: async_channel::Sender>, + prog: mpsc::UnboundedSender, + pub running: Arc>, } impl Scheduler { - pub(super) fn start() -> Self { + pub fn start() -> Self { let (todo_tx, todo_rx) = async_channel::unbounded(); let (prog_tx, prog_rx) = mpsc::unbounded_channel(); @@ -147,23 +147,9 @@ impl Scheduler { } } }); - - let running = self.running.clone(); - tokio::spawn(async move { - let mut last = TasksProgress::default(); - loop { - sleep(Duration::from_millis(500)).await; - - let new = TasksProgress::from(&*running.read()); - if last != new { - last = new; - Tasks::_update(new); - } - } - }); } - pub(super) fn cancel(&self, id: usize) -> bool { + pub fn cancel(&self, id: usize) -> bool { let mut running = self.running.write(); let b = running.all.remove(&id).is_some(); @@ -173,7 +159,20 @@ impl Scheduler { b } - pub(super) fn file_cut(&self, from: Url, mut to: Url, force: bool) { + pub async fn app_stop() { + let (tx, rx) = oneshot::channel::<()>(); + emit!(Call(Exec::call("stop", vec!["true".to_string()]).with_data(Some(tx)).vec(), Layer::App)); + rx.await.ok(); + } + + pub fn app_resume() { + emit!(Call( + Exec::call("stop", vec!["false".to_string()]).with_data(None::>).vec(), + Layer::App + )); + } + + pub fn file_cut(&self, from: Url, mut to: Url, force: bool) { let mut running = self.running.write(); let id = running.add(format!("Cut {:?} to {:?}", from, to)); @@ -204,7 +203,7 @@ impl Scheduler { }); } - pub(super) fn file_copy(&self, from: Url, mut to: Url, force: bool) { + pub fn file_copy(&self, from: Url, mut to: Url, force: bool) { let name = format!("Copy {:?} to {:?}", from, to); let id = self.running.write().add(name); @@ -220,7 +219,7 @@ impl Scheduler { }); } - pub(super) fn file_link(&self, from: Url, mut to: Url, relative: bool, force: bool) { + pub fn file_link(&self, from: Url, mut to: Url, relative: bool, force: bool) { let name = format!("Link {from:?} to {to:?}"); let id = self.running.write().add(name); @@ -239,7 +238,7 @@ impl Scheduler { }); } - pub(super) fn file_delete(&self, target: Url) { + pub fn file_delete(&self, target: Url) { let mut running = self.running.write(); let id = running.add(format!("Delete {:?}", target)); @@ -267,7 +266,7 @@ impl Scheduler { }); } - pub(super) fn file_trash(&self, target: Url) { + pub fn file_trash(&self, target: Url) { let name = format!("Trash {:?}", target); let id = self.running.write().add(name); @@ -280,7 +279,7 @@ impl Scheduler { }); } - pub(super) fn process_open(&self, opener: &Opener, args: &[impl AsRef]) { + pub fn process_open(&self, opener: &Opener, args: &[impl AsRef]) { let name = { let s = format!("Execute `{}`", opener.exec); let args = args.iter().map(|a| a.as_ref().to_string_lossy()).collect::>().join(" "); @@ -324,7 +323,7 @@ impl Scheduler { }); } - pub(super) fn precache_size(&self, targets: Vec<&Url>) { + pub fn precache_size(&self, targets: Vec<&Url>) { let throttle = Arc::new(Throttle::new(targets.len(), Duration::from_millis(300))); let mut handing = self.precache.size_handing.lock(); let mut running = self.running.write(); @@ -349,7 +348,7 @@ impl Scheduler { } } - pub(super) fn precache_mime(&self, targets: Vec) { + pub fn precache_mime(&self, targets: Vec) { let name = format!("Preload mimetype for {} files", targets.len()); let id = self.running.write().add(name); @@ -362,21 +361,21 @@ impl Scheduler { }); } - pub(super) fn precache_image(&self, targets: Vec) { + pub fn precache_image(&self, targets: Vec) { let name = format!("Precache of {} image files", targets.len()); let id = self.running.write().add(name); self.precache.image(id, targets).ok(); } - pub(super) fn precache_video(&self, targets: Vec) { + pub fn precache_video(&self, targets: Vec) { let name = format!("Precache of {} video files", targets.len()); let id = self.running.write().add(name); self.precache.video(id, targets).ok(); } - pub(super) fn precache_pdf(&self, targets: Vec) { + pub fn precache_pdf(&self, targets: Vec) { let name = format!("Precache of {} PDF files", targets.len()); let id = self.running.write().add(name); diff --git a/yazi-core/src/tasks/task.rs b/yazi-scheduler/src/task.rs similarity index 100% rename from yazi-core/src/tasks/task.rs rename to yazi-scheduler/src/task.rs diff --git a/yazi-core/src/tasks/workers/file.rs b/yazi-scheduler/src/workers/file.rs similarity index 99% rename from yazi-core/src/tasks/workers/file.rs rename to yazi-scheduler/src/workers/file.rs index 56ae4d58..3a50e262 100644 --- a/yazi-core/src/tasks/workers/file.rs +++ b/yazi-scheduler/src/workers/file.rs @@ -7,7 +7,7 @@ use tracing::warn; use yazi_config::TASKS; use yazi_shared::fs::{calculate_size, copy_with_progress, path_relative_to, Url}; -use crate::tasks::TaskOp; +use crate::TaskOp; pub(crate) struct File { tx: async_channel::Sender, diff --git a/yazi-core/src/tasks/workers/mod.rs b/yazi-scheduler/src/workers/mod.rs similarity index 100% rename from yazi-core/src/tasks/workers/mod.rs rename to yazi-scheduler/src/workers/mod.rs diff --git a/yazi-core/src/tasks/workers/precache.rs b/yazi-scheduler/src/workers/precache.rs similarity index 97% rename from yazi-core/src/tasks/workers/precache.rs rename to yazi-scheduler/src/workers/precache.rs index a3239ee4..9aa3ba60 100644 --- a/yazi-core/src/tasks/workers/precache.rs +++ b/yazi-scheduler/src/workers/precache.rs @@ -5,9 +5,9 @@ use parking_lot::Mutex; use tokio::{fs, sync::mpsc}; use yazi_adaptor::Image; use yazi_config::PREVIEW; -use yazi_shared::{emit, files::FilesOp, fs::{calculate_size, Url}, Throttle}; +use yazi_shared::{emit, fs::{calculate_size, FilesOp, Url}, Throttle}; -use crate::{external, tasks::TaskOp}; +use crate::{external, TaskOp}; pub(crate) struct Precache { tx: async_channel::Sender, diff --git a/yazi-core/src/tasks/workers/process.rs b/yazi-scheduler/src/workers/process.rs similarity index 95% rename from yazi-core/src/tasks/workers/process.rs rename to yazi-scheduler/src/workers/process.rs index 3707d655..2b1df4f8 100644 --- a/yazi-core/src/tasks/workers/process.rs +++ b/yazi-scheduler/src/workers/process.rs @@ -3,7 +3,7 @@ use std::{ffi::OsString, mem}; use anyhow::Result; use tokio::{io::{AsyncBufReadExt, BufReader}, select, sync::{mpsc, oneshot}}; -use crate::{external::{self, ShellOpt}, tasks::TaskOp, Ctx, BLOCKER}; +use crate::{external::{self, ShellOpt}, Scheduler, TaskOp, BLOCKER}; pub(crate) struct Process { sch: mpsc::UnboundedSender, @@ -37,7 +37,7 @@ impl Process { let opt = ShellOpt::from(&mut task); if task.block { let _guard = BLOCKER.acquire().await.unwrap(); - Ctx::stop().await; + Scheduler::app_stop().await; match external::shell(opt) { Ok(mut child) => { @@ -49,7 +49,7 @@ impl Process { self.fail(task.id, format!("Failed to spawn process: {e}"))?; } } - return Ok(Ctx::resume()); + return Ok(Scheduler::app_resume()); } if task.orphan { diff --git a/yazi-shared/src/event/event.rs b/yazi-shared/src/event/event.rs index ec665a58..d2ff9d61 100644 --- a/yazi-shared/src/event/event.rs +++ b/yazi-shared/src/event/event.rs @@ -4,7 +4,7 @@ use crossterm::event::KeyEvent; use tokio::sync::{mpsc::UnboundedSender, oneshot}; use super::Exec; -use crate::{files::FilesOp, fs::{Cha, Url}, term::Term, Layer, RoCell}; +use crate::{fs::{Cha, FilesOp, Url}, term::Term, Layer, RoCell}; static TX: RoCell> = RoCell::new(); diff --git a/yazi-shared/src/files/mod.rs b/yazi-shared/src/files/mod.rs deleted file mode 100644 index 600b5425..00000000 --- a/yazi-shared/src/files/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -mod file; -mod op; - -pub use file::*; -pub use op::*; diff --git a/yazi-shared/src/files/file.rs b/yazi-shared/src/fs/file.rs similarity index 100% rename from yazi-shared/src/files/file.rs rename to yazi-shared/src/fs/file.rs diff --git a/yazi-shared/src/fs/mod.rs b/yazi-shared/src/fs/mod.rs index 685326a8..9cd7865e 100644 --- a/yazi-shared/src/fs/mod.rs +++ b/yazi-shared/src/fs/mod.rs @@ -1,9 +1,13 @@ mod cha; +mod file; mod fns; +mod op; mod path; mod url; pub use cha::*; +pub use file::*; pub use fns::*; +pub use op::*; pub use path::*; pub use url::*; diff --git a/yazi-shared/src/files/op.rs b/yazi-shared/src/fs/op.rs similarity index 100% rename from yazi-shared/src/files/op.rs rename to yazi-shared/src/fs/op.rs diff --git a/yazi-shared/src/lib.rs b/yazi-shared/src/lib.rs index df211bd1..886efd8a 100644 --- a/yazi-shared/src/lib.rs +++ b/yazi-shared/src/lib.rs @@ -6,7 +6,6 @@ mod defer; mod env; mod errors; pub mod event; -pub mod files; pub mod fs; mod layer; mod mime;