diff options
Diffstat (limited to '')
-rw-r--r-- | pkgs/by-name/ts/tskm/src/cli.rs | 11 | ||||
-rw-r--r-- | pkgs/by-name/ts/tskm/src/interface/neorg/handle.rs | 12 | ||||
-rw-r--r-- | pkgs/by-name/ts/tskm/src/interface/neorg/mod.rs | 9 | ||||
-rw-r--r-- | pkgs/by-name/ts/tskm/src/interface/open/handle.rs | 96 |
4 files changed, 91 insertions, 37 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/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."); |