refactor: use workspace to speed up builds

This commit is contained in:
sxyazi 2023-07-31 09:58:42 +08:00
parent f7022266aa
commit a0533f75bb
No known key found for this signature in database
132 changed files with 498 additions and 294 deletions

4
.gitignore vendored
View file

@ -1 +1,3 @@
/target
target/
.DS_Store

115
Cargo.lock generated
View file

@ -58,6 +58,26 @@ version = "1.0.72"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3b13c32d80ecc7ab747b80c3784bce54ee8a7a0cc4fbda9bf4cda2cf6fe90854"
[[package]]
name = "app"
version = "0.1.0"
dependencies = [
"ansi-to-tui",
"anyhow",
"config",
"core",
"crossterm",
"futures",
"libc",
"ratatui",
"shared",
"signal-hook-tokio",
"tokio",
"tracing",
"tracing-appender",
"tracing-subscriber",
]
[[package]]
name = "async-channel"
version = "1.9.0"
@ -254,6 +274,22 @@ dependencies = [
"crossbeam-utils",
]
[[package]]
name = "config"
version = "0.1.0"
dependencies = [
"anyhow",
"crossterm",
"futures",
"glob",
"once_cell",
"ratatui",
"serde",
"shared",
"toml",
"xdg",
]
[[package]]
name = "console-api"
version = "0.5.0"
@ -290,6 +326,35 @@ dependencies = [
"tracing-subscriber",
]
[[package]]
name = "core"
version = "0.1.0"
dependencies = [
"anyhow",
"async-channel",
"base64 0.21.2",
"config",
"console-subscriber",
"crossterm",
"futures",
"image",
"indexmap 2.0.0",
"libc",
"md5",
"notify",
"once_cell",
"parking_lot",
"ratatui",
"serde",
"serde_json",
"shared",
"syntect",
"tokio",
"tracing",
"trash",
"unicode-width",
]
[[package]]
name = "core-foundation-sys"
version = "0.8.4"
@ -1549,6 +1614,18 @@ dependencies = [
"lazy_static",
]
[[package]]
name = "shared"
version = "0.1.0"
dependencies = [
"anyhow",
"crossterm",
"libc",
"parking_lot",
"ratatui",
"tokio",
]
[[package]]
name = "signal-hook"
version = "0.3.17"
@ -2340,9 +2417,9 @@ checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a"
[[package]]
name = "winnow"
version = "0.5.1"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "25b5872fa2e10bd067ae946f927e726d7d603eaeb6e02fa6a350e0722d2b8c11"
checksum = "8bd122eb777186e60c3fdf765a58ac76e41c582f1f535fbf3314434c6b58f3f7"
dependencies = [
"memchr",
]
@ -2362,40 +2439,6 @@ dependencies = [
"linked-hash-map",
]
[[package]]
name = "yazi"
version = "0.1.2"
dependencies = [
"ansi-to-tui",
"anyhow",
"async-channel",
"base64 0.21.2",
"console-subscriber",
"crossterm",
"futures",
"glob",
"image",
"indexmap 2.0.0",
"libc",
"md5",
"notify",
"once_cell",
"parking_lot",
"ratatui",
"serde",
"serde_json",
"signal-hook-tokio",
"syntect",
"tokio",
"toml",
"tracing",
"tracing-appender",
"tracing-subscriber",
"trash",
"unicode-width",
"xdg",
]
[[package]]
name = "zune-inflate"
version = "0.2.54"

View file

@ -1,37 +1,11 @@
[package]
name = "yazi"
version = "0.1.2"
edition = "2021"
[dependencies]
ansi-to-tui = "^3"
anyhow = "^1"
async-channel = "^1"
base64 = "^0"
console-subscriber = "^0"
crossterm = { version = "^0", features = [ "event-stream" ] }
futures = "^0"
glob = "^0"
image = "^0"
indexmap = "^2"
libc = "^0"
md5 = "^0"
notify = { version = "^6", default-features = false, features = [ "macos_fsevent" ] }
once_cell = "^1"
parking_lot = "^0"
ratatui = "^0"
serde = { version = "^1", features = [ "derive" ] }
serde_json = "^1"
signal-hook-tokio = { version = "^0", features = [ "futures-v0_3" ] }
syntect = "^5"
tokio = { version = "^1", features = [ "parking_lot", "macros", "rt-multi-thread", "sync", "fs", "process", "io-std", "io-util" ] }
toml = { version = "^0", features = [ "preserve_order" ] }
tracing = "^0"
tracing-appender = "^0"
tracing-subscriber = "^0"
trash = "^3"
unicode-width = "^0"
xdg = "^2"
[workspace]
resolver = "2"
members = [
"app",
"config",
"core",
"shared",
]
[profile.release]
strip = true

24
app/Cargo.toml Normal file
View file

@ -0,0 +1,24 @@
[package]
name = "app"
version = "0.1.0"
edition = "2021"
[dependencies]
config = { path = "../config" }
core = { path = "../core" }
shared = { path = "../shared" }
# External dependencies
anyhow = "^1"
tokio = { version = "^1", features = [ "parking_lot" ] }
crossterm = { version = "^0", features = [ "event-stream" ] }
ratatui = { version = "^0" }
ansi-to-tui = "^3"
signal-hook-tokio = { version = "^0", features = [ "futures-v0_3" ] }
libc = "^0"
futures = "^0"
# Logging
tracing = "^0"
tracing-appender = "^0"
tracing-subscriber = "^0"

View file

@ -1,18 +1,21 @@
use core::{emit, files::FilesOp, input::InputMode, Event};
use anyhow::{Ok, Result};
use config::keymap::{Control, Key, KeymapLayer};
use crossterm::event::KeyEvent;
use tokio::sync::oneshot::{self};
use shared::{absolute_path, Term};
use tokio::sync::oneshot;
use super::{root::Root, Ctx, Executor, Logs, Signals, Term};
use crate::{config::keymap::{Control, Key, KeymapLayer}, core::{files::FilesOp, input::InputMode, Event}, emit, misc::absolute_path};
use crate::{Ctx, Executor, Logs, Root, Signals};
pub struct App {
pub(super) struct App {
cx: Ctx,
term: Option<Term>,
signals: Signals,
}
impl App {
pub async fn run() -> Result<()> {
pub(super) async fn run() -> Result<()> {
let _log = Logs::init()?;
let term = Term::start()?;

View file

@ -1,4 +1,7 @@
use crate::{config::keymap::KeymapLayer, core::{input::Input, manager::Manager, select::Select, tasks::Tasks, which::Which, Position}, misc::tty_size};
use core::{input::Input, manager::Manager, select::Select, tasks::Tasks, which::Which, Position};
use config::keymap::KeymapLayer;
use shared::tty_size;
pub struct Ctx {
pub manager: Manager,
@ -9,7 +12,7 @@ pub struct Ctx {
}
impl Ctx {
pub fn new() -> Self {
pub(super) fn new() -> Self {
Self {
manager: Manager::new(),
which: Default::default(),
@ -20,7 +23,7 @@ impl Ctx {
}
#[inline]
pub fn cursor(&self) -> Option<(u16, u16)> {
pub(super) fn cursor(&self) -> Option<(u16, u16)> {
if self.input.visible {
return Some(self.input.cursor());
}
@ -28,7 +31,7 @@ impl Ctx {
}
#[inline]
pub fn layer(&self) -> KeymapLayer {
pub(super) fn layer(&self) -> KeymapLayer {
if self.which.visible {
KeymapLayer::Which
} else if self.input.visible {
@ -43,7 +46,7 @@ impl Ctx {
}
#[inline]
pub fn image_layer(&self) -> bool {
pub(super) fn image_layer(&self) -> bool {
match self.layer() {
KeymapLayer::Which => false,
KeymapLayer::Tasks => false,
@ -51,7 +54,7 @@ impl Ctx {
}
}
pub fn position(&self, pos: Position) -> Position {
pub(super) fn position(&self, pos: Position) -> Position {
match pos {
Position::Top => Position::Coords((tty_size().ws_col / 2).saturating_sub(25), 2),
Position::Hovered => self

View file

@ -1,12 +1,15 @@
use core::{emit, files::FilesSort, input::InputMode};
use std::path::PathBuf;
use super::Ctx;
use crate::{config::{keymap::{Control, Exec, Key, KeymapLayer}, manager::SortBy, KEYMAP}, core::{files::FilesSort, input::InputMode}, emit, misc::optional_bool};
use config::{keymap::{Control, Exec, Key, KeymapLayer}, manager::SortBy, KEYMAP};
use shared::optional_bool;
pub struct Executor;
use super::Ctx;
pub(super) struct Executor;
impl Executor {
pub fn handle(cx: &mut Ctx, key: Key) -> bool {
pub(super) fn handle(cx: &mut Ctx, key: Key) -> bool {
let layer = cx.layer();
if layer == KeymapLayer::Which {
return cx.which.press(key);
@ -33,7 +36,7 @@ impl Executor {
}
#[inline]
pub fn dispatch(cx: &mut Ctx, exec: &Vec<Exec>, layer: KeymapLayer) -> bool {
pub(super) fn dispatch(cx: &mut Ctx, exec: &Vec<Exec>, layer: KeymapLayer) -> bool {
let mut render = false;
for e in exec {
render |= match layer {

View file

@ -1,14 +1,15 @@
use ratatui::{buffer::Buffer, layout::{self, Constraint, Direction, Rect}, style::{Color, Style}, widgets::{Paragraph, Widget}};
use ratatui::{layout, prelude::{Buffer, Constraint, Direction, Rect}, style::{Color, Style}, widgets::{Paragraph, Widget}};
use shared::readable_home;
use super::tabs::Tabs;
use crate::{misc::readable_home, ui::Ctx};
use super::Tabs;
use crate::Ctx;
pub struct Layout<'a> {
pub(crate) struct Layout<'a> {
cx: &'a Ctx,
}
impl<'a> Layout<'a> {
pub fn new(cx: &'a Ctx) -> Self { Self { cx } }
pub(crate) fn new(cx: &'a Ctx) -> Self { Self { cx } }
}
impl<'a> Widget for Layout<'a> {

5
app/src/header/mod.rs Normal file
View file

@ -0,0 +1,5 @@
mod layout;
mod tabs;
pub(super) use layout::*;
pub(self) use tabs::*;

View file

@ -1,13 +1,14 @@
use config::THEME;
use ratatui::{buffer::Buffer, layout::{Alignment, Rect}, text::{Line, Span}, widgets::{Paragraph, Widget}};
use crate::{config::THEME, ui::Ctx};
use crate::Ctx;
pub struct Tabs<'a> {
pub(super) struct Tabs<'a> {
cx: &'a Ctx,
}
impl<'a> Tabs<'a> {
pub fn new(cx: &'a Ctx) -> Self { Self { cx } }
pub(super) fn new(cx: &'a Ctx) -> Self { Self { cx } }
}
impl<'a> Widget for Tabs<'a> {

View file

@ -1,14 +1,16 @@
use core::input::InputMode;
use ratatui::{buffer::Buffer, layout::Rect, style::{Color, Style}, text::Line, widgets::{Block, BorderType, Borders, Clear, Paragraph, Widget}};
use shared::Term;
use super::{Ctx, Term};
use crate::core::input::InputMode;
use crate::Ctx;
pub struct Input<'a> {
pub(crate) struct Input<'a> {
cx: &'a Ctx,
}
impl<'a> Input<'a> {
pub fn new(cx: &'a Ctx) -> Self { Self { cx } }
pub(crate) fn new(cx: &'a Ctx) -> Self { Self { cx } }
}
impl<'a> Widget for Input<'a> {

3
app/src/input/mod.rs Normal file
View file

@ -0,0 +1,3 @@
mod input;
pub(super) use input::*;

View file

@ -1,16 +1,13 @@
use anyhow::{Context, Result};
use config::LOG;
use tracing_appender::non_blocking::WorkerGuard;
use tracing_subscriber::{fmt, prelude::__tracing_subscriber_SubscriberExt, Registry};
pub struct Logs {}
pub(super) struct Logs {}
impl Logs {
pub fn init() -> Result<WorkerGuard> {
let root = xdg::BaseDirectories::with_prefix("yazi")
.context("failed to get XDG base directories")?
.get_state_home();
let appender = tracing_appender::rolling::never(root, "yazi.log");
pub(super) fn init() -> Result<WorkerGuard> {
let appender = tracing_appender::rolling::never(&LOG.root, "yazi.log");
let (handle, guard) = tracing_appender::non_blocking(appender);
// let filter = EnvFilter::from_default_env();

31
app/src/main.rs Normal file
View file

@ -0,0 +1,31 @@
mod app;
mod context;
mod executor;
mod header;
mod input;
mod logs;
mod manager;
mod root;
mod select;
mod signals;
mod status;
mod tasks;
mod which;
pub(self) use app::*;
pub(self) use context::*;
pub(self) use executor::*;
pub(self) use logs::*;
pub(self) use root::*;
pub(self) use signals::*;
#[tokio::main]
async fn main() -> anyhow::Result<()> {
// console_subscriber::init();
config::init();
core::adaptor::Adaptor::init();
App::run().await
}

View file

@ -1,6 +1,10 @@
use ratatui::{buffer::Buffer, layout::Rect, style::Style, widgets::{List, ListItem, Widget}};
use core::files::File;
use crate::{config::THEME, core::{self, files::File}, misc::readable_path, ui::Ctx};
use config::THEME;
use ratatui::{buffer::Buffer, layout::Rect, style::Style, widgets::{List, ListItem, Widget}};
use shared::readable_path;
use crate::Ctx;
pub struct Folder<'a> {
cx: &'a Ctx,
@ -10,18 +14,18 @@ pub struct Folder<'a> {
}
impl<'a> Folder<'a> {
pub fn new(cx: &'a Ctx, folder: &'a core::manager::Folder) -> Self {
pub(super) fn new(cx: &'a Ctx, folder: &'a core::manager::Folder) -> Self {
Self { cx, folder, is_preview: false, is_selection: true }
}
#[inline]
pub fn with_preview(mut self, state: bool) -> Self {
pub(super) fn with_preview(mut self, state: bool) -> Self {
self.is_preview = state;
self
}
#[inline]
pub fn with_selection(mut self, state: bool) -> Self {
pub(super) fn with_selection(mut self, state: bool) -> Self {
self.is_selection = state;
self
}

View file

@ -1,14 +1,16 @@
use core::manager::{Mode, ALL_RATIO, CURRENT_RATIO, PARENT_RATIO, PREVIEW_RATIO};
use ratatui::{buffer::Buffer, layout::{self, Constraint, Direction, Rect}, widgets::{Block, Borders, Padding, Widget}};
use super::{Folder, Preview};
use crate::{core::manager::{Mode, ALL_RATIO, CURRENT_RATIO, PARENT_RATIO, PREVIEW_RATIO}, ui::Ctx};
use crate::Ctx;
pub struct Layout<'a> {
pub(crate) struct Layout<'a> {
cx: &'a Ctx,
}
impl<'a> Layout<'a> {
pub fn new(cx: &'a Ctx) -> Self { Self { cx } }
pub(crate) fn new(cx: &'a Ctx) -> Self { Self { cx } }
}
impl<'a> Widget for Layout<'a> {

7
app/src/manager/mod.rs Normal file
View file

@ -0,0 +1,7 @@
mod folder;
mod layout;
mod preview;
pub(super) use folder::*;
pub(super) use layout::*;
pub(self) use preview::*;

View file

@ -1,15 +1,17 @@
use core::manager::{PreviewData, PREVIEW_BORDER};
use ansi_to_tui::IntoText;
use ratatui::{buffer::Buffer, layout::Rect, widgets::{Clear, Paragraph, Widget}};
use super::Folder;
use crate::{core::manager::{PreviewData, PREVIEW_BORDER}, ui::Ctx};
use crate::Ctx;
pub struct Preview<'a> {
pub(super) struct Preview<'a> {
cx: &'a Ctx,
}
impl<'a> Preview<'a> {
pub fn new(cx: &'a Ctx) -> Self { Self { cx } }
pub(super) fn new(cx: &'a Ctx) -> Self { Self { cx } }
}
impl<'a> Widget for Preview<'a> {

View file

@ -1,13 +1,13 @@
use ratatui::{buffer::Buffer, layout::{Constraint, Direction, Layout, Rect}, widgets::Widget};
use super::{header, manager, status, tasks, which::Which, Ctx, Input, Select};
use super::{header, input, manager, select, status, tasks, which, Ctx};
pub struct Root<'a> {
pub(super) struct Root<'a> {
cx: &'a Ctx,
}
impl<'a> Root<'a> {
pub fn new(cx: &'a Ctx) -> Self { Self { cx } }
pub(super) fn new(cx: &'a Ctx) -> Self { Self { cx } }
}
impl<'a> Widget for Root<'a> {
@ -26,15 +26,15 @@ impl<'a> Widget for Root<'a> {
}
if self.cx.select.visible {
Select::new(self.cx).render(area, buf);
select::Select::new(self.cx).render(area, buf);
}
if self.cx.input.visible {
Input::new(self.cx).render(area, buf);
input::Input::new(self.cx).render(area, buf);
}
if self.cx.which.visible {
Which::new(self.cx).render(area, buf);
which::Which::new(self.cx).render(area, buf);
}
}
}

3
app/src/select/mod.rs Normal file
View file

@ -0,0 +1,3 @@
mod select;
pub(super) use select::*;

View file

@ -1,13 +1,13 @@
use ratatui::{buffer::Buffer, layout::Rect, style::{Color, Style}, widgets::{Block, BorderType, Borders, Clear, List, ListItem, Widget}};
use super::Ctx;
use crate::Ctx;
pub struct Select<'a> {
pub(crate) struct Select<'a> {
cx: &'a Ctx,
}
impl<'a> Select<'a> {
pub fn new(cx: &'a Ctx) -> Self { Self { cx } }
pub(crate) fn new(cx: &'a Ctx) -> Self { Self { cx } }
}
impl<'a> Widget for Select<'a> {

View file

@ -1,12 +1,12 @@
use core::Event;
use anyhow::Result;
use crossterm::event::{Event as CrosstermEvent, EventStream};
use futures::StreamExt;
use libc::{SIGHUP, SIGINT, SIGQUIT, SIGTERM};
use tokio::{select, sync::{mpsc::{self, UnboundedReceiver, UnboundedSender}, oneshot}, task::JoinHandle};
use crate::core::Event;
pub struct Signals {
pub(super) struct Signals {
pub tx: UnboundedSender<Event>,
pub rx: UnboundedReceiver<Event>,
@ -15,7 +15,7 @@ pub struct Signals {
}
impl Signals {
pub fn start() -> Result<Self> {
pub(super) fn start() -> Result<Self> {
let (tx, rx) = mpsc::unbounded_channel();
let (term_tx, term_rx) = oneshot::channel();
@ -73,7 +73,7 @@ impl Signals {
})
}
pub fn stop_term(&mut self, state: bool) {
pub(super) fn stop_term(&mut self, state: bool) {
if state == self.term_stop_tx.is_none() {
return;
}

View file

@ -1,14 +1,14 @@
use ratatui::{buffer::Buffer, layout::{self, Constraint, Direction, Rect}, widgets::Widget};
use super::{Left, Right};
use crate::ui::Ctx;
use crate::Ctx;
pub struct Layout<'a> {
pub(crate) struct Layout<'a> {
cx: &'a Ctx,
}
impl<'a> Layout<'a> {
pub fn new(cx: &'a Ctx) -> Self { Self { cx } }
pub(crate) fn new(cx: &'a Ctx) -> Self { Self { cx } }
}
impl<'a> Widget for Layout<'a> {

View file

@ -1,13 +1,15 @@
use config::THEME;
use ratatui::{buffer::Buffer, layout::Rect, style::Modifier, text::{Line, Span}, widgets::{Paragraph, Widget}};
use shared::readable_size;
use crate::{config::THEME, misc::readable_size, ui::Ctx};
use crate::Ctx;
pub struct Left<'a> {
pub(super) struct Left<'a> {
cx: &'a Ctx,
}
impl<'a> Left<'a> {
pub fn new(cx: &'a Ctx) -> Self { Self { cx } }
pub(super) fn new(cx: &'a Ctx) -> Self { Self { cx } }
}
impl<'a> Widget for Left<'a> {

9
app/src/status/mod.rs Normal file
View file

@ -0,0 +1,9 @@
mod layout;
mod left;
mod progress;
mod right;
pub(super) use layout::*;
pub(self) use left::*;
pub(self) use progress::*;
pub(self) use right::*;

View file

@ -1,13 +1,14 @@
use config::THEME;
use ratatui::{buffer::Buffer, layout::Rect, text::Span, widgets::{Gauge, Widget}};
use crate::{config::THEME, ui::Ctx};
use crate::Ctx;
pub struct Progress<'a> {
pub(super) struct Progress<'a> {
cx: &'a Ctx,
}
impl<'a> Progress<'a> {
pub fn new(cx: &'a Ctx) -> Self { Self { cx } }
pub(super) fn new(cx: &'a Ctx) -> Self { Self { cx } }
}
impl<'a> Widget for Progress<'a> {

View file

@ -1,16 +1,18 @@
use std::os::unix::prelude::PermissionsExt;
use config::THEME;
use ratatui::{buffer::Buffer, layout::{Alignment, Rect}, text::{Line, Span}, widgets::{Paragraph, Widget}};
use shared::file_mode;
use super::Progress;
use crate::{config::THEME, misc::file_mode, ui::Ctx};
use crate::Ctx;
pub struct Right<'a> {
pub(super) struct Right<'a> {
cx: &'a Ctx,
}
impl<'a> Right<'a> {
pub fn new(cx: &'a Ctx) -> Self { Self { cx } }
pub(super) fn new(cx: &'a Ctx) -> Self { Self { cx } }
fn permissions(&self, s: &str) -> Vec<Span> {
// Colors

View file

@ -1,16 +1,18 @@
use core::tasks::TASKS_PERCENT;
use ratatui::{buffer::Buffer, layout::{self, Alignment, Constraint, Direction, Rect}, style::{Color, Modifier, Style}, widgets::{Block, BorderType, Borders, List, ListItem, Padding, Widget}};
use super::Clear;
use crate::{core::tasks::TASKS_PERCENT, ui::Ctx};
use crate::Ctx;
pub struct Layout<'a> {
pub(crate) struct Layout<'a> {
cx: &'a Ctx,
}
impl<'a> Layout<'a> {
pub fn new(cx: &'a Ctx) -> Self { Self { cx } }
pub(crate) fn new(cx: &'a Ctx) -> Self { Self { cx } }
pub fn area(area: Rect) -> Rect {
pub(super) fn area(area: Rect) -> Rect {
let chunk = layout::Layout::new()
.direction(Direction::Vertical)
.constraints(

5
app/src/tasks/mod.rs Normal file
View file

@ -0,0 +1,5 @@
mod clear;
mod layout;
pub(self) use clear::*;
pub(super) use layout::*;

View file

@ -1,14 +1,14 @@
use ratatui::{layout, prelude::{Buffer, Constraint, Direction, Rect}, style::{Color, Style}, widgets::{Block, Clear, Widget}};
use super::Side;
use crate::ui::Ctx;
use crate::Ctx;
pub struct Which<'a> {
pub(crate) struct Which<'a> {
cx: &'a Ctx,
}
impl<'a> Which<'a> {
pub fn new(cx: &'a Ctx) -> Self { Self { cx } }
pub(crate) fn new(cx: &'a Ctx) -> Self { Self { cx } }
}
impl Widget for Which<'_> {

5
app/src/which/mod.rs Normal file
View file

@ -0,0 +1,5 @@
mod layout;
mod side;
pub(super) use layout::*;
pub(self) use side::*;

View file

@ -1,14 +1,13 @@
use config::keymap::Control;
use ratatui::{prelude::{Buffer, Rect}, style::{Color, Style}, text::{Line, Span}, widgets::{Block, List, ListItem, Padding, Widget}};
use crate::config::keymap::Control;
pub struct Side<'a> {
pub(super) struct Side<'a> {
times: usize,
cands: Vec<&'a Control>,
}
impl<'a> Side<'a> {
pub fn new(times: usize, cands: Vec<&'a Control>) -> Self { Self { times, cands } }
pub(super) fn new(times: usize, cands: Vec<&'a Control>) -> Self { Self { times, cands } }
}
impl Widget for Side<'_> {

19
config/Cargo.toml Normal file
View file

@ -0,0 +1,19 @@
[package]
name = "config"
version = "0.1.0"
edition = "2021"
[dependencies]
shared = { path = "../shared" }
# External dependencies
toml = { version = "^0", features = [ "preserve_order" ] }
xdg = "^2"
serde = { version = "^1", features = [ "derive" ] }
once_cell = "^1"
crossterm = { version = "^0" }
anyhow = "^1"
ratatui = "^0"
glob = "^0"
futures = "^0"

View file

@ -1,3 +0,0 @@
# Configuration
[See ../docs for more information.](../docs)

View file

@ -22,7 +22,6 @@ keymap = [
{ on = [ "<Down>" ], exec = "arrow 1" },
{ on = [ "<Left>" ], exec = "leave" },
{ on = [ "<Right>" ], exec = "enter" },
{ on = [ "<Enter>" ], exec = "open" },
# Selection
{ on = [ "<Space>" ], exec = [ "select --state=none", "arrow 1" ] },
@ -34,13 +33,17 @@ keymap = [
# Operation
{ on = [ "o" ], exec = "open" },
{ on = [ "O" ], exec = "open --interactive" },
{ on = [ "<Enter>" ], exec = "open" },
{ on = [ "<C-Enter>" ], exec = "open --interactive" }, # It's cool if you're using a terminal that supports CSI u
{ on = [ "y" ], exec = "yank" },
{ on = [ "x" ], exec = "yank --cut" },
{ on = [ "p" ], exec = "paste" },
{ on = [ "P" ], exec = "paste --force" },
{ on = [ "k" ], exec = "paste --follow" },
{ on = [ "K" ], exec = "paste --follow --force" },
{ on = [ "d" ], exec = "remove" },
{ on = [ "D" ], exec = "remove --permanently" },
{ on = [ "c" ], exec = "create" },
{ on = [ "a" ], exec = "create" },
{ on = [ "r" ], exec = "rename" },
{ on = [ "." ], exec = "hidden toggle" },
{ on = [ "s" ], exec = "search fd" },
@ -49,6 +52,12 @@ keymap = [
{ on = [ "z" ], exec = "jump zoxide" },
{ on = [ "Z" ], exec = "jump fzf" },
# Copy
{ on = [ "c", "c" ], exec = "copy path" },
{ on = [ "c", "d" ], exec = "copy dirname" },
{ on = [ "c", "f" ], exec = "copy filename" },
{ on = [ "c", "n" ], exec = "copy name_without_ext" },
# Sorting
{ on = [ ",", "a" ], exec = "sort alphabetical" },
{ on = [ ",", "A" ], exec = "sort alphabetical --reverse" },
@ -67,6 +76,10 @@ keymap = [
{ on = [ "3" ], exec = "tab_switch 2" },
{ on = [ "4" ], exec = "tab_switch 3" },
{ on = [ "5" ], exec = "tab_switch 4" },
{ on = [ "6" ], exec = "tab_switch 5" },
{ on = [ "7" ], exec = "tab_switch 6" },
{ on = [ "8" ], exec = "tab_switch 7" },
{ on = [ "9" ], exec = "tab_switch 8" },
{ on = [ "[" ], exec = "tab_switch -1 --relative" },
{ on = [ "]" ], exec = "tab_switch 1 --relative" },
@ -151,7 +164,7 @@ keymap = [
{ on = [ "c" ], exec = "delete --cut --insert" },
{ on = [ "x" ], exec = [ "delete --cut", "move 1 --in-operating" ] },
# Copy/Paste
# Yank/Paste
{ on = [ "y" ], exec = [ "yank" ] },
{ on = [ "p" ], exec = [ "paste" ] },
{ on = [ "P" ], exec = [ "paste --before" ] },

View file

@ -11,7 +11,7 @@ max_height = 900
[opener]
folder = [
{ cmd = "open", args = [ "-R", "$*" ] },
{ cmd = "code", args = [ "$*" ] },
{ cmd = "vim", args = [ "$*" ] },
]
archive = [
{ cmd = "unar", args = [ "$1" ] },
@ -54,3 +54,6 @@ rules = [
{ mime = "application/zip", use = "archive" },
{ mime = "application/x-7z-compressed", use = "archive" },
]
[log]
enabled = false

View file

@ -1,7 +1,7 @@
use serde::{Deserialize, Deserializer};
use super::{Exec, Key};
use crate::config::MERGED_KEYMAP;
use crate::MERGED_KEYMAP;
#[derive(Clone, Debug, Deserialize)]
pub struct Control {

View file

@ -1,6 +1,7 @@
use once_cell::sync::Lazy;
pub mod keymap;
mod log;
pub mod manager;
pub mod open;
mod pattern;
@ -16,6 +17,7 @@ static MERGED_THEME: Lazy<String> = Lazy::new(|| Preset::theme());
static MERGED_YAZI: Lazy<String> = Lazy::new(|| Preset::yazi());
pub static KEYMAP: Lazy<keymap::Keymap> = Lazy::new(|| keymap::Keymap::new());
pub static LOG: Lazy<log::Log> = Lazy::new(|| log::Log::new());
pub static MANAGER: Lazy<manager::Manager> = Lazy::new(|| manager::Manager::new());
pub static OPEN: Lazy<open::Open> = Lazy::new(|| open::Open::new());
pub static PREVIEW: Lazy<preview::Preview> = Lazy::new(|| preview::Preview::new());
@ -23,6 +25,7 @@ pub static THEME: Lazy<theme::Theme> = Lazy::new(|| theme::Theme::new());
pub fn init() {
Lazy::force(&KEYMAP);
Lazy::force(&LOG);
Lazy::force(&MANAGER);
Lazy::force(&OPEN);
Lazy::force(&PREVIEW);

42
config/src/log/log.rs Normal file
View file

@ -0,0 +1,42 @@
use std::path::PathBuf;
use serde::{de, Deserialize, Deserializer};
use crate::MERGED_YAZI;
#[derive(Debug)]
pub struct Log {
pub enabled: bool,
pub root: PathBuf,
}
impl Log {
pub fn new() -> Self { toml::from_str(&MERGED_YAZI).unwrap() }
}
impl<'de> Deserialize<'de> for Log {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
#[derive(Deserialize)]
struct Outer {
log: Shadow,
}
#[derive(Deserialize)]
struct Shadow {
enabled: bool,
}
let outer = Outer::deserialize(deserializer)?;
let root = xdg::BaseDirectories::with_prefix("yazi")
.map_err(|e| de::Error::custom(e.to_string()))?
.get_state_home();
if !root.is_dir() {
std::fs::create_dir_all(&root).map_err(|e| de::Error::custom(e.to_string()))?;
}
Ok(Self { enabled: outer.log.enabled, root })
}
}

3
config/src/log/mod.rs Normal file
View file

@ -0,0 +1,3 @@
mod log;
pub use log::*;

View file

@ -3,7 +3,7 @@ use std::{env, fs, path::PathBuf};
use serde::Deserialize;
use super::SortBy;
use crate::config::MERGED_YAZI;
use crate::MERGED_YAZI;
#[derive(Debug, Deserialize)]
pub struct Manager {

View file

@ -1,9 +1,10 @@
use std::{collections::{BTreeMap, BTreeSet}, path::Path};
use serde::{Deserialize, Deserializer};
use shared::MIME_DIR;
use super::Opener;
use crate::{config::{Pattern, MERGED_YAZI}, misc::MIME_DIR};
use crate::{Pattern, MERGED_YAZI};
#[derive(Debug)]
pub struct Open {

View file

@ -40,16 +40,16 @@ impl Preset {
#[inline]
pub(crate) fn keymap() -> String {
Self::merge_str("yazi/keymap.toml", include_str!("../../config/keymap.toml"))
Self::merge_str("yazi/keymap.toml", include_str!("../preset/keymap.toml"))
}
#[inline]
pub(crate) fn theme() -> String {
Self::merge_str("yazi/theme.toml", include_str!("../../config/theme.toml"))
Self::merge_str("yazi/theme.toml", include_str!("../preset/theme.toml"))
}
#[inline]
pub(crate) fn yazi() -> String {
Self::merge_str("yazi/yazi.toml", include_str!("../../config/yazi.toml"))
Self::merge_str("yazi/yazi.toml", include_str!("../preset/yazi.toml"))
}
}

View file

@ -28,6 +28,7 @@ impl Default for PreviewAdaptor {
}
match env::var("TERM_PROGRAM").unwrap_or_default().as_str() {
"iTerm.app" => return Self::Iterm2,
"Hyper" => return Self::Sixel,
_ => {}
}
match env::var("XDG_SESSION_TYPE").unwrap_or_default().as_str() {

View file

@ -1,7 +1,7 @@
use serde::Deserialize;
use super::PreviewAdaptor;
use crate::config::MERGED_YAZI;
use crate::MERGED_YAZI;
#[derive(Debug, Deserialize)]
pub struct Preview {

View file

@ -3,7 +3,7 @@ use std::path::Path;
use serde::{Deserialize, Deserializer};
use super::Style;
use crate::config::{theme::Color, Pattern};
use crate::{theme::Color, Pattern};
pub struct Filetype {
pub name: Option<Pattern>,

View file

@ -2,7 +2,7 @@ use std::fmt;
use serde::{de::{self, Visitor}, Deserializer};
use crate::config::Pattern;
use crate::Pattern;
#[derive(Debug)]
pub struct Icon {

View file

@ -1,9 +1,10 @@
use std::path::PathBuf;
use serde::Deserialize;
use shared::absolute_path;
use super::{ColorGroup, Filetype, Icon, Style};
use crate::{config::MERGED_THEME, misc::absolute_path};
use crate::MERGED_THEME;
#[derive(Deserialize)]
pub struct Tab {

31
core/Cargo.toml Normal file
View file

@ -0,0 +1,31 @@
[package]
name = "core"
version = "0.1.0"
edition = "2021"
[dependencies]
config = { path = "../config" }
shared = { path = "../shared" }
# External dependencies
serde = { version = "^1" }
anyhow = "^1"
async-channel = "^1"
base64 = "^0"
console-subscriber = "^0"
crossterm = { version = "^0" }
futures = "^0"
image = "^0"
indexmap = "^2"
libc = "^0"
md5 = "^0"
notify = { version = "^6", default-features = false, features = [ "macos_fsevent" ] }
parking_lot = "^0"
ratatui = "^0"
serde_json = "^1"
syntect = "^5"
tokio = { version = "^1", features = [ "parking_lot", "macros", "rt-multi-thread", "sync", "fs", "process", "io-std", "io-util" ] }
trash = "^3"
unicode-width = "^0"
once_cell = "^1"
tracing = "^0"

View file

@ -1,12 +1,12 @@
use std::{path::{Path, PathBuf}, sync::atomic::{AtomicBool, Ordering}};
use anyhow::Result;
use config::{preview::PreviewAdaptor, PREVIEW};
use once_cell::sync::Lazy;
use ratatui::prelude::Rect;
use tokio::sync::mpsc::UnboundedSender;
use super::{iterm2::Iterm2, kitty::Kitty, ueberzug::Ueberzug};
use crate::config::{preview::PreviewAdaptor, PREVIEW};
static IMAGE_SHOWN: AtomicBool = AtomicBool::new(false);

View file

@ -1,11 +1,11 @@
use std::path::Path;
use anyhow::Result;
use config::PREVIEW;
use image::{imageops::FilterType, DynamicImage};
use shared::tty_ratio;
use tokio::fs;
use crate::{config::PREVIEW, misc::tty_ratio};
pub(super) struct Image;
impl Image {

View file

@ -4,9 +4,9 @@ use anyhow::Result;
use base64::{engine::general_purpose, Engine};
use image::{codecs::jpeg::JpegEncoder, DynamicImage};
use ratatui::prelude::Rect;
use shared::Term;
use super::image::Image;
use crate::ui::Term;
pub(super) struct Iterm2;

View file

@ -4,9 +4,9 @@ use anyhow::Result;
use base64::{engine::general_purpose, Engine};
use image::DynamicImage;
use ratatui::prelude::Rect;
use shared::Term;
use super::image::Image;
use crate::ui::Term;
pub(super) struct Kitty;

View file

@ -1,11 +1,10 @@
use std::{path::PathBuf, process::Stdio};
use anyhow::Result;
use config::PREVIEW;
use ratatui::prelude::Rect;
use tokio::{io::AsyncWriteExt, process::{Child, Command}, sync::mpsc::{self, UnboundedSender}};
use crate::config::PREVIEW;
pub(super) struct Ueberzug;
impl Ueberzug {

View file

@ -1,11 +1,11 @@
use std::{collections::BTreeMap, path::PathBuf};
use anyhow::Result;
use config::{keymap::{Control, KeymapLayer}, open::Opener};
use crossterm::event::KeyEvent;
use tokio::sync::{mpsc::UnboundedSender, oneshot};
use super::{files::{File, FilesOp}, input::InputOpt, manager::PreviewData, select::SelectOpt};
use crate::config::{keymap::{Control, KeymapLayer}, open::Opener};
static mut TX: Option<UnboundedSender<Event>> = None;
@ -60,61 +60,61 @@ impl Event {
#[macro_export]
macro_rules! emit {
(Key($key:expr)) => {
$crate::core::Event::Key($key).emit();
$crate::Event::Key($key).emit();
};
(Render) => {
$crate::core::Event::Render(format!("{}:{}", file!(), line!())).emit();
$crate::Event::Render(format!("{}:{}", file!(), line!())).emit();
};
(Resize($cols:expr, $rows:expr)) => {
$crate::core::Event::Resize($cols, $rows).emit();
$crate::Event::Resize($cols, $rows).emit();
};
(Stop($state:expr)) => {{
let (tx, rx) = tokio::sync::oneshot::channel();
$crate::core::Event::Stop($state, Some(tx)).wait(rx)
$crate::Event::Stop($state, Some(tx)).wait(rx)
}};
(Ctrl($exec:expr, $layer:expr)) => {
$crate::core::Event::Ctrl($exec, $layer).emit();
$crate::Event::Ctrl($exec, $layer).emit();
};
(Cd($op:expr)) => {
$crate::core::Event::Cd($op).emit();
$crate::Event::Cd($op).emit();
};
(Files($op:expr)) => {
$crate::core::Event::Files($op).emit();
$crate::Event::Files($op).emit();
};
(Pages($page:expr)) => {
$crate::core::Event::Pages($page).emit();
$crate::Event::Pages($page).emit();
};
(Mimetype($mimes:expr)) => {
$crate::core::Event::Mimetype($mimes).emit();
$crate::Event::Mimetype($mimes).emit();
};
(Hover) => {
$crate::core::Event::Hover(None).emit();
$crate::Event::Hover(None).emit();
};
(Hover($file:expr)) => {
$crate::core::Event::Hover(Some($file)).emit();
$crate::Event::Hover(Some($file)).emit();
};
(Preview($path:expr, $mime:expr, $data:expr)) => {
$crate::core::Event::Preview($path, $mime, $data).emit();
$crate::Event::Preview($path, $mime, $data).emit();
};
(Select($opt:expr)) => {{
let (tx, rx) = tokio::sync::oneshot::channel();
$crate::core::Event::Select($opt, tx).wait(rx)
$crate::Event::Select($opt, tx).wait(rx)
}};
(Input($opt:expr)) => {{
let (tx, rx) = tokio::sync::oneshot::channel();
$crate::core::Event::Input($opt, tx).wait(rx)
$crate::Event::Input($opt, tx).wait(rx)
}};
(Open($targets:expr, $opener:expr)) => {
$crate::core::Event::Open($targets, $opener).emit();
$crate::Event::Open($targets, $opener).emit();
};
(Progress($percent:expr, $tasks:expr)) => {
$crate::core::Event::Progress($percent, $tasks).emit();
$crate::Event::Progress($percent, $tasks).emit();
};
($event:ident) => {
$crate::core::Event::$event.emit();
$crate::Event::$event.emit();
};
}

View file

@ -1,10 +1,9 @@
use std::{path::PathBuf, process::Stdio, time::Duration};
use anyhow::Result;
use shared::DelayedBuffer;
use tokio::{io::{AsyncBufReadExt, BufReader}, process::Command, sync::mpsc::UnboundedReceiver};
use crate::misc::DelayedBuffer;
pub struct FdOpt {
pub cwd: PathBuf,
pub hidden: bool,

View file

@ -1,10 +1,9 @@
use std::path::Path;
use anyhow::{bail, Result};
use config::PREVIEW;
use tokio::process::Command;
use crate::config::PREVIEW;
pub async fn ffmpegthumbnailer(path: &Path, dest: &Path) -> Result<()> {
let output = Command::new("ffmpegthumbnailer")
.arg("-i")

View file

@ -1,10 +1,9 @@
use std::{collections::BTreeMap, ffi::OsStr, path::PathBuf};
use anyhow::{bail, Result};
use shared::MimeKind;
use tokio::process::Command;
use crate::misc::MimeKind;
pub async fn file(files: &[impl AsRef<OsStr>]) -> Result<BTreeMap<PathBuf, String>> {
if files.is_empty() {
bail!("no files to get mime types for");

View file

@ -1,10 +1,9 @@
use std::path::Path;
use anyhow::{bail, Result};
use config::PREVIEW;
use tokio::process::Command;
use crate::config::PREVIEW;
pub async fn jq(path: &Path) -> Result<String> {
let output = Command::new("jq")
.args(["-C", "--indent", &PREVIEW.tab_size.to_string(), "."])

View file

@ -1,10 +1,9 @@
use std::{path::PathBuf, process::Stdio, time::Duration};
use anyhow::Result;
use shared::DelayedBuffer;
use tokio::{io::{AsyncBufReadExt, BufReader}, process::Command, sync::mpsc::UnboundedReceiver};
use crate::misc::DelayedBuffer;
pub struct RgOpt {
pub cwd: PathBuf,
pub hidden: bool,

View file

@ -1,11 +1,11 @@
use std::{collections::BTreeMap, ops::{Deref, DerefMut}, path::{Path, PathBuf}};
use anyhow::Result;
use config::{manager::SortBy, MANAGER};
use indexmap::IndexMap;
use tokio::fs;
use super::File;
use crate::config::{manager::SortBy, MANAGER};
#[derive(Default)]
pub struct Files {

View file

@ -2,11 +2,12 @@ use std::ops::Range;
use anyhow::{anyhow, Result};
use ratatui::layout::Rect;
use shared::CharKind;
use tokio::sync::oneshot::Sender;
use unicode_width::UnicodeWidthStr;
use super::{mode::InputMode, op::InputOp, InputSnap, InputSnaps};
use crate::{core::{external, Position}, misc::CharKind};
use crate::{external, Position};
#[derive(Default)]
pub struct Input {

View file

@ -2,9 +2,10 @@ use std::path::{Path, PathBuf};
use indexmap::map::Slice;
use ratatui::layout::Rect;
use shared::tty_size;
use super::{ALL_RATIO, CURRENT_RATIO, DIR_PADDING, PARENT_RATIO};
use crate::{core::files::{File, Files, FilesOp}, emit, misc::tty_size};
use crate::{emit, files::{File, Files, FilesOp}};
#[derive(Default)]
pub struct Folder {

View file

@ -1,10 +1,12 @@
use std::{collections::{BTreeMap, BTreeSet, HashMap, HashSet}, env, mem, path::PathBuf};
use anyhow::Error;
use config::OPEN;
use shared::MIME_DIR;
use tokio::fs;
use super::{PreviewData, Tab, Tabs, Watcher};
use crate::{config::OPEN, core::{external, files::{File, FilesOp}, input::InputOpt, manager::Folder, select::SelectOpt, tasks::Tasks, Position}, emit, misc::MIME_DIR};
use crate::{emit, external, files::{File, FilesOp}, input::InputOpt, manager::Folder, select::SelectOpt, tasks::Tasks, Position};
pub struct Manager {
tabs: Tabs,

View file

@ -1,6 +1,6 @@
use std::fmt::Display;
use crate::config::theme::{self, ColorGroup};
use config::theme::{self, ColorGroup};
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
pub enum Mode {

View file

@ -1,12 +1,14 @@
use std::{fs::File, io::{BufRead, BufReader}, mem, path::{Path, PathBuf}, sync::OnceLock};
use anyhow::{anyhow, Result};
use config::{PREVIEW, THEME};
use ratatui::prelude::Rect;
use shared::{tty_size, MimeKind};
use syntect::{easy::HighlightFile, highlighting::{Theme, ThemeSet}, parsing::SyntaxSet, util::as_24_bit_terminal_escaped};
use tokio::{fs, task::JoinHandle};
use super::{ALL_RATIO, CURRENT_RATIO, PARENT_RATIO, PREVIEW_BORDER, PREVIEW_MARGIN, PREVIEW_RATIO};
use crate::{config::{PREVIEW, THEME}, core::{adaptor::Adaptor, external, files::{Files, FilesOp}, tasks::Precache}, emit, misc::{tty_size, MimeKind}};
use crate::{adaptor::Adaptor, emit, external, files::{Files, FilesOp}, tasks::Precache};
static SYNTECT_SYNTAX: OnceLock<SyntaxSet> = OnceLock::new();
static SYNTECT_THEME: OnceLock<Theme> = OnceLock::new();

Some files were not shown because too many files have changed in this diff Show more