about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorBenedikt Peetz <benedikt.peetz@b-peetz.de>2025-02-14 16:39:45 +0100
committerBenedikt Peetz <benedikt.peetz@b-peetz.de>2025-02-14 16:39:45 +0100
commite30b69dd4c2ebfb4ae77b38037b66f3e6fcb17bc (patch)
tree3f68362bf4b0a1ea097d3b584f52b2da4c00ff71
parentfix(yt/cli): Make most of the arguments to `yt select <cmd> <hash>` optional (diff)
downloadyt-e30b69dd4c2ebfb4ae77b38037b66f3e6fcb17bc.zip
feat(yt): Make colorization of the output configurable
-rw-r--r--contrib/config.toml3
-rw-r--r--yt/src/cli.rs4
-rw-r--r--yt/src/config/default.rs7
-rw-r--r--yt/src/config/definitions.rs7
-rw-r--r--yt/src/config/file_system.rs12
-rw-r--r--yt/src/config/mod.rs10
-rw-r--r--yt/src/main.rs4
-rw-r--r--yt/src/update/mod.rs2
-rw-r--r--yt/src/videos/display/mod.rs72
-rw-r--r--yt/src/videos/mod.rs2
10 files changed, 81 insertions, 42 deletions
diff --git a/contrib/config.toml b/contrib/config.toml
index ffd91a1..ac06959 100644
--- a/contrib/config.toml
+++ b/contrib/config.toml
@@ -8,6 +8,9 @@
 # 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>.
 
+[global]
+display_colors = true
+
 [select]
 playback_speed = 2.7
 subtitle_langs = ""
diff --git a/yt/src/cli.rs b/yt/src/cli.rs
index e95b93f..6e6dd3a 100644
--- a/yt/src/cli.rs
+++ b/yt/src/cli.rs
@@ -38,6 +38,10 @@ pub struct CliArgs {
     #[arg(long="verbose", short = 'v', action = ArgAction::Count)]
     pub verbosity: u8,
 
+    /// Display colors [defaults to true, if the config file has no value]
+    #[arg(long, short = 'C')]
+    pub color: Option<bool>,
+
     /// Set the path to the videos.db. This overrides the default and the config file.
     #[arg(long, short)]
     pub db_path: Option<PathBuf>,
diff --git a/yt/src/config/default.rs b/yt/src/config/default.rs
index 926f422..9189545 100644
--- a/yt/src/config/default.rs
+++ b/yt/src/config/default.rs
@@ -44,6 +44,13 @@ pub(super) fn create_path(path: PathBuf) -> Result<PathBuf> {
 
 pub(crate) const PREFIX: &str = "yt";
 
+pub(crate) mod global {
+    pub(crate) fn display_colors() -> bool {
+        // TODO: This should probably check if the output is a tty and otherwise return `false` <2025-02-14>
+        true
+    }
+}
+
 pub(crate) mod select {
     pub(crate) fn playback_speed() -> f64 {
         2.7
diff --git a/yt/src/config/definitions.rs b/yt/src/config/definitions.rs
index 3d025b3..9f8b971 100644
--- a/yt/src/config/definitions.rs
+++ b/yt/src/config/definitions.rs
@@ -15,6 +15,7 @@ use serde::Deserialize;
 #[derive(Debug, Deserialize, PartialEq)]
 #[serde(deny_unknown_fields)]
 pub(crate) struct ConfigFile {
+    pub global: Option<GlobalConfig>,
     pub select: Option<SelectConfig>,
     pub watch: Option<WatchConfig>,
     pub paths: Option<PathsConfig>,
@@ -24,6 +25,12 @@ pub(crate) struct ConfigFile {
 
 #[derive(Debug, Deserialize, PartialEq, Clone, Copy)]
 #[serde(deny_unknown_fields)]
+pub(crate) struct GlobalConfig {
+    pub display_colors: Option<bool>,
+}
+
+#[derive(Debug, Deserialize, PartialEq, Clone, Copy)]
+#[serde(deny_unknown_fields)]
 pub(crate) struct UpdateConfig {
     pub max_backlog: Option<u32>,
 }
diff --git a/yt/src/config/file_system.rs b/yt/src/config/file_system.rs
index 6709a2b..49e02fe 100644
--- a/yt/src/config/file_system.rs
+++ b/yt/src/config/file_system.rs
@@ -11,8 +11,8 @@
 use crate::config::{DownloadConfig, PathsConfig, SelectConfig, WatchConfig};
 
 use super::{
-    default::{create_path, download, paths, select, update, watch},
-    Config, UpdateConfig,
+    default::{create_path, download, global, paths, select, update, watch},
+    Config, GlobalConfig, UpdateConfig,
 };
 
 use std::{fs::read_to_string, path::PathBuf};
@@ -70,6 +70,7 @@ impl Config {
     pub fn from_config_file(
         db_path: Option<PathBuf>,
         config_path: Option<PathBuf>,
+        display_colors: Option<bool>,
     ) -> Result<Self> {
         let config_file_path =
             config_path.map_or_else(|| -> Result<_> { paths::config_path() }, Ok)?;
@@ -79,6 +80,13 @@ impl Config {
                 .context("Failed to parse the config file as toml")?;
 
         Ok(Self {
+            global: GlobalConfig {
+                display_colors: {
+                    let config_value: Option<bool> = get! {@option config, global, display_colors};
+
+                    display_colors.unwrap_or(config_value.unwrap_or_else(global::display_colors))
+                },
+            },
             select: SelectConfig {
                 playback_speed: get! {select::playback_speed, config, select, playback_speed},
                 subtitle_langs: get! {select::subtitle_langs, config, select, subtitle_langs},
diff --git a/yt/src/config/mod.rs b/yt/src/config/mod.rs
index 36dd3fc..be99caa 100644
--- a/yt/src/config/mod.rs
+++ b/yt/src/config/mod.rs
@@ -21,15 +21,21 @@ pub mod file_system;
 
 #[derive(Serialize, Debug)]
 pub struct Config {
+    pub global: GlobalConfig,
     pub select: SelectConfig,
     pub watch: WatchConfig,
     pub paths: PathsConfig,
     pub download: DownloadConfig,
     pub update: UpdateConfig,
 }
+// These structures could get non-copy fields in the future.
+
+#[derive(Serialize, Debug)]
+#[allow(missing_copy_implementations)]
+pub struct GlobalConfig {
+    pub display_colors: bool,
+}
 #[derive(Serialize, Debug)]
-// This structure could get non-copy fields in the future.
-// The same thing applies to all the other structures here.
 #[allow(missing_copy_implementations)]
 pub struct UpdateConfig {
     pub max_backlog: u32,
diff --git a/yt/src/main.rs b/yt/src/main.rs
index 3097eea..4378346 100644
--- a/yt/src/main.rs
+++ b/yt/src/main.rs
@@ -90,7 +90,7 @@ async fn main() -> Result<()> {
     });
 
     let app = {
-        let config = Config::from_config_file(args.db_path, args.config_path)?;
+        let config = Config::from_config_file(args.db_path, args.config_path, args.color)?;
         App::new(config).await?
     };
 
@@ -151,7 +151,7 @@ async fn main() -> Result<()> {
                         .to_formatted_video(&app)
                         .await
                         .context("Failed to format video")?
-                        .colorize())
+                        .colorize(&app))
                         .to_info_display()
                 );
             }
diff --git a/yt/src/update/mod.rs b/yt/src/update/mod.rs
index e3ab54e..3cdc61b 100644
--- a/yt/src/update/mod.rs
+++ b/yt/src/update/mod.rs
@@ -253,7 +253,7 @@ async fn process_subscription(
                 .to_formatted_video(app)
                 .await
                 .with_context(|| format!("Failed to format video: '{}'", video.title))?
-                .colorize())
+                .colorize(app))
                 .to_line_display()
         );
         Ok(())
diff --git a/yt/src/videos/display/mod.rs b/yt/src/videos/display/mod.rs
index 4e5ee50..4a32e52 100644
--- a/yt/src/videos/display/mod.rs
+++ b/yt/src/videos/display/mod.rs
@@ -41,40 +41,44 @@ pub struct ColorizedFormattedVideo(FormattedVideo);
 
 impl FormattedVideo {
     #[must_use]
-    pub fn colorize(self) -> ColorizedFormattedVideo {
-        let Self {
-            cache_path,
-            description,
-            duration,
-            extractor_hash,
-            last_status_change,
-            parent_subscription_name,
-            priority,
-            publish_date,
-            status,
-            status_change,
-            thumbnail_url,
-            title,
-            url,
-            video_options,
-        } = self;
-
-        ColorizedFormattedVideo(Self {
-            cache_path: cache_path.blue().bold().to_string(),
-            description,
-            duration: duration.cyan().bold().to_string(),
-            extractor_hash: extractor_hash.bright_purple().italic().to_string(),
-            last_status_change: last_status_change.bright_cyan().to_string(),
-            parent_subscription_name: parent_subscription_name.bright_magenta().to_string(),
-            priority,
-            publish_date: publish_date.bright_white().bold().to_string(),
-            status: status.red().bold().to_string(),
-            status_change,
-            thumbnail_url,
-            title: title.green().bold().to_string(),
-            url: url.italic().to_string(),
-            video_options: video_options.bright_green().to_string(),
-        })
+    pub fn colorize(self, app: &App) -> ColorizedFormattedVideo {
+        if app.config.global.display_colors {
+            let Self {
+                cache_path,
+                description,
+                duration,
+                extractor_hash,
+                last_status_change,
+                parent_subscription_name,
+                priority,
+                publish_date,
+                status,
+                status_change,
+                thumbnail_url,
+                title,
+                url,
+                video_options,
+            } = self;
+
+            ColorizedFormattedVideo(Self {
+                cache_path: cache_path.blue().bold().to_string(),
+                description,
+                duration: duration.cyan().bold().to_string(),
+                extractor_hash: extractor_hash.bright_purple().italic().to_string(),
+                last_status_change: last_status_change.bright_cyan().to_string(),
+                parent_subscription_name: parent_subscription_name.bright_magenta().to_string(),
+                priority,
+                publish_date: publish_date.bright_white().bold().to_string(),
+                status: status.red().bold().to_string(),
+                status_change,
+                thumbnail_url,
+                title: title.green().bold().to_string(),
+                url: url.italic().to_string(),
+                video_options: video_options.bright_green().to_string(),
+            })
+        } else {
+            ColorizedFormattedVideo(self)
+        }
     }
 }
 
diff --git a/yt/src/videos/mod.rs b/yt/src/videos/mod.rs
index 9704f73..156d01d 100644
--- a/yt/src/videos/mod.rs
+++ b/yt/src/videos/mod.rs
@@ -41,7 +41,7 @@ pub async fn query(app: &App, limit: Option<usize>, search_query: Option<String>
         .try_collect::<Vec<FormattedVideo>>()
         .await?
         .into_iter()
-        .map(|vid| (&vid.colorize()).to_line_display())
+        .map(|vid| (&vid.colorize(app)).to_line_display())
         .collect();
 
     if let Some(query) = search_query {