aboutsummaryrefslogtreecommitdiffstats
path: root/pkgs/by-name/ts/tskm/src/interface/open/handle.rs
diff options
context:
space:
mode:
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.rs293
1 files changed, 150 insertions, 143 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 dc0d165d..5b9100bc 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,77 @@
-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::{browser::open_in_browser, cli::OpenCommand, rofi, state::State, task};
+
+fn is_empty(project: &task::Project) -> Result<bool> {
+ let tabs = get_tabs(project)?;
-use crate::{cli::OpenCommand, rofi, task};
+ if tabs.is_empty() {
+ Ok(true)
+ } else if tabs.len() > 1 {
+ Ok(false)
+ } else {
+ let url = &tabs[0].1;
-pub fn handle(command: OpenCommand) -> Result<()> {
+ Ok(url == &Url::from_str("qute://start/").expect("Hardcoded"))
+ }
+}
+
+#[allow(clippy::too_many_lines)]
+pub async 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).with_context(|| {
- format!(
- "Failed to open project ('{}') in Firefox",
- project.to_project_display()
- )
- })?;
- project.untouch().with_context(|| {
- format!(
- "Failed to untouch project ('{}')",
- project.to_project_display()
- )
- })?;
+ 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::<Vec<Url>>)
+ .await
+ .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 } => {
- 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).with_context(|| {
- format!("Failed to open project: {}", project.to_project_display())
- })?;
+ open_in_browser(&project, state, urls)
+ .await
+ .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,130 +89,108 @@ pub fn handle(command: OpenCommand) -> Result<()> {
.touch()
.context("Failed to touch project")?;
- open_in_browser(&selected_project).context("Failed to open project")?;
+ open_in_browser(&selected_project, state, urls)
+ .await
+ .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;
+ }
- let selected = session_store
- .windows
- .iter()
- .map(|w| w.selected)
- .collect::<Vec<_>>();
+ // 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 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<_>>();
+ 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;
+ }
- for (index, entry) in tabs.iter().enumerate() {
- let index = index + 1;
- let is_selected = {
- if selected.contains(&index) {
- "🔻 "
- } else {
- " "
+ return Err(err).with_context(|| {
+ format!(
+ "While trying to get the sessionstore for {}",
+ project.to_project_display()
+ )
+ });
}
};
- println!("{}{}", is_selected, entry.url);
+
+ for (active, url) in tabs {
+ let is_selected = {
+ if active {
+ "🔻 "
+ } else {
+ " "
+ }
+ };
+ println!("{is_selected}{url}");
+ }
}
}
}
+
Ok(())
}
-fn open_in_browser(selected_project: &task::Project) -> Result<()> {
- let old_project: Option<task::Project> =
- task::Project::get_current().context("Failed to get currently active project")?;
- // We have ensured that only one task may be active
- let old_task: Option<task::Id> =
- task::Id::get_current().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().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();
- 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
- }
- });
-
- if let Some(task) = tracking_task {
- info!(
- "Starting task {} -> tracking",
- selected_project.to_project_display()
- );
- task.start()
- .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()
- .with_context(|| format!("Failed to stop task {task}"))?;
- }
- if let Some(task) = old_task {
- task.start()
- .with_context(|| format!("Failed to start task {task}"))?;
- }
+fn get_tabs(project: &task::Project) -> Result<Vec<(bool, Url)>> {
+ let session_store = project.get_sessionstore()?;
- 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")?;
- }
+ 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(())
+ Ok(tabs
+ .into_iter()
+ .map(|(active, hist)| (active, hist.url.clone()))
+ .collect())
}