Skip to content

Commit

Permalink
Clean up code (#109)
Browse files Browse the repository at this point in the history
Simplify path generation for worktree creation.
Move Suggestion into error module.
Simplify config for get_single_selection.
Move last tmux function in lib to tmux module.
Less cloning of tmux.
  • Loading branch information
petersimonsson authored Jul 7, 2024
1 parent f3070eb commit 203a31b
Show file tree
Hide file tree
Showing 8 changed files with 121 additions and 134 deletions.
30 changes: 10 additions & 20 deletions src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ use crate::{
execute_command, get_single_selection,
picker::Preview,
session::{create_sessions, SessionContainer},
session_exists, set_up_tmux_env, switch_to_session,
tmux::Tmux,
Result, TmsError,
};
Expand Down Expand Up @@ -151,7 +150,7 @@ impl Cli {
}

Some(CliCommand::Windows) => {
windows_command(config, tmux)?;
windows_command(&config, tmux)?;
Ok(SubCommandGiven::Yes)
}
// Handle the config subcommand
Expand Down Expand Up @@ -263,20 +262,16 @@ fn switch_command(config: Config, tmux: &Tmux) -> Result<()> {
.collect::<Vec<String>>();
}

if let Some(target_session) = get_single_selection(
&sessions,
Preview::SessionPane,
config.picker_colors,
config.shortcuts,
tmux.clone(),
)? {
if let Some(target_session) =
get_single_selection(&sessions, Preview::SessionPane, &config, tmux)?
{
tmux.switch_client(&target_session.replace('.', "_"));
}

Ok(())
}

fn windows_command(config: Config, tmux: &Tmux) -> Result<()> {
fn windows_command(config: &Config, tmux: &Tmux) -> Result<()> {
let windows = tmux.list_windows(
"'#{?window_attached,,#{window_index} #{window_name}}'",
None,
Expand All @@ -290,13 +285,8 @@ fn windows_command(config: Config, tmux: &Tmux) -> Result<()> {
.map(|s| s.to_string())
.collect();

if let Some(target_window) = get_single_selection(
&windows,
Preview::SessionPane,
config.picker_colors,
config.shortcuts,
tmux.clone(),
)? {
if let Some(target_window) = get_single_selection(&windows, Preview::SessionPane, config, tmux)?
{
if let Some((windex, _)) = target_window.split_once(' ') {
tmux.select_window(windex);
}
Expand Down Expand Up @@ -616,7 +606,7 @@ fn clone_repo_command(args: &CloneRepoCommand, config: Config, tmux: &Tmux) -> R

let mut session_name = repo_name.to_string();

if session_exists(&session_name, tmux) {
if tmux.session_exists(&session_name) {
session_name = format!(
"{}/{}",
path.parent()
Expand All @@ -629,8 +619,8 @@ fn clone_repo_command(args: &CloneRepoCommand, config: Config, tmux: &Tmux) -> R
}

tmux.new_session(Some(&session_name), Some(&path.display().to_string()));
set_up_tmux_env(&repo, &session_name, tmux)?;
switch_to_session(&session_name, tmux);
tmux.set_up_tmux_env(&repo, &session_name)?;
tmux.switch_to_session(&session_name);

Ok(())
}
Expand Down
2 changes: 1 addition & 1 deletion src/configs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use std::{env, fmt::Display, fs::canonicalize, io::Write, path::PathBuf};

use ratatui::style::{Color, Style};

use crate::{keymap::Keymap, Suggestion};
use crate::{error::Suggestion, keymap::Keymap};

type Result<T> = error_stack::Result<T, ConfigError>;

Expand Down
9 changes: 9 additions & 0 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,12 @@ impl Display for TmsError {
}

impl Error for TmsError {}

#[derive(Debug)]
pub struct Suggestion(pub &'static str);
impl Display for Suggestion {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
use crossterm::style::Stylize;
f.write_str(&format!("Suggestion: {}", self.0).green().bold().to_string())
}
}
94 changes: 6 additions & 88 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,85 +8,15 @@ pub mod repos;
pub mod session;
pub mod tmux;

use error_stack::ResultExt;
use git2::Repository;
use std::{fmt::Display, process};
use configs::Config;
use std::process;

use crate::{
configs::PickerColorConfig,
dirty_paths::DirtyUtf8Path,
error::{Result, TmsError},
keymap::Keymap,
picker::{Picker, Preview},
tmux::Tmux,
};

pub fn switch_to_session(repo_short_name: &str, tmux: &Tmux) {
if !is_in_tmux_session() {
tmux.attach_session(Some(repo_short_name), None);
} else {
let result = tmux.switch_client(repo_short_name);
if !result.status.success() {
tmux.attach_session(Some(repo_short_name), None);
}
}
}

pub fn session_exists(repo_short_name: &str, tmux: &Tmux) -> bool {
// Get the tmux sessions
let sessions = tmux.list_sessions("'#S'");

// If the session already exists switch to it, else create the new session and then switch
sessions.lines().any(|line| {
// tmux will return the output with extra ' and \n characters
line.to_owned().retain(|char| char != '\'' && char != '\n');
line == repo_short_name
})
}

pub fn set_up_tmux_env(repo: &Repository, repo_name: &str, tmux: &Tmux) -> Result<()> {
if repo.is_bare() {
if repo
.worktrees()
.change_context(TmsError::GitError)?
.is_empty()
{
// Add the default branch as a tree (usually either main or master)
let head = repo.head().change_context(TmsError::GitError)?;
let head_short = head
.shorthand()
.ok_or(TmsError::NonUtf8Path)
.attach_printable("The selected repository has an unusable path")?;
let path_to_default_tree = format!("{}{}", repo.path().to_string()?, head_short);
let path = std::path::Path::new(&path_to_default_tree);
repo.worktree(
head_short,
path,
Some(git2::WorktreeAddOptions::new().reference(Some(&head))),
)
.change_context(TmsError::GitError)?;
}
for tree in repo.worktrees().change_context(TmsError::GitError)?.iter() {
let tree = tree.ok_or(TmsError::NonUtf8Path).attach_printable(format!(
"The path to the found sub-tree {tree:?} has a non-utf8 path",
))?;
let window_name = tree.to_string();
let path_to_tree = repo
.find_worktree(tree)
.change_context(TmsError::GitError)?
.path()
.to_string()?;

tmux.new_window(Some(&window_name), Some(&path_to_tree), Some(repo_name));
}
// Kill that first extra window
tmux.kill_window(&format!("{repo_name}:^"));
} else {
// Extra stuff?? I removed launching python environments here but that could be exposed in the configuration
}
Ok(())
}

pub fn execute_command(command: &str, args: Vec<String>) -> process::Output {
process::Command::new(command)
.args(args)
Expand All @@ -95,26 +25,14 @@ pub fn execute_command(command: &str, args: Vec<String>) -> process::Output {
.unwrap_or_else(|_| panic!("Failed to execute command `{command}`"))
}

pub fn is_in_tmux_session() -> bool {
std::env::var("TERM_PROGRAM").is_ok_and(|program| program == "tmux")
}

pub fn get_single_selection(
list: &[String],
preview: Preview,
colors: Option<PickerColorConfig>,
keymap: Option<Keymap>,
tmux: Tmux,
config: &Config,
tmux: &Tmux,
) -> Result<Option<String>> {
let mut picker = Picker::new(list, preview, keymap, tmux).set_colors(colors);
let mut picker = Picker::new(list, preview, config.shortcuts.as_ref(), tmux)
.set_colors(config.picker_colors.as_ref());

picker.run()
}
#[derive(Debug)]
pub struct Suggestion(&'static str);
impl Display for Suggestion {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
use crossterm::style::Stylize;
f.write_str(&format!("Suggestion: {}", self.0).green().bold().to_string())
}
}
20 changes: 7 additions & 13 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,11 @@ use error_stack::Report;

use tms::{
cli::{Cli, SubCommandGiven},
error::Result,
error::{Result, Suggestion},
get_single_selection,
picker::Preview,
session::{create_sessions, SessionContainer},
tmux::Tmux,
Suggestion,
};

fn main() -> Result<()> {
Expand All @@ -32,17 +31,12 @@ fn main() -> Result<()> {
let sessions = create_sessions(&config)?;
let session_strings = sessions.list();

let selected_str = if let Some(str) = get_single_selection(
&session_strings,
Preview::None,
config.picker_colors,
config.shortcuts,
tmux.clone(),
)? {
str
} else {
return Ok(());
};
let selected_str =
if let Some(str) = get_single_selection(&session_strings, Preview::None, &config, &tmux)? {
str
} else {
return Ok(());
};

if let Some(session) = sessions.find_session(&selected_str) {
session.switch_to(&tmux)?;
Expand Down
12 changes: 6 additions & 6 deletions src/picker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,21 +38,21 @@ pub enum Preview {
None,
}

pub struct Picker {
pub struct Picker<'a> {
matcher: Nucleo<String>,
preview: Preview,

colors: Option<PickerColorConfig>,
colors: Option<&'a PickerColorConfig>,

selection: ListState,
filter: String,
cursor_pos: u16,
keymap: Keymap,
tmux: Tmux,
tmux: &'a Tmux,
}

impl Picker {
pub fn new(list: &[String], preview: Preview, keymap: Option<Keymap>, tmux: Tmux) -> Self {
impl<'a> Picker<'a> {
pub fn new(list: &[String], preview: Preview, keymap: Option<&Keymap>, tmux: &'a Tmux) -> Self {
let matcher = Nucleo::new(nucleo::Config::DEFAULT, Arc::new(request_redraw), None, 1);

let injector = matcher.injector();
Expand Down Expand Up @@ -81,7 +81,7 @@ impl Picker {
}
}

pub fn set_colors(mut self, colors: Option<PickerColorConfig>) -> Self {
pub fn set_colors(mut self, colors: Option<&'a PickerColorConfig>) -> Self {
self.colors = colors;

self
Expand Down
11 changes: 5 additions & 6 deletions src/session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ use crate::{
dirty_paths::DirtyUtf8Path,
error::TmsError,
repos::{find_repos, find_submodules},
session_exists, set_up_tmux_env, switch_to_session,
tmux::Tmux,
Result,
};
Expand Down Expand Up @@ -209,24 +208,24 @@ fn switch_to_repo_session(selected_str: &str, found_repo: &Repository, tmux: &Tm
};
let repo_short_name = selected_str.replace('.', "_");

if !session_exists(&repo_short_name, tmux) {
if !tmux.session_exists(&repo_short_name) {
tmux.new_session(Some(&repo_short_name), Some(&path));
set_up_tmux_env(found_repo, &repo_short_name, tmux)?;
tmux.set_up_tmux_env(found_repo, &repo_short_name)?;
}

switch_to_session(&repo_short_name, tmux);
tmux.switch_to_session(&repo_short_name);

Ok(())
}

fn switch_to_bookmark_session(selected_str: &str, tmux: &Tmux, path: &Path) -> Result<()> {
let session_name = selected_str.replace('.', "_");

if !session_exists(&session_name, tmux) {
if !tmux.session_exists(&session_name) {
tmux.new_session(Some(&session_name), path.to_str());
}

switch_to_session(&session_name, tmux);
tmux.switch_to_session(&session_name);

Ok(())
}
Expand Down
Loading

0 comments on commit 203a31b

Please sign in to comment.