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 | 190 |
1 files changed, 190 insertions, 0 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 new file mode 100644 index 00000000..0cf60b41 --- /dev/null +++ b/pkgs/by-name/ts/tskm/src/interface/open/handle.rs @@ -0,0 +1,190 @@ +// 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::{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 { non_empty } => { + for project in task::Project::all().context("Failed to get all project files")? { + 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 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, urls } => { + project.touch().context("Failed to touch project")?; + open_in_browser(&project, state, urls).with_context(|| { + format!("Failed to open project: {}", project.to_project_display()) + })?; + } + OpenCommand::Select { urls } => { + let selected_project: task::Project = task::Project::from_project_string( + &rofi::select( + task::Project::all() + .context("Failed to get all registered projects")? + .iter() + .map(task::Project::to_project_display) + .collect::<Vec<_>>() + .as_slice(), + ) + .context("Failed to get selected project")?, + ) + .expect("This should work, as we send only projects in"); + + selected_project + .touch() + .context("Failed to touch project")?; + + open_in_browser(&selected_project, state, urls).context("Failed to open project")?; + } + 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"); + } + }; + + 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; + } + } + } + } + + if projects.len() > 1 { + println!("/* {} */", project.to_project_display()); + } + + 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() + ) + }); + } + }; + + for (active, url) in tabs { + let is_selected = { + if active { + "🔻 " + } else { + " " + } + }; + println!("{is_selected}{url}"); + } + } + } + } + + Ok(()) +} + +fn get_tabs(project: &task::Project) -> Result<Vec<(bool, Url)>> { + let session_store = project.get_sessionstore()?; + + 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()) +} |