fancy_tree/config/main/
mod.rs1use super::ConfigFile;
3use crate::color::ColorChoice;
4use crate::lua::interop;
5use crate::sorting;
6use crate::tree::Entry;
7use mlua::{
8 Either::{self, Left, Right},
9 FromLua, Lua,
10};
11use std::cmp::Ordering;
12use std::path::Path;
13
14type Sorting = Either<sorting::Sorting, mlua::Function>;
17
18#[derive(Debug)]
20pub struct Main {
21 color: ColorChoice,
23 skip: Option<mlua::Function>,
25 sorting: Sorting,
27 level: Option<usize>,
29}
30
31impl Main {
32 #[inline]
34 pub fn color_choice(&self) -> ColorChoice {
35 self.color
36 }
37 pub fn should_skip<P, F>(&self, entry: &Entry<P>, git_helper: F) -> bool
42 where
43 P: AsRef<Path>,
44 F: FnOnce() -> bool,
45 {
46 let default = entry.is_hidden() || git_helper();
47 let path = entry.path();
48 let attributes = interop::FileAttributes::from(entry);
49
50 self.skip
52 .as_ref()
53 .map_or(Ok(default), |f| f.call::<bool>((path, attributes, default)))
54 .unwrap_or(default)
55 }
56
57 pub fn cmp<L, R>(&self, left: L, right: R) -> Ordering
59 where
60 L: AsRef<Path>,
61 R: AsRef<Path>,
62 {
63 match self.sorting.as_ref() {
65 Left(sorting) => sorting.cmp(left, right),
66 Right(f) => f
67 .call((left.as_ref(), right.as_ref()))
68 .map(Self::isize_to_ordering)
69 .unwrap_or(Ordering::Equal),
70 }
71 }
72
73 fn default_sorting() -> Sorting {
75 Left(Default::default())
76 }
77
78 fn isize_to_ordering(n: isize) -> Ordering {
80 match n {
81 ..=-1 => Ordering::Less,
82 0 => Ordering::Equal,
83 1.. => Ordering::Greater,
84 }
85 }
86
87 pub fn level(&self) -> Option<usize> {
89 self.level
90 }
91}
92
93impl Default for Main {
94 fn default() -> Self {
95 Self {
96 color: Default::default(),
97 skip: None,
98 sorting: Self::default_sorting(),
99 level: None,
100 }
101 }
102}
103
104impl ConfigFile for Main {
105 const FILENAME: &'static str = "config.lua";
106 const DEFAULT_MODULE: &'static str = include_str!("./config.lua");
107}
108
109impl FromLua for Main {
110 fn from_lua(value: mlua::Value, _lua: &Lua) -> mlua::Result<Self> {
111 let type_name = value.type_name();
112
113 let conversion_error = || mlua::Error::FromLuaConversionError {
114 from: type_name,
115 to: String::from("config::Main"),
116 message: None,
117 };
118
119 let table = value.as_table().ok_or_else(conversion_error)?;
120 let color = table
121 .get::<Option<ColorChoice>>("color")?
122 .unwrap_or_default();
123 let skip: Option<mlua::Function> = table.get("skip")?;
124 let sorting = table
125 .get::<Option<Sorting>>("sorting")?
126 .unwrap_or_else(Self::default_sorting);
127 let level = table.get("level")?;
128 let main = Main {
129 color,
130 skip,
131 sorting,
132 level,
133 };
134 Ok(main)
135 }
136}
137
138#[cfg(test)]
139mod tests {
140 use super::*;
141 use rstest::rstest;
142
143 #[rstest]
144 #[case(-1, Ordering::Less)]
145 #[case(0, Ordering::Equal)]
146 #[case(1, Ordering::Greater)]
147 fn test_isize_to_ordering(#[case] n: isize, #[case] expected: Ordering) {
148 assert_eq!(expected, Main::isize_to_ordering(n));
149 }
150}