aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBenedikt Peetz <benedikt.peetz@b-peetz.de>2025-04-07 12:39:18 +0200
committerBenedikt Peetz <benedikt.peetz@b-peetz.de>2025-04-07 12:39:18 +0200
commit9fd872419d424aa8c5cc2e907c7504e12f96c488 (patch)
treeb59ae1ed026973739e029f33342f92f8535f1d64
parentfix(modules/legacy/conf/xdg/url-handler): Always use dash in name (diff)
downloadnixos-config-9fd872419d424aa8c5cc2e907c7504e12f96c488.zip
feat(pkgs/tskm): Support opening URLs (and correctly default)
-rw-r--r--pkgs/by-name/ts/tskm/src/cli.rs11
-rw-r--r--pkgs/by-name/ts/tskm/src/interface/open/handle.rs84
2 files changed, 68 insertions, 27 deletions
diff --git a/pkgs/by-name/ts/tskm/src/cli.rs b/pkgs/by-name/ts/tskm/src/cli.rs
index bd389ca5..1c72b3c2 100644
--- a/pkgs/by-name/ts/tskm/src/cli.rs
+++ b/pkgs/by-name/ts/tskm/src/cli.rs
@@ -2,6 +2,7 @@ use std::path::PathBuf;
use anyhow::{bail, Result};
use clap::{ArgAction, Parser, Subcommand};
+use url::Url;
use crate::{
interface::{input::Input, project::ProjectName},
@@ -104,14 +105,20 @@ pub enum OpenCommand {
Project {
/// The project to open.
#[arg(value_parser = task::Project::from_project_string)]
- project: Option<task::Project>,
+ project: task::Project,
+
+ /// The URL to open.
+ url: Option<Url>,
},
/// Open a selected project in it's Firefox profile.
///
/// This will use rofi's dmenu mode to select one project from the list of all registered
/// projects.
- Select,
+ Select {
+ /// The URL to open.
+ url: Option<Url>,
+ },
/// List all open tabs in the project.
ListTabs {
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 0b565abd..15c7ac4d 100644
--- a/pkgs/by-name/ts/tskm/src/interface/open/handle.rs
+++ b/pkgs/by-name/ts/tskm/src/interface/open/handle.rs
@@ -1,7 +1,13 @@
-use std::process;
+use std::{
+ fs,
+ net::{IpAddr, Ipv4Addr},
+ path::PathBuf,
+ process,
+};
use anyhow::{bail, Context, Result};
use log::{error, info};
+use url::Url;
use crate::{cli::OpenCommand, rofi, state::State, task};
@@ -11,7 +17,7 @@ pub fn handle(command: OpenCommand, state: &mut State) -> Result<()> {
for project in task::Project::all().context("Failed to get all project files")? {
if project.is_touched() {
info!("Reviewing project: '{}'", project.to_project_display());
- open_in_browser(project, state).with_context(|| {
+ open_in_browser(project, state, None).with_context(|| {
format!(
"Failed to open project ('{}') in Firefox",
project.to_project_display()
@@ -26,23 +32,13 @@ pub fn handle(command: OpenCommand, state: &mut State) -> Result<()> {
}
}
}
- OpenCommand::Project { project } => {
- let project = if let Some(p) = project {
- p
- } else if let Some(p) =
- task::Project::get_current().context("Failed to get currently focused project")?
- {
- p
- } else {
- bail!("You need to either supply a project or have a project active!");
- };
-
+ OpenCommand::Project { project, url } => {
project.touch().context("Failed to touch project")?;
- open_in_browser(&project, state).with_context(|| {
+ open_in_browser(&project, state, url).with_context(|| {
format!("Failed to open project: {}", project.to_project_display())
})?;
}
- OpenCommand::Select => {
+ OpenCommand::Select { url } => {
let selected_project: task::Project = task::Project::from_project_string(
&rofi::select(
task::Project::all()
@@ -60,7 +56,7 @@ pub fn handle(command: OpenCommand, state: &mut State) -> Result<()> {
.touch()
.context("Failed to touch project")?;
- open_in_browser(&selected_project, state).context("Failed to open project")?;
+ open_in_browser(&selected_project, state, url).context("Failed to open project")?;
}
OpenCommand::ListTabs { project } => {
let project = if let Some(p) = project {
@@ -109,7 +105,11 @@ pub fn handle(command: OpenCommand, state: &mut State) -> Result<()> {
Ok(())
}
-fn open_in_browser(selected_project: &task::Project, state: &mut State) -> Result<()> {
+fn open_in_browser(
+ selected_project: &task::Project,
+ state: &mut State,
+ url: Option<Url>,
+) -> Result<()> {
let old_project: Option<task::Project> =
task::Project::get_current().context("Failed to get currently active project")?;
let old_task: Option<task::Task> =
@@ -154,14 +154,48 @@ fn open_in_browser(selected_project: &task::Project, state: &mut State) -> Resul
tracking_task
};
- let status = process::Command::new("firefox")
- .args([
- "-P",
- selected_project.to_project_display().as_str(),
- "about:newtab",
- ])
- .status()
- .context("Failed to start firefox")?;
+ let status = {
+ let mut args = vec!["-P".to_owned(), selected_project.to_project_display()];
+ if let Some(url) = url {
+ args.push(url.to_string());
+ } else {
+ let (ip, pid): (IpAddr, u32) = {
+ let link = fs::read_link(
+ dirs::home_dir()
+ .expect("Exists")
+ .join(".mozilla/firefox")
+ .join(selected_project.to_project_display())
+ .join("lock"),
+ )?;
+ let (ip, pid) = link
+ .to_str()
+ .expect("Should work")
+ .split_once(':')
+ .expect("The split works");
+
+ (
+ ip.parse().expect("Should be a valid ip address"),
+ pid.parse().expect("Should be a valid pid"),
+ )
+ };
+
+ assert_eq!(ip, Ipv4Addr::new(127, 0, 0, 1));
+ if PathBuf::from("/proc").join(pid.to_string()).exists() {
+ // Another Firefox instance has already been started for this project
+ // Add a buffer URL to force Firefox to open it in the already open instance
+ args.push("about:newtab".to_owned());
+ } else {
+ // This project does not yet have another Firefox instance
+ // We do not need to add anything to the arguments, Firefox will open a new
+ // instance.
+ }
+ };
+
+ process::Command::new("firefox")
+ .args(args)
+ .status()
+ .context("Failed to start firefox")?
+ };
if !status.success() {
error!("Firefox run exited with error.");