ronantakizawa/codereview-bench huggingface dataset:
Repository: sxyazi/yazi
File: yazi-parser/src/mgr/hidden.rs (Rust)

Code before:
use mlua::{ExternalError, FromLua, IntoLua, Lua, Value};
use yazi_shared::event::CmdCow;

#[derive(Debug)]
pub struct HiddenOpt {
	pub state: Option<bool>,
}

impl From<CmdCow> for HiddenOpt {
	fn from(c: CmdCow) -> Self {
		let state = match c.first_str() {
			Some("show") => Some(true),
			Some("hide") => Some(false),
			_ => None,
		};

		Self { state }
	}
}

impl FromLua for HiddenOpt {
	fn from_lua(_: Value, _: &Lua) -> mlua::Result<Self> { Err("unsupported".into_lua_err()) }
}

impl IntoLua for HiddenOpt {
	fn into_lua(self, _: &Lua) -> mlua::Result<Value> { Err("unsupported".into_lua_err()) }
}


Review comment (suggestion):
[nitpick] This line is quite complex with chained operations. Consider breaking it down into multiple lines for better readability.
```suggestion
		let state = match c.first_str() {
			Some(s) => FromStr::from_str(s).transpose()?.unwrap_or_default(),
			None => HiddenOptState::default(),
		};
		Ok(Self { state })
```

Code after:
use std::str::FromStr;

use mlua::{ExternalError, FromLua, IntoLua, Lua, Value};
use serde::{Deserialize, Serialize};
use yazi_shared::event::CmdCow;

#[derive(Debug, Default)]
pub struct HiddenOpt {
	pub state: HiddenOptState,
}

impl TryFrom<CmdCow> for HiddenOpt {
	type Error = anyhow::Error;

	fn try_from(c: CmdCow) -> Result<Self, Self::Error> {
		Ok(Self { state: c.first_str().map(FromStr::from_str).transpose()?.unwrap_or_default() })
	}
}

impl FromLua for HiddenOpt {
	fn from_lua(_: Value, _: &Lua) -> mlua::Result<Self> { Err("unsupported".into_lua_err()) }
}

impl IntoLua for HiddenOpt {
	fn into_lua(self, _: &Lua) -> mlua::Result<Value> { Err("unsupported".into_lua_err()) }
}

// --- State
#[derive(Clone, Copy, Debug, Default, Deserialize, Eq, PartialEq, Serialize)]
#[serde(rename_all = "kebab-case")]
pub enum HiddenOptState {
	#[default]
	None,
	Show,
	Hide,
	Toggle,
}

impl FromStr for HiddenOptState {
	type Err = serde::de::value::Error;
Repository: sxyazi/yazi
File: yazi-binding/src/elements/renderable.rs (Rust)

Code before:
use std::any::TypeId;

use mlua::{AnyUserData, ExternalError};

use super::{Bar, Border, Clear, Gauge, Line, List, Table, Text};
use crate::{Error, elements::{Area, Rect}};

#[derive(Clone, Debug)]
pub enum Renderable {
	Line(Line),
	Text(Text),
	List(Box<List>),
	Bar(Bar),
	Clear(Clear),
	Border(Border),
	Gauge(Box<Gauge>),
	Table(Box<Table>),
}

impl Renderable {
	pub fn area(&self) -> Area {
		match self {
			Self::Line(line) => line.area,
			Self::Text(text) => text.area,
			Self::List(list) => list.area,
			Self::Bar(bar) => bar.area,
			Self::Clear(clear) => clear.area,
			Self::Border(border) => border.area,
			Self::Gauge(gauge) => gauge.area,
			Self::Table(table) => table.area,
		}

Review comment (suggestion):
The removed import `Rect` might still be needed elsewhere in the file. Verify that all usages of `Rect` have been properly addressed or replaced with `Area`.

Code after:
use std::any::TypeId;

use mlua::{AnyUserData, ExternalError};

use super::{Bar, Border, Clear, Gauge, Line, List, Table, Text};
use crate::{Error, elements::Area};

#[derive(Clone, Debug)]
pub enum Renderable {
	Line(Line),
	Text(Text),
	List(Box<List>),
	Bar(Bar),
	Clear(Clear),
	Border(Border),
	Gauge(Box<Gauge>),
	Table(Box<Table>),
}

impl Renderable {
	pub fn area(&self) -> Area {
		match self {
			Self::Line(line) => line.area,
			Self::Text(text) => text.area,
			Self::List(list) => list.area,
			Self::Bar(bar) => bar.area,
			Self::Clear(clear) => clear.area,
			Self::Border(border) => border.area,
			Self::Gauge(gauge) => gauge.area,
			Self::Table(table) => table.area,
		}
Repository: sxyazi/yazi
File: yazi-shared/src/url/cov.rs (Rust)

Code before:
}

impl<'a> UrlCov<'a> {
	#[inline]
	pub fn new(url: impl Into<Url<'a>>) -> Self { Self(url.into()) }
}

// --- Buf
#[derive(Clone, Debug, Deserialize, Eq, Serialize)]
pub struct UrlBufCov(pub UrlBuf);

impl Deref for UrlBufCov {
	type Target = UrlBuf;

	fn deref(&self) -> &Self::Target { &self.0 }
}

impl From<UrlBuf> for UrlBufCov {
	fn from(value: UrlBuf) -> Self { Self(value) }
}

impl From<&UrlCov<'_>> for UrlBufCov {
	fn from(value: &UrlCov<'_>) -> Self { Self(UrlBuf::from(&value.0)) }
}

impl From<UrlBufCov> for UrlBuf {
	fn from(value: UrlBufCov) -> Self { value.0 }
}

impl<'a> From<&'a UrlBufCov> for Url<'a> {
	fn from(value: &'a UrlBufCov) -> Self { value.0.as_url() }
}

impl Hash for UrlBufCov {
	fn hash<H: Hasher>(&self, state: &mut H) { self.as_url().hash(state) }
}

impl PartialEq for UrlBufCov {
	fn eq(&self, other: &Self) -> bool { self.covariant(other) }
}

impl PartialEq<UrlBuf> for UrlBufCov {
	fn eq(&self, other: &UrlBuf) -> bool { self.covariant(other) }
}

impl UrlBufCov {
	#[inline]
	pub fn as_url(&self) -> UrlCov<'_> { UrlCov::from(self) }

	#[inline]
	pub fn parent_url(&self) -> Option<UrlBufCov> { self.0.parent_url().map(UrlBufCov) }

Review comment (suggestion):
[nitpick] The new From implementation for UrlCow to UrlBufCov should be placed before the existing From implementation for &UrlCov to maintain consistent ordering of trait implementations.

Code after:
}

impl<'a> UrlCov<'a> {
	#[inline]
	pub fn new(url: impl Into<Url<'a>>) -> Self { Self(url.into()) }
}

// --- Buf
#[derive(Clone, Debug, Deserialize, Eq, Serialize)]
pub struct UrlBufCov(pub UrlBuf);

impl Deref for UrlBufCov {
	type Target = UrlBuf;

	fn deref(&self) -> &Self::Target { &self.0 }
}

impl From<UrlBuf> for UrlBufCov {
	fn from(value: UrlBuf) -> Self { Self(value) }
}

impl From<UrlBufCov> for UrlBuf {
	fn from(value: UrlBufCov) -> Self { value.0 }
}

impl From<UrlCow<'_>> for UrlBufCov {
	fn from(value: UrlCow<'_>) -> Self { Self(value.into_owned()) }
}

impl From<&UrlCov<'_>> for UrlBufCov {
	fn from(value: &UrlCov<'_>) -> Self { Self(UrlBuf::from(&value.0)) }
}

impl<'a> From<&'a UrlBufCov> for Url<'a> {
	fn from(value: &'a UrlBufCov) -> Self { value.0.as_url() }
}

impl Hash for UrlBufCov {
	fn hash<H: Hasher>(&self, state: &mut H) { self.as_url().hash(state) }
}

impl PartialEq for UrlBufCov {
	fn eq(&self, other: &Self) -> bool { self.covariant(other) }
}

impl PartialEq<UrlBuf> for UrlBufCov {
	fn eq(&self, other: &UrlBuf) -> bool { self.covariant(other) }
}

impl UrlBufCov {
	#[inline]
Repository: sxyazi/yazi
File: yazi-plugin/preset/plugins/mime.lua (Lua)

Code before:
local SUPPORTED_TYPES = "application/audio/biosig/chemical/font/image/inode/message/model/rinex/text/vector/video/x-epoc/"

local M = {}

local function match_mimetype(s)
	local type, sub = s:match("^([-a-z]+/)([+-.a-zA-Z0-9]+)%s*$")
	if type and sub and SUPPORTED_TYPES:find(type, 1, true)  then
		return type:gsub("^x%-", "", 1) .. sub:gsub("^x%-", "", 1):gsub("^vnd%.", "", 1)
	end
end

function M:fetch(job)
	local urls = {}
	for _, file in ipairs(job.files) do
		urls[#urls + 1] = tostring(file.url)
	end

	local cmd = os.getenv("YAZI_FILE_ONE") or "file"
	local child, err = Command(cmd):arg({ "-bL", "--mime-type", "--" }):arg(urls):stdout(Command.PIPED):spawn()
	if not child then
		return true, Err("Failed to start `%s`, error: %s", cmd, err)
	end

	local updates, last = {}, ya.time()
	local flush = function(force)
		if not force and ya.time() - last < 0.3 then
			return
		end
		if next(updates) then
			ya.emit("update_mimes", { updates = updates })
			updates, last = {}, ya.time()
		end
	end

Review comment (suggestion):
The pattern `%%s+$` expects one or more whitespace characters at the end, but the original pattern was `%s*$` (zero or more). This change could cause valid MIME types without trailing whitespace to not match.
```suggestion
		local typ, sub = s:match(string.format("(%s/)([+-.a-z0-9]+)%%s*$", pat))
```

Code after:
-- stylua: ignore
local TYPE_PATS = { "text", "image", "video", "application", "audio", "font", "inode", "message", "model", "vector", "biosig", "chemical", "rinex", "x%-epoc" }

local M = {}

local function match_mimetype(s)
	for _, pat in ipairs(TYPE_PATS) do
		local typ, sub = s:match(string.format("(%s/)([+-.a-z0-9]+)%%s+$", pat))
		if not sub then
		elseif s:find(typ .. sub, 1, true) == 1 then
			return typ:gsub("^x%-", "", 1) .. sub:gsub("^x%-", "", 1):gsub("^vnd%.", "", 1)
		else
			return nil, true
		end
	end
end

function M:fetch(job)
	local urls = {}
	for _, file in ipairs(job.files) do
		urls[#urls + 1] = tostring(file.url)
	end

	local cmd = os.getenv("YAZI_FILE_ONE") or "file"
	local child, err = Command(cmd):arg({ "-bL", "--mime-type", "--" }):arg(urls):stdout(Command.PIPED):spawn()
	if not child then
		return true, Err("Failed to start `%s`, error: %s", cmd, err)
	end

	local updates, last = {}, ya.time()
	local flush = function(force)
		if not force and ya.time() - last < 0.3 then
			return
Repository: sxyazi/yazi
File: yazi-plugin/preset/plugins/mime.lua (Lua)

Code before:
local SUPPORTED_TYPES = "application/audio/biosig/chemical/font/image/inode/message/model/rinex/text/vector/video/x-epoc/"

local M = {}

local function match_mimetype(s)
	local type, sub = s:match("^([-a-z]+/)([+-.a-zA-Z0-9]+)%s*$")
	if type and sub and SUPPORTED_TYPES:find(type, 1, true)  then
		return type:gsub("^x%-", "", 1) .. sub:gsub("^x%-", "", 1):gsub("^vnd%.", "", 1)
	end
end

function M:fetch(job)
	local urls = {}
	for _, file in ipairs(job.files) do
		urls[#urls + 1] = tostring(file.url)
	end

	local cmd = os.getenv("YAZI_FILE_ONE") or "file"
	local child, err = Command(cmd):arg({ "-bL", "--mime-type", "--" }):arg(urls):stdout(Command.PIPED):spawn()
	if not child then
		return true, Err("Failed to start `%s`, error: %s", cmd, err)
	end

	local updates, last = {}, ya.time()
	local flush = function(force)
		if not force and ya.time() - last < 0.3 then
			return
		end
		if next(updates) then
			ya.emit("update_mimes", { updates = updates })
			updates, last = {}, ya.time()
		end
	end

Review comment (bug):
The character class `[+-.a-z0-9]+` is missing uppercase letters that were present in the original pattern `[+-.a-zA-Z0-9]+`. This will cause MIME subtypes with uppercase letters to fail matching.
```suggestion
		local typ, sub = s:match(string.format("(%s/)([+-.a-zA-Z0-9]+)%%s+$", pat))
```

Code after:
-- stylua: ignore
local TYPE_PATS = { "text", "image", "video", "application", "audio", "font", "inode", "message", "model", "vector", "biosig", "chemical", "rinex", "x%-epoc" }

local M = {}

local function match_mimetype(s)
	for _, pat in ipairs(TYPE_PATS) do
		local typ, sub = s:match(string.format("(%s/)([+-.a-z0-9]+)%%s+$", pat))
		if not sub then
		elseif s:find(typ .. sub, 1, true) == 1 then
			return typ:gsub("^x%-", "", 1) .. sub:gsub("^x%-", "", 1):gsub("^vnd%.", "", 1)
		else
			return nil, true
		end
	end
end

function M:fetch(job)
	local urls = {}
	for _, file in ipairs(job.files) do
		urls[#urls + 1] = tostring(file.url)
	end

	local cmd = os.getenv("YAZI_FILE_ONE") or "file"
	local child, err = Command(cmd):arg({ "-bL", "--mime-type", "--" }):arg(urls):stdout(Command.PIPED):spawn()
	if not child then
		return true, Err("Failed to start `%s`, error: %s", cmd, err)
	end

	local updates, last = {}, ya.time()
	local flush = function(force)
		if not force and ya.time() - last < 0.3 then
			return
Repository: sxyazi/yazi
File: yazi-plugin/preset/plugins/mime.lua (Lua)

Code before:
local SUPPORTED_TYPES = "application/audio/biosig/chemical/font/image/inode/message/model/rinex/text/vector/video/x-epoc/"

local M = {}

local function match_mimetype(s)
	local type, sub = s:match("^([-a-z]+/)([+-.a-zA-Z0-9]+)%s*$")
	if type and sub and SUPPORTED_TYPES:find(type, 1, true)  then
		return type:gsub("^x%-", "", 1) .. sub:gsub("^x%-", "", 1):gsub("^vnd%.", "", 1)
	end
end

function M:fetch(job)
	local urls = {}
	for _, file in ipairs(job.files) do
		urls[#urls + 1] = tostring(file.url)
	end

	local cmd = os.getenv("YAZI_FILE_ONE") or "file"
	local child, err = Command(cmd):arg({ "-bL", "--mime-type", "--" }):arg(urls):stdout(Command.PIPED):spawn()
	if not child then
		return true, Err("Failed to start `%s`, error: %s", cmd, err)
	end

	local updates, last = {}, ya.time()
	local flush = function(force)
		if not force and ya.time() - last < 0.3 then
			return
		end
		if next(updates) then
			ya.emit("update_mimes", { updates = updates })
			updates, last = {}, ya.time()
		end
	end

	local i, valid, state = 1, nil, {}
	repeat
		local line, event = child:read_line_with { timeout = 300 }
		if event == 3 then

Review comment (suggestion):
This condition `s:find(typ .. sub, 1, true) == 1` will always be true if `typ` and `sub` were matched from the beginning of string `s`. The logic appears redundant and may indicate a copy-paste error.
```suggestion
		else
			return typ:gsub("^x%-", "", 1) .. sub:gsub("^x%-", "", 1):gsub("^vnd%.", "", 1)
```

Code after:
-- stylua: ignore
local TYPE_PATS = { "text", "image", "video", "application", "audio", "font", "inode", "message", "model", "vector", "biosig", "chemical", "rinex", "x%-epoc" }

local M = {}

local function match_mimetype(s)
	for _, pat in ipairs(TYPE_PATS) do
		local typ, sub = s:match(string.format("(%s/)([+-.a-z0-9]+)%%s+$", pat))
		if not sub then
		elseif s:find(typ .. sub, 1, true) == 1 then
			return typ:gsub("^x%-", "", 1) .. sub:gsub("^x%-", "", 1):gsub("^vnd%.", "", 1)
		else
			return nil, true
		end
	end
end

function M:fetch(job)
	local urls = {}
	for _, file in ipairs(job.files) do
		urls[#urls + 1] = tostring(file.url)
	end

	local cmd = os.getenv("YAZI_FILE_ONE") or "file"
	local child, err = Command(cmd):arg({ "-bL", "--mime-type", "--" }):arg(urls):stdout(Command.PIPED):spawn()
	if not child then
		return true, Err("Failed to start `%s`, error: %s", cmd, err)
	end

	local updates, last = {}, ya.time()
	local flush = function(force)
		if not force and ya.time() - last < 0.3 then
			return
		end
		if next(updates) then
			ya.emit("update_mimes", { updates = updates })
			updates, last = {}, ya.time()
		end
Repository: sxyazi/yazi
File: yazi-shared/src/pool/pool.rs (Rust)

Code before:
use core::hash::BuildHasher;
use std::marker::PhantomData;

use hashbrown::hash_map::RawEntryMut;

use crate::pool::{SYMBOLS, Symbol, SymbolPtr};

pub struct Pool<T: ?Sized> {
	_phantom: PhantomData<T>,
}

impl Pool<[u8]> {
	pub fn intern(value: &[u8]) -> Symbol<[u8]> {
		let hash = foldhash::fast::FixedState::default().hash_one(value);

		match SYMBOLS.lock().raw_entry_mut().from_key_hashed_nocheck(hash, value) {
			RawEntryMut::Occupied(mut oe) => {
				let (ptr, count) = oe.get_key_value_mut();

				*count += 1;
				Symbol::new(ptr.clone())
			}
			RawEntryMut::Vacant(ve) => {
				let boxed = value.to_vec().into_boxed_slice();
				let ptr = SymbolPtr::leaked(Box::leak(boxed));

				ve.insert_hashed_nocheck(hash, ptr.clone(), 1);
				Symbol::new(ptr)
			}
		}
	}
}

impl Pool<str> {
	pub fn intern(value: impl AsRef<str>) -> Symbol<str> {
		let symbol = Pool::<[u8]>::intern(value.as_ref().as_bytes());
		Symbol::new(symbol.into_ptr())
	}
}


Review comment (security):
Using `from_key_hashed_nocheck` bypasses hash verification. This could be vulnerable to hash collision attacks if the input is user-controlled. Consider using the safer `from_key_hashed` method unless performance is critical and input is trusted.
```suggestion
		match SYMBOLS.lock().raw_entry_mut().from_key_hashed(hash, value) {
```

Code after:
use std::marker::PhantomData;

use hashbrown::hash_map::RawEntryMut;

use crate::pool::{SYMBOLS, Symbol, SymbolPtr, compute_hash};

pub struct Pool<T: ?Sized> {
	_phantom: PhantomData<T>,
}

impl Pool<[u8]> {
	pub fn intern(value: &[u8]) -> Symbol<[u8]> {
		let hash = compute_hash(value);

		match SYMBOLS.lock().raw_entry_mut().from_key_hashed_nocheck(hash, value) {
			RawEntryMut::Occupied(mut oe) => {
				let (ptr, count) = oe.get_key_value_mut();

				*count += 1;
				Symbol::new(ptr.clone())
			}
			RawEntryMut::Vacant(ve) => {
				let boxed = value.to_vec().into_boxed_slice();
				let ptr = SymbolPtr::leaked(Box::leak(boxed));

				ve.insert_hashed_nocheck(hash, ptr.clone(), 1);
				Symbol::new(ptr)
			}
		}
	}
}

impl Pool<str> {
	pub fn intern(value: impl AsRef<str>) -> Symbol<str> {
		let symbol = Pool::<[u8]>::intern(value.as_ref().as_bytes());
		Symbol::new(symbol.into_ptr())
	}
}
Repository: sxyazi/yazi
File: yazi-shared/src/pool/pool.rs (Rust)

Code before:
use core::hash::BuildHasher;
use std::marker::PhantomData;

use hashbrown::hash_map::RawEntryMut;

use crate::pool::{SYMBOLS, Symbol, SymbolPtr};

pub struct Pool<T: ?Sized> {
	_phantom: PhantomData<T>,
}

impl Pool<[u8]> {
	pub fn intern(value: &[u8]) -> Symbol<[u8]> {
		let hash = foldhash::fast::FixedState::default().hash_one(value);

		match SYMBOLS.lock().raw_entry_mut().from_key_hashed_nocheck(hash, value) {
			RawEntryMut::Occupied(mut oe) => {
				let (ptr, count) = oe.get_key_value_mut();

				*count += 1;
				Symbol::new(ptr.clone())
			}
			RawEntryMut::Vacant(ve) => {
				let boxed = value.to_vec().into_boxed_slice();
				let ptr = SymbolPtr::leaked(Box::leak(boxed));

				ve.insert_hashed_nocheck(hash, ptr.clone(), 1);
				Symbol::new(ptr)
			}
		}
	}
}

impl Pool<str> {
	pub fn intern(value: impl AsRef<str>) -> Symbol<str> {
		let symbol = Pool::<[u8]>::intern(value.as_ref().as_bytes());
		Symbol::new(symbol.into_ptr())
	}
}


Review comment (security):
Using `insert_hashed_nocheck` bypasses hash verification. This could be vulnerable to hash collision attacks if the input is user-controlled. Consider using the safer `insert_hashed` method unless performance is critical and input is trusted.
```suggestion
				ve.insert_hashed(hash, ptr.clone(), 1);
```

Code after:
use std::marker::PhantomData;

use hashbrown::hash_map::RawEntryMut;

use crate::pool::{SYMBOLS, Symbol, SymbolPtr, compute_hash};

pub struct Pool<T: ?Sized> {
	_phantom: PhantomData<T>,
}

impl Pool<[u8]> {
	pub fn intern(value: &[u8]) -> Symbol<[u8]> {
		let hash = compute_hash(value);

		match SYMBOLS.lock().raw_entry_mut().from_key_hashed_nocheck(hash, value) {
			RawEntryMut::Occupied(mut oe) => {
				let (ptr, count) = oe.get_key_value_mut();

				*count += 1;
				Symbol::new(ptr.clone())
			}
			RawEntryMut::Vacant(ve) => {
				let boxed = value.to_vec().into_boxed_slice();
				let ptr = SymbolPtr::leaked(Box::leak(boxed));

				ve.insert_hashed_nocheck(hash, ptr.clone(), 1);
				Symbol::new(ptr)
			}
		}
	}
}

impl Pool<str> {
	pub fn intern(value: impl AsRef<str>) -> Symbol<str> {
		let symbol = Pool::<[u8]>::intern(value.as_ref().as_bytes());
		Symbol::new(symbol.into_ptr())
	}
}
Repository: sxyazi/yazi
File: yazi-cli/src/shared/shared.rs (Rust)

Code before:
pub async fn maybe_exists(path: impl AsRef<Path>) -> bool {
	match Local::symlink_metadata(path).await {
		Ok(_) => true,
		Err(e) => e.kind() != std::io::ErrorKind::NotFound,
	}
}

pub async fn copy_and_seal(from: &Path, to: &Path) -> io::Result<()> {
	let b = Local::read(from).await?;
	ok_or_not_found(remove_sealed(to).await)?;

	let mut file = Gate::default().create_new(true).write(true).truncate(true).open(to).await?;
	file.write_all(&b).await?;

	let mut perm = file.metadata().await?.permissions();
	perm.set_readonly(true);
	file.set_permissions(perm).await?;

	Ok(())
}

// TODO: use `yazi_fs` instead of `tokio::fs`
pub async fn remove_sealed(p: &Path) -> io::Result<()> {
	#[cfg(windows)]
	{
		let mut perm = tokio::fs::metadata(p).await?.permissions();
		perm.set_readonly(false);
		tokio::fs::set_permissions(p, perm).await?;
	}

	tokio::fs::remove_file(p).await
}


Review comment (security):
The change from `tokio::fs::metadata` to `Local::metadata` appears unrelated to the PR's purpose of refactoring `Url::pair()`. This change could break functionality if `Local` is not properly imported or doesn't have the same API.
```suggestion
		let mut perm = tokio::fs::metadata(p).await?.permissions();
```

Code after:
pub async fn maybe_exists(path: impl AsRef<Path>) -> bool {
	match Local::symlink_metadata(path).await {
		Ok(_) => true,
		Err(e) => e.kind() != std::io::ErrorKind::NotFound,
	}
}

pub async fn copy_and_seal(from: &Path, to: &Path) -> io::Result<()> {
	let b = Local::read(from).await?;
	ok_or_not_found(remove_sealed(to).await)?;

	let mut file = Gate::default().create_new(true).write(true).truncate(true).open(to).await?;
	file.write_all(&b).await?;

	let mut perm = file.metadata().await?.permissions();
	perm.set_readonly(true);
	file.set_permissions(perm).await?;

	Ok(())
}

// TODO: use `yazi_fs` instead of `tokio::fs`
pub async fn remove_sealed(p: &Path) -> io::Result<()> {
	#[cfg(windows)]
	{
		let mut perm = Local::metadata(p).await?.permissions();
		perm.set_readonly(false);
		tokio::fs::set_permissions(p, perm).await?;
	}

	Local::remove_file(p).await
}
Repository: sxyazi/yazi
File: yazi-cli/src/shared/shared.rs (Rust)

Code before:
}

pub async fn copy_and_seal(from: &Path, to: &Path) -> io::Result<()> {
	let b = Local::read(from).await?;
	ok_or_not_found(remove_sealed(to).await)?;

	let mut file = Gate::default().create_new(true).write(true).truncate(true).open(to).await?;
	file.write_all(&b).await?;

	let mut perm = file.metadata().await?.permissions();
	perm.set_readonly(true);
	file.set_permissions(perm).await?;

	Ok(())
}

// TODO: use `yazi_fs` instead of `tokio::fs`
pub async fn remove_sealed(p: &Path) -> io::Result<()> {
	#[cfg(windows)]
	{
		let mut perm = tokio::fs::metadata(p).await?.permissions();
		perm.set_readonly(false);
		tokio::fs::set_permissions(p, perm).await?;
	}

	tokio::fs::remove_file(p).await
}


Review comment (suggestion):
The change from `tokio::fs::remove_file` to `Local::remove_file` appears unrelated to the PR's purpose and could break functionality if `Local` doesn't provide the same API or isn't properly imported.
```suggestion
	tokio::fs::remove_file(p).await
```

Code after:
}

pub async fn copy_and_seal(from: &Path, to: &Path) -> io::Result<()> {
	let b = Local::read(from).await?;
	ok_or_not_found(remove_sealed(to).await)?;

	let mut file = Gate::default().create_new(true).write(true).truncate(true).open(to).await?;
	file.write_all(&b).await?;

	let mut perm = file.metadata().await?.permissions();
	perm.set_readonly(true);
	file.set_permissions(perm).await?;

	Ok(())
}

// TODO: use `yazi_fs` instead of `tokio::fs`
pub async fn remove_sealed(p: &Path) -> io::Result<()> {
	#[cfg(windows)]
	{
		let mut perm = Local::metadata(p).await?.permissions();
		perm.set_readonly(false);
		tokio::fs::set_permissions(p, perm).await?;
	}

	Local::remove_file(p).await
}
Repository: sxyazi/yazi
File: yazi-core/src/tasks/tasks.rs (Rust)

Code before:
					last = new;
					AppProxy::update_progress(new);
				}
			}
		});

		Self {
			scheduler: Arc::new(scheduler),
			handle,

			visible: false,
			cursor: 0,
			snaps: Default::default(),
			summary: Default::default(),
		}
	}

	pub fn shutdown(&self) {
		self.scheduler.shutdown();
		self.handle.abort();
	}

	pub fn limit() -> usize {
		(Dimension::available().rows * TASKS_PERCENT / 100).saturating_sub(TASKS_BORDER + TASKS_PADDING)
			as usize
	}

	pub fn paginate(&self) -> Vec<TaskSnap> {
		self.ongoing().lock().values().take(Self::limit()).map(Into::into).collect()
	}

	pub fn ongoing(&self) -> &Arc<Mutex<Ongoing>> { &self.scheduler.ongoing }
}


Review comment (suggestion):
The magic number `3` should be defined as a named constant to clarify that it represents the number of lines per task in the new layout. Consider adding `const LINES_PER_TASK: usize = 3;` and using it here.

Code after:
					last = new;
					AppProxy::update_progress(new);
				}
			}
		});

		Self {
			scheduler: Arc::new(scheduler),
			handle,

			visible: false,
			cursor: 0,
			snaps: Default::default(),
			summary: Default::default(),
		}
	}

	pub fn shutdown(&self) {
		self.scheduler.shutdown();
		self.handle.abort();
	}

	pub fn limit() -> usize {
		((Dimension::available().rows * TASKS_PERCENT / 100)
			.saturating_sub(TASKS_BORDER + TASKS_PADDING) as usize)
			/ 3
	}

	pub fn paginate(&self) -> Vec<TaskSnap> {
		self.ongoing().lock().values().take(Self::limit()).map(Into::into).collect()
	}

	pub fn ongoing(&self) -> &Arc<Mutex<Ongoing>> { &self.scheduler.ongoing }
}