1pub extern crate glob;
2pub extern crate regex;
3pub extern crate tempfile;
4pub extern crate unicode_names2;
5
6#[cfg(feature = "ron_deser")]
7pub extern crate ron;
8
9#[cfg(feature = "dag")]
10pub extern crate daggy;
11
12#[cfg(feature = "ldap")]
13pub extern crate ldap3;
14
15#[cfg(feature = "image_processing")]
16pub extern crate image;
17
18#[cfg(feature = "file_dialog")]
19pub extern crate rfd;
20
21#[cfg(feature = "grapheme")]
22pub extern crate unicode_segmentation;
23
24pub mod app_root_dir;
25mod base;
26pub mod clipboard;
27pub mod datetime;
28pub mod finder;
29pub mod text;
31pub mod uploader;
32pub mod version;
33
34#[cfg(feature = "dag")]
35pub mod dag;
36
37#[cfg(feature = "file_dialog")]
38pub mod dialog;
39
40#[cfg(feature = "p4")]
41pub mod perforce;
42
43#[cfg(feature = "git")]
44pub mod git_cmd;
45
46#[cfg(feature = "html")]
47pub mod html_scraping;
48
49#[cfg(feature = "image_processing")]
50pub mod img_processing;
51
52#[cfg(feature = "ldap")]
53pub mod ldap;
54
55#[cfg(feature = "python")]
56pub mod py;
57
58#[cfg(feature = "sound")]
59pub mod sound;
60
61#[cfg(feature = "notify")]
62pub mod notify;
63
64#[cfg(feature = "grapheme")]
65pub mod grapheme;
66
67#[cfg(feature = "web_client")]
68pub mod web;
69
70pub use base::*;
71pub use uploader::{CopyOp, FileCopySpec, TemplateFile};
72
73use anyhow::{anyhow, Result as AnyResult};
74
75#[cfg(feature = "fern_log")]
76use fern::colors::{Color, ColoredLevelConfig};
77
78pub use log::{debug, error, info, warn};
79use serde::Deserialize;
80use std::{
81 collections::BTreeSet,
82 path::{Path, PathBuf},
83};
84
85pub type ResultInfo = Result<Option<Report>, Report>;
87
88#[derive(Debug, Clone, PartialEq, Eq)]
90pub struct Report {
91 title: String,
92 desc: String,
93}
94
95impl Report {
96 pub fn new(title: &str, desc: &str) -> Self {
97 Self::into_new(title, desc.to_owned())
98 }
99
100 pub fn into_new(title: &str, desc: String) -> Self {
101 Self {
102 title: title.to_owned(),
103 desc,
104 }
105 }
106}
107
108impl From<anyhow::Error> for Report {
109 fn from(err: anyhow::Error) -> Self {
110 Self::into_new("Context Error", err.to_string())
111 }
112}
113
114pub fn unimplemented_not_panic() -> ResultInfo {
116 Err(Report::into_new("Error", "Unimplemented".to_owned()))
117}
118
119pub fn todo_not_panic() -> ResultInfo {
120 Ok(Some(Report::into_new("To Do", "Unimplemented".to_owned())))
121}
122
123pub fn ok_with_info(title: &str, desc: &str) -> ResultInfo {
124 Ok(Some(Report::new(title, desc)))
125}
126
127pub fn show_result_dialog(result_info: &ResultInfo) {
128 match result_info {
129 Ok(None) => {
130 }
132 Ok(Some(_report)) => {
133 #[cfg(feature = "file_dialog")]
134 dialog::info_dialog(&_report.title, &_report.desc);
135 }
136 Err(_report) => {
137 #[cfg(feature = "file_dialog")]
138 dialog::error_dialog(&_report.title, &_report.desc);
139 }
140 }
141}
142
143#[cfg(feature = "fern_log")]
148pub fn setup_logger(level: log::LevelFilter) -> Result<fern::Dispatch, fern::InitError> {
149 let colors = ColoredLevelConfig::new()
150 .error(Color::Red)
151 .warn(Color::Yellow)
152 .info(Color::Green)
153 .debug(Color::Blue);
154 Ok(fern::Dispatch::new()
155 .format(move |out, message, record| {
156 out.finish(format_args!(
157 "{}[{}][{}] {}",
158 chrono::Local::now().format("[%Y-%m-%d][%H:%M:%S]"),
159 record.target(),
160 colors.color(record.level()),
161 message
162 ))
163 })
164 .level(level)
165 .level_for("mkutil::finder", log::LevelFilter::Info)
166 .level_for("html5ever", log::LevelFilter::Warn)
167 .chain(std::io::stdout()))
168}
169
170#[cfg(feature = "fern_log")]
172pub fn apply_fern_log(level: log::LevelFilter) {
173 let logger = setup_logger(level).unwrap();
174 logger.apply().unwrap();
175}
176
177pub fn record_binary_state(state: &mut BTreeSet<String>, key: &str, should_add: bool) {
180 if should_add {
181 if !state.contains(key) {
182 state.insert(key.to_owned());
183 };
184 } else {
185 state.remove(key);
186 };
187}
188
189#[cfg(test)]
190mod tests {
191 use super::*;
192 #[test]
193 fn get_app_root_dir() {
194 let root_dir = app_root_dir::application_root_dir();
195 eprintln!("App root dir: {:?}", root_dir);
196 assert!(root_dir.is_ok());
197 }
198}