mirror of
https://github.com/sxyazi/yazi.git
synced 2026-07-21 23:01:05 +00:00
feat: new fs.expand_url API (#2476)
This commit is contained in:
parent
faee35fc44
commit
abfbd1cd9f
6 changed files with 58 additions and 21 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
|
@ -3624,6 +3624,7 @@ dependencies = [
|
|||
"ratatui",
|
||||
"serde",
|
||||
"tokio",
|
||||
"tracing",
|
||||
"uzers",
|
||||
"windows-sys 0.59.0",
|
||||
"yazi-macro",
|
||||
|
|
|
|||
|
|
@ -31,8 +31,11 @@ impl<'a> Runtime<'a> {
|
|||
fn args(lua: &Lua) -> mlua::Result<Value> {
|
||||
Composer::make(lua, 5, |lua, key| {
|
||||
match key {
|
||||
b"chooser_file" => ARGS.chooser_file.as_ref().map(Url::from).into_lua(lua)?,
|
||||
b"entries" => {
|
||||
lua.create_sequence_from(ARGS.entries.iter().map(Url::from))?.into_lua(lua)?
|
||||
}
|
||||
b"cwd_file" => ARGS.cwd_file.as_ref().map(Url::from).into_lua(lua)?,
|
||||
b"chooser_file" => ARGS.chooser_file.as_ref().map(Url::from).into_lua(lua)?,
|
||||
_ => return Ok(Value::Nil),
|
||||
}
|
||||
.into_lua(lua)
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ pub fn compose(lua: &Lua) -> mlua::Result<Value> {
|
|||
b"create" => create(lua)?,
|
||||
b"remove" => remove(lua)?,
|
||||
b"read_dir" => read_dir(lua)?,
|
||||
b"expand_url" => expand_url(lua)?,
|
||||
b"unique_name" => unique_name(lua)?,
|
||||
b"partitions" => partitions(lua)?,
|
||||
_ => return Ok(Value::Nil),
|
||||
|
|
@ -150,6 +151,17 @@ fn read_dir(lua: &Lua) -> mlua::Result<Function> {
|
|||
})
|
||||
}
|
||||
|
||||
fn expand_url(lua: &Lua) -> mlua::Result<Function> {
|
||||
lua.create_function(|_, value: Value| {
|
||||
use yazi_fs::expand_path;
|
||||
Ok(Url::from(match value {
|
||||
Value::String(s) => expand_path(s.to_str()?.as_ref()),
|
||||
Value::UserData(ud) => expand_path(&*ud.borrow::<yazi_shared::url::Url>()?),
|
||||
_ => Err("must be a string or a Url".into_lua_err())?,
|
||||
}))
|
||||
})
|
||||
}
|
||||
|
||||
fn unique_name(lua: &Lua) -> mlua::Result<Function> {
|
||||
lua.create_async_function(|lua, url: UrlRef| async move {
|
||||
match yazi_fs::unique_name(url.clone(), async { false }).await {
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ percent-encoding = "2.3.1"
|
|||
ratatui = { workspace = true }
|
||||
serde = { workspace = true }
|
||||
tokio = { workspace = true }
|
||||
tracing = { workspace = true }
|
||||
|
||||
[target."cfg(unix)".dependencies]
|
||||
libc = { workspace = true }
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
use std::{io::{Error, ErrorKind, Read, Write}, time::Duration};
|
||||
|
||||
use tracing::error;
|
||||
|
||||
pub struct Handle {
|
||||
#[cfg(unix)]
|
||||
inner: std::os::fd::RawFd,
|
||||
|
|
@ -32,7 +34,7 @@ impl Read for Handle {
|
|||
use std::os::{fd::IntoRawFd, unix::io::FromRawFd};
|
||||
let mut f = unsafe { std::fs::File::from_raw_fd(self.inner) };
|
||||
let result = f.read(buf);
|
||||
self.inner = f.into_raw_fd();
|
||||
_ = f.into_raw_fd();
|
||||
result
|
||||
}
|
||||
#[cfg(windows)]
|
||||
|
|
@ -40,7 +42,7 @@ impl Read for Handle {
|
|||
use std::os::windows::io::{FromRawHandle, IntoRawHandle};
|
||||
let mut f = unsafe { std::fs::File::from_raw_handle(self.inner) };
|
||||
let result = f.read(buf);
|
||||
self.inner = f.into_raw_handle();
|
||||
_ = f.into_raw_handle();
|
||||
result
|
||||
}
|
||||
}
|
||||
|
|
@ -75,18 +77,23 @@ impl Write for Handle {
|
|||
|
||||
#[cfg(unix)]
|
||||
impl Handle {
|
||||
pub(super) fn new(out: bool) -> std::io::Result<Self> {
|
||||
pub(super) fn new(out: bool) -> Self {
|
||||
use std::{fs::OpenOptions, os::fd::IntoRawFd};
|
||||
|
||||
let fileno = if out { libc::STDOUT_FILENO } else { libc::STDIN_FILENO };
|
||||
Ok(if unsafe { libc::isatty(fileno) } == 1 {
|
||||
Self { inner: fileno, close: false }
|
||||
} else {
|
||||
Self {
|
||||
inner: OpenOptions::new().read(!out).write(out).open("/dev/tty")?.into_raw_fd(),
|
||||
close: true,
|
||||
use libc::{STDIN_FILENO, STDOUT_FILENO};
|
||||
|
||||
let resort = Self { inner: if out { STDOUT_FILENO } else { STDIN_FILENO }, close: false };
|
||||
if unsafe { libc::isatty(resort.inner) } == 1 {
|
||||
return resort;
|
||||
}
|
||||
|
||||
match OpenOptions::new().read(!out).write(out).open("/dev/tty") {
|
||||
Ok(f) => Self { inner: f.into_raw_fd(), close: true },
|
||||
Err(err) => {
|
||||
error!("Failed to open /dev/tty, falling back to stdin/stdout: {err}");
|
||||
resort
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn poll(&mut self, timeout: Duration) -> std::io::Result<bool> {
|
||||
|
|
@ -121,7 +128,9 @@ impl Handle {
|
|||
|
||||
#[cfg(windows)]
|
||||
impl Handle {
|
||||
pub(super) fn new(out: bool) -> std::io::Result<Self> {
|
||||
pub(super) fn new(out: bool) -> Self {
|
||||
use std::{io::{Error, stdin, stdout}, os::windows::io::AsRawHandle};
|
||||
|
||||
use windows_sys::Win32::{Foundation::{GENERIC_READ, GENERIC_WRITE, INVALID_HANDLE_VALUE}, Globalization::CP_UTF8, Storage::FileSystem::{CreateFileW, FILE_SHARE_READ, FILE_SHARE_WRITE, OPEN_EXISTING}, System::Console::GetConsoleOutputCP};
|
||||
|
||||
let name: Vec<u16> = if out { "CONOUT$\0" } else { "CONIN$\0" }.encode_utf16().collect();
|
||||
|
|
@ -137,15 +146,25 @@ impl Handle {
|
|||
)
|
||||
};
|
||||
|
||||
if result == INVALID_HANDLE_VALUE {
|
||||
Err(std::io::Error::last_os_error())
|
||||
} else {
|
||||
Ok(Self {
|
||||
if result != INVALID_HANDLE_VALUE {
|
||||
return Self {
|
||||
inner: result,
|
||||
close: true,
|
||||
out_utf8: unsafe { GetConsoleOutputCP() } == CP_UTF8,
|
||||
incomplete_utf8: Default::default(),
|
||||
})
|
||||
};
|
||||
}
|
||||
|
||||
error!(
|
||||
"Failed to open {}, falling back to stdin/stdout: {}",
|
||||
if out { "CONOUT$" } else { "CONIN$" },
|
||||
Error::last_os_error()
|
||||
);
|
||||
Self {
|
||||
inner: if out { stdout().as_raw_handle() } else { stdin().as_raw_handle() },
|
||||
close: false,
|
||||
out_utf8: unsafe { GetConsoleOutputCP() } == CP_UTF8,
|
||||
incomplete_utf8: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -11,9 +11,10 @@ pub struct Tty {
|
|||
|
||||
impl Default for Tty {
|
||||
fn default() -> Self {
|
||||
let stdin = Handle::new(false).expect("failed to open stdin");
|
||||
let stdout = Handle::new(true).expect("failed to open stdout");
|
||||
Self { stdin: Mutex::new(stdin), stdout: Mutex::new(BufWriter::new(stdout)) }
|
||||
Self {
|
||||
stdin: Mutex::new(Handle::new(false)),
|
||||
stdout: Mutex::new(BufWriter::new(Handle::new(true))),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue