about summary refs log tree commit diff stats
path: root/pkgs/by-name/ts/tskm/src/interface/input/handle.rs
diff options
context:
space:
mode:
Diffstat (limited to 'pkgs/by-name/ts/tskm/src/interface/input/handle.rs')
-rw-r--r--pkgs/by-name/ts/tskm/src/interface/input/handle.rs124
1 files changed, 80 insertions, 44 deletions
diff --git a/pkgs/by-name/ts/tskm/src/interface/input/handle.rs b/pkgs/by-name/ts/tskm/src/interface/input/handle.rs
index 0ff0e56e..76eea6dc 100644
--- a/pkgs/by-name/ts/tskm/src/interface/input/handle.rs
+++ b/pkgs/by-name/ts/tskm/src/interface/input/handle.rs
@@ -1,23 +1,33 @@
+// nixos-config - My current NixOS configuration
+//
+// Copyright (C) 2025 Benedikt Peetz <benedikt.peetz@b-peetz.de>
+// SPDX-License-Identifier: GPL-3.0-or-later
+//
+// This file is part of my nixos-config.
+//
+// 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 std::{
-    fs, process,
+    collections::{HashMap, HashSet},
+    fs,
     str::FromStr,
-    thread::{self, sleep},
-    time::Duration,
 };
 
 use anyhow::{Context, Result};
-use log::{error, info};
+use log::info;
 
-use crate::cli::InputCommand;
+use crate::{browser::open_in_browser, cli::InputCommand, state::State};
 
-use super::Input;
+use super::{Input, Tag};
 
 /// # Errors
 /// When command handling fails.
 ///
 /// # Panics
 /// When internal assertions fail.
-pub fn handle(command: InputCommand) -> Result<()> {
+#[allow(clippy::too_many_lines)]
+pub fn handle(command: InputCommand, state: &mut State) -> Result<()> {
     match command {
         InputCommand::Add { inputs } => {
             for input in inputs {
@@ -33,47 +43,37 @@ pub fn handle(command: InputCommand) -> Result<()> {
                 })?;
             }
         }
-        InputCommand::File { file } => {
-            let file = fs::read_to_string(file)?;
-            for line in file.lines() {
-                let input = Input::from_str(line)?;
+        InputCommand::File { file, tags } => {
+            let file = fs::read_to_string(&file)
+                .with_context(|| format!("Failed to read input file '{}'", file.display()))?;
+
+            let mut tag_set = HashSet::with_capacity(tags.len());
+            for tag in tags {
+                tag_set.insert(tag);
+            }
+
+            for line in file.lines().map(str::trim) {
+                if line.is_empty() {
+                    continue;
+                }
+
+                let mut input = Input::from_str(line)?;
+                input.tags = input.tags.union(&tag_set).cloned().collect();
+
                 input.commit().with_context(|| {
                     format!("Failed to add input ('{input}') to the input storage.")
                 })?;
             }
         }
         InputCommand::Review { project } => {
-            let project = project.to_project_display();
-
-            let local_project = project.clone();
-            let handle = thread::spawn(move || {
-                // We assume that the project is not yet open.
-                let mut firefox = process::Command::new("firefox")
-                    .args(["-P", local_project.as_str(), "about:newtab"])
-                    .spawn()?;
-
-                Ok::<_, anyhow::Error>(firefox.wait()?)
-            });
-            // Give Firefox some time to start.
-            info!("Waiting on firefox to start");
-            sleep(Duration::from_secs(4));
-
-            let project_str = project.as_str();
             'outer: for all in Input::all()?.chunks(100) {
                 info!("Starting review for the first hundred URLs.");
 
-                for input in all {
-                    info!("-> '{input}'");
-                    let status = process::Command::new("firefox")
-                        .args(["-P", project_str, input.url().to_string().as_str()])
-                        .status()?;
-
-                    if status.success() {
-                        input.remove()?;
-                    } else {
-                        error!("Adding `{input}` to Firefox failed!");
-                    }
-                }
+                open_in_browser(
+                    &project,
+                    state,
+                    Some(all.iter().map(|f| f.url.clone()).collect()),
+                )?;
 
                 {
                     use std::io::{stdin, stdout, Write};
@@ -98,15 +98,51 @@ pub fn handle(command: InputCommand) -> Result<()> {
                     }
                 }
             }
-
-            info!("Waiting for firefox to stop");
-            handle.join().expect("Should be joinable")?;
         }
-        InputCommand::List => {
-            for url in Input::all()? {
+        InputCommand::List { tags } => {
+            let mut tag_set = HashSet::with_capacity(tags.len());
+            for tag in tags {
+                tag_set.insert(tag);
+            }
+
+            for url in Input::all()?
+                .iter()
+                .filter(|input| tag_set.is_subset(&input.tags))
+            {
                 println!("{url}");
             }
         }
+        InputCommand::Tags {} => {
+            let mut without_tags = 0;
+            let mut tag_set: HashMap<Tag, u64> = HashMap::new();
+
+            for input in Input::all()? {
+                if input.tags.is_empty() {
+                    without_tags += 1;
+                }
+
+                for tag in input.tags {
+                    if let Some(number) = tag_set.get_mut(&tag) {
+                        *number += 1;
+                    } else {
+                        tag_set.insert(tag, 1);
+                    }
+                }
+            }
+
+            let mut tags: Vec<(Tag, u64)> = tag_set.into_iter().collect();
+            tags.sort_by_key(|(_, number)| *number);
+            tags.reverse();
+
+            for (tag, number) in tags {
+                println!("{tag} {number}");
+            }
+
+            if without_tags != 0 {
+                println!();
+                println!("Witohut tags: {without_tags}");
+            }
+        }
     }
     Ok(())
 }