summaryrefslogtreecommitdiffstats
path: root/src/icon
diff options
context:
space:
mode:
authorCanop <cano.petrole@gmail.com>2020-11-17 20:31:34 +0100
committerCanop <cano.petrole@gmail.com>2020-11-17 20:31:34 +0100
commit985a31722419ea23b194091fc5feb129b79f5017 (patch)
treec1a8d92fdc538ef435ee706b8742add0584c7e00 /src/icon
parent3128dacc5c2066392a53f91718a7db438706b4c2 (diff)
some code cleaning
Diffstat (limited to 'src/icon')
-rw-r--r--src/icon/icon_plugin.rs21
-rw-r--r--src/icon/mod.rs14
-rw-r--r--src/icon/vscode.rs144
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
+ }
+}