mirror of
https://github.com/sxyazi/yazi.git
synced 2026-07-25 08:41: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",
|
"ratatui",
|
||||||
"serde",
|
"serde",
|
||||||
"tokio",
|
"tokio",
|
||||||
|
"tracing",
|
||||||
"uzers",
|
"uzers",
|
||||||
"windows-sys 0.59.0",
|
"windows-sys 0.59.0",
|
||||||
"yazi-macro",
|
"yazi-macro",
|
||||||
|
|
|
||||||
|
|
@ -31,8 +31,11 @@ impl<'a> Runtime<'a> {
|
||||||
fn args(lua: &Lua) -> mlua::Result<Value> {
|
fn args(lua: &Lua) -> mlua::Result<Value> {
|
||||||
Composer::make(lua, 5, |lua, key| {
|
Composer::make(lua, 5, |lua, key| {
|
||||||
match 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"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),
|
_ => return Ok(Value::Nil),
|
||||||
}
|
}
|
||||||
.into_lua(lua)
|
.into_lua(lua)
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ pub fn compose(lua: &Lua) -> mlua::Result<Value> {
|
||||||
b"create" => create(lua)?,
|
b"create" => create(lua)?,
|
||||||
b"remove" => remove(lua)?,
|
b"remove" => remove(lua)?,
|
||||||
b"read_dir" => read_dir(lua)?,
|
b"read_dir" => read_dir(lua)?,
|
||||||
|
b"expand_url" => expand_url(lua)?,
|
||||||
b"unique_name" => unique_name(lua)?,
|
b"unique_name" => unique_name(lua)?,
|
||||||
b"partitions" => partitions(lua)?,
|
b"partitions" => partitions(lua)?,
|
||||||
_ => return Ok(Value::Nil),
|
_ => 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> {
|
fn unique_name(lua: &Lua) -> mlua::Result<Function> {
|
||||||
lua.create_async_function(|lua, url: UrlRef| async move {
|
lua.create_async_function(|lua, url: UrlRef| async move {
|
||||||
match yazi_fs::unique_name(url.clone(), async { false }).await {
|
match yazi_fs::unique_name(url.clone(), async { false }).await {
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ percent-encoding = "2.3.1"
|
||||||
ratatui = { workspace = true }
|
ratatui = { workspace = true }
|
||||||
serde = { workspace = true }
|
serde = { workspace = true }
|
||||||
tokio = { workspace = true }
|
tokio = { workspace = true }
|
||||||
|
tracing = { workspace = true }
|
||||||
|
|
||||||
[target."cfg(unix)".dependencies]
|
[target."cfg(unix)".dependencies]
|
||||||
libc = { workspace = true }
|
libc = { workspace = true }
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
use std::{io::{Error, ErrorKind, Read, Write}, time::Duration};
|
use std::{io::{Error, ErrorKind, Read, Write}, time::Duration};
|
||||||
|
|
||||||
|
use tracing::error;
|
||||||
|
|
||||||
pub struct Handle {
|
pub struct Handle {
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
inner: std::os::fd::RawFd,
|
inner: std::os::fd::RawFd,
|
||||||
|
|
@ -32,7 +34,7 @@ impl Read for Handle {
|
||||||
use std::os::{fd::IntoRawFd, unix::io::FromRawFd};
|
use std::os::{fd::IntoRawFd, unix::io::FromRawFd};
|
||||||
let mut f = unsafe { std::fs::File::from_raw_fd(self.inner) };
|
let mut f = unsafe { std::fs::File::from_raw_fd(self.inner) };
|
||||||
let result = f.read(buf);
|
let result = f.read(buf);
|
||||||
self.inner = f.into_raw_fd();
|
_ = f.into_raw_fd();
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
|
|
@ -40,7 +42,7 @@ impl Read for Handle {
|
||||||
use std::os::windows::io::{FromRawHandle, IntoRawHandle};
|
use std::os::windows::io::{FromRawHandle, IntoRawHandle};
|
||||||
let mut f = unsafe { std::fs::File::from_raw_handle(self.inner) };
|
let mut f = unsafe { std::fs::File::from_raw_handle(self.inner) };
|
||||||
let result = f.read(buf);
|
let result = f.read(buf);
|
||||||
self.inner = f.into_raw_handle();
|
_ = f.into_raw_handle();
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -75,18 +77,23 @@ impl Write for Handle {
|
||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
impl Handle {
|
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};
|
use std::{fs::OpenOptions, os::fd::IntoRawFd};
|
||||||
|
|
||||||
let fileno = if out { libc::STDOUT_FILENO } else { libc::STDIN_FILENO };
|
use libc::{STDIN_FILENO, STDOUT_FILENO};
|
||||||
Ok(if unsafe { libc::isatty(fileno) } == 1 {
|
|
||||||
Self { inner: fileno, close: false }
|
let resort = Self { inner: if out { STDOUT_FILENO } else { STDIN_FILENO }, close: false };
|
||||||
} else {
|
if unsafe { libc::isatty(resort.inner) } == 1 {
|
||||||
Self {
|
return resort;
|
||||||
inner: OpenOptions::new().read(!out).write(out).open("/dev/tty")?.into_raw_fd(),
|
}
|
||||||
close: true,
|
|
||||||
|
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> {
|
pub(super) fn poll(&mut self, timeout: Duration) -> std::io::Result<bool> {
|
||||||
|
|
@ -121,7 +128,9 @@ impl Handle {
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
impl Handle {
|
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};
|
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();
|
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 {
|
if result != INVALID_HANDLE_VALUE {
|
||||||
Err(std::io::Error::last_os_error())
|
return Self {
|
||||||
} else {
|
|
||||||
Ok(Self {
|
|
||||||
inner: result,
|
inner: result,
|
||||||
close: true,
|
close: true,
|
||||||
out_utf8: unsafe { GetConsoleOutputCP() } == CP_UTF8,
|
out_utf8: unsafe { GetConsoleOutputCP() } == CP_UTF8,
|
||||||
incomplete_utf8: Default::default(),
|
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 {
|
impl Default for Tty {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
let stdin = Handle::new(false).expect("failed to open stdin");
|
Self {
|
||||||
let stdout = Handle::new(true).expect("failed to open stdout");
|
stdin: Mutex::new(Handle::new(false)),
|
||||||
Self { stdin: Mutex::new(stdin), stdout: Mutex::new(BufWriter::new(stdout)) }
|
stdout: Mutex::new(BufWriter::new(Handle::new(true))),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue