diff options
author | Canop <cano.petrole@gmail.com> | 2020-11-17 20:31:34 +0100 |
---|---|---|
committer | Canop <cano.petrole@gmail.com> | 2020-11-17 20:31:34 +0100 |
commit | 985a31722419ea23b194091fc5feb129b79f5017 (patch) | |
tree | c1a8d92fdc538ef435ee706b8742add0584c7e00 /src/icon | |
parent | 3128dacc5c2066392a53f91718a7db438706b4c2 (diff) |
some code cleaning
Diffstat (limited to 'src/icon')
-rw-r--r-- | src/icon/icon_plugin.rs | 21 | ||||
-rw-r--r-- | src/icon/mod.rs | 14 | ||||
-rw-r--r-- | src/icon/vscode.rs | 144 |
3 files changed, 179 insertions, 0 deletions
diff --git a/src/icon/icon_plugin.rs b/src/icon/icon_plugin.rs new file mode 100644 index 0000000..0c46689 --- /dev/null +++ b/src/icon/icon_plugin.rs @@ -0,0 +1,21 @@ +use { + crate::tree::TreeLineType, +}; + +pub trait IconPlugin { + fn get_icon( + &self, + tree_line_type : &TreeLineType, + + // Use case: + // For files- use libmagic to get file type + // For directories: get list of files to get dir type + // Recommended to avoid for performance reasons. + full_path : &std::path::PathBuf, + name : &str, + double_ext : Option<&str>, + ext : Option<&str>, + ) -> char; +} + + diff --git a/src/icon/mod.rs b/src/icon/mod.rs new file mode 100644 index 0000000..2dc3353 --- /dev/null +++ b/src/icon/mod.rs @@ -0,0 +1,14 @@ + +mod icon_plugin; +mod vscode; + +pub use { + icon_plugin::IconPlugin, +}; + +pub fn icon_plugin(icon_set: &str) -> Option<Box<dyn IconPlugin + Send + Sync >> { + match icon_set { + "vscode" => Some(Box::new(vscode::VSCodeIconPlugin::new())), + _ => None + } +} diff --git a/src/icon/vscode.rs b/src/icon/vscode.rs new file mode 100644 index 0000000..2241bd1 --- /dev/null +++ b/src/icon/vscode.rs @@ -0,0 +1,144 @@ +use { + super::*, + crate::tree::TreeLineType, + std::collections::HashMap, +}; + +pub struct VSCodeIconPlugin { + icon_name_to_icon_codepoint_map: HashMap<&'static str, u32>, + file_name_to_icon_name_map: HashMap<&'static str, &'static str>, + double_extension_to_icon_name_map: HashMap<&'static str, &'static str>, + extension_to_icon_name_map: HashMap<&'static str, &'static str>, + default_icon_point: u32, +} + +impl VSCodeIconPlugin { + fn sanity_check( + part_to_icon_name_map: &HashMap<&str, &str>, + icon_name_to_icon_codepoint_map: &HashMap<&str, u32>, + ) { + let offending_entries = part_to_icon_name_map + .iter() + .map(|(_k, icon_name)| + (icon_name, icon_name_to_icon_codepoint_map.contains_key(icon_name)) + ) + // Find if any entry is not present + .filter(|(_entry, entry_present)| !entry_present) + .collect::<Vec<_>>(); + for oe in &offending_entries { + eprintln!("{} is not a valid icon name", oe.0); + } + if !offending_entries.is_empty() { + eprintln!("Terminating execution"); + std::process::exit(53); + } + } + + pub fn new() -> Self { + let icon_name_to_icon_codepoint_map: HashMap<&'static str, u32> + = ( include!( "../../resources/icons/vscode/data/icon_name_to_icon_code_point_map.rs" ) ).iter().cloned().collect(); + + let double_extension_to_icon_name_map: HashMap<&'static str, &'static str> + = ( include!( "../../resources/icons/vscode/data/double_extension_to_icon_name_map.rs" ) ).iter().cloned().collect(); + + let extension_to_icon_name_map: HashMap<&'static str, &'static str> + = ( include!( "../../resources/icons/vscode/data/extension_to_icon_name_map.rs" ) ).iter().cloned().collect(); + + let file_name_to_icon_name_map: HashMap<&'static str, &'static str> + = ( include!( "../../resources/icons/vscode/data/file_name_to_icon_name_map.rs" ) ).iter().cloned().collect(); + + #[cfg(debug_assertions)] + { + Self::sanity_check( &file_name_to_icon_name_map , &icon_name_to_icon_codepoint_map ); + Self::sanity_check( &double_extension_to_icon_name_map , &icon_name_to_icon_codepoint_map ); + Self::sanity_check( &extension_to_icon_name_map , &icon_name_to_icon_codepoint_map ); + } + + let default_icon_point = *icon_name_to_icon_codepoint_map.get("default_file").unwrap(); + Self { + icon_name_to_icon_codepoint_map, + file_name_to_icon_name_map, + double_extension_to_icon_name_map, + extension_to_icon_name_map, + default_icon_point, + } + } + + fn handle_single_extension( + &self, + ext: Option<String> + ) -> &'static str { + match ext { + None => "default_file", + Some(ref e) => { + match self.extension_to_icon_name_map.get(e as &str) { + None => "default_file", + Some(icon_name) => icon_name, + } + } + } + } + + fn handle_file( + &self, + name: &str, + double_ext: Option<String>, + ext: Option<String>, + ) -> &'static str { + match self.file_name_to_icon_name_map.get(name) { + Some(icon_name) => icon_name, + _ => self.handle_double_extension(double_ext, ext), + } + } + + fn handle_double_extension( + &self, + double_ext: Option<String>, + ext: Option<String>, + ) -> &'static str { + match double_ext { + None => self.handle_single_extension(ext), + Some(ref de) => { + match self.double_extension_to_icon_name_map.get(de as &str) { + None => self.handle_single_extension(ext), + Some(icon_name) => icon_name, + } + } + } + } +} + +impl IconPlugin for VSCodeIconPlugin { + fn get_icon( + &self, + tree_line_type: &TreeLineType, + _full_path: &std::path::PathBuf, + name: &str, + double_ext: Option<&str>, + ext: Option<&str>, + ) -> char { + let icon_name = match tree_line_type { + TreeLineType::Dir => "default_folder", + TreeLineType::SymLink{ .. } => "emoji_type_link", //bad but nothing better + TreeLineType::File => { + self.handle_file( + &name.to_ascii_lowercase(), + double_ext.map(|de| de.to_ascii_lowercase()), + ext.map(|e| e.to_ascii_lowercase()), + ) + }, + TreeLineType::Pruning => "file_type_kite", //irrelevant + _ => "default_file", + }; + + let entry_icon = unsafe { + std::char::from_u32_unchecked( + *self.icon_name_to_icon_codepoint_map + .get( icon_name ) + .unwrap_or(&self.default_icon_point) + ) + }; + + entry_icon + } +} |