mirror of
https://github.com/sxyazi/yazi.git
synced 2024-12-01 10:17:47 +03:00
fix: can't display file name with invalid utf-8 (#529)
This commit is contained in:
parent
d41cd5684e
commit
e987855fca
@ -33,10 +33,10 @@ impl Manager {
|
||||
|
||||
let ext = url.extension();
|
||||
match by {
|
||||
"name" => ext.map_or_else(String::new, |s| format!(".{}", s.to_string_lossy().to_string())),
|
||||
"name" => ext.map_or_else(String::new, |s| format!(".{}", s.to_string_lossy().into_owned())),
|
||||
"ext" if ext.is_some() => format!("{}.", url.file_stem().unwrap().to_string_lossy()),
|
||||
"dot_ext" if ext.is_some() => url.file_stem().unwrap().to_string_lossy().to_string(),
|
||||
_ => url.file_name().map_or_else(String::new, |s| s.to_string_lossy().to_string()),
|
||||
"dot_ext" if ext.is_some() => url.file_stem().unwrap().to_string_lossy().into_owned(),
|
||||
_ => url.file_name().map_or_else(String::new, |s| s.to_string_lossy().into_owned()),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
use mlua::{Table, TableExt};
|
||||
use ratatui::{prelude::Buffer, widgets::Widget};
|
||||
use ratatui::{buffer::Buffer, widgets::Widget};
|
||||
use tracing::error;
|
||||
use yazi_plugin::{bindings::Cast, elements::{render_widgets, Rect}, LUA};
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
use mlua::{Table, TableExt};
|
||||
use ratatui::{prelude::Buffer, widgets::Widget};
|
||||
use ratatui::{buffer::Buffer, widgets::Widget};
|
||||
use tracing::error;
|
||||
use yazi_plugin::{bindings::Cast, elements::{render_widgets, Rect}, LUA};
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
use ratatui::{prelude::Buffer, widgets::Widget};
|
||||
use ratatui::{buffer::Buffer, widgets::Widget};
|
||||
|
||||
use crate::Ctx;
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
use ratatui::{layout::{self, Constraint}, prelude::{Buffer, Direction, Rect}, widgets::{List, ListItem, Widget}};
|
||||
use ratatui::{buffer::Buffer, layout::{self, Constraint, Direction, Rect}, widgets::{List, ListItem, Widget}};
|
||||
use yazi_config::THEME;
|
||||
|
||||
use crate::Ctx;
|
||||
|
@ -1,4 +1,4 @@
|
||||
use ratatui::{buffer::Buffer, layout::{self, Rect}, prelude::{Constraint, Direction}, widgets::{Paragraph, Widget}};
|
||||
use ratatui::{buffer::Buffer, layout::{self, Constraint, Direction, Rect}, widgets::{Paragraph, Widget}};
|
||||
use yazi_config::THEME;
|
||||
|
||||
use super::Bindings;
|
||||
|
@ -19,12 +19,14 @@ impl<'a, 'b> Tabs<'a, 'b> {
|
||||
|
||||
lua.register_userdata_type::<yazi_core::tab::Tab>(|reg| {
|
||||
reg.add_method("name", |lua, me, ()| {
|
||||
Some(lua.create_string(
|
||||
me.current.cwd.file_name().map_or_else(
|
||||
|| me.current.cwd.as_os_str().as_encoded_bytes(),
|
||||
|n| n.as_encoded_bytes(),
|
||||
Some(
|
||||
lua.create_string(
|
||||
me.current
|
||||
.cwd
|
||||
.file_name()
|
||||
.map_or(me.current.cwd.as_os_str().as_encoded_bytes(), |n| n.as_encoded_bytes()),
|
||||
),
|
||||
))
|
||||
)
|
||||
.transpose()
|
||||
});
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
use ratatui::{layout, prelude::{Buffer, Constraint, Direction, Rect}, widgets::{Block, Widget}};
|
||||
use ratatui::{buffer::Buffer, layout, layout::{Constraint, Direction, Rect}, widgets::{Block, Widget}};
|
||||
use yazi_config::THEME;
|
||||
|
||||
use super::Side;
|
||||
|
@ -1,4 +1,4 @@
|
||||
use ratatui::{prelude::{Buffer, Rect}, text::{Line, Span}, widgets::{Block, List, ListItem, Padding, Widget}};
|
||||
use ratatui::{buffer::Buffer, layout::Rect, text::{Line, Span}, widgets::{Block, List, ListItem, Padding, Widget}};
|
||||
use yazi_config::{keymap::Control, THEME};
|
||||
|
||||
pub(super) struct Side<'a> {
|
||||
|
@ -1,4 +1,4 @@
|
||||
use mlua::{prelude::LuaUserDataFields, FromLua, UserData};
|
||||
use mlua::{FromLua, UserData};
|
||||
use yazi_shared::term::Term;
|
||||
|
||||
#[derive(Debug, Clone, Copy, FromLua)]
|
||||
@ -17,7 +17,7 @@ impl Default for Window {
|
||||
}
|
||||
|
||||
impl UserData for Window {
|
||||
fn add_fields<'lua, F: LuaUserDataFields<'lua, Self>>(fields: &mut F) {
|
||||
fn add_fields<'lua, F: mlua::UserDataFields<'lua, Self>>(fields: &mut F) {
|
||||
fields.add_field_method_get("rows", |_, me| Ok(me.rows));
|
||||
fields.add_field_method_get("cols", |_, me| Ok(me.cols));
|
||||
fields.add_field_method_get("width", |_, me| Ok(me.width));
|
||||
|
@ -1,7 +1,7 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use anyhow::bail;
|
||||
use mlua::{prelude::{Lua, LuaResult}, AnyUserData, IntoLua, Value};
|
||||
use mlua::{AnyUserData, IntoLua, Lua, Value};
|
||||
use yazi_shared::OrderedFloat;
|
||||
|
||||
use crate::elements::Renderable;
|
||||
@ -59,7 +59,7 @@ impl<'a> TryFrom<Value<'a>> for ValueSendable {
|
||||
}
|
||||
|
||||
impl<'lua> IntoLua<'lua> for ValueSendable {
|
||||
fn into_lua(self, lua: &Lua) -> LuaResult<Value> {
|
||||
fn into_lua(self, lua: &Lua) -> mlua::Result<Value> {
|
||||
match self {
|
||||
ValueSendable::Nil => Ok(Value::Nil),
|
||||
ValueSendable::Boolean(b) => Ok(Value::Boolean(b)),
|
||||
@ -121,7 +121,7 @@ impl TryInto<ValueSendableKey> for ValueSendable {
|
||||
}
|
||||
|
||||
impl<'lua> IntoLua<'lua> for ValueSendableKey {
|
||||
fn into_lua(self, lua: &Lua) -> LuaResult<Value> {
|
||||
fn into_lua(self, lua: &Lua) -> mlua::Result<Value> {
|
||||
match self {
|
||||
ValueSendableKey::Nil => Ok(Value::Nil),
|
||||
ValueSendableKey::Boolean(b) => Ok(Value::Boolean(b)),
|
||||
|
@ -58,7 +58,7 @@ impl ListItem {
|
||||
return Ok(Self { content, style: None });
|
||||
}
|
||||
Value::String(s) => {
|
||||
return Ok(Self { content: s.to_str()?.to_string().into(), style: None });
|
||||
return Ok(Self { content: s.to_string_lossy().into_owned().into(), style: None });
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
@ -10,7 +10,9 @@ impl Span {
|
||||
pub fn install(lua: &Lua, ui: &Table) -> mlua::Result<()> {
|
||||
ui.set(
|
||||
"Span",
|
||||
lua.create_function(|_, content: String| Ok(Self(ratatui::text::Span::raw(content))))?,
|
||||
lua.create_function(|_, content: mlua::String| {
|
||||
Ok(Self(ratatui::text::Span::raw(content.to_string_lossy().into_owned())))
|
||||
})?,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
2
yazi-plugin/src/external/shell.rs
vendored
2
yazi-plugin/src/external/shell.rs
vendored
@ -54,7 +54,7 @@ pub fn shell(opt: ShellOpt) -> Result<Child> {
|
||||
|
||||
#[cfg(windows)]
|
||||
{
|
||||
let args: Vec<String> = opt.args.iter().map(|s| s.to_string_lossy().to_string()).collect();
|
||||
let args: Vec<String> = opt.args.iter().map(|s| s.to_string_lossy().into_owned()).collect();
|
||||
let args_: Vec<&str> = args.iter().map(|s| s.as_ref()).collect();
|
||||
let expanded = parser::parse(opt.cmd.to_string_lossy().as_ref(), &args_);
|
||||
Ok(
|
||||
|
@ -1,6 +1,6 @@
|
||||
use std::time::Duration;
|
||||
|
||||
use mlua::{prelude::LuaUserDataMethods, IntoLua, Table, UserData, Value};
|
||||
use mlua::{IntoLua, Table, UserData, Value};
|
||||
use tokio::{io::{AsyncBufReadExt, AsyncReadExt, BufReader}, process::{ChildStderr, ChildStdin, ChildStdout}, select};
|
||||
|
||||
use super::Status;
|
||||
@ -22,14 +22,12 @@ impl Child {
|
||||
}
|
||||
|
||||
impl UserData for Child {
|
||||
fn add_methods<'lua, M: LuaUserDataMethods<'lua, Self>>(methods: &mut M) {
|
||||
fn add_methods<'lua, M: mlua::UserDataMethods<'lua, Self>>(methods: &mut M) {
|
||||
#[inline]
|
||||
// TODO: return mlua::String instead of String
|
||||
async fn read_line(me: &mut Child) -> (String, u8) {
|
||||
async fn read(t: Option<impl AsyncBufReadExt + Unpin>) -> Option<String> {
|
||||
let Some(mut r) = t else {
|
||||
return None;
|
||||
};
|
||||
|
||||
let mut r = t?;
|
||||
let mut buf = String::new();
|
||||
match r.read_line(&mut buf).await {
|
||||
Ok(0) | Err(_) => None,
|
||||
@ -46,10 +44,7 @@ impl UserData for Child {
|
||||
|
||||
methods.add_async_method_mut("read", |_, me, len: usize| async move {
|
||||
async fn read(t: Option<impl AsyncBufReadExt + Unpin>, len: usize) -> Option<Vec<u8>> {
|
||||
let Some(mut r) = t else {
|
||||
return None;
|
||||
};
|
||||
|
||||
let mut r = t?;
|
||||
let mut buf = vec![0; len];
|
||||
match r.read(&mut buf).await {
|
||||
Ok(0) | Err(_) => return None,
|
||||
|
@ -1,6 +1,6 @@
|
||||
use std::process::Stdio;
|
||||
|
||||
use mlua::{prelude::LuaUserDataMethods, AnyUserData, IntoLua, Lua, Table, UserData, Value};
|
||||
use mlua::{AnyUserData, IntoLua, Lua, Table, UserData, Value};
|
||||
|
||||
use super::{output::Output, Child};
|
||||
|
||||
@ -35,19 +35,29 @@ impl Command {
|
||||
}
|
||||
|
||||
impl UserData for Command {
|
||||
fn add_methods<'lua, M: LuaUserDataMethods<'lua, Self>>(methods: &mut M) {
|
||||
methods.add_function("arg", |_, (ud, arg): (AnyUserData, String)| {
|
||||
ud.borrow_mut::<Self>()?.inner.arg(arg);
|
||||
fn add_methods<'lua, M: mlua::UserDataMethods<'lua, Self>>(methods: &mut M) {
|
||||
methods.add_function("arg", |_, (ud, arg): (AnyUserData, mlua::String)| {
|
||||
ud.borrow_mut::<Self>()?.inner.arg(arg.to_string_lossy().as_ref());
|
||||
Ok(ud)
|
||||
});
|
||||
methods.add_function("args", |_, (ud, args): (AnyUserData, Vec<String>)| {
|
||||
ud.borrow_mut::<Self>()?.inner.args(args);
|
||||
Ok(ud)
|
||||
});
|
||||
methods.add_function("env", |_, (ud, key, value): (AnyUserData, String, String)| {
|
||||
ud.borrow_mut::<Self>()?.inner.env(key, value);
|
||||
methods.add_function("args", |_, (ud, args): (AnyUserData, Vec<mlua::String>)| {
|
||||
{
|
||||
let mut me = ud.borrow_mut::<Self>()?;
|
||||
for arg in args {
|
||||
me.inner.arg(arg.to_string_lossy().as_ref());
|
||||
}
|
||||
}
|
||||
Ok(ud)
|
||||
});
|
||||
methods.add_function(
|
||||
"env",
|
||||
|_, (ud, key, value): (AnyUserData, mlua::String, mlua::String)| {
|
||||
ud.borrow_mut::<Self>()?
|
||||
.inner
|
||||
.env(key.to_string_lossy().as_ref(), value.to_string_lossy().as_ref());
|
||||
Ok(ud)
|
||||
},
|
||||
);
|
||||
methods.add_function("stdin", |_, (ud, stdio): (AnyUserData, u8)| {
|
||||
ud.borrow_mut::<Self>()?.inner.stdin(match stdio {
|
||||
PIPED => Stdio::piped(),
|
||||
|
@ -1,4 +1,4 @@
|
||||
use mlua::{prelude::LuaUserDataFields, UserData};
|
||||
use mlua::UserData;
|
||||
|
||||
use super::Status;
|
||||
|
||||
@ -11,7 +11,7 @@ impl Output {
|
||||
}
|
||||
|
||||
impl UserData for Output {
|
||||
fn add_fields<'lua, F: LuaUserDataFields<'lua, Self>>(fields: &mut F) {
|
||||
fn add_fields<'lua, F: mlua::UserDataFields<'lua, Self>>(fields: &mut F) {
|
||||
fields.add_field_method_get("status", |_, me| Ok(Status::new(me.inner.status)));
|
||||
fields.add_field_method_get("stdout", |lua, me| lua.create_string(&me.inner.stdout));
|
||||
fields.add_field_method_get("stderr", |lua, me| lua.create_string(&me.inner.stderr));
|
||||
|
@ -9,7 +9,7 @@ impl Status {
|
||||
}
|
||||
|
||||
impl UserData for Status {
|
||||
fn add_methods<'lua, M: mlua::prelude::LuaUserDataMethods<'lua, Self>>(methods: &mut M) {
|
||||
fn add_methods<'lua, M: mlua::UserDataMethods<'lua, Self>>(methods: &mut M) {
|
||||
methods.add_method("success", |_, me, ()| Ok(me.inner.success()));
|
||||
methods.add_method("code", |_, me, ()| Ok(me.inner.code()));
|
||||
}
|
||||
|
@ -17,10 +17,10 @@ impl Utils {
|
||||
|
||||
match k {
|
||||
Value::Integer(_) => {
|
||||
args.push(v.to_str()?.to_owned());
|
||||
args.push(v.to_string_lossy().into_owned());
|
||||
}
|
||||
Value::String(s) => {
|
||||
named.insert(s.to_str()?.replace('_', "-"), v.to_str()?.to_owned());
|
||||
named.insert(s.to_str()?.replace('_', "-"), v.to_string_lossy().into_owned());
|
||||
}
|
||||
_ => return Err("invalid key in exec".into_lua_err()),
|
||||
}
|
||||
|
@ -10,17 +10,18 @@ impl Utils {
|
||||
pub(super) fn text(lua: &Lua, ya: &Table) -> mlua::Result<()> {
|
||||
ya.set(
|
||||
"truncate",
|
||||
lua.create_function(|_, (text, max): (String, usize)| {
|
||||
lua.create_function(|_, (text, max): (mlua::String, usize)| {
|
||||
let mut width = 0;
|
||||
let flow = text.chars().try_fold(String::with_capacity(max), |mut s, c| {
|
||||
width += c.width().unwrap_or(0);
|
||||
if s.width() < max {
|
||||
s.push(c);
|
||||
ControlFlow::Continue(s)
|
||||
} else {
|
||||
ControlFlow::Break(s)
|
||||
}
|
||||
});
|
||||
let flow =
|
||||
text.to_string_lossy().chars().try_fold(String::with_capacity(max), |mut s, c| {
|
||||
width += c.width().unwrap_or(0);
|
||||
if s.width() < max {
|
||||
s.push(c);
|
||||
ControlFlow::Continue(s)
|
||||
} else {
|
||||
ControlFlow::Break(s)
|
||||
}
|
||||
});
|
||||
|
||||
Ok(match flow {
|
||||
ControlFlow::Break(s) => s,
|
||||
@ -29,7 +30,10 @@ impl Utils {
|
||||
})?,
|
||||
)?;
|
||||
|
||||
ya.set("mime_valid", lua.create_function(|_, mime: String| Ok(mime_valid(&mime)))?)?;
|
||||
ya.set(
|
||||
"mime_valid",
|
||||
lua.create_function(|_, mime: mlua::String| Ok(mime_valid(mime.as_bytes())))?,
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -98,7 +98,7 @@ impl AsRef<OsStr> for Url {
|
||||
impl ToString for Url {
|
||||
fn to_string(&self) -> String {
|
||||
if self.scheme == UrlScheme::Regular {
|
||||
return self.path.to_string_lossy().to_string();
|
||||
return self.path.to_string_lossy().into_owned();
|
||||
}
|
||||
|
||||
let scheme = match self.scheme {
|
||||
|
@ -1,23 +1,23 @@
|
||||
pub const MIME_DIR: &str = "inode/directory";
|
||||
|
||||
pub fn mime_valid(s: &str) -> bool {
|
||||
let parts = s.split('/').collect::<Vec<_>>();
|
||||
pub fn mime_valid(b: &[u8]) -> bool {
|
||||
let parts = b.split(|&b| b == b'/').collect::<Vec<_>>();
|
||||
if parts.len() != 2 || parts[1].is_empty() {
|
||||
return false;
|
||||
}
|
||||
|
||||
matches!(
|
||||
parts[0],
|
||||
"application"
|
||||
| "audio"
|
||||
| "example"
|
||||
| "font"
|
||||
| "image"
|
||||
| "inode"
|
||||
| "message"
|
||||
| "model"
|
||||
| "multipart"
|
||||
| "text"
|
||||
| "video"
|
||||
b"application"
|
||||
| b"audio"
|
||||
| b"example"
|
||||
| b"font"
|
||||
| b"image"
|
||||
| b"inode"
|
||||
| b"message"
|
||||
| b"model"
|
||||
| b"multipart"
|
||||
| b"text"
|
||||
| b"video"
|
||||
)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user