diff options
Diffstat (limited to 'pkgs/by-name/ts/tskm/src/interface/open/handle.rs')
-rw-r--r-- | pkgs/by-name/ts/tskm/src/interface/open/handle.rs | 276 |
1 files changed, 139 insertions, 137 deletions
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..0cf60b41 100644 --- a/pkgs/by-name/ts/tskm/src/interface/open/handle.rs +++ b/pkgs/by-name/ts/tskm/src/interface/open/handle.rs @@ -1,48 +1,73 @@ -use std::process; +// nixos-config - My current NixOS configuration +// +// Copyright (C) 2025 Benedikt Peetz <benedikt.peetz@b-peetz.de> +// SPDX-License-Identifier: GPL-3.0-or-later +// +// This file is part of my nixos-config. +// +// 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::str::FromStr; use anyhow::{bail, Context, Result}; use log::{error, info}; +use url::Url; -use crate::{cli::OpenCommand, rofi, state::State, task}; +use crate::{browser::open_in_browser, cli::OpenCommand, rofi, state::State, task}; +fn is_empty(project: &task::Project) -> Result<bool> { + let tabs = get_tabs(project)?; + + if tabs.is_empty() { + Ok(true) + } else if tabs.len() > 1 { + Ok(false) + } else { + let url = &tabs[0].1; + + Ok(url == &Url::from_str("qute://start/").expect("Hardcoded")) + } +} + +#[allow(clippy::too_many_lines)] pub fn handle(command: OpenCommand, state: &mut State) -> Result<()> { match command { - OpenCommand::Review => { + OpenCommand::Review { non_empty } => { 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(|| { - format!( - "Failed to open project ('{}') in Firefox", - project.to_project_display() - ) - })?; - project.untouch().with_context(|| { + let is_empty = is_empty(project)?; + + if project.is_touched() || (non_empty && !is_empty) { + info!( + "Reviewing project: '{}' ({})", + project.to_project_display(), + if is_empty { "is empty" } else { "is not empty" } + ); + open_in_browser(project, state, None).with_context(|| { format!( - "Failed to untouch project ('{}')", + "Failed to open project ('{}') in qutebrowser", project.to_project_display() ) })?; + + if project.is_touched() { + project.untouch().with_context(|| { + format!( + "Failed to untouch project ('{}')", + project.to_project_display() + ) + })?; + } } } } - 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, urls } => { project.touch().context("Failed to touch project")?; - open_in_browser(&project, state).with_context(|| { + open_in_browser(&project, state, urls).with_context(|| { format!("Failed to open project: {}", project.to_project_display()) })?; } - OpenCommand::Select => { + OpenCommand::Select { urls } => { let selected_project: task::Project = task::Project::from_project_string( &rofi::select( task::Project::all() @@ -60,129 +85,106 @@ 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, urls).context("Failed to open project")?; } - OpenCommand::ListTabs { 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::ListTabs { projects, mode } => { + let projects = { + if let Some(p) = projects { + p + } else if mode.is_some() { + task::Project::all() + .context("Failed to get all projects")? + .to_owned() + } else if let Some(p) = task::Project::get_current() + .context("Failed to get currently focused project")? + { + vec![p] + } else { + bail!("You need to either select projects or pass --mode"); + } }; - let session_store = project.get_sessionstore().with_context(|| { - format!( - "Failed to get session store for project: '{}'", - project.to_project_display() - ) - })?; + for project in &projects { + if let Some(mode) = mode { + match mode { + crate::cli::ListMode::Empty => { + if !is_empty(project)? { + continue; + } + + // We do not need to print, tabs they are always empty. + if projects.len() > 1 { + println!("/* {} */", project.to_project_display()); + } + continue; + } + crate::cli::ListMode::NonEmpty => { + if is_empty(project)? { + continue; + } + } + } + } - let selected = session_store - .windows - .iter() - .map(|w| w.selected) - .collect::<Vec<_>>(); + if projects.len() > 1 { + println!("/* {} */", project.to_project_display()); + } - let tabs = session_store - .windows - .iter() - .flat_map(|window| window.tabs.iter()) - .map(|tab| tab.entries.get(tab.index - 1).expect("This should be Some")) - .collect::<Vec<_>>(); - - for (index, entry) in tabs.iter().enumerate() { - let index = index + 1; - let is_selected = { - if selected.contains(&index) { - "🔻 " - } else { - " " + let tabs = match get_tabs(project) { + Ok(ok) => ok, + Err(err) => { + if projects.len() > 1 { + error!( + "While trying to get the sessionstore for {}: {:?}", + project.to_project_display(), + err + ); + continue; + } + + return Err(err).with_context(|| { + format!( + "While trying to get the sessionstore for {}", + project.to_project_display() + ) + }); } }; - println!("{}{}", is_selected, entry.url); - } - } - } - Ok(()) -} -fn open_in_browser(selected_project: &task::Project, state: &mut State) -> Result<()> { - let old_project: Option<task::Project> = - task::Project::get_current().context("Failed to get currently active project")?; - let old_task: Option<task::Task> = - task::Task::get_current(state).context("Failed to get currently active task")?; - - selected_project.activate().with_context(|| { - format!( - "Failed to active project: '{}'", - selected_project.to_project_display() - ) - })?; - - let tracking_task = { - let all_tasks = selected_project.get_tasks(state).with_context(|| { - format!( - "Failed to get assoctiated tasks for project: '{}'", - selected_project.to_project_display() - ) - })?; - - let tracking_task = all_tasks.into_iter().find(|t| { - let maybe_desc = t.description(state); - if let Ok(desc) = maybe_desc { - desc == "tracking" - } else { - error!( - "Getting task description returned error: {}", - maybe_desc.expect_err("We already check for Ok") - ); - false + for (active, url) in tabs { + let is_selected = { + if active { + "🔻 " + } else { + " " + } + }; + println!("{is_selected}{url}"); + } } - }); - - if let Some(task) = tracking_task { - info!( - "Starting task {} -> tracking", - selected_project.to_project_display() - ); - task.start(state) - .with_context(|| format!("Failed to start task {task}"))?; } - 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")?; - - if !status.success() { - error!("Firefox run exited with error."); } - if let Some(task) = tracking_task { - task.stop(state) - .with_context(|| format!("Failed to stop task {task}"))?; - } - if let Some(task) = old_task { - task.start(state) - .with_context(|| format!("Failed to start task {task}"))?; - } + Ok(()) +} - if let Some(project) = old_project { - project.activate().with_context(|| { - format!("Failed to active project {}", project.to_project_display()) - })?; - } else { - task::Project::clear().context("Failed to clear currently focused project")?; - } +fn get_tabs(project: &task::Project) -> Result<Vec<(bool, Url)>> { + let session_store = project.get_sessionstore()?; - Ok(()) + let tabs = session_store + .windows + .iter() + .flat_map(|window| window.tabs.iter()) + .filter_map(|tab| { + tab.history + .iter() + .find(|hist| hist.active) + .map(|hist| (tab.active, hist)) + }) + .collect::<Vec<_>>(); + + Ok(tabs + .into_iter() + .map(|(active, hist)| (active, hist.url.clone())) + .collect()) } |