diff options
Diffstat (limited to '')
-rw-r--r-- | pkgs/by-name/ts/tskm/Cargo.lock | 102 | ||||
-rw-r--r-- | pkgs/by-name/ts/tskm/Cargo.toml | 4 | ||||
-rw-r--r-- | pkgs/by-name/ts/tskm/flake.lock | 6 | ||||
-rw-r--r-- | pkgs/by-name/ts/tskm/src/cli.rs | 48 | ||||
-rw-r--r-- | pkgs/by-name/ts/tskm/src/interface/input/handle.rs | 34 | ||||
-rw-r--r-- | pkgs/by-name/ts/tskm/src/interface/input/mod.rs | 32 | ||||
-rw-r--r-- | pkgs/by-name/ts/tskm/src/task/mod.rs | 13 |
7 files changed, 189 insertions, 50 deletions
diff --git a/pkgs/by-name/ts/tskm/Cargo.lock b/pkgs/by-name/ts/tskm/Cargo.lock index 0c339a9a..8233a371 100644 --- a/pkgs/by-name/ts/tskm/Cargo.lock +++ b/pkgs/by-name/ts/tskm/Cargo.lock @@ -46,9 +46,9 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.18" +version = "0.6.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" +checksum = "301af1932e46185686725e0fad2f8f2aa7da69dd70bf6ecc44d6b703844a3933" dependencies = [ "anstyle", "anstyle-parse", @@ -61,33 +61,33 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.10" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" +checksum = "862ed96ca487e809f1c8e5a8447f6ee2cf102f846893800b20cebdf541fc6bbd" [[package]] name = "anstyle-parse" -version = "0.2.6" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" +checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" +checksum = "6c8bdeb6047d8983be085bab0ba1472e6dc604e7041dbf6fcd5e71523014fae9" dependencies = [ "windows-sys", ] [[package]] name = "anstyle-wincon" -version = "3.0.8" +version = "3.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6680de5231bd6ee4c6191b8a1325daa282b415391ec9d3a37bd34f2060dc73fa" +checksum = "403f75924867bb1033c59fbf0797484329750cfbe3c4325cd33127941fabc882" dependencies = [ "anstyle", "once_cell_polyfill", @@ -101,6 +101,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" [[package]] +name = "arraydeque" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d902e3d592a523def97af8f317b08ce16b7ab854c1985a0c671e6f15cebc236" + +[[package]] name = "autocfg" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -114,9 +120,9 @@ checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" [[package]] name = "bumpalo" -version = "3.17.0" +version = "3.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf" +checksum = "793db76d6187cd04dff33004d8e6c9cc4e05cd330500379d2394209271b4aeee" [[package]] name = "byteorder" @@ -126,9 +132,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "cc" -version = "1.2.24" +version = "1.2.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16595d3be041c03b09d08d0858631facccee9221e579704070e6e9e4915d3bc7" +checksum = "956a5e21988b87f372569b66183b78babf23ebc2e744b733e4350a752c4dafac" dependencies = [ "shlex", ] @@ -178,9 +184,9 @@ dependencies = [ [[package]] name = "clap_complete" -version = "4.5.51" +version = "4.5.52" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d2267df7f3c8e74e38268887ea5235d4dfadd39bfff2d56ab82d61776be355e" +checksum = "1a554639e42d0c838336fc4fbedb9e2df3ad1fa4acda149f9126b4ccfcd7900f" dependencies = [ "clap", "clap_lex", @@ -208,9 +214,9 @@ checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" [[package]] name = "colorchoice" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" +checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" [[package]] name = "core-foundation-sys" @@ -260,6 +266,15 @@ dependencies = [ ] [[package]] +name = "encoding_rs" +version = "0.8.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" +dependencies = [ + "cfg-if", +] + +[[package]] name = "fallible-iterator" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -282,6 +297,12 @@ dependencies = [ ] [[package]] +name = "foldhash" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" + +[[package]] name = "form_urlencoded" version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -323,12 +344,30 @@ dependencies = [ ] [[package]] +name = "hashbrown" +version = "0.15.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84b26c544d002229e640969970a2e74021aadf6e2f96372b9c58eff97de08eb3" +dependencies = [ + "foldhash", +] + +[[package]] name = "hashlink" version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ba4ff7128dee98c7dc9794b6a411377e1404dba1c97deb8d1a55297bd25d8af" dependencies = [ - "hashbrown", + "hashbrown 0.14.5", +] + +[[package]] +name = "hashlink" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7382cf6263419f2d8df38c55d7da83da5c18aef87fc7a7fc1fb1e344edfe14c1" +dependencies = [ + "hashbrown 0.15.3", ] [[package]] @@ -561,6 +600,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75761162ae2b0e580d7e7c390558127e5f01b4194debd6221fd8c207fc80e3f5" [[package]] +name = "md5" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "490cc448043f947bae3cbee9c203358d62dbee0db12107a74be5c30ccfd09771" + +[[package]] name = "memchr" version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -667,7 +712,7 @@ dependencies = [ "bitflags", "fallible-iterator", "fallible-streaming-iterator", - "hashlink", + "hashlink 0.9.1", "libsqlite3-sys", "smallvec", ] @@ -733,9 +778,9 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "smallvec" -version = "1.15.0" +version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8917285742e9f3e1683f0a9c4e6b57960b7314d0b08d30d1ecd426713ee2eee9" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" [[package]] name = "stable_deref_trait" @@ -881,12 +926,14 @@ dependencies = [ "dirs", "log", "lz4_flex", + "md5", "serde", "serde_json", "stderrlog", "taskchampion", "url", "walkdir", + "yaml-rust2", ] [[package]] @@ -1205,6 +1252,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb" [[package]] +name = "yaml-rust2" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18b783b2c2789414f8bb84ca3318fc9c2d7e7be1c22907d37839a58dedb369d3" +dependencies = [ + "arraydeque", + "encoding_rs", + "hashlink 0.10.0", +] + +[[package]] name = "yoke" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" diff --git a/pkgs/by-name/ts/tskm/Cargo.toml b/pkgs/by-name/ts/tskm/Cargo.toml index 413530eb..f635ba1e 100644 --- a/pkgs/by-name/ts/tskm/Cargo.toml +++ b/pkgs/by-name/ts/tskm/Cargo.toml @@ -18,7 +18,7 @@ edition = "2021" [dependencies] anyhow = { version = "1.0.98", default-features = false } clap = { version = "4.5.39", features = [ "derive", "std", "color", "help", "usage", "error-context", "suggestions", ], default-features = false } -clap_complete = { version = "4.5.51", features = ["unstable-dynamic"] } +clap_complete = { version = "4.5.52", features = ["unstable-dynamic"] } dirs = { version = "6.0.0", default-features = false } log = { version = "0.4.27", default-features = false } lz4_flex = { version = "0.11.3", features = ["std"], default-features = false } @@ -28,6 +28,8 @@ stderrlog = { version = "0.6.0", default-features = false } taskchampion = { version = "2.0.3", default-features = false } url = { version = "2.5.4", features = ["serde"], default-features = false } walkdir = { version = "2.5.0", default-features = false } +md5 = { version = "0.7.0", default-features = false } +yaml-rust2 = "0.10.2" [profile.release] lto = true diff --git a/pkgs/by-name/ts/tskm/flake.lock b/pkgs/by-name/ts/tskm/flake.lock index 280e8a51..ea422f02 100644 --- a/pkgs/by-name/ts/tskm/flake.lock +++ b/pkgs/by-name/ts/tskm/flake.lock @@ -2,11 +2,11 @@ "nodes": { "nixpkgs": { "locked": { - "lastModified": 1748406211, - "narHash": "sha256-B3BsCRbc+x/d0WiG1f+qfSLUy+oiIfih54kalWBi+/M=", + "lastModified": 1749174413, + "narHash": "sha256-urN9UMK5cd1dzhR+Lx0xHeTgBp2MatA5+6g9JaxjuQs=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "3d1f29646e4b57ed468d60f9d286cde23a8d1707", + "rev": "6ad174a6dc07c7742fc64005265addf87ad08615", "type": "github" }, "original": { diff --git a/pkgs/by-name/ts/tskm/src/cli.rs b/pkgs/by-name/ts/tskm/src/cli.rs index a1dd2d8e..0e32fa62 100644 --- a/pkgs/by-name/ts/tskm/src/cli.rs +++ b/pkgs/by-name/ts/tskm/src/cli.rs @@ -8,15 +8,18 @@ // 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::{ffi::OsStr, path::PathBuf}; +use std::{ffi::OsStr, fmt::Display, path::PathBuf}; use anyhow::{bail, Result}; -use clap::{builder::StyledStr, ArgAction, Parser, Subcommand}; +use clap::{builder::StyledStr, ArgAction, Parser, Subcommand, ValueEnum}; use clap_complete::{ArgValueCompleter, CompletionCandidate}; use url::Url; use crate::{ - interface::{input::Input, project::ProjectName}, + interface::{ + input::{Input, Tag}, + project::ProjectName, + }, state, task, }; @@ -153,7 +156,14 @@ pub enum InputCommand { /// Add all URLs in the file as inputs to be categorized. /// /// This expects each line to contain one URL. - File { file: PathBuf }, + File { + /// The file to read from. + file: PathBuf, + + /// Additional tags to apply to every read URL in the file. + #[arg(add = ArgValueCompleter::new(complete_tag))] + tags: Vec<Tag>, + }, /// Like 'review', but for the inputs that have previously been added. /// It takes a project in which to open the URLs. @@ -164,7 +174,11 @@ pub enum InputCommand { }, /// List all the previously added inputs. - List, + List { + /// Only list the inputs that have all the specified tags + #[arg(add = ArgValueCompleter::new(complete_tag))] + tags: Vec<Tag>, + }, } fn complete_task_id(current: &OsStr) -> Vec<CompletionCandidate> { @@ -272,3 +286,27 @@ fn complete_input_url(current: &OsStr) -> Vec<CompletionCandidate> { output } +fn complete_tag(current: &OsStr) -> Vec<CompletionCandidate> { + let mut output = vec![]; + + let Some(current) = current.to_str() else { + return output; + }; + + if !current.starts_with('+') { + output.push(CompletionCandidate::new(format!("+{current}"))); + } + + output +} + +#[cfg(test)] +mod test { + use clap::CommandFactory; + + use super::CliArgs; + #[test] + fn verify_cli() { + CliArgs::command().debug_assert(); + } +} 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..0469870c 100644 --- a/pkgs/by-name/ts/tskm/src/interface/input/handle.rs +++ b/pkgs/by-name/ts/tskm/src/interface/input/handle.rs @@ -9,6 +9,7 @@ // If not, see <https://www.gnu.org/licenses/gpl-3.0.txt>. use std::{ + collections::HashSet, fs, process, str::FromStr, thread::{self, sleep}, @@ -43,10 +44,23 @@ 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.") })?; @@ -112,8 +126,16 @@ 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}"); } } 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) diff --git a/pkgs/by-name/ts/tskm/src/task/mod.rs b/pkgs/by-name/ts/tskm/src/task/mod.rs index 04efbec5..9c671273 100644 --- a/pkgs/by-name/ts/tskm/src/task/mod.rs +++ b/pkgs/by-name/ts/tskm/src/task/mod.rs @@ -10,14 +10,14 @@ use std::{ fmt::Display, - fs::{self, File, read_to_string}, + fs::{self, read_to_string, File}, path::PathBuf, process::Command, str::FromStr, sync::OnceLock, }; -use anyhow::{Context, Result, bail}; +use anyhow::{bail, Context, Result}; use log::{debug, info, trace}; use taskchampion::Tag; @@ -76,7 +76,6 @@ impl Task { pub fn uuid(&self) -> &taskchampion::Uuid { &self.uuid } - #[must_use] pub fn working_set_id(&self, state: &mut State) -> Result<usize> { Ok(state .replica() @@ -356,5 +355,13 @@ pub(crate) fn run_task(args: &[&str]) -> Result<String> { trace!("Output (stdout): '{}'", stdout.trim()); trace!("Output (stderr): '{}'", stderr.trim()); + if !output.status.success() { + bail!( + "Command `task {}` failed with status: {}", + args.join(" "), + output.status + ); + } + Ok(stdout.trim().to_owned()) } |