aboutsummaryrefslogtreecommitdiffstats
path: root/src/config/file_system.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/config/file_system.rs')
-rw-r--r--src/config/file_system.rs123
1 files changed, 123 insertions, 0 deletions
diff --git a/src/config/file_system.rs b/src/config/file_system.rs
new file mode 100644
index 0000000..8528130
--- /dev/null
+++ b/src/config/file_system.rs
@@ -0,0 +1,123 @@
+// yt - A fully featured command line YouTube client
+//
+// Copyright (C) 2024 Benedikt Peetz <benedikt.peetz@b-peetz.de>
+// SPDX-License-Identifier: GPL-3.0-or-later
+//
+// This file is part of Yt.
+//
+// You should have received a copy of the License along with this program.
+// If not, see <https://www.gnu.org/licenses/gpl-3.0.txt>.
+
+use crate::config::{DownloadConfig, PathsConfig, SelectConfig, WatchConfig};
+
+use super::{
+ default::{create_path, download, paths, select, update, watch},
+ Config, UpdateConfig,
+};
+
+use std::{fs::read_to_string, path::PathBuf};
+
+use anyhow::{Context, Result};
+use toml::Table;
+use bytes::Bytes;
+
+macro_rules! get {
+ ($default:path, $config:expr, $get_fn:ident, $key_one:expr, $($keys:expr),*) => {
+ try_get!{@default $default, $config, $get_fn, $key_one, $($keys),*}
+ .with_context(|| format!("Failed to parse '{}' as a '{}'", stringify!($key_one), stringify!($get_fn)))?
+ };
+ (@path_if_none $config:expr, $option_default:expr, $default:path, $key_one:expr, $($keys:expr),*) => {
+ {
+ let maybe_download_dir =
+ try_get! {@option $config, as_str, $key_one, $($keys),*};
+
+ let down_dir = if let Some(dir) = maybe_download_dir {
+ PathBuf::from(dir)
+ } else {
+ if let Some(path) = $option_default {
+ path
+ } else {
+ $default()
+ .with_context(|| format!("Failed to get default path for: '{}.{}'", stringify!($key_one), stringify!($($keys),*)))?
+ }
+ };
+ create_path(down_dir)?
+ }
+ };
+ (@path $config:expr, $default:path, $key_one:expr, $($keys:expr),*) => {
+ get! {@path_if_none $config, None, $default, $key_one, $($keys),*}
+ };
+}
+macro_rules! try_get {
+ (@option $config:expr, $get_fn:ident, $key_one:expr, $($keys:expr),*) => {
+ $config.get($key_one).map(|val| {
+ try_get! {@option val, $get_fn, $($keys),*}
+ }).flatten().flatten()
+ };
+ (@option $config:expr, $get_fn:ident, $key_one:expr) => {
+ $config.get($key_one).map(|val| val.$get_fn())
+ };
+
+ (@default $default:path, $config:expr, $get_fn:ident, $key_one:expr, $($keys:expr),*) => {
+ if let Some(a) = $config.get($key_one) {
+ try_get! {@default $default, a, $get_fn, $($keys),*}
+ } else {
+ Some($default())
+ }
+ };
+ (@default $default:path, $config:expr, $get_fn:ident, $key_one:expr) => {
+ if let Some(a) = $config.get($key_one) {
+ a.$get_fn()
+ } else {
+ Some($default())
+ }
+ };
+}
+
+impl Config {
+ pub fn from_config_file(
+ db_path: Option<PathBuf>,
+ config_path: Option<PathBuf>,
+ ) -> Result<Self> {
+ let config_file_path = config_path
+ .map(|val| Ok(val))
+ .unwrap_or_else(|| -> Result<_> { paths::config_path() })?;
+
+ let config: Table = read_to_string(config_file_path)?
+ .parse()
+ .context("Failed to parse the config file as toml")?;
+
+ Ok(Self {
+ select: SelectConfig {
+ playback_speed: get! {select::playback_speed, config, as_float, "select", "playback_speed"},
+ subtitle_langs:
+ get! {select::subtitle_langs, config, as_str, "select", "subtitle_langs"}
+ .to_owned(),
+ },
+ watch: WatchConfig {
+ local_comments_length: get! {watch::local_comments_length, config, as_integer, "watch", "local_comments_length"}
+ as usize,
+ },
+ update: UpdateConfig {
+ max_backlog: get! {update::max_backlog, config, as_integer, "update", "max_backlog"}
+ as u32,
+ },
+ paths: PathsConfig {
+ download_dir: get! {@path config, paths::download_dir, "paths", "download_dir"},
+ mpv_config_path: get! {@path config, paths::mpv_config_path, "paths", "mpv_config_path"},
+ mpv_input_path: get! {@path config, paths::mpv_input_path, "paths", "mpv_input_path"},
+ database_path: get! {@path_if_none config, db_path, paths::database_path, "paths", "database_path"},
+ last_selection_path: get! {@path config, paths::last_selection_path, "paths", "last_selection_path"},
+ },
+ download: DownloadConfig {
+ max_cache_size: {
+ let bytes_str = get! {download::max_cache_size, config, as_str, "download", "max_cache_path"};
+ let number: Bytes = bytes_str
+ .parse()
+ .context("Failed to parse max_cache_size")?;
+ number.as_u64()
+ },
+ },
+ })
+ }
+}