diff --git a/src/cli.rs b/src/cli.rs index 86f117b..5b1f045 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -2,7 +2,7 @@ use std::{collections::HashMap, env::current_dir, fs::canonicalize, path::PathBu use crate::{ clone::git_clone, - configs::{Config, SearchDirectory, SessionSortOrderConfig}, + configs::{CloneRepoSwitchConfig, Config, SearchDirectory, SessionSortOrderConfig}, dirty_paths::DirtyUtf8Path, execute_command, get_single_selection, marks::{marks_command, MarksCommand}, @@ -105,6 +105,13 @@ pub struct ConfigCommand { #[arg(long, value_name = "Alphabetical | LastAttached")] /// Set the sort order of the sessions in the switch command session_sort_order: Option, + #[arg(long, value_name = "Always | Never | Foreground", verbatim_doc_comment)] + /// Whether to automatically switch to the new session after the `clone-repo` command finishes + /// `Always` will always switch tmux to the new session + /// `Never` will always create the new session in the background + /// When set to `Foreground`, the new session will only be opened in the background if the active + /// tmux session has changed since starting the clone process (for long clone processes on larger repos) + clone_repo_switch: Option, } #[derive(Debug, Args)] @@ -428,6 +435,10 @@ fn config_command(args: &ConfigCommand, mut config: Config) -> Result<()> { config.session_sort_order = Some(order.to_owned()); } + if let Some(switch) = &args.clone_repo_switch { + config.clone_repo_switch = Some(switch.to_owned()); + } + config.save().change_context(TmsError::ConfigError)?; println!("Configuration has been stored"); Ok(()) @@ -650,11 +661,26 @@ fn clone_repo_command(args: &CloneRepoCommand, config: Config, tmux: &Tmux) -> R let repo_name = repo_name.trim_end_matches(".git"); path.push(repo_name); + let previous_session = tmux.current_session("#{session_name}"); + println!("Cloning into '{repo_name}'..."); let repo = git_clone(&args.repository, &path)?; let mut session_name = repo_name.to_string(); + let switch_config = config + .clone_repo_switch + .unwrap_or(CloneRepoSwitchConfig::Always); + + let switch = match switch_config { + CloneRepoSwitchConfig::Always => true, + CloneRepoSwitchConfig::Never => false, + CloneRepoSwitchConfig::Foreground => { + let active_session = tmux.current_session("#{session_name}"); + previous_session == active_session + } + }; + if tmux.session_exists(&session_name) { session_name = format!( "{}/{}", @@ -669,7 +695,9 @@ fn clone_repo_command(args: &CloneRepoCommand, config: Config, tmux: &Tmux) -> R tmux.new_session(Some(&session_name), Some(&path.display().to_string())); tmux.set_up_tmux_env(&repo, &session_name)?; - tmux.switch_to_session(&session_name); + if switch { + tmux.switch_to_session(&session_name); + } Ok(()) } diff --git a/src/configs.rs b/src/configs.rs index 7dafe38..73979c1 100644 --- a/src/configs.rs +++ b/src/configs.rs @@ -49,6 +49,7 @@ pub struct Config { pub bookmarks: Option>, pub session_configs: Option>, pub marks: Option>, + pub clone_repo_switch: Option, } impl Config { @@ -368,6 +369,29 @@ impl ValueEnum for SessionSortOrderConfig { } } +#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)] +pub enum CloneRepoSwitchConfig { + Always, + Never, + Foreground, +} + +impl ValueEnum for CloneRepoSwitchConfig { + fn value_variants<'a>() -> &'a [Self] { + &[Self::Always, Self::Never, Self::Foreground] + } + + fn to_possible_value(&self) -> Option { + match self { + CloneRepoSwitchConfig::Always => Some(clap::builder::PossibleValue::new("Always")), + CloneRepoSwitchConfig::Never => Some(clap::builder::PossibleValue::new("Never")), + CloneRepoSwitchConfig::Foreground => { + Some(clap::builder::PossibleValue::new("Foreground")) + } + } + } +} + #[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)] pub struct SessionConfig { pub create_script: Option, diff --git a/src/tmux.rs b/src/tmux.rs index 0db369f..65ac481 100644 --- a/src/tmux.rs +++ b/src/tmux.rs @@ -76,6 +76,17 @@ impl Tmux { Tmux::stdout_to_string(output) } + pub fn current_session(&self, format: &str) -> String { + let output = self.execute_tmux_command(&[ + "list-sessions", + "-F", + format, + "-f", + "#{session_attached}", + ]); + Tmux::stdout_to_string(output) + } + pub fn kill_session(&self, session: &str) -> process::Output { self.execute_tmux_command(&["kill-session", "-t", session]) } diff --git a/tests/cli.rs b/tests/cli.rs index aaf3b93..ccffa89 100644 --- a/tests/cli.rs +++ b/tests/cli.rs @@ -3,7 +3,9 @@ use pretty_assertions::assert_eq; use ratatui::style::Color; use std::{fs, str::FromStr}; use tempfile::tempdir; -use tms::configs::{Config, PickerColorConfig, SearchDirectory, SessionSortOrderConfig}; +use tms::configs::{ + CloneRepoSwitchConfig, Config, PickerColorConfig, SearchDirectory, SessionSortOrderConfig, +}; #[test] fn tms_fails_with_missing_config() -> anyhow::Result<()> { @@ -64,6 +66,7 @@ fn tms_config() -> anyhow::Result<()> { bookmarks: None, session_configs: None, marks: None, + clone_repo_switch: Some(CloneRepoSwitchConfig::Always), }; let mut tms = Command::cargo_bin("tms")?; @@ -99,6 +102,8 @@ fn tms_config() -> anyhow::Result<()> { &picker_info_color.to_string(), "--picker-prompt-color", &picker_prompt_color.to_string(), + "--clone-repo-switch", + "Always", ]); tms.assert().success().code(0);