feat: prepare for Windows

This commit is contained in:
Pig Fang 2023-08-09 09:58:07 +08:00 committed by sxyazi
parent b70f83ced7
commit c96bee7715
No known key found for this signature in database
10 changed files with 67 additions and 28 deletions

View file

@ -14,9 +14,7 @@ ansi-to-tui = "^3"
anyhow = "^1"
crossterm = { version = "^0", features = [ "event-stream" ] }
futures = "^0"
libc = "^0"
ratatui = "^0"
signal-hook-tokio = { version = "^0", features = [ "futures-v0_3" ] }
tokio = { version = "^1", features = [ "parking_lot" ] }
unicode-width = "^0"
@ -25,6 +23,10 @@ tracing = "^0"
tracing-appender = "^0"
tracing-subscriber = "^0"
[target.'cfg(not(target_os = "windows"))'.dependencies]
libc = "^0"
signal-hook-tokio = { version = "^0", features = [ "futures-v0_3" ] }
[[bin]]
name = "yazi"
path = "src/main.rs"

View file

@ -1,5 +1,4 @@
use core::{emit, files::FilesOp, input::InputMode, Event};
use std::{ffi::OsString, os::unix::prelude::OsStrExt};
use anyhow::{Ok, Result};
use config::{keymap::{Control, Key, KeymapLayer}, BOOT};
@ -43,6 +42,7 @@ impl App {
fn dispatch_quit(&mut self) {
if let Some(p) = &BOOT.cwd_file {
use std::os::unix::prelude::OsStrExt;
let cwd = self.cx.manager.cwd().as_os_str();
std::fs::write(p, cwd.as_bytes()).ok();
}

View file

@ -1,9 +1,8 @@
use core::Event;
use anyhow::Result;
use crossterm::event::{Event as CrosstermEvent, EventStream};
use crossterm::event::{Event as CrosstermEvent, EventStream, KeyEvent, KeyEventKind};
use futures::StreamExt;
use libc::{SIGHUP, SIGINT, SIGQUIT, SIGTERM};
use tokio::{select, sync::{mpsc::{self, UnboundedReceiver, UnboundedSender}, oneshot}, task::JoinHandle};
pub(super) struct Signals {
@ -46,7 +45,13 @@ impl Signals {
}
}
#[cfg(target_os = "windows")]
fn spawn_system_task(&self) -> Result<()> { Ok(()) }
#[cfg(not(target_os = "windows"))]
fn spawn_system_task(&self) -> Result<JoinHandle<()>> {
use libc::{SIGHUP, SIGINT, SIGQUIT, SIGTERM};
let tx = self.tx.clone();
let mut signals = signal_hook_tokio::Signals::new([SIGHUP, SIGTERM, SIGINT, SIGQUIT])?;
@ -76,7 +81,9 @@ impl Signals {
_ = &mut stop_rx => break,
Some(Ok(event)) = reader.next() => {
let event = match event {
CrosstermEvent::Key(key) => Event::Key(key),
// We need to check key event kind;
// otherwise event will be dispatched twice.
CrosstermEvent::Key(key @ KeyEvent { kind: KeyEventKind::Press, .. }) => Event::Key(key),
CrosstermEvent::Paste(str) => Event::Paste(str),
CrosstermEvent::Resize(cols, rows) => Event::Resize(cols, rows),
_ => continue,

View file

@ -1,8 +1,5 @@
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::Ctx;
@ -70,8 +67,10 @@ impl Widget for Right<'_> {
let mut spans = vec![];
// Permissions
#[cfg(not(target_os = "windows"))]
if let Some(h) = &manager.hovered {
spans.extend(self.permissions(&file_mode(h.meta.permissions().mode())))
use std::os::unix::prelude::PermissionsExt;
spans.extend(self.permissions(&shared::file_mode(h.meta.permissions().mode())))
}
// Position

23
config/src/dir.rs Normal file
View file

@ -0,0 +1,23 @@
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())
}

View file

@ -3,6 +3,7 @@
use shared::RoCell;
mod boot;
mod dir;
pub mod keymap;
mod log;
pub mod manager;

View file

@ -1,8 +1,8 @@
use std::path::{Path, PathBuf};
use crossterm::terminal::size;
use indexmap::map::Slice;
use ratatui::layout::Rect;
use shared::tty_size;
use super::{ALL_RATIO, CURRENT_RATIO, DIR_PADDING, PARENT_RATIO};
use crate::{emit, files::{File, Files, FilesOp}};
@ -27,7 +27,7 @@ impl Folder {
}
#[inline]
pub fn limit() -> usize { tty_size().ws_row.saturating_sub(DIR_PADDING) as usize }
pub fn limit() -> usize { size().unwrap_or_default().1.saturating_sub(DIR_PADDING) as usize }
pub fn update(&mut self, op: FilesOp) -> bool {
let b = match op {
@ -183,12 +183,12 @@ impl Folder {
pub fn rect_current(&self, path: &Path) -> Option<Rect> {
let pos = self.position(path)? - self.offset;
let s = tty_size();
let s = size().unwrap_or_default();
Some(Rect {
x: (s.ws_col as u32 * PARENT_RATIO / ALL_RATIO) as u16,
x: (s.0 as u32 * PARENT_RATIO / ALL_RATIO) as u16,
y: pos as u16,
width: (s.ws_col as u32 * CURRENT_RATIO / ALL_RATIO) as u16,
width: (s.0 as u32 * CURRENT_RATIO / ALL_RATIO) as u16,
height: 1,
})
}

View file

@ -125,7 +125,16 @@ impl File {
match fs::remove_file(&task.to).await {
Err(e) if e.kind() != NotFound => Err(e)?,
_ => fs::symlink(src, &task.to).await?,
_ => {
#[cfg(target_os = "windows")]
{
fs::symlink_file(src, &task.to).await?
}
#[cfg(not(target_os = "windows"))]
{
fs::symlink(src, &task.to).await?
}
}
}
if task.cut {

View file

@ -91,6 +91,10 @@ pub fn copy_with_progress(from: &Path, to: &Path) -> mpsc::Receiver<Result<u64,
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
#[allow(clippy::collapsible_else_if)]
pub fn file_mode(mode: u32) -> String {

View file

@ -1,16 +1,10 @@
use libc::{ioctl, winsize, STDOUT_FILENO, TIOCGWINSZ};
#[inline]
pub fn tty_size() -> winsize {
unsafe {
let s: winsize = std::mem::zeroed();
ioctl(STDOUT_FILENO, TIOCGWINSZ, &s);
s
}
}
use crossterm::terminal::window_size;
#[inline]
pub fn tty_ratio() -> (f64, f64) {
let s = tty_size();
(f64::from(s.ws_xpixel) / f64::from(s.ws_col), f64::from(s.ws_ypixel) / f64::from(s.ws_row))
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)
}
}