mirror of
https://github.com/sxyazi/yazi.git
synced 2026-07-25 08:41:05 +00:00
..
This commit is contained in:
parent
c96bee7715
commit
ea2e44c901
21 changed files with 179 additions and 95 deletions
59
Cargo.lock
generated
59
Cargo.lock
generated
|
|
@ -344,6 +344,7 @@ dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"clap",
|
"clap",
|
||||||
"crossterm 0.27.0",
|
"crossterm 0.27.0",
|
||||||
|
"dirs",
|
||||||
"futures",
|
"futures",
|
||||||
"glob",
|
"glob",
|
||||||
"indexmap 2.0.0",
|
"indexmap 2.0.0",
|
||||||
|
|
@ -355,7 +356,6 @@ dependencies = [
|
||||||
"shell-words",
|
"shell-words",
|
||||||
"toml",
|
"toml",
|
||||||
"validator",
|
"validator",
|
||||||
"xdg",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -515,6 +515,27 @@ dependencies = [
|
||||||
"crypto-common",
|
"crypto-common",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "dirs"
|
||||||
|
version = "5.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225"
|
||||||
|
dependencies = [
|
||||||
|
"dirs-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "dirs-sys"
|
||||||
|
version = "0.4.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"option-ext",
|
||||||
|
"redox_users",
|
||||||
|
"windows-sys 0.48.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "either"
|
name = "either"
|
||||||
version = "1.9.0"
|
version = "1.9.0"
|
||||||
|
|
@ -587,7 +608,7 @@ checksum = "d4029edd3e734da6fe05b6cd7bd2960760a616bd2ddd0d59a0124746d6272af0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"libc",
|
"libc",
|
||||||
"redox_syscall",
|
"redox_syscall 0.3.5",
|
||||||
"windows-sys 0.48.0",
|
"windows-sys 0.48.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
@ -1212,6 +1233,12 @@ dependencies = [
|
||||||
"pkg-config",
|
"pkg-config",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "option-ext"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "overload"
|
name = "overload"
|
||||||
version = "0.1.1"
|
version = "0.1.1"
|
||||||
|
|
@ -1236,7 +1263,7 @@ checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"libc",
|
"libc",
|
||||||
"redox_syscall",
|
"redox_syscall 0.3.5",
|
||||||
"smallvec",
|
"smallvec",
|
||||||
"windows-targets 0.48.2",
|
"windows-targets 0.48.2",
|
||||||
]
|
]
|
||||||
|
|
@ -1415,6 +1442,15 @@ dependencies = [
|
||||||
"num_cpus",
|
"num_cpus",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "redox_syscall"
|
||||||
|
version = "0.2.16"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 1.3.2",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "redox_syscall"
|
name = "redox_syscall"
|
||||||
version = "0.3.5"
|
version = "0.3.5"
|
||||||
|
|
@ -1424,6 +1460,17 @@ dependencies = [
|
||||||
"bitflags 1.3.2",
|
"bitflags 1.3.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "redox_users"
|
||||||
|
version = "0.4.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b"
|
||||||
|
dependencies = [
|
||||||
|
"getrandom",
|
||||||
|
"redox_syscall 0.2.16",
|
||||||
|
"thiserror",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "regex"
|
name = "regex"
|
||||||
version = "1.9.3"
|
version = "1.9.3"
|
||||||
|
|
@ -2307,12 +2354,6 @@ dependencies = [
|
||||||
"memchr",
|
"memchr",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "xdg"
|
|
||||||
version = "2.5.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "213b7324336b53d2414b2db8537e56544d981803139155afa84f76eeebb7a546"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "yaml-rust"
|
name = "yaml-rust"
|
||||||
version = "0.4.5"
|
version = "0.4.5"
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ use std::{path::Path, sync::Arc};
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use config::PREVIEW;
|
use config::PREVIEW;
|
||||||
use image::{imageops::FilterType, DynamicImage, ImageFormat};
|
use image::{imageops::FilterType, DynamicImage, ImageFormat};
|
||||||
use shared::tty_ratio;
|
use shared::Term;
|
||||||
use tokio::fs;
|
use tokio::fs;
|
||||||
|
|
||||||
pub struct Image;
|
pub struct Image;
|
||||||
|
|
@ -11,7 +11,7 @@ pub struct Image;
|
||||||
impl Image {
|
impl Image {
|
||||||
pub(super) async fn crop(path: &Path, size: (u16, u16)) -> Result<DynamicImage> {
|
pub(super) async fn crop(path: &Path, size: (u16, u16)) -> Result<DynamicImage> {
|
||||||
let (w, h) = {
|
let (w, h) = {
|
||||||
let r = tty_ratio();
|
let r = Term::ratio();
|
||||||
let (w, h) = ((size.0 as f64 * r.0) as u32, (size.1 as f64 * r.1) as u32);
|
let (w, h) = ((size.0 as f64 * r.0) as u32, (size.1 as f64 * r.1) as u32);
|
||||||
(w.min(PREVIEW.max_width), h.min(PREVIEW.max_height))
|
(w.min(PREVIEW.max_width), h.min(PREVIEW.max_height))
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -42,11 +42,19 @@ impl App {
|
||||||
|
|
||||||
fn dispatch_quit(&mut self) {
|
fn dispatch_quit(&mut self) {
|
||||||
if let Some(p) = &BOOT.cwd_file {
|
if let Some(p) = &BOOT.cwd_file {
|
||||||
use std::os::unix::prelude::OsStrExt;
|
|
||||||
let cwd = self.cx.manager.cwd().as_os_str();
|
let cwd = self.cx.manager.cwd().as_os_str();
|
||||||
|
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
{
|
||||||
|
std::fs::write(p, cwd.to_string_lossy().as_bytes()).ok();
|
||||||
|
}
|
||||||
|
#[cfg(not(target_os = "windows"))]
|
||||||
|
{
|
||||||
|
use std::os::unix::ffi::OsStrExt;
|
||||||
std::fs::write(p, cwd.as_bytes()).ok();
|
std::fs::write(p, cwd.as_bytes()).ok();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn dispatch_key(&mut self, key: KeyEvent) {
|
fn dispatch_key(&mut self, key: KeyEvent) {
|
||||||
let key = Key::from(key);
|
let key = Key::from(key);
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
use core::{input::Input, manager::Manager, select::Select, tasks::Tasks, which::Which, Position};
|
use core::{input::Input, manager::Manager, select::Select, tasks::Tasks, which::Which, Position};
|
||||||
|
|
||||||
use config::keymap::KeymapLayer;
|
use config::keymap::KeymapLayer;
|
||||||
use libc::winsize;
|
use crossterm::terminal::WindowSize;
|
||||||
use ratatui::prelude::Rect;
|
use ratatui::prelude::Rect;
|
||||||
use shared::tty_size;
|
use shared::Term;
|
||||||
|
|
||||||
pub struct Ctx {
|
pub struct Ctx {
|
||||||
pub manager: Manager,
|
pub manager: Manager,
|
||||||
|
|
@ -25,14 +25,14 @@ impl Ctx {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn area(&self, pos: &Position) -> Rect {
|
pub(super) fn area(&self, pos: &Position) -> Rect {
|
||||||
let winsize { ws_row, ws_col, .. } = tty_size();
|
let WindowSize { rows, columns, .. } = Term::size();
|
||||||
|
|
||||||
let (x, y) = match pos {
|
let (x, y) = match pos {
|
||||||
Position::None => return Rect::default(),
|
Position::None => return Rect::default(),
|
||||||
Position::Top(Rect { mut x, mut y, width, height }) => {
|
Position::Top(Rect { mut x, mut y, width, height }) => {
|
||||||
x = x.min(ws_col.saturating_sub(*width));
|
x = x.min(columns.saturating_sub(*width));
|
||||||
y = y.min(ws_row.saturating_sub(*height));
|
y = y.min(rows.saturating_sub(*height));
|
||||||
((tty_size().ws_col / 2).saturating_sub(width / 2) + x, y)
|
((columns / 2).saturating_sub(width / 2) + x, y)
|
||||||
}
|
}
|
||||||
Position::Hovered(rect @ Rect { mut x, y, width, height }) => {
|
Position::Hovered(rect @ Rect { mut x, y, width, height }) => {
|
||||||
let Some(r) =
|
let Some(r) =
|
||||||
|
|
@ -41,8 +41,8 @@ impl Ctx {
|
||||||
return self.area(&Position::Top(*rect));
|
return self.area(&Position::Top(*rect));
|
||||||
};
|
};
|
||||||
|
|
||||||
x = x.min(ws_col.saturating_sub(*width));
|
x = x.min(columns.saturating_sub(*width));
|
||||||
if y + height + r.y + r.height > ws_row {
|
if y + height + r.y + r.height > rows {
|
||||||
(x + r.x, r.y.saturating_sub(height.saturating_sub(1)))
|
(x + r.x, r.y.saturating_sub(height.saturating_sub(1)))
|
||||||
} else {
|
} else {
|
||||||
(x + r.x, y + r.y + r.height)
|
(x + r.x, y + r.y + r.height)
|
||||||
|
|
@ -51,7 +51,7 @@ impl Ctx {
|
||||||
};
|
};
|
||||||
|
|
||||||
let (w, h) = pos.dimension().unwrap();
|
let (w, h) = pos.dimension().unwrap();
|
||||||
Rect { x, y, width: w.min(ws_col.saturating_sub(x)), height: h.min(ws_row.saturating_sub(y)) }
|
Rect { x, y, width: w.min(columns.saturating_sub(x)), height: h.min(rows.saturating_sub(y)) }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ pub(super) struct Right<'a> {
|
||||||
impl<'a> Right<'a> {
|
impl<'a> Right<'a> {
|
||||||
pub(super) fn new(cx: &'a Ctx) -> Self { Self { cx } }
|
pub(super) fn new(cx: &'a Ctx) -> Self { Self { cx } }
|
||||||
|
|
||||||
|
#[cfg(not(target_os = "windows"))]
|
||||||
fn permissions(&self, s: &str) -> Vec<Span> {
|
fn permissions(&self, s: &str) -> Vec<Span> {
|
||||||
// Colors
|
// Colors
|
||||||
let mode = self.cx.manager.active().mode();
|
let mode = self.cx.manager.active().mode();
|
||||||
|
|
|
||||||
3
build.sh
3
build.sh
|
|
@ -1,11 +1,14 @@
|
||||||
cargo +stable build --release --target aarch64-apple-darwin
|
cargo +stable build --release --target aarch64-apple-darwin
|
||||||
cargo +stable build --release --target x86_64-apple-darwin
|
cargo +stable build --release --target x86_64-apple-darwin
|
||||||
cargo +stable build --release --target x86_64-unknown-linux-gnu
|
cargo +stable build --release --target x86_64-unknown-linux-gnu
|
||||||
|
cargo +stable build --release --target x86_64-pc-windows-gnu
|
||||||
|
|
||||||
mv target/aarch64-apple-darwin/release/yazi yazi-aarch64-apple-darwin
|
mv target/aarch64-apple-darwin/release/yazi yazi-aarch64-apple-darwin
|
||||||
mv target/x86_64-apple-darwin/release/yazi yazi-x86_64-apple-darwin
|
mv target/x86_64-apple-darwin/release/yazi yazi-x86_64-apple-darwin
|
||||||
mv target/x86_64-unknown-linux-gnu/release/yazi yazi-x86_64-unknown-linux-gnu
|
mv target/x86_64-unknown-linux-gnu/release/yazi yazi-x86_64-unknown-linux-gnu
|
||||||
|
mv target/x86_64-pc-windows-gnu/release/yazi yazi-x86_64-pc-windows-gnu
|
||||||
|
|
||||||
zip -j yazi-aarch64-apple-darwin.zip yazi-aarch64-apple-darwin
|
zip -j yazi-aarch64-apple-darwin.zip yazi-aarch64-apple-darwin
|
||||||
zip -j yazi-x86_64-apple-darwin.zip yazi-x86_64-apple-darwin
|
zip -j yazi-x86_64-apple-darwin.zip yazi-x86_64-apple-darwin
|
||||||
zip -j yazi-x86_64-unknown-linux-gnu.zip yazi-x86_64-unknown-linux-gnu
|
zip -j yazi-x86_64-unknown-linux-gnu.zip yazi-x86_64-unknown-linux-gnu
|
||||||
|
zip -j yazi-x86_64-pc-windows-gnu.zip yazi-x86_64-pc-windows-gnu
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ shared = { path = "../shared" }
|
||||||
anyhow = "^1"
|
anyhow = "^1"
|
||||||
clap = { version = "^4", features = [ "derive" ] }
|
clap = { version = "^4", features = [ "derive" ] }
|
||||||
crossterm = "^0"
|
crossterm = "^0"
|
||||||
|
dirs = "^5"
|
||||||
futures = "^0"
|
futures = "^0"
|
||||||
glob = "^0"
|
glob = "^0"
|
||||||
indexmap = "^2"
|
indexmap = "^2"
|
||||||
|
|
@ -20,4 +21,3 @@ serde = { version = "^1", features = [ "derive" ] }
|
||||||
shell-words = "^1"
|
shell-words = "^1"
|
||||||
toml = { version = "^0", features = [ "preserve_order" ] }
|
toml = { version = "^0", features = [ "preserve_order" ] }
|
||||||
validator = { version = "^0", features = [ "derive" ] }
|
validator = { version = "^0", features = [ "derive" ] }
|
||||||
xdg = "^2"
|
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,11 @@
|
||||||
use std::{env, fs, os::unix::prelude::OsStrExt, path::{Path, PathBuf}, time::{self, SystemTime}};
|
use std::{env, fs, path::{Path, PathBuf}, time::{self, SystemTime}};
|
||||||
|
|
||||||
use clap::{command, Parser};
|
use clap::{command, Parser};
|
||||||
use md5::{Digest, Md5};
|
use md5::{Digest, Md5};
|
||||||
use shared::absolute_path;
|
use shared::absolute_path;
|
||||||
|
|
||||||
|
use crate::Xdg;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Boot {
|
pub struct Boot {
|
||||||
pub cwd: PathBuf,
|
pub cwd: PathBuf,
|
||||||
|
|
@ -63,9 +65,16 @@ impl Default for Boot {
|
||||||
impl Boot {
|
impl Boot {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn cache(&self, path: &Path) -> PathBuf {
|
pub fn cache(&self, path: &Path) -> PathBuf {
|
||||||
self
|
#[cfg(target_os = "windows")]
|
||||||
.cache_dir
|
let h = Md5::new_with_prefix(path.to_string_lossy().as_bytes());
|
||||||
.join(format!("{:x}", Md5::new_with_prefix(path.as_os_str().as_bytes()).finalize()))
|
|
||||||
|
#[cfg(not(target_os = "windows"))]
|
||||||
|
let h = {
|
||||||
|
use std::os::unix::ffi::OsStrExt;
|
||||||
|
Md5::new_with_prefix(path.as_os_str().as_bytes())
|
||||||
|
};
|
||||||
|
|
||||||
|
self.cache_dir.join(format!("{:x}", h.finalize()))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|
|
||||||
|
|
@ -1,23 +0,0 @@
|
||||||
use std::path::PathBuf;
|
|
||||||
|
|
||||||
#[cfg(target_os = "windows")]
|
|
||||||
pub(crate) fn get_config_file(path: &str) -> PathBuf { dirs::config_dir().unwrap().join(path) }
|
|
||||||
|
|
||||||
#[cfg(not(target_os = "windows"))]
|
|
||||||
pub(crate) fn get_config_file(path: &str) -> PathBuf {
|
|
||||||
xdg::BaseDirectories::new().unwrap().get_config_file(path)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(target_os = "windows")]
|
|
||||||
pub(crate) fn get_state_dir() -> Result<PathBuf, String> {
|
|
||||||
dirs::data_dir()
|
|
||||||
.map(|dir| dir.join("yazi").join("state"))
|
|
||||||
.ok_or_else(|| String::from("failed to get state directory"))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(not(target_os = "windows"))]
|
|
||||||
pub(crate) fn get_state_dir() -> Result<PathBuf, String> {
|
|
||||||
xdg::BaseDirectories::with_prefix("yazi")
|
|
||||||
.map(|dirs| dirs.get_state_home())
|
|
||||||
.map_err(|e| e.to_string())
|
|
||||||
}
|
|
||||||
|
|
@ -3,7 +3,6 @@
|
||||||
use shared::RoCell;
|
use shared::RoCell;
|
||||||
|
|
||||||
mod boot;
|
mod boot;
|
||||||
mod dir;
|
|
||||||
pub mod keymap;
|
pub mod keymap;
|
||||||
mod log;
|
mod log;
|
||||||
pub mod manager;
|
pub mod manager;
|
||||||
|
|
@ -14,9 +13,11 @@ pub mod preview;
|
||||||
pub mod tasks;
|
pub mod tasks;
|
||||||
pub mod theme;
|
pub mod theme;
|
||||||
mod validation;
|
mod validation;
|
||||||
|
mod xdg;
|
||||||
|
|
||||||
pub(crate) use pattern::*;
|
pub(crate) use pattern::*;
|
||||||
pub(crate) use preset::*;
|
pub(crate) use preset::*;
|
||||||
|
pub(crate) use xdg::*;
|
||||||
|
|
||||||
static MERGED_KEYMAP: RoCell<String> = RoCell::new();
|
static MERGED_KEYMAP: RoCell<String> = RoCell::new();
|
||||||
static MERGED_THEME: RoCell<String> = RoCell::new();
|
static MERGED_THEME: RoCell<String> = RoCell::new();
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
use std::fs;
|
use std::fs;
|
||||||
|
|
||||||
use toml::Table;
|
use toml::Table;
|
||||||
use xdg::BaseDirectories;
|
|
||||||
|
use crate::xdg::Xdg;
|
||||||
|
|
||||||
pub(crate) struct Preset;
|
pub(crate) struct Preset;
|
||||||
|
|
||||||
|
|
@ -28,7 +29,7 @@ impl Preset {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn merge_str(user: &str, base: &str) -> String {
|
fn merge_str(user: &str, base: &str) -> String {
|
||||||
let path = BaseDirectories::new().unwrap().get_config_file(user);
|
let path = Xdg::config_dir().unwrap().join(user);
|
||||||
let mut user = fs::read_to_string(path).unwrap_or_default().parse::<Table>().unwrap();
|
let mut user = fs::read_to_string(path).unwrap_or_default().parse::<Table>().unwrap();
|
||||||
|
|
||||||
let base = base.parse::<Table>().unwrap();
|
let base = base.parse::<Table>().unwrap();
|
||||||
|
|
@ -38,16 +39,16 @@ impl Preset {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub(crate) fn keymap() -> String {
|
pub(crate) fn keymap() -> String {
|
||||||
Self::merge_str("yazi/keymap.toml", include_str!("../preset/keymap.toml"))
|
Self::merge_str("keymap.toml", include_str!("../preset/keymap.toml"))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub(crate) fn theme() -> String {
|
pub(crate) fn theme() -> String {
|
||||||
Self::merge_str("yazi/theme.toml", include_str!("../preset/theme.toml"))
|
Self::merge_str("theme.toml", include_str!("../preset/theme.toml"))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub(crate) fn yazi() -> String {
|
pub(crate) fn yazi() -> String {
|
||||||
Self::merge_str("yazi/yazi.toml", include_str!("../preset/yazi.toml"))
|
Self::merge_str("yazi.toml", include_str!("../preset/yazi.toml"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
35
config/src/xdg.rs
Normal file
35
config/src/xdg.rs
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
pub(super) struct Xdg;
|
||||||
|
|
||||||
|
impl Xdg {
|
||||||
|
pub(super) fn config_dir() -> Option<PathBuf> {
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
{
|
||||||
|
dirs::config_dir().map(|p| p.join("yazi").join("config"))
|
||||||
|
}
|
||||||
|
#[cfg(not(target_os = "windows"))]
|
||||||
|
{
|
||||||
|
std::env::var_os("XDG_CONFIG_HOME")
|
||||||
|
.map(PathBuf::from)
|
||||||
|
.and_then(|p| p.is_absolute().then_some(p))
|
||||||
|
.or_else(|| dirs::home_dir().map(|h| h.join(".config")))
|
||||||
|
.map(|p| p.join("yazi"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) fn state_dir() -> Option<PathBuf> {
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
{
|
||||||
|
dirs::data_dir().map(|p| p.join("yazi").join("state"))
|
||||||
|
}
|
||||||
|
#[cfg(not(target_os = "windows"))]
|
||||||
|
{
|
||||||
|
std::env::var_os("XDG_STATE_HOME")
|
||||||
|
.map(PathBuf::from)
|
||||||
|
.and_then(|p| p.is_absolute().then_some(p))
|
||||||
|
.or_else(|| dirs::home_dir().map(|h| h.join(".local/state")))
|
||||||
|
.map(|p| p.join("yazi"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
use crossterm::terminal::size;
|
|
||||||
use indexmap::map::Slice;
|
use indexmap::map::Slice;
|
||||||
use ratatui::layout::Rect;
|
use ratatui::layout::Rect;
|
||||||
|
use shared::Term;
|
||||||
|
|
||||||
use super::{ALL_RATIO, CURRENT_RATIO, DIR_PADDING, PARENT_RATIO};
|
use super::{ALL_RATIO, CURRENT_RATIO, DIR_PADDING, PARENT_RATIO};
|
||||||
use crate::{emit, files::{File, Files, FilesOp}};
|
use crate::{emit, files::{File, Files, FilesOp}};
|
||||||
|
|
@ -27,7 +27,7 @@ impl Folder {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn limit() -> usize { size().unwrap_or_default().1.saturating_sub(DIR_PADDING) as usize }
|
pub fn limit() -> usize { Term::size().rows.saturating_sub(DIR_PADDING) as usize }
|
||||||
|
|
||||||
pub fn update(&mut self, op: FilesOp) -> bool {
|
pub fn update(&mut self, op: FilesOp) -> bool {
|
||||||
let b = match op {
|
let b = match op {
|
||||||
|
|
@ -183,12 +183,12 @@ impl Folder {
|
||||||
|
|
||||||
pub fn rect_current(&self, path: &Path) -> Option<Rect> {
|
pub fn rect_current(&self, path: &Path) -> Option<Rect> {
|
||||||
let pos = self.position(path)? - self.offset;
|
let pos = self.position(path)? - self.offset;
|
||||||
let s = size().unwrap_or_default();
|
let s = Term::size();
|
||||||
|
|
||||||
Some(Rect {
|
Some(Rect {
|
||||||
x: (s.0 as u32 * PARENT_RATIO / ALL_RATIO) as u16,
|
x: (s.columns as u32 * PARENT_RATIO / ALL_RATIO) as u16,
|
||||||
y: pos as u16,
|
y: pos as u16,
|
||||||
width: (s.0 as u32 * CURRENT_RATIO / ALL_RATIO) as u16,
|
width: (s.columns as u32 * CURRENT_RATIO / ALL_RATIO) as u16,
|
||||||
height: 1,
|
height: 1,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
use std::{collections::{BTreeMap, BTreeSet, HashMap, HashSet}, env, ffi::OsStr, io::{stdout, BufWriter, Write}, mem, os::unix::prelude::OsStrExt, path::{Path, PathBuf}};
|
use std::{collections::{BTreeMap, BTreeSet, HashMap, HashSet}, env, ffi::OsStr, io::{stdout, BufWriter, Write}, mem, path::{Path, PathBuf}};
|
||||||
|
|
||||||
use anyhow::{anyhow, bail, Error, Result};
|
use anyhow::{anyhow, bail, Error, Result};
|
||||||
use config::{open::Opener, BOOT, OPEN};
|
use config::{open::Opener, BOOT, OPEN};
|
||||||
|
|
@ -231,9 +231,17 @@ impl Manager {
|
||||||
};
|
};
|
||||||
|
|
||||||
{
|
{
|
||||||
let b = old.iter().map(|o| o.as_os_str()).collect::<Vec<_>>().join(OsStr::new("\n"));
|
let s = old.iter().map(|o| o.as_os_str()).collect::<Vec<_>>().join(OsStr::new("\n"));
|
||||||
let mut f = OpenOptions::new().write(true).create_new(true).open(&tmp).await?;
|
let mut f = OpenOptions::new().write(true).create_new(true).open(&tmp).await?;
|
||||||
f.write_all(b.as_bytes()).await?;
|
#[cfg(target_os = "windows")]
|
||||||
|
{
|
||||||
|
f.write_all(s.to_string_lossy().as_bytes()).await?;
|
||||||
|
}
|
||||||
|
#[cfg(not(target_os = "windows"))]
|
||||||
|
{
|
||||||
|
use std::os::unix::ffi::OsStrExt;
|
||||||
|
f.write_all(s.as_bytes()).await?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let _guard = BLOCKER.acquire().await.unwrap();
|
let _guard = BLOCKER.acquire().await.unwrap();
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ use adaptor::Adaptor;
|
||||||
use anyhow::{anyhow, bail, Result};
|
use anyhow::{anyhow, bail, Result};
|
||||||
use config::{BOOT, PREVIEW};
|
use config::{BOOT, PREVIEW};
|
||||||
use ratatui::prelude::Rect;
|
use ratatui::prelude::Rect;
|
||||||
use shared::{tty_size, MimeKind};
|
use shared::{MimeKind, Term};
|
||||||
use syntect::{easy::HighlightFile, util::as_24_bit_terminal_escaped};
|
use syntect::{easy::HighlightFile, util::as_24_bit_terminal_escaped};
|
||||||
use tokio::{fs, task::JoinHandle};
|
use tokio::{fs, task::JoinHandle};
|
||||||
|
|
||||||
|
|
@ -31,16 +31,16 @@ pub enum PreviewData {
|
||||||
|
|
||||||
impl Preview {
|
impl Preview {
|
||||||
fn rect() -> Rect {
|
fn rect() -> Rect {
|
||||||
let s = tty_size();
|
let s = Term::size();
|
||||||
|
|
||||||
let x = (s.ws_col as u32 * (PARENT_RATIO + CURRENT_RATIO) / ALL_RATIO) as u16;
|
let x = (s.columns as u32 * (PARENT_RATIO + CURRENT_RATIO) / ALL_RATIO) as u16;
|
||||||
let width = (s.ws_col as u32 * PREVIEW_RATIO / ALL_RATIO) as u16;
|
let width = (s.columns as u32 * PREVIEW_RATIO / ALL_RATIO) as u16;
|
||||||
|
|
||||||
Rect {
|
Rect {
|
||||||
x: x.saturating_add(PREVIEW_BORDER / 2),
|
x: x.saturating_add(PREVIEW_BORDER / 2),
|
||||||
y: PREVIEW_MARGIN / 2,
|
y: PREVIEW_MARGIN / 2,
|
||||||
width: width.saturating_sub(PREVIEW_BORDER),
|
width: width.saturating_sub(PREVIEW_BORDER),
|
||||||
height: s.ws_row.saturating_sub(PREVIEW_MARGIN),
|
height: s.rows.saturating_sub(PREVIEW_MARGIN),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ use std::{collections::{BTreeMap, HashMap, HashSet}, ffi::OsStr, io::{stdout, Wr
|
||||||
|
|
||||||
use config::{manager::SortBy, open::Opener, OPEN};
|
use config::{manager::SortBy, open::Opener, OPEN};
|
||||||
use crossterm::terminal::{disable_raw_mode, enable_raw_mode};
|
use crossterm::terminal::{disable_raw_mode, enable_raw_mode};
|
||||||
use shared::{tty_size, Defer, MimeKind, Term};
|
use shared::{Defer, MimeKind, Term};
|
||||||
use tokio::{io::{stdin, AsyncReadExt}, select, sync::mpsc, time};
|
use tokio::{io::{stdin, AsyncReadExt}, select, sync::mpsc, time};
|
||||||
use tracing::trace;
|
use tracing::trace;
|
||||||
|
|
||||||
|
|
@ -29,7 +29,7 @@ impl Tasks {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn limit() -> usize {
|
pub fn limit() -> usize {
|
||||||
(tty_size().ws_row * TASKS_PERCENT / 100).saturating_sub(TASKS_PADDING) as usize
|
(Term::size().rows * TASKS_PERCENT / 100).saturating_sub(TASKS_PADDING) as usize
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn toggle(&mut self) -> bool {
|
pub fn toggle(&mut self) -> bool {
|
||||||
|
|
|
||||||
|
|
@ -91,11 +91,8 @@ pub fn copy_with_progress(from: &Path, to: &Path) -> mpsc::Receiver<Result<u64,
|
||||||
rx
|
rx
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(target_os = "windows")]
|
|
||||||
pub fn file_mode(_: u32) -> String { String::new() }
|
|
||||||
|
|
||||||
#[cfg(not(target_os = "windows"))]
|
|
||||||
// Convert a file mode to a string representation
|
// Convert a file mode to a string representation
|
||||||
|
#[cfg(not(target_os = "windows"))]
|
||||||
#[allow(clippy::collapsible_else_if)]
|
#[allow(clippy::collapsible_else_if)]
|
||||||
pub fn file_mode(mode: u32) -> String {
|
pub fn file_mode(mode: u32) -> String {
|
||||||
use libc::{S_IFBLK, S_IFCHR, S_IFDIR, S_IFIFO, S_IFLNK, S_IFMT, S_IFSOCK, S_IRGRP, S_IROTH, S_IRUSR, S_ISGID, S_ISUID, S_ISVTX, S_IWGRP, S_IWOTH, S_IWUSR, S_IXGRP, S_IXOTH, S_IXUSR};
|
use libc::{S_IFBLK, S_IFCHR, S_IFDIR, S_IFIFO, S_IFLNK, S_IFMT, S_IFSOCK, S_IRGRP, S_IROTH, S_IRUSR, S_ISGID, S_ISUID, S_ISVTX, S_IWGRP, S_IWOTH, S_IWUSR, S_IXGRP, S_IXOTH, S_IXUSR};
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,6 @@ mod mime;
|
||||||
mod ro_cell;
|
mod ro_cell;
|
||||||
mod term;
|
mod term;
|
||||||
mod throttle;
|
mod throttle;
|
||||||
mod tty;
|
|
||||||
|
|
||||||
pub use buffer::*;
|
pub use buffer::*;
|
||||||
pub use chars::*;
|
pub use chars::*;
|
||||||
|
|
@ -18,4 +17,3 @@ pub use mime::*;
|
||||||
pub use ro_cell::*;
|
pub use ro_cell::*;
|
||||||
pub use term::*;
|
pub use term::*;
|
||||||
pub use throttle::*;
|
pub use throttle::*;
|
||||||
pub use tty::*;
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
use std::{io::{stdout, Stdout, Write}, ops::{Deref, DerefMut}};
|
use std::{io::{stdout, Stdout, Write}, ops::{Deref, DerefMut}};
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use crossterm::{cursor::{MoveTo, SetCursorStyle}, event::{DisableBracketedPaste, DisableFocusChange, EnableBracketedPaste, EnableFocusChange, KeyboardEnhancementFlags, PopKeyboardEnhancementFlags, PushKeyboardEnhancementFlags}, execute, queue, terminal::{disable_raw_mode, enable_raw_mode, supports_keyboard_enhancement, Clear, ClearType, EnterAlternateScreen, LeaveAlternateScreen}};
|
use crossterm::{cursor::{MoveTo, SetCursorStyle}, event::{DisableBracketedPaste, DisableFocusChange, EnableBracketedPaste, EnableFocusChange, KeyboardEnhancementFlags, PopKeyboardEnhancementFlags, PushKeyboardEnhancementFlags}, execute, queue, terminal::{disable_raw_mode, enable_raw_mode, supports_keyboard_enhancement, Clear, ClearType, EnterAlternateScreen, LeaveAlternateScreen, WindowSize}};
|
||||||
use ratatui::{backend::CrosstermBackend, Terminal};
|
use ratatui::{backend::CrosstermBackend, Terminal};
|
||||||
|
|
||||||
pub struct Term {
|
pub struct Term {
|
||||||
|
|
@ -32,6 +32,21 @@ impl Term {
|
||||||
Ok(term)
|
Ok(term)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn size() -> WindowSize {
|
||||||
|
if let Ok(s) = crossterm::terminal::window_size() {
|
||||||
|
return s;
|
||||||
|
};
|
||||||
|
// TODO
|
||||||
|
WindowSize { rows: 1, columns: 1, width: 0, height: 0 }
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn ratio() -> (f64, f64) {
|
||||||
|
let s = Self::size();
|
||||||
|
(f64::from(s.width) / f64::from(s.columns), f64::from(s.height) / f64::from(s.rows))
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn clear(stdout: &mut impl Write) -> Result<()> {
|
pub fn clear(stdout: &mut impl Write) -> Result<()> {
|
||||||
execute!(stdout, Clear(ClearType::All))?;
|
execute!(stdout, Clear(ClearType::All))?;
|
||||||
|
|
|
||||||
|
|
@ -1,10 +0,0 @@
|
||||||
use crossterm::terminal::window_size;
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn tty_ratio() -> (f64, f64) {
|
|
||||||
if let Ok(ws) = window_size() {
|
|
||||||
(f64::from(ws.width) / f64::from(ws.columns), f64::from(ws.height) / f64::from(ws.rows))
|
|
||||||
} else {
|
|
||||||
(1f64, 1f64)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Loading…
Add table
Reference in a new issue