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 | 294 |
1 files changed, 116 insertions, 178 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 82f468b3..ca54b422 100644 --- a/pkgs/by-name/ts/tskm/src/interface/open/handle.rs +++ b/pkgs/by-name/ts/tskm/src/interface/open/handle.rs @@ -8,37 +8,46 @@ // 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::{ - fs, - net::{IpAddr, Ipv4Addr}, - path::PathBuf, - process, -}; - -use anyhow::{Context, Result, bail}; -use log::{error, info, warn}; +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)?; + + Ok(tabs.is_empty()) +} + +#[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()); + 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 Firefox", - project.to_project_display() - ) - })?; - project.untouch().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() + ) + })?; + } } } } @@ -68,175 +77,104 @@ pub fn handle(command: OpenCommand, state: &mut State) -> Result<()> { open_in_browser(&selected_project, state, url).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() - ) - })?; - - let selected = session_store - .windows - .iter() - .map(|w| w.selected) - .collect::<Vec<_>>(); - - 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 { - " " + 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; + } + } } - }; - println!("{}{}", is_selected, entry.url); - } - } - } - Ok(()) -} - -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> = - 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 - } - }); - - 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 = { - 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"); + if projects.len() > 1 { + println!("/* {} */", project.to_project_display()); + } - ( - ip.parse().expect("Should be a valid ip address"), - pid.parse().expect("Should be a valid pid"), - ) + 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() + ) + }); + } }; - 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. + for (active, url) in tabs { + let is_selected = { + if active { + "🔻 " + } else { + " " + } + }; + println!("{is_selected}{url}"); } - } 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."); + } } - 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()) } |