feat(shell): add show_item_in_dir api

This commit is contained in:
amrbashir
2024-02-28 03:25:18 +02:00
parent dc6d3321e5
commit 5092683f97
31 changed files with 401 additions and 252 deletions
+9
View File
@@ -27,6 +27,15 @@ pub enum Error {
/// JSON error.
#[error(transparent)]
Json(#[from] serde_json::Error),
/// API not supported on the current platform
#[error("API not supported on the current platform")]
UnsupportedPlatform,
#[error(transparent)]
#[cfg(windows)]
Win32Error(#[from] windows::core::Error),
/// Path doesn't have a parent.
#[error("Path doesn't have a parent: {0}")]
NoParent(PathBuf),
}
impl Serialize for Error {
+4
View File
@@ -64,6 +64,10 @@ impl<R: Runtime> Shell<R> {
pub fn open(&self, path: impl Into<String>, with: Option<open::Program>) -> Result<()> {
open::open(&self.open_scope, path.into(), with).map_err(Into::into)
}
pub fn show_item_in_directory<P: AsRef<Path>>(&self, p: P) -> Result<()> {
open::show_item_in_directory(p)
}
}
pub trait ShellExt<R: Runtime> {
@@ -9,6 +9,22 @@ use serde::{Deserialize, Deserializer};
use crate::scope::OpenScope;
use std::str::FromStr;
#[cfg(windows)]
#[path = "windows.rs"]
mod platform;
#[cfg(target_os = "macos")]
#[path = "macos.rs"]
mod platform;
#[cfg(any(
target_os = "linux",
target_os = "dragonfly",
target_os = "freebsd",
target_os = "netbsd",
target_os = "openbsd"
))]
#[path = "linux.rs"]
mod platform;
/// Program to use on the [`open()`] call.
pub enum Program {
/// Use the `open` program.
@@ -120,3 +136,29 @@ impl Program {
pub fn open<P: AsRef<str>>(scope: &OpenScope, path: P, with: Option<Program>) -> crate::Result<()> {
scope.open(path.as_ref(), with).map_err(Into::into)
}
pub fn show_item_in_directory<P: AsRef<std::path::Path>>(p: P) -> crate::Result<()> {
let p = p.as_ref().canonicalize()?;
#[cfg(any(
windows,
target_os = "maco",
target_os = "linux",
target_os = "dragonfly",
target_os = "freebsd",
target_os = "netbsd",
target_os = "openbsd"
))]
return platform::show_item_in_directory(p);
#[cfg(not(any(
windows,
target_os = "maco",
target_os = "linux",
target_os = "dragonfly",
target_os = "freebsd",
target_os = "netbsd",
target_os = "openbsd"
)))]
Err(crate::Error::UnsupportedPlatform)
}
+51
View File
@@ -0,0 +1,51 @@
use std::{ffi::OsString, path::PathBuf};
use windows::{
core::{w, HSTRING, PCWSTR},
Win32::{
Foundation::{ERROR_FILE_NOT_FOUND, HWND},
System::Com::CoInitialize,
UI::{
Shell::{ILCreateFromPathW, ILFree, SHOpenFolderAndSelectItems, ShellExecuteW},
WindowsAndMessaging::SW_SHOW,
},
},
};
pub fn show_item_in_directory(file: PathBuf) -> crate::Result<()> {
let _ = unsafe { CoInitialize(None) };
let dir = file
.parent()
.ok_or_else(|| crate::Error::NoParent(file.clone()))?;
let dir = OsString::from(dir);
let dir = HSTRING::from(dir);
let dir_item = unsafe { ILCreateFromPathW(PCWSTR::from_raw(dir.as_ptr())) };
let file = OsString::from(file);
let file = HSTRING::from(file);
let file_item = unsafe { ILCreateFromPathW(PCWSTR::from_raw(file.as_ptr())) };
unsafe {
if let Err(e) = SHOpenFolderAndSelectItems(dir_item, Some(&[file_item]), 0) {
if e.code().0 == ERROR_FILE_NOT_FOUND.0 as i32 {
ShellExecuteW(
HWND::default(),
w!("open"),
PCWSTR::from_raw(dir.as_ptr()),
PCWSTR::null(),
PCWSTR::null(),
SW_SHOW,
);
}
}
}
unsafe {
ILFree(Some(dir_item));
ILFree(Some(file_item));
}
Ok(())
}