about summary refs log tree commit diff stats
path: root/pkgs/by-name/ts/tskm/src/interface/input
diff options
context:
space:
mode:
Diffstat (limited to 'pkgs/by-name/ts/tskm/src/interface/input')
-rw-r--r--pkgs/by-name/ts/tskm/src/interface/input/handle.rs114
-rw-r--r--pkgs/by-name/ts/tskm/src/interface/input/mod.rs32
2 files changed, 92 insertions, 54 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 9c39cfef..76eea6dc 100644
--- a/pkgs/by-name/ts/tskm/src/interface/input/handle.rs
+++ b/pkgs/by-name/ts/tskm/src/interface/input/handle.rs
@@ -9,25 +9,25 @@
 // 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 {
@@ -43,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};
@@ -108,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(())
 }
diff --git a/pkgs/by-name/ts/tskm/src/interface/input/mod.rs b/pkgs/by-name/ts/tskm/src/interface/input/mod.rs
index 747ba349..1d1d67f4 100644
--- a/pkgs/by-name/ts/tskm/src/interface/input/mod.rs
+++ b/pkgs/by-name/ts/tskm/src/interface/input/mod.rs
@@ -9,7 +9,12 @@
 // If not, see <https://www.gnu.org/licenses/gpl-3.0.txt>.
 
 use std::{
-    collections::HashSet, fmt::Display, fs, io::Write, path::PathBuf, process::Command,
+    collections::{HashMap, HashSet},
+    fmt::Display,
+    fs,
+    io::Write,
+    path::PathBuf,
+    process::Command,
     str::FromStr,
 };
 
@@ -58,7 +63,7 @@ impl Tag {
     }
 }
 
-#[derive(Debug, Clone)]
+#[derive(Debug, Clone, PartialEq, Eq)]
 pub struct Input {
     url: Url,
     tags: HashSet<Tag>,
@@ -175,7 +180,7 @@ impl Input {
         Ok(())
     }
 
-    /// Get all previously [`Self::commit`]ed inputs.
+    /// Get all previously [committed][`Self::commit`] inputs.
     ///
     /// # Errors
     /// When IO handling fails.
@@ -203,13 +208,20 @@ impl Input {
 
             let url_values = fs::read_to_string(PathBuf::from(url_value_file))?;
 
-            output.extend(
-                url_values
-                    .lines()
-                    .map(Self::from_str)
-                    .collect::<Result<Vec<Self>, _>>()?
-                    .into_iter(),
-            );
+            let mut inputs: HashMap<Url, Self> = HashMap::new();
+            for input in url_values
+                .lines()
+                .map(Self::from_str)
+                .collect::<Result<Vec<Self>, _>>()?
+            {
+                if let Some(found) = inputs.get_mut(&input.url) {
+                    found.tags = found.tags.union(&input.tags).cloned().collect();
+                } else {
+                    assert_eq!(inputs.insert(input.url.clone(), input), None);
+                }
+            }
+
+            output.extend(inputs.drain().map(|(_, value)| value));
         }
 
         Ok(output)