feat: finish exec runner
This commit is contained in:
@@ -114,7 +114,7 @@ pub enum CliExtCommands {
|
|||||||
/// The scope where unlink file extension.
|
/// The scope where unlink file extension.
|
||||||
#[arg(short = 't', long = "target", value_name = "TARGET", required = true, value_enum, default_value_t = RegScope::User)]
|
#[arg(short = 't', long = "target", value_name = "TARGET", required = true, value_enum, default_value_t = RegScope::User)]
|
||||||
target: RegScope,
|
target: RegScope,
|
||||||
// The file extensions used for this operation. Specify * for all file extension.
|
// The file extensions (without leading dot) used for this operation. Specify * for all file extension.
|
||||||
#[arg(required = true, value_name = "EXTS", num_args = 1..)]
|
#[arg(required = true, value_name = "EXTS", num_args = 1..)]
|
||||||
exts: Vec<String>,
|
exts: Vec<String>,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
use crate::cli;
|
use crate::cli;
|
||||||
use crate::manifest;
|
use crate::manifest;
|
||||||
|
use comfy_table::Table;
|
||||||
|
use std::collections::{HashMap, HashSet};
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use thiserror::Error as TeError;
|
use thiserror::Error as TeError;
|
||||||
|
use toml;
|
||||||
|
|
||||||
// region: Error Handling
|
// region: Error Handling
|
||||||
|
|
||||||
@@ -20,6 +23,19 @@ pub enum Error {
|
|||||||
/// Error when operating Program.
|
/// Error when operating Program.
|
||||||
#[error("{0}")]
|
#[error("{0}")]
|
||||||
Program(#[from] wfassoc::highlevel::ProgramError),
|
Program(#[from] wfassoc::highlevel::ProgramError),
|
||||||
|
/// Error when serializing TOML
|
||||||
|
#[error("{0}")]
|
||||||
|
SerializeToml(#[from] toml::ser::Error),
|
||||||
|
|
||||||
|
/// Find duplicated name when converting extension name to index
|
||||||
|
#[error("given extension name {0} has been specified more than one time")]
|
||||||
|
DupExtName(String),
|
||||||
|
/// Find invalid name when converting extension name to index
|
||||||
|
#[error("given extension name {0} is not presented in application")]
|
||||||
|
BadExtName(String),
|
||||||
|
/// Find star (*) extension name with other extension names when converting extension name to index
|
||||||
|
#[error("given extension name {0} is not presented in application")]
|
||||||
|
ExclusiveStarExtName(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Result type used in this module.
|
/// Result type used in this module.
|
||||||
@@ -27,13 +43,38 @@ type Result<T> = std::result::Result<T, Error>;
|
|||||||
|
|
||||||
// endregion
|
// endregion
|
||||||
|
|
||||||
// region: Utilities Functions
|
// region: Utilities
|
||||||
|
|
||||||
fn stringified_exts_to_indices(
|
fn stringified_exts_to_indices(
|
||||||
program: &wfassoc::Program,
|
program: &wfassoc::Program,
|
||||||
exts: Vec<String>,
|
exts: Vec<String>,
|
||||||
) -> Result<Vec<usize>> {
|
) -> Result<Vec<usize>> {
|
||||||
todo!()
|
// Check for duplicate extension names
|
||||||
|
let mut seen = HashSet::new();
|
||||||
|
for ext in &exts {
|
||||||
|
if !seen.insert(ext.as_str()) {
|
||||||
|
return Err(Error::DupExtName(ext.clone()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for star (*) with other extensions
|
||||||
|
let has_star = exts.iter().any(|ext| ext == "*");
|
||||||
|
if has_star && exts.len() > 1 {
|
||||||
|
return Err(Error::ExclusiveStarExtName("*".to_string()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// If star is present alone, return fixed list from zero to the maximum ext index.
|
||||||
|
if has_star {
|
||||||
|
return Ok((0..program.get_ext_count()).collect());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert each extension name to index using program.find_ext()
|
||||||
|
let indices = exts
|
||||||
|
.into_iter()
|
||||||
|
.map(|ext| program.find_ext(&ext).ok_or(Error::BadExtName(ext)))
|
||||||
|
.collect::<Result<Vec<_>>>()?;
|
||||||
|
|
||||||
|
Ok(indices)
|
||||||
}
|
}
|
||||||
|
|
||||||
// endregion
|
// endregion
|
||||||
@@ -87,7 +128,31 @@ fn run_ext_list(
|
|||||||
view: wfassoc::View,
|
view: wfassoc::View,
|
||||||
style: cli::ExtListStyle,
|
style: cli::ExtListStyle,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
todo!()
|
// Fetch info
|
||||||
|
let mut ext_list: HashMap<String, Option<String>> = HashMap::new();
|
||||||
|
for index in 0..program.get_ext_count() {
|
||||||
|
let ext = program.get_ext(index)?;
|
||||||
|
let status = program.query_ext(view, index)?;
|
||||||
|
ext_list.insert(ext.dotted_inner(), status.map(|s| s.get_name().to_string()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output by styles
|
||||||
|
use cli::ExtListStyle;
|
||||||
|
match style {
|
||||||
|
ExtListStyle::Human => {
|
||||||
|
let mut table = Table::new();
|
||||||
|
table.set_header(["Extension", "Association"]);
|
||||||
|
for (k, v) in ext_list {
|
||||||
|
table.add_row([k, v.unwrap_or("".to_string())]);
|
||||||
|
}
|
||||||
|
println!("{table}");
|
||||||
|
}
|
||||||
|
ExtListStyle::Machine => {
|
||||||
|
let stoml = toml::to_string(&ext_list)?;
|
||||||
|
println!("{stoml}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
// endregion
|
// endregion
|
||||||
|
|||||||
@@ -246,6 +246,7 @@ pub struct Program {
|
|||||||
behaviors: Vec<Rc<ProgramBehavior>>,
|
behaviors: Vec<Rc<ProgramBehavior>>,
|
||||||
|
|
||||||
ext_keys: Vec<ProgramProgIdExtKey>,
|
ext_keys: Vec<ProgramProgIdExtKey>,
|
||||||
|
ext_keys_map: HashMap<String, usize>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TryFrom<Schema> for Program {
|
impl TryFrom<Schema> for Program {
|
||||||
@@ -386,7 +387,7 @@ impl Program {
|
|||||||
.map(|behavior| Self::resolve_index(&behavior, &behaviors, &behaviors_index_map))
|
.map(|behavior| Self::resolve_index(&behavior, &behaviors, &behaviors_index_map))
|
||||||
.transpose()?;
|
.transpose()?;
|
||||||
|
|
||||||
// We build ProgIdKey and ExtKey list at the same time
|
// We build ext keys
|
||||||
let mut ext_keys: Vec<ProgramProgIdExtKey> = Vec::with_capacity(schema.exts.len());
|
let mut ext_keys: Vec<ProgramProgIdExtKey> = Vec::with_capacity(schema.exts.len());
|
||||||
for (key, value) in &schema.exts {
|
for (key, value) in &schema.exts {
|
||||||
// Build ProgId first.
|
// Build ProgId first.
|
||||||
@@ -403,7 +404,7 @@ impl Program {
|
|||||||
let ext = concept::Ext::new(key.as_str())?;
|
let ext = concept::Ext::new(key.as_str())?;
|
||||||
let ext_key = lowlevel::ExtKey::new(ext);
|
let ext_key = lowlevel::ExtKey::new(ext);
|
||||||
|
|
||||||
// Create program Ext key struct
|
// Create program ProgId Ext key struct
|
||||||
let progid_ext_key = ProgramProgIdExtKey {
|
let progid_ext_key = ProgramProgIdExtKey {
|
||||||
ext_key,
|
ext_key,
|
||||||
progid_key,
|
progid_key,
|
||||||
@@ -415,6 +416,12 @@ impl Program {
|
|||||||
// Add them into list
|
// Add them into list
|
||||||
ext_keys.push(progid_ext_key);
|
ext_keys.push(progid_ext_key);
|
||||||
}
|
}
|
||||||
|
// The build ext keys map
|
||||||
|
let ext_keys_map = ext_keys
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.map(|(i, ext)| (ext.ext_key.inner().inner().to_string(), i))
|
||||||
|
.collect();
|
||||||
|
|
||||||
// Everything is okey
|
// Everything is okey
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
@@ -429,10 +436,39 @@ impl Program {
|
|||||||
icons,
|
icons,
|
||||||
behaviors,
|
behaviors,
|
||||||
ext_keys,
|
ext_keys,
|
||||||
|
ext_keys_map,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Program {
|
||||||
|
pub fn resolve_name(&self) -> Result<String, ProgramError> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn resolve_icon(&self) -> Result<concept::IconRc, ProgramError> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_ext_count(&self) -> usize {
|
||||||
|
self.ext_keys.len()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_ext(&self, index: usize) -> Result<&concept::Ext, ProgramError> {
|
||||||
|
match self.ext_keys.get(index) {
|
||||||
|
Some(program_key) => {
|
||||||
|
let ext_key = &program_key.ext_key;
|
||||||
|
Ok(ext_key.inner())
|
||||||
|
}
|
||||||
|
None => Err(ProgramError::BadIndex),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn find_ext(&self, body: &str) -> Option<usize> {
|
||||||
|
self.ext_keys_map.get(body).copied()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Program {
|
impl Program {
|
||||||
/// Register this application.
|
/// Register this application.
|
||||||
///
|
///
|
||||||
@@ -577,6 +613,11 @@ impl Program {
|
|||||||
Some(program_key) => {
|
Some(program_key) => {
|
||||||
let ext_key = &mut program_key.ext_key;
|
let ext_key = &mut program_key.ext_key;
|
||||||
let progid_key = &program_key.progid_key;
|
let progid_key = &program_key.progid_key;
|
||||||
|
debug_println!(
|
||||||
|
"Linking ProgId \"{0}\" to extension \"{1}\"subkey...",
|
||||||
|
progid_key.inner().to_string(),
|
||||||
|
ext_key.inner().to_string()
|
||||||
|
);
|
||||||
|
|
||||||
// Before setting it, we must make sure this extension is existing
|
// Before setting it, we must make sure this extension is existing
|
||||||
ext_key.ensure(scope)?;
|
ext_key.ensure(scope)?;
|
||||||
@@ -591,6 +632,10 @@ impl Program {
|
|||||||
match self.ext_keys.get_mut(index) {
|
match self.ext_keys.get_mut(index) {
|
||||||
Some(program_key) => {
|
Some(program_key) => {
|
||||||
let ext_key = &mut program_key.ext_key;
|
let ext_key = &mut program_key.ext_key;
|
||||||
|
debug_println!(
|
||||||
|
"Unlinking for extension \"{0}\"subkey...",
|
||||||
|
ext_key.inner().to_string()
|
||||||
|
);
|
||||||
|
|
||||||
// Before setting it, we must make sure this extension is existing
|
// Before setting it, we must make sure this extension is existing
|
||||||
ext_key.ensure(scope)?;
|
ext_key.ensure(scope)?;
|
||||||
@@ -609,6 +654,10 @@ impl Program {
|
|||||||
match self.ext_keys.get(index) {
|
match self.ext_keys.get(index) {
|
||||||
Some(program_key) => {
|
Some(program_key) => {
|
||||||
let ext_key = &program_key.ext_key;
|
let ext_key = &program_key.ext_key;
|
||||||
|
debug_println!(
|
||||||
|
"Querying for extension \"{0}\"subkey...",
|
||||||
|
ext_key.inner().to_string()
|
||||||
|
);
|
||||||
|
|
||||||
// If there is no such extension key, return None about this extension.
|
// If there is no such extension key, return None about this extension.
|
||||||
if !ext_key.is_exist(view)? {
|
if !ext_key.is_exist(view)? {
|
||||||
|
|||||||
Reference in New Issue
Block a user