1
0

write shit

This commit is contained in:
2025-10-09 16:07:23 +08:00
parent 2c8cb26ebf
commit 3f23d6b549
2 changed files with 78 additions and 46 deletions

View File

@ -28,7 +28,9 @@ pub enum Error {
// endregion // endregion
/// The scope where wfassoc will operate. // region: Basic Types
/// The scope where wfassoc will register and unregister.
#[derive(Debug, Copy, Clone)] #[derive(Debug, Copy, Clone)]
pub enum Scope { pub enum Scope {
/// Scope for current user. /// Scope for current user.
@ -37,6 +39,18 @@ pub enum Scope {
System, System,
} }
/// The view when wfassoc querying infomations.
#[derive(Debug, Copy, Clone)]
pub enum View {
/// The view of current user.
User,
/// The view of system.
System,
/// Hybrid view of User and System.
/// It can be seen as that we use System first and then use User to override any existing items.
Hybrid,
}
/// Check whether current process has administrative privilege. /// Check whether current process has administrative privilege.
/// ///
/// It usually means that checking whether current process is running as Administrator. /// It usually means that checking whether current process is running as Administrator.
@ -90,10 +104,13 @@ pub fn has_privilege() -> bool {
is_member != 0 is_member != 0
} }
// endregion
// region: File Extension // region: File Extension
/// The struct representing an file extension which must start with dot (`.`) /// The struct representing an file extension which must start with dot (`.`)
/// and followed by at least one arbitrary characters. /// and followed by at least one arbitrary characters.
#[derive(Debug, Clone)]
pub struct FileExt { pub struct FileExt {
/// The body of file extension (excluding dot). /// The body of file extension (excluding dot).
inner: String, inner: String,
@ -110,14 +127,14 @@ impl FileExt {
} }
} }
pub fn query(&self, scope: Scope) -> Option<FileExtAssoc> { pub fn query(&self, view: View) -> Option<FileExtAssoc> {
FileExtAssoc::new(self, scope) FileExtAssoc::new(self, view)
} }
} }
/// The error occurs when try parsing string into FileExt. /// The error occurs when try parsing string into FileExt.
#[derive(Debug, TeError)] #[derive(Debug, TeError)]
#[error("given file extension name is illegal")] #[error("given file extension is illegal")]
pub struct ParseFileExtError {} pub struct ParseFileExtError {}
impl ParseFileExtError { impl ParseFileExtError {
@ -141,34 +158,44 @@ impl FromStr for FileExt {
} }
/// The association infomations of specific file extension. /// The association infomations of specific file extension.
#[derive(Debug)]
pub struct FileExtAssoc { pub struct FileExtAssoc {
default: String, default: String,
open_with_progids: Vec<String>, open_with_progids: Vec<String>,
} }
impl FileExtAssoc { impl FileExtAssoc {
fn new(file_ext: &FileExt, scope: Scope) -> Option<Self> { fn new(file_ext: &FileExt, view: View) -> Option<Self> {
let hk = match scope { use winreg::RegKey;
Scope::User => winreg::RegKey::predef(winreg::enums::HKEY_CURRENT_USER), use winreg::enums::{HKEY_CLASSES_ROOT, HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE, KEY_READ};
Scope::System => winreg::RegKey::predef(winreg::enums::HKEY_LOCAL_MACHINE),
};
let classes = hk
.open_subkey_with_flags("Software\\Classes", winreg::enums::KEY_READ)
.unwrap();
let thisext =
match classes.open_subkey_with_flags(file_ext.to_string(), winreg::enums::KEY_READ) {
Ok(v) => v,
Err(e) => return None,
};
let default = thisext.get_value("").unwrap_or(String::new()); // navigate to extension container
let open_with_progids = if let Ok(progids) = let hk = match view {
thisext.open_subkey_with_flags("OpenWithProdIds", winreg::enums::KEY_READ) View::User => RegKey::predef(HKEY_CURRENT_USER),
{ View::System => RegKey::predef(HKEY_LOCAL_MACHINE),
progids.enum_keys().map(|x| x.unwrap()).collect() View::Hybrid => RegKey::predef(HKEY_CLASSES_ROOT),
} else {
Vec::new()
}; };
let classes = match view {
View::User | View::System => hk
.open_subkey_with_flags("Software\\Classes", KEY_READ)
.unwrap(),
View::Hybrid => hk.open_subkey_with_flags("", KEY_READ).unwrap(),
};
// open extension key if possible
let thisext = match classes.open_subkey_with_flags(file_ext.to_string(), KEY_READ) {
Ok(v) => v,
Err(_) => return None,
};
// fetch extension infos.
let default = thisext.get_value("").unwrap_or(String::new());
let open_with_progids =
if let Ok(progids) = thisext.open_subkey_with_flags("OpenWithProdIds", KEY_READ) {
progids.enum_keys().map(|x| x.unwrap()).filter(|k| !k.is_empty()).collect()
} else {
Vec::new()
};
Some(Self { Some(Self {
default, default,

View File

@ -2,7 +2,7 @@ use clap::{Parser, Subcommand};
use comfy_table::Table; use comfy_table::Table;
use std::process; use std::process;
use thiserror::Error as TeError; use thiserror::Error as TeError;
use wfassoc::{Error as WfError, FileExt, Scope}; use wfassoc::{Error as WfError, FileExt, Scope, View};
// region: Basic Types // region: Basic Types
@ -95,31 +95,36 @@ fn run_query(cli: Cli) -> Result<()> {
".kra", ".xcf", ".avif", ".qoi", ".apng", ".exr", ".kra", ".xcf", ".avif", ".qoi", ".apng", ".exr",
]; ];
let mut table = Table::new();
table.set_header(["Extension", "Default Open", "Open With"]);
for ext in exts.iter().map(|e| FileExt::new(e).unwrap()) { for ext in exts.iter().map(|e| FileExt::new(e).unwrap()) {
if let Some(ext_assoc) = ext.query(Scope::User) { if let Some(ext_assoc) = ext.query(View::Hybrid) {
if ext_assoc.len_open_with_progid() == 0 { println!("{:?}", ext_assoc)
table.add_row([ext.to_string().as_str(), ext_assoc.get_default(), ""]);
} else {
for (i, open_with_entry) in ext_assoc.iter_open_with_progids().enumerate() {
if i == 0 {
table.add_row([
ext.to_string().as_str(),
ext_assoc.get_default(),
open_with_entry,
]);
} else {
table.add_row(["", "", open_with_entry]);
}
}
}
} else {
table.add_row([ext.to_string().as_str(), "", ""]);
} }
} }
println!("{table}"); // let mut table = Table::new();
// table.set_header(["Extension", "Default Open", "Open With"]);
// for ext in exts.iter().map(|e| FileExt::new(e).unwrap()) {
// if let Some(ext_assoc) = ext.query(View::Hybrid) {
// if ext_assoc.len_open_with_progid() == 0 {
// table.add_row([ext.to_string().as_str(), ext_assoc.get_default(), ""]);
// } else {
// for (i, open_with_entry) in ext_assoc.iter_open_with_progids().enumerate() {
// if i == 0 {
// table.add_row([
// ext.to_string().as_str(),
// ext_assoc.get_default(),
// open_with_entry,
// ]);
// } else {
// table.add_row(["", "", open_with_entry]);
// }
// }
// }
// } else {
// table.add_row([ext.to_string().as_str(), "", ""]);
// }
// }
// println!("{table}");
// let program = Program::new(); // let program = Program::new();
// program.query()?; // program.query()?;