use crate::error::FileError;
use crate::filename;
use crate::settings::ARGS;
use crate::VERSION;
use directories::ProjectDirs;
use lazy_static::lazy_static;
use log::LevelFilter;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::fs;
#[cfg(not(test))]
use std::fs::File;
#[cfg(not(test))]
use std::io::Write;
use std::path::Path;
use std::path::PathBuf;
use std::sync::RwLock;
const CURRENT_EXE: &str = "tp-note";
const CONFIG_FILENAME: &str = "tp-note.toml";
const ARG_DEFAULT_DEBUG: LevelFilter = LevelFilter::Error;
const ARG_DEFAULT_EDITOR: bool = false;
const ARG_DEFAULT_NO_FILENAME_SYNC: bool = false;
const ARG_DEFAULT_POPUP: bool = true;
#[cfg(not(test))]
pub const FILENAME_LEN_MAX: usize =
255
- FILENAME_COPY_COUNTER_EXTRA_SEPARATOR.len()
- FILENAME_COPY_COUNTER_OPENING_BRACKETS.len() - 2 - FILENAME_COPY_COUNTER_CLOSING_BRACKETS.len()
- 6;
#[cfg(test)]
pub const FILENAME_LEN_MAX: usize = 10;
const FILENAME_SORT_TAG_CHARS: &str = "0123456789.-_ \t";
const FILENAME_SORT_TAG_EXTRA_SEPARATOR: char = '\'';
const FILENAME_COPY_COUNTER_EXTRA_SEPARATOR: &str = "-";
const FILENAME_COPY_COUNTER_OPENING_BRACKETS: &str = "(";
const FILENAME_COPY_COUNTER_CLOSING_BRACKETS: &str = ")";
pub const FILENAME_COPY_COUNTER_MAX: usize = 400;
pub const FILENAME_EXTENSION_DEFAULT: &str = "md";
pub const FILENAME_EXTENSIONS_MD: &[&str] = &["md", "markdown", "markdn", "mdown", "mdtxt"];
pub const FILENAME_EXTENSIONS_RST: &[&str] = &["rst", "rest"];
pub const FILENAME_EXTENSIONS_HTML: &[&str] = &["htmlnote"];
pub const FILENAME_EXTENSIONS_TXT: &[&str] = &["txtnote", "adoc", "asciidoc", "mediawiki", "mw"];
pub const FILENAME_EXTENSIONS_NO_VIEWER: &[&str] = &["t2t"];
const CLIPBOARD_READ_ENABLED: bool = true;
const CLIPBOARD_EMPTY_ENABLED: bool = true;
const TMPL_COMPULSORY_HEADER_FIELD: &str = "title";
const TMPL_NEW_CONTENT: &str = "\
---
title: {{ dir_path | trim_tag | cut | json_encode }}
subtitle: {{ 'Note' | json_encode }}
author: {{ username | json_encode }}
date: {{ now() | date(format='%Y-%m-%d') | json_encode }}
lang: {{ get_env(name='LANG', default='') | json_encode }}
---
";
const TMPL_NEW_FILENAME: &str = "\
{{ now() | date(format='%Y%m%d-') }}\
{{ fm_title | sanit(alpha=true) }}{% if fm_subtitle | default(value='') | sanit != '' %}--{% endif %}\
{{ fm_subtitle | default(value='') | sanit }}{{ extension_default | prepend_dot }}\
";
const TMPL_COPY_CONTENT: &str = "\
---
title: {{ fm_title | default(value = path|trim_tag) | cut | json_encode }}
subtitle: {{ fm_subtitle | default(value = 'Note') | cut | json_encode }}
author: {{ fm_author | default(value=username) | json_encode }}
date: {{ fm_date | default(value = now()|date(format='%Y-%m-%d')) | json_encode }}
lang: {{ fm_lang | default(value = get_env(name='LANG', default='')) | json_encode }}
{% for k, v in fm_all\
| remove(var='fm_title')\
| remove(var='fm_subtitle')\
| remove(var='fm_author')\
| remove(var='fm_date')\
| remove(var='fm_lang') %}\
{{ k }}:\t\t{{ v | json_encode }}
{% endfor %}\
---
{{ stdin ~ clipboard }}
";
const TMPL_COPY_FILENAME: &str = "\
{{ fm_sort_tag | default(value = now() | date(format='%Y%m%d-')) }}\
{{ fm_title | sanit(alpha=true) }}\
{% if fm_subtitle | default(value='') | sanit != '' %}--{% endif %}\
{{ fm_subtitle | default(value='') | sanit }}\
{{ fm_file_ext | default(value = extension_default ) | prepend_dot }}\
";
const TMPL_CLIPBOARD_CONTENT: &str = "\
{%- set lname = stdin ~ clipboard | linkname -%}
{%- set ok_linkname = lname !=''\
and not lname is starting_with(\"http\")\
and not lname is starting_with(\"HTTP\") -%}
---
{% if ok_linkname %}\
title: {{ stdin ~ clipboard | linkname | cut | json_encode }}
{% else %}\
title: {{ stdin ~ clipboard | heading | cut | json_encode }}
{% endif %}\
{% if stdin ~ clipboard | linkname !='' and stdin ~ clipboard | heading == stdin ~ clipboard %}\
subtitle: {{ 'URL' | json_encode }}
{% else %}\
subtitle: {{ 'Note' | json_encode }}
{% endif %}\
author: {{ username | json_encode }}
date: {{ now() | date(format='%Y-%m-%d') | json_encode }}
lang: {{ get_env(name='LANG', default='') | json_encode }}
---
{{ stdin ~ clipboard }}
";
const TMPL_CLIPBOARD_FILENAME: &str = "\
{{ now() | date(format='%Y%m%d-') }}\
{{ fm_title | sanit(alpha=true) }}\
{% if fm_subtitle | default(value='') | sanit != '' %}--{% endif %}\
{{ fm_subtitle | default(value='') | sanit }}{{ extension_default | prepend_dot }}\
";
const TMPL_ANNOTATE_CONTENT: &str = "\
---
title: {% filter json_encode %}{{ path | stem }}{{ path | copy_counter }}\
{{ path | ext | prepend_dot }}{% endfilter %}
{% if stdin ~ clipboard | linkname !='' and stdin ~ clipboard | heading == stdin ~ clipboard %}\
subtitle: {{ 'URL' | json_encode }}
{% else %}\
subtitle: {{ 'Note' | json_encode }}
{% endif %}\
author: {{ username | json_encode }}
date: {{ now() | date(format='%Y-%m-%d') | json_encode }}
lang: {{ get_env(name='LANG', default='') | json_encode }}
---
[{{ path | filename }}](<{{ path | filename }}>)
{% if stdin ~ clipboard != '' %}{% if stdin ~ clipboard != stdin ~ clipboard | heading %}
---
{% endif %}
{{ stdin ~ clipboard }}
{% endif %}
";
const TMPL_ANNOTATE_FILENAME: &str = "\
{{ path | tag }}{{ fm_title | sanit(alpha=true) }}\
{% if fm_subtitle | default(value='') | sanit != '' %}--{% endif %}\
{{ fm_subtitle | default(value='') | sanit }}{{ extension_default | prepend_dot }}\
";
const TMPL_SYNC_FILENAME: &str = "\
{{ fm_sort_tag | default(value = path | tag) }}\
{{ fm_title | default(value='No title') | sanit(alpha=true) }}\
{% if fm_subtitle | default(value='') | sanit != '' %}--{% endif %}\
{{ fm_subtitle | default(value='') | sanit }}\
{{ fm_file_ext | default(value = path | ext) | prepend_dot }}\
";
#[cfg(all(target_family = "unix", not(target_vendor = "apple")))]
const APP_ARGS_BROWSER: &[&[&str]] = &[
&[
"flatpak",
"run",
"org.mozilla.firefox",
"--new-window",
"--private-window",
],
&["firefox", "--new-window", "--private-window"],
&["firefox-esr", "--new-window", "--private-window"],
&[
"flatpak",
"run",
"com.github.Eloston.UngoogledChromium",
"--new-window",
"--incognito",
],
&[
"flatpak",
"run",
"org.chromium.Chromium",
"--new-window",
"--incognito",
],
&["chromium-browser", "--new-window", "--incognito"],
&["chrome", "--new-window", "--incognito"],
];
#[cfg(target_family = "windows")]
const APP_ARGS_BROWSER: &[&[&str]] = &[
&[
"C:\\Program Files\\Mozilla Firefox\\firefox.exe",
"--new-window",
"--private-window",
],
&[
"C:\\Program Files\\Google\\Chrome\\Application\\chrome",
"--new-window",
"--incognito",
],
&[
"C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe",
"--inprivate",
],
];
#[cfg(all(target_family = "unix", target_vendor = "apple"))]
const APP_ARGS_BROWSER: &[&[&str]] = &[];
#[cfg(all(target_family = "unix", not(target_vendor = "apple")))]
const APP_ARGS_EDITOR: &[&[&str]] = &[
&["code", "-w", "-n"],
&["flatpak", "run", "com.visualstudio.code", "-w", "-n"],
&["atom", "-w"],
&["marktext", "--no-sandbox", "--new-window"],
&[
"flatpak",
"run",
"com.github.marktext.marktext",
"--new-window",
],
&["typora"],
&["retext"],
&["geany", "-s", "-i", "-m"],
&["gedit", "-w"],
&["mousepad", "--disable-server"],
&["leafpad"],
&["nvim-qt", "--nofork"],
&["gvim", "--nofork"],
];
#[cfg(target_family = "windows")]
const APP_ARGS_EDITOR: &[&[&str]] = &[
&["C:\\Program Files\\Typora\\Typora.exe"],
&[
"C:\\Program Files\\Mark Text\\Mark Text.exe",
"--new-window",
],
&[
"C:\\Program Files\\Notepad++\\notepad++.exe",
"-nosession",
"-multiInst",
],
&["C:\\Windows\\notepad.exe"],
];
#[cfg(all(target_family = "unix", target_vendor = "apple"))]
const APP_ARGS_EDITOR: &[&[&str]] = &[
&["code", "-w", "-n"],
&["atom", "-w"],
&["marktext", "--no-sandbox"],
&["typora"],
&["gvim", "--nofork"],
&["mate"],
&["open", "-a", "TextEdit"],
&["open", "-a", "TextMate"],
&["open"],
];
#[cfg(all(target_family = "unix", not(target_vendor = "apple")))]
const APP_ARGS_EDITOR_CONSOLE: &[&[&str]] = &[&["nvim"], &["nano"], &["vim"], &["emacs"], &["vi"]];
#[cfg(target_family = "windows")]
const APP_ARGS_EDITOR_CONSOLE: &[&[&str]] = &[&[]];
#[cfg(all(target_family = "unix", target_vendor = "apple"))]
const APP_ARGS_EDITOR_CONSOLE: &[&[&str]] = &[
&["nvim"],
&["nano"],
&["pico"],
&["vim"],
&["emacs"],
&["vi"],
];
const VIEWER_STARTUP_DELAY: isize = 500;
const VIEWER_MISSING_HEADER_DISABLES: bool = false;
const VIEWER_NOTIFY_PERIOD: u64 = 1000;
const VIEWER_TCP_CONNECTIONS_MAX: usize = 16;
const VIEWER_SERVED_MIME_TYPES: &[&[&str]] = &[
&["apng", "image/apng"],
&["avif", "image/avif"],
&["bmp", "image/bmp"],
&["gif", "image/gif"],
&["html", "text/html"],
&["htm", "text/html"],
&["ico", "image/vnd.microsoft.icon"],
&["jpeg", "image/jpeg"],
&["jpg", "image/jpeg"],
&["pdf", "application/pdf"],
&["png", "image/png"],
&["svg", "image/svg+xml"],
&["tiff", "image/tiff"],
&["tif", "image/tiff"],
&["webp", "image/webp"],
&["mp3", "audio/mp3"],
&["ogg", "audio/ogg"],
&["oga", "audio/ogg"],
&["weba", "audio/webm"],
&["flac", "audio/flac"],
&["wav", "audio/wav"],
&["opus", "audio/opus"],
&["mp4", "video/mp4"],
&["ogv", "video/ogg"],
&["webm", "video/webm"],
&["ogx", "application/ogg"],
];
pub const VIEWER_RENDITION_TMPL: &str = r#"<!DOCTYPE html>
<html lang="{{ fm_lang | default(value='en') }}">
<head>
<meta charset="UTF-8">
<title>{{ fm_title }}</title>
<style>
table, th, td { font-weight: normal; }
table.center {
margin-left: auto;
margin-right: auto;
background-color: #f3f2e4;
border:1px solid grey;
}
th, td {
padding: 3px;
padding-left:15px;
padding-right:15px;
}
th.key{ color:#444444; text-align:right; }
th.val{
color:#316128;
text-align:left;
font-family:sans-serif;
}
th.keygrey{ color:grey; text-align:right; }
th.valgrey{ color:grey; text-align:left; }
pre { white-space: pre-wrap; }
em { color: #523626; }
a { color: #316128; }
h1 { font-size: 150% }
h2 { font-size: 132% }
h3 { font-size: 115% }
h4, h5, h6 { font-size: 100% }
h1, h2, h3, h4, h5, h6 { color: #263292; font-family:sans-serif; }
</style>
</head>
<body>
<table class="center">
<tr>
<th class="key">title:</th>
<th class="val"><b>{{ fm_title }}</b></th>
</tr>
<tr>
<th class="key">subtitle:</th>
<th class="val">{{ fm_subtitle | default(value='') }}</th>
</tr>
<tr>
<th class="keygrey">date:</th>
<th class="valgrey">{{ fm_date | default(value='') }}</th>
</tr>
{% for k, v in fm_all| remove(var='fm_title')| remove(var='fm_subtitle')| remove(var='fm_date') %}
<tr>
<th class="keygrey">{{ k }}:</th>
<th class="valgrey">{{ v }}</th>
</tr>
{% endfor %}
</table>
<div class="note-body">{{ note_body }}</div>
<script>{{ note_js }}</script>
</body>
</html>
"#;
pub const VIEWER_ERROR_TMPL: &str = r#"<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Syntax error</title>
<style>
.note-error { color: #523626; }
pre { white-space: pre-wrap; }
a { color: #316128; }
h1, h2, h3, h4, h5, h6 { color: #d3af2c; font-family:sans-serif; }
</style>
</head>
<body>
<h3>Syntax error</h3>
<p> in note file: <pre>{{ path }}</pre><p>
<div class="note-error">
<hr>
<pre>{{ note_error }}</pre>
<hr>
</div>
{{ note_erroneous_content }}
<script>{{ note_js }}</script>
</body>
</html>
"#;
pub const EXPORTER_RENDITION_TMPL: &str = r#"<!DOCTYPE html>
<html lang="{{ fm_lang | default(value='en') }}">
<head>
<meta charset="utf-8">
<title>{{ fm_title }}</title>
<style>
table, th, td { font-weight: normal; }
table.center {
margin-left: auto;
margin-right: auto;
background-color: #f3f2e4;
border:1px solid grey;
}
th, td {
padding: 3px;
padding-left:15px;
padding-right:15px;
}
th.key{ color:#444444; text-align:right; }
th.val{
color:#316128;
text-align:left;
font-family:sans-serif;
}
th.keygrey{ color:grey; text-align:right; }
th.valgrey{ color:grey; text-align:left; }
pre { white-space: pre-wrap; }
em { color: #523626; }
a { color: #316128; }
h1 { font-size: 150% }
h2 { font-size: 132% }
h3 { font-size: 115% }
h4, h5, h6 { font-size: 100% }
h1, h2, h3, h4, h5, h6 { color: #263292; font-family:sans-serif; }
</style>
</head>
<body>
<table class="center">
<tr>
<th class="key">title:</th>
<th class="val"><b>{{ fm_title }}</b></th>
</tr>
<tr>
<th class="key">subtitle:</th>
<th class="val">{{ fm_subtitle | default(value='') }}</th>
</tr>
<tr>
<th class="keygrey">date:</th>
<th class="valgrey">{{ fm_date | default(value='') }}</th>
</tr>
{% for k, v in fm_all| remove(var='fm_title')| remove(var='fm_subtitle')| remove(var='fm_date') %}
<tr>
<th class="keygrey">{{ k }}:</th>
<th class="valgrey">{{ v }}</th>
</tr>
{% endfor %}
</table>
<div class="note-body">{{ note_body }}</div>
</body>
</html>
"#;
#[derive(Debug, Serialize, Deserialize)]
pub struct Cfg {
pub version: String,
pub arg_default: ArgDefault,
pub filename: Filename,
pub clipboard: Clipboard,
pub tmpl: Tmpl,
pub app_args: AppArgs,
pub viewer: Viewer,
pub exporter: Exporter,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct ArgDefault {
pub debug: LevelFilter,
pub edit: bool,
pub no_filename_sync: bool,
pub popup: bool,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct Filename {
pub sort_tag_chars: String,
pub sort_tag_extra_separator: char,
pub copy_counter_extra_separator: String,
pub copy_counter_opening_brackets: String,
pub copy_counter_closing_brackets: String,
pub extension_default: String,
pub extensions_md: Vec<String>,
pub extensions_rst: Vec<String>,
pub extensions_html: Vec<String>,
pub extensions_txt: Vec<String>,
pub extensions_no_viewer: Vec<String>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct Clipboard {
pub read_enabled: bool,
pub empty_enabled: bool,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct Tmpl {
pub compulsory_header_field: String,
pub new_content: String,
pub new_filename: String,
pub copy_content: String,
pub copy_filename: String,
pub clipboard_content: String,
pub clipboard_filename: String,
pub annotate_content: String,
pub annotate_filename: String,
pub sync_filename: String,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct AppArgs {
pub browser: Vec<Vec<String>>,
pub editor: Vec<Vec<String>>,
pub editor_console: Vec<Vec<String>>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct Viewer {
pub startup_delay: isize,
pub missing_header_disables: bool,
pub notify_period: u64,
pub tcp_connections_max: usize,
pub served_mime_types: Vec<Vec<String>>,
pub rendition_tmpl: String,
pub error_tmpl: String,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct Exporter {
pub rendition_tmpl: String,
}
impl ::std::default::Default for Cfg {
fn default() -> Self {
let version = match VERSION {
Some(v) => v.to_string(),
None => "".to_string(),
};
Cfg {
version,
arg_default: ArgDefault::default(),
tmpl: Tmpl::default(),
app_args: AppArgs::default(),
clipboard: Clipboard::default(),
filename: Filename::default(),
viewer: Viewer::default(),
exporter: Exporter::default(),
}
}
}
impl ::std::default::Default for ArgDefault {
fn default() -> Self {
ArgDefault {
debug: ARG_DEFAULT_DEBUG,
edit: ARG_DEFAULT_EDITOR,
no_filename_sync: ARG_DEFAULT_NO_FILENAME_SYNC,
popup: ARG_DEFAULT_POPUP,
}
}
}
impl ::std::default::Default for Filename {
fn default() -> Self {
Filename {
sort_tag_chars: FILENAME_SORT_TAG_CHARS.to_string(),
sort_tag_extra_separator: FILENAME_SORT_TAG_EXTRA_SEPARATOR,
copy_counter_extra_separator: FILENAME_COPY_COUNTER_EXTRA_SEPARATOR.to_string(),
copy_counter_opening_brackets: FILENAME_COPY_COUNTER_OPENING_BRACKETS.to_string(),
copy_counter_closing_brackets: FILENAME_COPY_COUNTER_CLOSING_BRACKETS.to_string(),
extension_default: FILENAME_EXTENSION_DEFAULT.to_string(),
extensions_md: FILENAME_EXTENSIONS_MD
.iter()
.map(|a| (*a).to_string())
.collect(),
extensions_rst: FILENAME_EXTENSIONS_RST
.iter()
.map(|a| (*a).to_string())
.collect(),
extensions_html: FILENAME_EXTENSIONS_HTML
.iter()
.map(|a| (*a).to_string())
.collect(),
extensions_txt: FILENAME_EXTENSIONS_TXT
.iter()
.map(|a| (*a).to_string())
.collect(),
extensions_no_viewer: FILENAME_EXTENSIONS_NO_VIEWER
.iter()
.map(|a| (*a).to_string())
.collect(),
}
}
}
impl ::std::default::Default for Tmpl {
fn default() -> Self {
Tmpl {
compulsory_header_field: TMPL_COMPULSORY_HEADER_FIELD.to_string(),
new_content: TMPL_NEW_CONTENT.to_string(),
new_filename: TMPL_NEW_FILENAME.to_string(),
copy_content: TMPL_COPY_CONTENT.to_string(),
copy_filename: TMPL_COPY_FILENAME.to_string(),
clipboard_content: TMPL_CLIPBOARD_CONTENT.to_string(),
clipboard_filename: TMPL_CLIPBOARD_FILENAME.to_string(),
annotate_content: TMPL_ANNOTATE_CONTENT.to_string(),
annotate_filename: TMPL_ANNOTATE_FILENAME.to_string(),
sync_filename: TMPL_SYNC_FILENAME.to_string(),
}
}
}
impl ::std::default::Default for AppArgs {
fn default() -> Self {
AppArgs {
editor: APP_ARGS_EDITOR
.iter()
.map(|i| i.iter().map(|a| (*a).to_string()).collect())
.collect(),
editor_console: APP_ARGS_EDITOR_CONSOLE
.iter()
.map(|i| i.iter().map(|a| (*a).to_string()).collect())
.collect(),
browser: APP_ARGS_BROWSER
.iter()
.map(|i| i.iter().map(|a| (*a).to_string()).collect())
.collect(),
}
}
}
impl ::std::default::Default for Clipboard {
fn default() -> Self {
Clipboard {
read_enabled: CLIPBOARD_READ_ENABLED,
empty_enabled: CLIPBOARD_EMPTY_ENABLED,
}
}
}
impl ::std::default::Default for Viewer {
fn default() -> Self {
Viewer {
startup_delay: VIEWER_STARTUP_DELAY,
missing_header_disables: VIEWER_MISSING_HEADER_DISABLES,
notify_period: VIEWER_NOTIFY_PERIOD,
tcp_connections_max: VIEWER_TCP_CONNECTIONS_MAX,
served_mime_types: VIEWER_SERVED_MIME_TYPES
.iter()
.map(|i| i.iter().map(|a| (*a).to_string()).collect())
.collect(),
rendition_tmpl: VIEWER_RENDITION_TMPL.to_string(),
error_tmpl: VIEWER_ERROR_TMPL.to_string(),
}
}
}
impl ::std::default::Default for Exporter {
fn default() -> Self {
Exporter {
rendition_tmpl: EXPORTER_RENDITION_TMPL.to_string(),
}
}
}
lazy_static! {
pub static ref VIEWER_SERVED_MIME_TYPES_HMAP: HashMap<&'static str, &'static str> = {
let mut hm = HashMap::new();
for l in &CFG.viewer.served_mime_types {
if l.len() >= 2
{
hm.insert(l[0].as_str(), l[1].as_str());
};
};
hm
};
}
lazy_static! {
pub static ref CFG_FILE_LOADING: RwLock<Result<(), FileError>> = RwLock::new(Ok(()));
}
#[cfg(not(test))]
#[inline]
fn config_load_path(config_path: &Path) -> Result<Cfg, FileError> {
if config_path.exists() {
let config: Cfg = toml::from_str(&fs::read_to_string(config_path)?)?;
if config
.filename
.sort_tag_chars
.find(config.filename.sort_tag_extra_separator)
.is_some()
{
return Err(FileError::ConfigFileSortTag {
chars: config.filename.sort_tag_chars.escape_default().to_string(),
extra_separator: config
.filename
.sort_tag_extra_separator
.escape_default()
.to_string(),
});
}
Ok(config)
} else {
#[allow(clippy::or_fun_call)]
fs::create_dir_all(config_path.parent().unwrap_or(Path::new("")))?;
let mut buffer = File::create(config_path)?;
buffer.write_all(toml::to_string_pretty(&Cfg::default())?.as_bytes())?;
Ok(Cfg::default())
}
}
#[cfg(test)]
#[inline]
fn config_load_path(_config_path: &Path) -> Result<Cfg, FileError> {
Ok(Cfg::default())
}
lazy_static! {
pub static ref CFG: Cfg = {
let config_path = if let Some(c) = &ARGS.config {
Path::new(c)
} else {
match &*CONFIG_PATH {
Some(p) => p.as_path(),
None => {
let mut cfg_file_loading = CFG_FILE_LOADING.write().unwrap();
*cfg_file_loading = Err(FileError::PathToConfigFileNotFound);
return Cfg::default();
},
}
};
config_load_path(config_path)
.unwrap_or_else(|e|{
let mut cfg_file_loading = CFG_FILE_LOADING.write().unwrap();
*cfg_file_loading = Err(e);
Cfg::default()
})
};
}
lazy_static! {
pub static ref CONFIG_PATH : Option<PathBuf> = {
if let Some(c) = &ARGS.config {
Some(PathBuf::from(c))
} else {
let config = ProjectDirs::from("rs", "", CURRENT_EXE)?;
let mut config = PathBuf::from(config.config_dir());
config.push(Path::new(CONFIG_FILENAME));
Some(config)
}
};
}
pub fn backup_config_file() -> Result<PathBuf, FileError> {
if let Some(ref config_path) = *CONFIG_PATH {
if config_path.exists() {
let config_path_bak = filename::find_unused((config_path).to_path_buf())?;
fs::rename(&config_path.as_path(), &config_path_bak)?;
Ok(config_path_bak)
} else {
Err(FileError::ConfigFileNotFound)
}
} else {
Err(FileError::PathToConfigFileNotFound)
}
}