about summary refs log tree commit diff stats
path: root/pkgs/by-name/ts/tskm
diff options
context:
space:
mode:
Diffstat (limited to 'pkgs/by-name/ts/tskm')
-rw-r--r--pkgs/by-name/ts/tskm/Cargo.lock74
-rw-r--r--pkgs/by-name/ts/tskm/Cargo.toml4
-rw-r--r--pkgs/by-name/ts/tskm/flake.lock6
-rw-r--r--pkgs/by-name/ts/tskm/src/cli.rs11
-rw-r--r--pkgs/by-name/ts/tskm/src/interface/neorg/handle.rs12
-rw-r--r--pkgs/by-name/ts/tskm/src/interface/neorg/mod.rs9
-rw-r--r--pkgs/by-name/ts/tskm/src/interface/open/handle.rs96
7 files changed, 155 insertions, 57 deletions
diff --git a/pkgs/by-name/ts/tskm/Cargo.lock b/pkgs/by-name/ts/tskm/Cargo.lock
index 68823d3c..e4beb42a 100644
--- a/pkgs/by-name/ts/tskm/Cargo.lock
+++ b/pkgs/by-name/ts/tskm/Cargo.lock
@@ -117,9 +117,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
 
 [[package]]
 name = "cc"
-version = "1.2.17"
+version = "1.2.18"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1fcb57c740ae1daf453ae85f16e37396f672b039e00d9d866e07ddb24e328e3a"
+checksum = "525046617d8376e3db1deffb079e91cef90a89fc3ca5c185bbf8c9ecdd15cd5c"
 dependencies = [
  "shlex",
 ]
@@ -147,9 +147,9 @@ dependencies = [
 
 [[package]]
 name = "clap"
-version = "4.5.34"
+version = "4.5.35"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e958897981290da2a852763fe9cdb89cd36977a5d729023127095fa94d95e2ff"
+checksum = "d8aa86934b44c19c50f87cc2790e19f54f7a67aedb64101c2e1a2e5ecfb73944"
 dependencies = [
  "clap_builder",
  "clap_derive",
@@ -157,9 +157,9 @@ dependencies = [
 
 [[package]]
 name = "clap_builder"
-version = "4.5.34"
+version = "4.5.35"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "83b0f35019843db2160b5bb19ae09b4e6411ac33fc6a712003c33e03090e2489"
+checksum = "2414dbb2dd0695280da6ea9261e327479e9d37b0630f6b53ba2a11c60c679fd9"
 dependencies = [
  "anstream",
  "anstyle",
@@ -333,9 +333,9 @@ checksum = "fbd780fe5cc30f81464441920d82ac8740e2e46b29a6fad543ddd075229ce37e"
 
 [[package]]
 name = "iana-time-zone"
-version = "0.1.62"
+version = "0.1.63"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b2fd658b06e56721792c5df4475705b6cda790e9298d19d2f8af083457bcd127"
+checksum = "b0c919e5debc312ad217002b8048a17b7d83f80703865bbfcfebb0458b0b27d8"
 dependencies = [
  "android_system_properties",
  "core-foundation-sys",
@@ -582,9 +582,9 @@ checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
 
 [[package]]
 name = "miniz_oxide"
-version = "0.8.7"
+version = "0.8.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ff70ce3e48ae43fa075863cef62e8b43b71a4f2382229920e0df362592919430"
+checksum = "3be647b768db090acb35d5ec5db2b0e1f1de11133ca123b9eacf5137868f892a"
 dependencies = [
  "adler2",
 ]
@@ -732,9 +732,9 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
 
 [[package]]
 name = "smallvec"
-version = "1.14.0"
+version = "1.15.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7fcf8323ef1faaee30a44a340193b1ac6814fd9b7b4e88e9d4519a3e4abe1cfd"
+checksum = "8917285742e9f3e1683f0a9c4e6b57960b7314d0b08d30d1ecd426713ee2eee9"
 
 [[package]]
 name = "stable_deref_trait"
@@ -1057,11 +1057,37 @@ dependencies = [
 
 [[package]]
 name = "windows-core"
-version = "0.52.0"
+version = "0.61.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9"
+checksum = "4763c1de310c86d75a878046489e2e5ba02c649d185f21c67d4cf8a56d098980"
 dependencies = [
- "windows-targets",
+ "windows-implement",
+ "windows-interface",
+ "windows-link",
+ "windows-result",
+ "windows-strings",
+]
+
+[[package]]
+name = "windows-implement"
+version = "0.60.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "windows-interface"
+version = "0.59.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
 ]
 
 [[package]]
@@ -1071,6 +1097,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "76840935b766e1b0a05c0066835fb9ec80071d4c09a16f6bd5f7e655e3c14c38"
 
 [[package]]
+name = "windows-result"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c64fd11a4fd95df68efcfee5f44a294fe71b8bc6a91993e2791938abcc712252"
+dependencies = [
+ "windows-link",
+]
+
+[[package]]
+name = "windows-strings"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7a2ba9642430ee452d5a7aa78d72907ebe8cfda358e8cb7918a2050581322f97"
+dependencies = [
+ "windows-link",
+]
+
+[[package]]
 name = "windows-sys"
 version = "0.59.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 41fc5888..39feea0c 100644
--- a/pkgs/by-name/ts/tskm/Cargo.toml
+++ b/pkgs/by-name/ts/tskm/Cargo.toml
@@ -7,7 +7,7 @@ edition = "2021"
 
 [dependencies]
 anyhow = "1.0.97"
-clap = { version = "4.5.34", features = ["derive"] }
+clap = { version = "4.5.35", features = ["derive"] }
 dirs = "6.0.0"
 log = "0.4.27"
 lz4_flex = "0.11.3"
@@ -80,7 +80,7 @@ missing_errors_doc = "allow"
 
 [build-dependencies]
 anyhow = "1.0.97"
-clap = { version = "4.5.34", features = ["derive"] }
+clap = { version = "4.5.35", features = ["derive"] }
 clap_complete = "4.5.47"
 dirs = "6.0.0"
 log = "0.4.27"
diff --git a/pkgs/by-name/ts/tskm/flake.lock b/pkgs/by-name/ts/tskm/flake.lock
index 82448387..eb3616c8 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": 1743076231,
-        "narHash": "sha256-yQugdVfi316qUfqzN8JMaA2vixl+45GxNm4oUfXlbgw=",
+        "lastModified": 1744096231,
+        "narHash": "sha256-kUfx3FKU1Etnua3EaKvpeuXs7zoFiAcli1gBwkPvGSs=",
         "owner": "NixOS",
         "repo": "nixpkgs",
-        "rev": "6c5963357f3c1c840201eda129a99d455074db04",
+        "rev": "b2b0718004cc9a5bca610326de0a82e6ea75920b",
         "type": "github"
       },
       "original": {
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/neorg/handle.rs b/pkgs/by-name/ts/tskm/src/interface/neorg/handle.rs
index 577de02c..d904b12e 100644
--- a/pkgs/by-name/ts/tskm/src/interface/neorg/handle.rs
+++ b/pkgs/by-name/ts/tskm/src/interface/neorg/handle.rs
@@ -13,10 +13,10 @@ pub fn handle(command: NeorgCommand, state: &mut State) -> Result<()> {
     match command {
         NeorgCommand::Task { id } => {
             let project = id.project(state)?;
-            let path = dirs::data_local_dir()
+            let base = dirs::data_local_dir()
                 .expect("This should exists")
-                .join("tskm/notes")
-                .join(project.get_neorg_path()?);
+                .join("tskm/notes");
+            let path = base.join(project.get_neorg_path()?);
 
             fs::create_dir_all(path.parent().expect("This should exist"))?;
 
@@ -69,11 +69,7 @@ pub fn handle(command: NeorgCommand, state: &mut State) -> Result<()> {
                     .args([
                         "commit",
                         "--message",
-                        format!(
-                            "chore({}): Update",
-                            path.parent().expect("Should have a parent").display()
-                        )
-                        .as_str(),
+                        format!("chore({}): Update", project.get_neorg_path()?.display()).as_str(),
                         "--no-gpg-sign",
                     ])
                     .current_dir(path.parent().expect("Will exist"))
diff --git a/pkgs/by-name/ts/tskm/src/interface/neorg/mod.rs b/pkgs/by-name/ts/tskm/src/interface/neorg/mod.rs
index dc5cdf19..51d58ab3 100644
--- a/pkgs/by-name/ts/tskm/src/interface/neorg/mod.rs
+++ b/pkgs/by-name/ts/tskm/src/interface/neorg/mod.rs
@@ -8,11 +8,18 @@ pub mod handle;
 pub use handle::handle;
 
 impl Project {
+    /// Return the stored neorg path of this project.
+    /// The returned path will never start with a slash (/).
     pub(super) fn get_neorg_path(&self) -> Result<PathBuf> {
         let project_path = run_task(&[
             "_get",
             format!("rc.context.{}.rc.neorg_path", self.to_context_display()).as_str(),
         ])?;
-        Ok(PathBuf::from(project_path.as_str()))
+
+        let final_path = project_path
+            .strip_prefix('/')
+            .unwrap_or(project_path.as_str());
+
+        Ok(PathBuf::from(final_path))
     }
 }
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..4d7341b2 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 log::{error, info, warn};
+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,58 @@ 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 lock_file = dirs::home_dir()
+                .expect("Exists")
+                .join(".mozilla/firefox")
+                .join(selected_project.to_project_display())
+                .join("lock");
+
+            if lock_file.exists() {
+                let (ip, pid): (IpAddr, u32) = {
+                    let link = fs::read_link(&lock_file).with_context(|| {
+                        format!("Failed to readlink lock at '{}'", lock_file.display())
+                    })?;
+
+                    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"),
+                    )
+                };
+
+                if ip != Ipv4Addr::new(127, 0, 0, 2) {
+                    warn!("Your ip is weird..");
+                }
+
+                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.
+                }
+            } else {
+                // There is no lock file and thus no instance already open.
+            }
+        };
+
+        process::Command::new("firefox")
+            .args(args)
+            .status()
+            .context("Failed to start firefox")?
+    };
 
     if !status.success() {
         error!("Firefox run exited with error.");