fancy_tree/config/icons/
mod.rs1use super::ConfigFile;
3use crate::lua::interop;
4use crate::tree::{
5 Entry,
6 entry::{Attributes, attributes::FileAttributes},
7};
8use mlua::{FromLua, Lua};
9use std::path::Path;
10
11#[derive(Debug, Default)]
13pub struct Icons {
14 get_icon: Option<mlua::Function>,
16}
17
18impl Icons {
19 const DEFAULT_FILE_ICON: &'static str = "\u{f0214}"; const DEFAULT_EXECUTABLE_ICON: &'static str = "\u{f070e}"; const DEFAULT_DIRECTORY_ICON: &'static str = "\u{f024b}"; const DEFAULT_SYMLINK_ICON: &'static str = "\u{cf481}"; const EMPTY_ICON: &'static str = " ";
30
31 pub fn get_icon<P>(&self, entry: &Entry<P>) -> String
36 where
37 P: AsRef<Path>,
38 {
39 let default_icon = Self::default_icon(entry);
41 self.get_icon
42 .as_ref()
43 .and_then(|f| {
44 let path = entry.path();
45 let attributes = interop::FileAttributes::from(entry);
46 f.call::<Option<String>>((path, attributes, default_icon))
48 .ok()
49 })
50 .unwrap_or_else(|| Some(String::from(default_icon)))
51 .unwrap_or_else(|| String::from(Self::EMPTY_ICON))
52 }
53
54 fn default_icon<P>(entry: &Entry<P>) -> &str
56 where
57 P: AsRef<Path>,
58 {
59 match entry.attributes() {
60 Attributes::Directory(_) => Self::DEFAULT_DIRECTORY_ICON,
61 Attributes::File(attributes) => Self::get_file_icon(attributes),
62 Attributes::Symlink(_) => Self::DEFAULT_SYMLINK_ICON,
63 }
64 }
65
66 fn get_file_icon(attributes: &FileAttributes) -> &'static str {
68 if attributes.is_executable() {
69 return Self::DEFAULT_EXECUTABLE_ICON;
70 }
71 attributes
72 .language()
73 .and_then(|language| language.nerd_font_glyph())
74 .unwrap_or(Self::DEFAULT_FILE_ICON)
75 }
76}
77
78impl ConfigFile for Icons {
79 const FILENAME: &'static str = "icons.lua";
80 const DEFAULT_MODULE: &'static str = include_str!("./icons.lua");
81}
82
83impl FromLua for Icons {
84 fn from_lua(value: mlua::Value, lua: &Lua) -> mlua::Result<Self> {
85 Option::<mlua::Function>::from_lua(value, lua).map(|get_icon| Self { get_icon })
86 }
87}