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
/// The scope where wfassoc will operate.
// region: Basic Types
/// The scope where wfassoc will register and unregister.
#[derive(Debug, Copy, Clone)]
pub enum Scope {
/// Scope for current user.
@ -37,6 +39,18 @@ pub enum Scope {
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.
///
/// It usually means that checking whether current process is running as Administrator.
@ -90,10 +104,13 @@ pub fn has_privilege() -> bool {
is_member != 0
}
// endregion
// region: File Extension
/// The struct representing an file extension which must start with dot (`.`)
/// and followed by at least one arbitrary characters.
#[derive(Debug, Clone)]
pub struct FileExt {
/// The body of file extension (excluding dot).
inner: String,
@ -110,14 +127,14 @@ impl FileExt {
}
}
pub fn query(&self, scope: Scope) -> Option<FileExtAssoc> {
FileExtAssoc::new(self, scope)
pub fn query(&self, view: View) -> Option<FileExtAssoc> {
FileExtAssoc::new(self, view)
}
}
/// The error occurs when try parsing string into FileExt.
#[derive(Debug, TeError)]
#[error("given file extension name is illegal")]
#[error("given file extension is illegal")]
pub struct ParseFileExtError {}
impl ParseFileExtError {
@ -141,31 +158,41 @@ impl FromStr for FileExt {
}
/// The association infomations of specific file extension.
#[derive(Debug)]
pub struct FileExtAssoc {
default: String,
open_with_progids: Vec<String>,
}
impl FileExtAssoc {
fn new(file_ext: &FileExt, scope: Scope) -> Option<Self> {
let hk = match scope {
Scope::User => winreg::RegKey::predef(winreg::enums::HKEY_CURRENT_USER),
Scope::System => winreg::RegKey::predef(winreg::enums::HKEY_LOCAL_MACHINE),
fn new(file_ext: &FileExt, view: View) -> Option<Self> {
use winreg::RegKey;
use winreg::enums::{HKEY_CLASSES_ROOT, HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE, KEY_READ};
// navigate to extension container
let hk = match view {
View::User => RegKey::predef(HKEY_CURRENT_USER),
View::System => RegKey::predef(HKEY_LOCAL_MACHINE),
View::Hybrid => RegKey::predef(HKEY_CLASSES_ROOT),
};
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 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", winreg::enums::KEY_READ)
{
progids.enum_keys().map(|x| x.unwrap()).collect()
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()
};

View File

@ -2,7 +2,7 @@ use clap::{Parser, Subcommand};
use comfy_table::Table;
use std::process;
use thiserror::Error as TeError;
use wfassoc::{Error as WfError, FileExt, Scope};
use wfassoc::{Error as WfError, FileExt, Scope, View};
// region: Basic Types
@ -95,31 +95,36 @@ fn run_query(cli: Cli) -> Result<()> {
".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()) {
if let Some(ext_assoc) = ext.query(Scope::User) {
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(), "", ""]);
if let Some(ext_assoc) = ext.query(View::Hybrid) {
println!("{:?}", ext_assoc)
}
}
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();
// program.query()?;