diff options
author | Benedikt Peetz <benedikt.peetz@b-peetz.de> | 2025-07-20 18:41:16 +0200 |
---|---|---|
committer | Benedikt Peetz <benedikt.peetz@b-peetz.de> | 2025-07-20 18:41:16 +0200 |
commit | 24d7d3e14ff14d6e43670023bd0862e82f9408e7 (patch) | |
tree | 79d0da401fac0dbc451f8c0ac63e2306d4c4ac16 | |
parent | modules/legacy/conf/iamb: Move to `by-name` and modernize (diff) | |
download | nixos-config-24d7d3e14ff14d6e43670023bd0862e82f9408e7.zip |
pkgs/tskm: Support raw paths in place of URLs
Otherwise, using `tskm` as an URL opener might fail (e.g., as `xdg-open /some/path`, would still invoke it).
-rw-r--r-- | pkgs/by-name/ts/tskm/src/browser/mod.rs | 16 | ||||
-rw-r--r-- | pkgs/by-name/ts/tskm/src/cli.rs | 6 | ||||
-rw-r--r-- | pkgs/by-name/ts/tskm/src/interface/open/handle.rs | 2 | ||||
-rw-r--r-- | pkgs/by-name/ts/tskm/src/interface/open/mod.rs | 30 |
4 files changed, 44 insertions, 10 deletions
diff --git a/pkgs/by-name/ts/tskm/src/browser/mod.rs b/pkgs/by-name/ts/tskm/src/browser/mod.rs index d83bcbc4..2129982f 100644 --- a/pkgs/by-name/ts/tskm/src/browser/mod.rs +++ b/pkgs/by-name/ts/tskm/src/browser/mod.rs @@ -14,11 +14,14 @@ use url::Url; use crate::{state::State, task}; #[allow(clippy::too_many_lines)] -pub fn open_in_browser( +pub fn open_in_browser<U>( selected_project: &task::Project, state: &mut State, - urls: Option<Vec<Url>>, -) -> Result<()> { + urls: Option<Vec<U>>, +) -> Result<()> +where + U: Into<Url>, +{ let old_project: Option<task::Project> = task::Project::get_current().context("Failed to get currently active project")?; let old_task: Option<task::Task> = @@ -129,7 +132,7 @@ pub fn open_in_browser( if let Some(mut stream) = socket { let real_url = if let Some(urls) = urls { - urls.into_iter().map(|url| url.to_string()).collect() + urls.into_iter().map(|url| url.into().to_string()).collect() } else { // Always add a new tab, so that qutebrowser is marked as “urgent”. vec!["qute://start".to_owned()] @@ -153,7 +156,10 @@ pub fn open_in_browser( ExitStatus::default() } else { let args = if let Some(urls) = urls { - urls.iter().map(ToString::to_string).collect() + urls.into_iter() + .map(Into::<Url>::into) + .map(|u| u.to_string()) + .collect() } else { vec![] }; diff --git a/pkgs/by-name/ts/tskm/src/cli.rs b/pkgs/by-name/ts/tskm/src/cli.rs index 23d9545f..359c1050 100644 --- a/pkgs/by-name/ts/tskm/src/cli.rs +++ b/pkgs/by-name/ts/tskm/src/cli.rs @@ -13,11 +13,11 @@ use std::{ffi::OsStr, path::PathBuf}; use anyhow::{bail, Result}; use clap::{builder::StyledStr, ArgAction, Parser, Subcommand, ValueEnum}; use clap_complete::{ArgValueCompleter, CompletionCandidate}; -use url::Url; use crate::{ interface::{ input::{Input, Tag}, + open::UrlLike, project::ProjectName, }, state, task, @@ -127,7 +127,7 @@ pub enum OpenCommand { project: task::Project, /// The URLs to open. - urls: Option<Vec<Url>>, + urls: Option<Vec<UrlLike>>, }, /// Open a selected project in it's Qutebrowser profile. @@ -136,7 +136,7 @@ pub enum OpenCommand { /// projects. Select { /// The URLs to open. - urls: Option<Vec<Url>>, + urls: Option<Vec<UrlLike>>, }, /// List all open tabs in the project. diff --git a/pkgs/by-name/ts/tskm/src/interface/open/handle.rs b/pkgs/by-name/ts/tskm/src/interface/open/handle.rs index 0cf60b41..3897a63b 100644 --- a/pkgs/by-name/ts/tskm/src/interface/open/handle.rs +++ b/pkgs/by-name/ts/tskm/src/interface/open/handle.rs @@ -43,7 +43,7 @@ pub fn handle(command: OpenCommand, state: &mut State) -> Result<()> { project.to_project_display(), if is_empty { "is empty" } else { "is not empty" } ); - open_in_browser(project, state, None).with_context(|| { + open_in_browser(project, state, None::<Vec<Url>>).with_context(|| { format!( "Failed to open project ('{}') in qutebrowser", project.to_project_display() diff --git a/pkgs/by-name/ts/tskm/src/interface/open/mod.rs b/pkgs/by-name/ts/tskm/src/interface/open/mod.rs index e302c7d1..e403b4a8 100644 --- a/pkgs/by-name/ts/tskm/src/interface/open/mod.rs +++ b/pkgs/by-name/ts/tskm/src/interface/open/mod.rs @@ -8,7 +8,11 @@ // 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::File, io::Read, str::FromStr}; +use std::{ + fs::{self, File}, + io::Read, + str::FromStr, +}; use anyhow::{anyhow, Context, Result}; use taskchampion::chrono::NaiveDateTime; @@ -20,6 +24,30 @@ use crate::task::Project; pub mod handle; pub use handle::handle; +/// An Url that also accepts file paths +#[derive(Debug, Clone)] +pub struct UrlLike(Url); + +impl FromStr for UrlLike { + type Err = url::ParseError; + + fn from_str(s: &str) -> std::result::Result<Self, Self::Err> { + if let Ok(u) = fs::canonicalize(s) { + Ok(Self(Url::from_file_path(u).expect( + "The path could be canonicalized, as such it is valid for this", + ))) + } else { + Url::from_str(s).map(Self) + } + } +} + +impl From<UrlLike> for Url { + fn from(value: UrlLike) -> Self { + value.0 + } +} + impl Project { pub(super) fn get_sessionstore(&self) -> Result<SessionStore> { let path = dirs::data_local_dir() |