├── README.md ├── bin └── t └── t-smart-tmux-session-manager.tmux /README.md: -------------------------------------------------------------------------------- 1 | # Introducing Sesh 🎉 2 | 3 | I've rewritten this project in Go and called it "sesh". It's more flexible and faster than the original script. I'm no longer maintaining this project. I'll leave it up for historical purposes, but I recommend you check out the new project. 4 | 5 | [Check out sesh](https://github.com/joshmedeski/sesh) 6 | 7 | # t - the smart tmux session manager 8 | 9 | tmux is a powerful tool, but dealing with sessions can be painful. This script makes it easy to create and switch tmux sessions: 10 | 11 |
12 | Documentation 13 | 14 | ## Prerequisites 15 | 16 | - [tmux](https://github.com/tmux/tmux) (>= 3.2) 17 | - [tpm](https://github.com/tmux-plugins/tpm) 18 | - [zoxide](https://github.com/ajeetdsouza/zoxide) 19 | - [fzf](https://github.com/junegunn/fzf) (>=0.35.0) 20 | 21 | _Note: some users have had issues with fzf integration on tmux 3.2a where upon 22 | spawning fzf it would lock the tmux pane. Upgrading to 3.3a seems to be a viable 23 | workaround_ Check [#104](https://github.com/joshmedeski/t-smart-tmux-session-manager/issues/104) 24 | 25 | ```sh 26 | brew install tmux zoxide fzf 27 | ``` 28 | 29 | Use the package manager of your OS if you are not on macOS. 30 | 31 | ## How to install 32 | 33 | ### 1. Install tpm plugin 34 | 35 | Add the following line to your `tmux.conf` file: 36 | 37 | ```sh 38 | set -g @plugin 'joshmedeski/t-smart-tmux-session-manager' 39 | ``` 40 | 41 | **Note:** tpm recommends you list your plugins and then run tpm at the very bottom of your `tmux.conf`. 42 | 43 | Then, run `I` to install the plugin. 44 | 45 | ### 2. Add to path 46 | 47 | To use the `t` script from anywhere, select your shell environment and follow the instructions. 48 | 49 | **Note:** you'll need to check the path of your tpm plugins. It may be `~/.tmux/plugins` or `~/.config/tmux/plugins` depending on where your `tmux.conf` is located. 50 | 51 |
52 | bash 53 | 54 | Add the following line to `~/.bashrc` 55 | 56 | ```sh 57 | # ~/.tmux/plugins 58 | export PATH=$HOME/.tmux/plugins/t-smart-tmux-session-manager/bin:$PATH 59 | # ~/.config/tmux/plugins 60 | export PATH=$HOME/.config/tmux/plugins/t-smart-tmux-session-manager/bin:$PATH 61 | ``` 62 | 63 |
64 | 65 |
66 | zsh 67 | 68 | Add the following line to `~/.zprofile` 69 | 70 | ```sh 71 | # ~/.tmux/plugins 72 | export PATH=$HOME/.tmux/plugins/t-smart-tmux-session-manager/bin:$PATH 73 | # ~/.config/tmux/plugins 74 | export PATH=$HOME/.config/tmux/plugins/t-smart-tmux-session-manager/bin:$PATH 75 | ``` 76 | 77 |
78 | 79 |
80 | fish 81 | 82 | Add the following line to `~/.config/fish/config.fish` 83 | 84 | ```fish 85 | # ~/.tmux/plugins 86 | fish_add_path $HOME/.tmux/plugins/t-smart-tmux-session-manager/bin 87 | # ~/.config/tmux/plugins 88 | fish_add_path $HOME/.config/tmux/plugins/t-smart-tmux-session-manager/bin 89 | ``` 90 | 91 |
92 | 93 | ### 3. Recommended tmux settings 94 | 95 | I recommend you add these settings to your `tmux.conf` to have a better experience with this plugin. 96 | 97 | ```sh 98 | bind-key x kill-pane # skip "kill-pane 1? (y/n)" prompt 99 | set -g detach-on-destroy off # don't exit from tmux when closing a session 100 | ``` 101 | 102 | ### 4. Customize Prompt (optional) 103 | 104 | If your terminal supports [Nerd Font symbols](https://www.nerdfonts.com/), you can customize your prompt. 105 | 106 | ```sh 107 | set -g @t-fzf-prompt ' ' 108 | ``` 109 | 110 | Or you can replace the prompt with anything you'd like. 111 | 112 | ## How to use 113 | 114 | ```sh 115 | Run interactive mode 116 | t 117 | ctrl-s list only tmux sessions 118 | ctrl-x list only zoxide results 119 | ctrl-f list results from the find command 120 | 121 | Go to session (matches tmux session, zoxide result, or directory) 122 | t {name} 123 | 124 | Open popup (while in tmux) 125 | +T 126 | ctrl-s list only tmux sessions 127 | ctrl-x list only zoxide results 128 | ctrl-f list results from the find command 129 | 130 | Show help 131 | t -h 132 | t --help 133 | ``` 134 | 135 | By default, this plugin is bound to `+T` which triggers a fzf-tmux popup that display zoxide results. Type the result you want and when you hit enter it will create a tmux session and connect to it or, if the sessions already exists, switch to it. 136 | 137 | If you are not in tmux, you can simply run `t` to start the interactive script, or call `t {name}` to jump directly to a session of your choosing. 138 | 139 | ### Key Bindings 140 | 141 | - `ctrl-s` list only tmux sessions 142 | - `ctrl-x` list only zoxide results 143 | - `ctrl-f` find by directory 144 | 145 | ## Extra features 146 | 147 | ### Cloning repositories 148 | 149 | You can quickly clone a repository to your preferred directory by using the `t` command combined with the `-r` flag (or `--repo`). 150 | 151 | First, you have to set the `T_REPOS_DIR` variable in your shell environment. Make sure to set it where you want your repositories cloned. 152 | 153 |
154 | bash 155 | 156 | Add the following line to `~/.bashrc` 157 | 158 | ```sh 159 | export T_REPOS_DIR="~/repos" 160 | ``` 161 | 162 |
163 | 164 |
165 | zsh 166 | 167 | Add the following line to `~/.zshrc` 168 | 169 | ```sh 170 | export T_REPOS_DIR="~/repos" 171 | ``` 172 | 173 |
174 | 175 |
176 | fish 177 | 178 | Add the following line to `~/.config/fish/conf.d/t.fish` 179 | 180 | ```fish 181 | set -Ux T_REPOS_DIR ~/repos 182 | ``` 183 | 184 |
185 | 186 | In order to use the feature, simply run: 187 | 188 | ```sh 189 | t -r https://github.com/joshmedeski/t-smart-tmux-session-manager.git 190 | ``` 191 | 192 | **Note:** it has to be a valid git remote url (ending in `.git`) or order to work. 193 | 194 | I prefer to copy the repository URL to my clipboard and run the following command on macOS. 195 | 196 |
197 | bash/zsh 198 | 199 | ```sh 200 | t -r $(pbpaste) 201 | ``` 202 | 203 |
204 | 205 |
206 | fish 207 | 208 | ```sh 209 | t -r (pbpaste) 210 | ``` 211 | 212 |
213 | 214 | If you want to overwrite the directory to clone to, you can overwrite the `T_REPOS_DIR` variable before running the command: 215 | 216 | ```sh 217 | T_REPOS_DIR=~/code t --repo https://github.com/joshmedeski/tmux-list.git 218 | ``` 219 | 220 | ## How to customize 221 | 222 | ### Use Git Root for session name 223 | 224 | You may prefer your session names starting from the root of the git repository. This can help with naming conflicts if you have multiple directories with the same name on your machine and make it clear when you have multiple sessions open in the same git repository. 225 | 226 |
227 | bash 228 | 229 | Add the following line to `~/.bashrc` 230 | 231 | ```sh 232 | export T_SESSION_USE_GIT_ROOT="true" 233 | ``` 234 | 235 |
236 | 237 |
238 | zsh 239 | 240 | Add the following line to `~/.zshrc` 241 | 242 | ```sh 243 | export T_SESSION_USE_GIT_ROOT="true" 244 | ``` 245 | 246 |
247 | 248 |
249 | fish 250 | 251 | Add the following line to `~/.config/fish/conf.d/t.fish` 252 | 253 | ```fish 254 | set -Ux T_SESSION_USE_GIT_ROOT true 255 | ``` 256 | 257 |
258 | 259 | ### Include parent dir in session name 260 | 261 | You may prefer your session names having a prefix of the parent directory. This can help with naming conflicts if you have multiple directories with the same name on your machine. 262 | 263 |
264 | bash 265 | 266 | Add the following line to `~/.bashrc` 267 | 268 | ```sh 269 | export T_SESSION_NAME_INCLUDE_PARENT="true" 270 | ``` 271 | 272 |
273 | 274 |
275 | zsh 276 | 277 | Add the following line to `~/.zshrc` 278 | 279 | ```sh 280 | export T_SESSION_NAME_INCLUDE_PARENT="true" 281 | ``` 282 | 283 |
284 | 285 |
286 | fish 287 | 288 | Add the following line to `~/.config/fish/conf.d/t.fish` 289 | 290 | ```fish 291 | set -Ux T_SESSION_NAME_INCLUDE_PARENT true 292 | ``` 293 | 294 |
295 | 296 | ### Custom fzf-tmux keybinding 297 | 298 | By default, the `t` popup is bound to `T`. In order to overwrite your own custom key binding, add setting the `@t-bind` varaible to your `tmux.conf`: 299 | 300 | ```sh 301 | set -g @t-bind "K" 302 | ``` 303 | 304 | You can unbind the default by using `none`. 305 | 306 | ```sh 307 | set -g @t-bind "none" # unbind default 308 | ``` 309 | 310 | ### Change default fzf results 311 | 312 | By default, t will display tmux sessions and zoxide results by default. You can change this by setting `@t-fzf-default-results` variable to your `tmux.conf`: 313 | 314 | ```sh 315 | set -g @t-fzf-default-results 'sessions' # show tmux sessions by default 316 | ``` 317 | 318 | ```sh 319 | set -g @t-fzf-default-results 'zoxide' # show zoxide results by default 320 | ``` 321 | 322 | ### Custom find command 323 | 324 | By default, the find key binding (`^f`) will run a simple `find` command to search for directories in and around your home directory. 325 | 326 | ```sh 327 | find ~ -maxdepth 3 -type d 328 | ``` 329 | 330 | You can customize this command by setting `@t-find-binding` variable to your `tmux.conf`: 331 | 332 | In this example, I'm setting the prompt with a custom [Nerd Font icon](https://www.nerdfonts.com/) and using [fd](https://github.com/sharkdp/fd) to search directories (including hidden ones) up to two levels deep from my home directory. 333 | 334 | ```sh 335 | set -g @t-fzf-find-binding 'ctrl-f:change-prompt( )+reload(fd -H -d 2 -t d . ~)' 336 | ``` 337 | 338 | Run `man fzf` to learn more about how to customize key bindings with fzf. 339 | 340 | ### FZF_TMUX_OPTS 341 | 342 | If you want to overwrite the fzf-tmux options, you can set the `FZF_TMUX_OPTS` variable in your shell environment. 343 | 344 | ```bash 345 | # ~/.bashrc or ~/.zshrc 346 | export FZF_TMUX_OPTS="-p 55%,60%" 347 | ``` 348 | 349 | ```fish 350 | # ~/.config/fish/config.fish 351 | set -Ux FZF_TMUX_OPTS "-p 55%,60%" 352 | ``` 353 | 354 | Run `man fzf-tmux` to learn more about the available options. 355 | 356 | ### Custom Border Label 357 | 358 | If you want to customize the fzf popup border label, you can add `T_FZF_BORDER_LABEL` to your shell variable 359 | 360 | ```bash 361 | # ~/.bashrc or ~/.zshrc 362 | export T_FZF_BORDER_LABEL=' Your Custom Label ' 363 | ``` 364 | 365 | or if you use fish: 366 | 367 | ```fish 368 | # ~/.config/fish/config.fish 369 | set -Ux T_FZF_BORDER_LABEL " Your Custom Label " 370 | ``` 371 | 372 | ## Background 373 | 374 | Interested in learning more about how this script came to be? Check out [Smart tmux sessions with zoxide and fzf](https://www.joshmedeski.com/posts/smart-tmux-sessions-with-zoxide-and-fzf/). 375 | ] 376 | 377 | ## Startup script 378 | 379 | You can run a startup script when you create a new session. This is useful for running a command when you create a new session, like starting a dev server or automatically opening neovim to begin editing a file. 380 | 381 | This works by adding a `.t` file to your desired directory. Here is a quick script for bootstrapping that file: 382 | 383 | ```sh 384 | touch .t && chmod +x .t && echo -e '#!/usr/bin/env bash\n' > .t && nvim .t 385 | ``` 386 | 387 | I like opening Neovim and the find file Telescope prompt to quickly find a file to edit. Here is an example of what I put in many of my projects: 388 | 389 | ```sh 390 | #!/usr/bin/env bash 391 | nvim -c 'Telescope find_files' 392 | ``` 393 | 394 | So, when you open any project that detects a `.t` it will automatically run that script when a session is created. 395 | 396 | This feature is in early development so please feel free to give feedback if you have ideas for how to improve on it. 397 | 398 | ## Bonus: macOS keyboard shortcut 399 | 400 | My personal workflow uses [macOS Keyboard Shortcuts for tmux](https://www.joshmedeski.com/posts/macos-keyboard-shortcuts-for-tmux/). I have bound the `t` popup to `cmd+j` with the following code: 401 | 402 |
403 | Alacritty 404 | 405 | Add the following line to your `alacritty.yml` 406 | 407 | ```yml 408 | key_bindings: 409 | - { key: K, mods: Command, chars: "\x02\x54" } # open t - tmux smart session manager 410 | ``` 411 | 412 |
413 | 414 |
415 | Kitty 416 | 417 | Add the following line to your `kitty.conf` 418 | 419 | ```sh 420 | map cmd+k send_text all \x02\x54 421 | ``` 422 | 423 |
424 | 425 |
426 | WezTerm 427 | 428 | Add the following line to your `wezterm.lua` inside the **keys** options 429 | 430 | ```sh 431 | { key = 'j', mods = 'CMD', action = wezterm.action.SendString '\x02\x54' }, -- open t - tmux smart session manager 432 | 433 | ``` 434 | 435 |
436 | 437 | **Note:** These bindings are based off the default prefix, `ctrl+b` (which converts to `\x02`). If you changed your prefix, I recommend [watching my video](https://www.joshmedeski.com/posts/macos-keyboard-shortcuts-for-tmux/) which goes into depth how to customize your own keybindings in Alacritty. 438 | 439 |
440 | -------------------------------------------------------------------------------- /bin/t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # determine if the tmux server is running 4 | if tmux list-sessions &>/dev/null; then 5 | TMUX_RUNNING=0 6 | else 7 | TMUX_RUNNING=1 8 | fi 9 | 10 | # determine the user's current position relative tmux: 11 | # serverless - there is no running tmux server 12 | # attached - the user is currently attached to the running tmux server 13 | # detached - the user is currently not attached to the running tmux server 14 | T_RUNTYPE="serverless" 15 | if [ "$TMUX_RUNNING" -eq 0 ]; then 16 | if [ "$TMUX" ]; then # inside tmux 17 | T_RUNTYPE="attached" 18 | else # outside tmux 19 | T_RUNTYPE="detached" 20 | fi 21 | fi 22 | 23 | # display help text with an argument 24 | if [ "$1" = "-h" ] || [ "$1" == "--help" ]; then 25 | printf "\n" 26 | printf "\033[1m t - the smart tmux session manager\033[0m\n" 27 | printf "\033[37m https://github.com/joshmedeski/t-smart-tmux-session-manager\n" 28 | printf "\n" 29 | printf "\033[32m Run interactive mode\n" 30 | printf "\033[34m t\n" 31 | printf "\033[34m ctrl-s list only tmux sessions\n" 32 | printf "\033[34m ctrl-x list only zoxide results\n" 33 | printf "\033[34m ctrl-f list results from the find command\n" 34 | printf "\n" 35 | printf "\033[32m Go to session (matches tmux session, zoxide result, or directory)\n" 36 | printf "\033[34m t {name}\n" 37 | printf "\n" 38 | printf "\033[32m Open popup (while in tmux)\n" 39 | 40 | if [ "$TMUX_RUNNING" -eq 0 ]; then 41 | T_BIND=$(tmux show-option -gvq "@t-bind") 42 | if [ "$T_BIND" = "" ]; then 43 | T_BIND="T" 44 | fi 45 | printf "\033[34m +%s\n" "$T_BIND" 46 | printf "\033[34m ctrl-s list only tmux sessions\n" 47 | printf "\033[34m ctrl-x list only zoxide results\n" 48 | printf "\033[34m ctrl-f list results from the find command\n" 49 | else 50 | printf "\033[34m start tmux server to see bindings\n" "$T_BIND" 51 | fi 52 | 53 | printf "\n" 54 | printf "\033[32m Show help\n" 55 | printf "\033[34m t -h\n" 56 | printf "\033[34m t --help\n" 57 | printf "\n" 58 | exit 0 59 | fi 60 | 61 | HOME_REPLACER="" # default to a noop 62 | echo "$HOME" | grep -E "^[a-zA-Z0-9\-_/.@]+$" &>/dev/null # chars safe to use in sed 63 | HOME_SED_SAFE=$? 64 | if [ $HOME_SED_SAFE -eq 0 ]; then # $HOME should be safe to use in sed 65 | HOME_REPLACER="s|^$HOME/|~/|" 66 | fi 67 | 68 | get_fzf_prompt() { 69 | local fzf_prompt 70 | local fzf_default_prompt='> ' 71 | if [ "$TMUX_RUNNING" -eq 0 ]; then 72 | fzf_prompt="$(tmux show -gqv '@t-fzf-prompt')" 73 | fi 74 | [ -n "$fzf_prompt" ] && echo "$fzf_prompt" || echo "$fzf_default_prompt" 75 | } 76 | PROMPT=$(get_fzf_prompt) 77 | 78 | get_fzf_find_binding() { 79 | local fzf_find_binding 80 | local fzf_find_binding_default='ctrl-f:change-prompt(find> )+reload(find ~ -maxdepth 3 -type d)' 81 | if [ "$TMUX_RUNNING" -eq 0 ]; then 82 | fzf_find_binding="$(tmux show -gqv '@t-fzf-find-binding')" 83 | fi 84 | [ -n "$fzf_find_binding" ] && echo "$fzf_find_binding" || echo "$fzf_find_binding_default" 85 | } 86 | 87 | FIND_BIND=$(get_fzf_find_binding) 88 | 89 | get_sessions_by_mru() { 90 | if [ "$T_RUNTYPE" == "attached" ]; then 91 | CURRENT_SID=$(tmux display-message -p "#{session_id}") 92 | else 93 | CURRENT_SID="" 94 | fi 95 | tmux list-sessions \ 96 | -f "#{!=:#{session_id},$CURRENT_SID}" \ 97 | -F '#{session_last_attached} #{session_name}' \ 98 | | sort --numeric-sort --reverse | awk '{print $2}; END {print "———"}' 99 | } 100 | 101 | get_zoxide_results() { 102 | zoxide query -l | sed -e "$HOME_REPLACER" 103 | } 104 | 105 | get_fzf_results() { 106 | if [ "$TMUX_RUNNING" -eq 0 ]; then 107 | fzf_default_results="$(tmux show -gqv '@t-fzf-default-results')" 108 | case $fzf_default_results in 109 | sessions) 110 | get_sessions_by_mru 111 | ;; 112 | zoxide) 113 | get_zoxide_results 114 | ;; 115 | *) 116 | get_sessions_by_mru && get_zoxide_results # default shows both 117 | ;; 118 | esac 119 | else 120 | get_zoxide_results # only show zoxide results when outside tmux 121 | fi 122 | } 123 | 124 | fzf_border_label_default=' t - smart tmux session manager ' 125 | BORDER_LABEL=${T_FZF_BORDER_LABEL:-$fzf_border_label_default} 126 | 127 | HEADER=" ^s sessions ^x zoxide ^f find" 128 | SESSION_BIND="ctrl-s:change-prompt(sessions> )+reload(tmux list-sessions -F '#S')" 129 | ZOXIDE_BIND="ctrl-x:change-prompt(zoxide> )+reload(zoxide query -l | sed -e \"$HOME_REPLACER\")" 130 | TAB_BIND="tab:down,btab:up" 131 | 132 | if [ $# -ge 1 ]; then # argument provided 133 | if [ "$1" = "-r" ] || [ "$1" == "--repo" ]; then 134 | if [[ -z $T_REPOS_DIR ]]; then 135 | echo "T_REPOS_DIR has not been set" 136 | exit 1 137 | fi 138 | 139 | if [ -z "$2" ]; then 140 | echo "No repository url provided -r {url}" 141 | exit 1 142 | fi 143 | 144 | REPO_URL=$2 145 | cd $T_REPOS_DIR 146 | 147 | if git clone --recursive $REPO_URL; then 148 | RESULT="$T_REPOS_DIR/$(basename "$_" .git)" 149 | else 150 | exit $? # exit code from last command 151 | fi 152 | 153 | else # not -r or --repo 154 | zoxide query "$1" &>/dev/null 155 | ZOXIDE_RESULT_EXIT_CODE=$? 156 | if [ $ZOXIDE_RESULT_EXIT_CODE -eq 0 ]; then # zoxide result found 157 | RESULT=$(zoxide query "$1") 158 | else # no zoxide result found 159 | ls "$1" &>/dev/null 160 | LS_EXIT_CODE=$? 161 | if [ $LS_EXIT_CODE -eq 0 ]; then # directory found 162 | RESULT=$1 163 | else # no directory found 164 | echo "No directory found." 165 | exit 1 166 | fi 167 | fi 168 | fi 169 | else # argument not provided 170 | case $T_RUNTYPE in 171 | attached) 172 | if [[ -z $FZF_TMUX_OPTS ]]; then 173 | FZF_TMUX_OPTS="-p 53%,58%" 174 | fi 175 | 176 | RESULT=$( 177 | (get_fzf_results) | fzf-tmux \ 178 | --bind "$FIND_BIND" \ 179 | --bind "$SESSION_BIND" \ 180 | --bind "$TAB_BIND" \ 181 | --bind "$ZOXIDE_BIND" \ 182 | --border-label "$BORDER_LABEL" \ 183 | --header "$HEADER" \ 184 | --no-sort \ 185 | --prompt "$PROMPT" \ 186 | $FZF_TMUX_OPTS 187 | ) 188 | ;; 189 | detached) 190 | RESULT=$( 191 | (get_fzf_results) | fzf \ 192 | --bind "$FIND_BIND" \ 193 | --bind "$SESSION_BIND" \ 194 | --bind "$TAB_BIND" \ 195 | --bind "$ZOXIDE_BIND" \ 196 | --border \ 197 | --border-label "$BORDER_LABEL" \ 198 | --header "$HEADER" \ 199 | --no-sort \ 200 | --prompt "$PROMPT" 201 | ) 202 | ;; 203 | serverless) 204 | RESULT=$( 205 | (get_fzf_results) | fzf \ 206 | --bind "$FIND_BIND" \ 207 | --bind "$TAB_BIND" \ 208 | --bind "$ZOXIDE_BIND" \ 209 | --border \ 210 | --border-label "$BORDER_LABEL" \ 211 | --header " ^x zoxide ^f find" \ 212 | --no-sort \ 213 | --prompt "$PROMPT" 214 | ) 215 | ;; 216 | esac 217 | fi 218 | 219 | if [ "$RESULT" = "" ]; then # no result 220 | exit 0 # exit silently 221 | fi 222 | 223 | if [ $HOME_SED_SAFE -eq 0 ]; then 224 | RESULT=$(echo "$RESULT" | sed -e "s|^~/|$HOME/|") # get real home path back 225 | fi 226 | 227 | zoxide add "$RESULT" &>/dev/null # add to zoxide database 228 | 229 | if [[ $RESULT != /* ]]; then # not folder path from zoxide result 230 | SESSION_NAME=$RESULT 231 | elif [[ $T_SESSION_USE_GIT_ROOT == 'true' ]]; then 232 | GIT_ROOT=$(git -C $RESULT rev-parse --show-toplevel 2>/dev/null) && echo $GIT_ROOT >/dev/null 233 | if [[ $? -ne 0 ]]; then # not inside git repository 234 | SESSION_NAME=$(basename "$RESULT" | tr ' .:' '_') 235 | else # is in git repository 236 | BASENAME=$(basename $GIT_ROOT) 237 | RELATIVE_PATH=${RESULT#$GIT_ROOT} 238 | 239 | # git worktree 240 | GIT_WORKTREE_ROOT=$(git -C $RESULT rev-parse --git-common-dir 2>/dev/null) && echo $GIT_WORKTREE_ROOT >/dev/null 241 | if [[ $? -eq 0 ]] && [[ ! $GIT_WORKTREE_ROOT =~ ^(\.\./)*\.git$ ]]; then # is inside git worktree 242 | GIT_WORKTREE_ROOT=$(echo $GIT_WORKTREE_ROOT | sed -E 's/(\/.git|\/.bare)$//') # remove .git or .bare suffix 243 | BASENAME=$(basename $GIT_WORKTREE_ROOT) 244 | RELATIVE_PATH=${RESULT#$GIT_WORKTREE_ROOT} 245 | fi 246 | 247 | SEPARATOR="/" 248 | FORMATTED_PATH="${RELATIVE_PATH//\//$SEPARATOR}" 249 | SESSION_NAME=$(echo $BASENAME$FORMATTED_PATH | tr ' .:' '_') 250 | fi 251 | elif [[ $T_SESSION_NAME_INCLUDE_PARENT == 'true' ]]; then 252 | SESSION_NAME=$(echo "$RESULT" | tr ' .:' '_' | awk -F "/" '{print $(NF-1)"/"$NF}') 253 | else 254 | SESSION_NAME=$(basename "$RESULT" | tr ' .:' '_') 255 | fi 256 | 257 | if [ "$T_RUNTYPE" != "serverless" ]; then 258 | SESSION=$(tmux list-sessions -F '#S' | grep "^$SESSION_NAME$") # find existing session 259 | fi 260 | 261 | if [ "$SESSION" = "" ]; then # session is missing 262 | SESSION="$SESSION_NAME" 263 | if [ -e $RESULT/.t ]; then 264 | tmux new-session -d -s "$SESSION" -c "$RESULT" $RESULT/.t # create session and run .t startup script 265 | else 266 | tmux new-session -d -s "$SESSION" -c "$RESULT" # create session 267 | fi 268 | fi 269 | 270 | case $T_RUNTYPE in # attach to session 271 | attached) 272 | tmux switch-client -t "$SESSION" 273 | ;; 274 | detached | serverless) 275 | tmux attach -t "$SESSION" 276 | ;; 277 | esac 278 | -------------------------------------------------------------------------------- /t-smart-tmux-session-manager.tmux: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | CURRENT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" 4 | 5 | tmux_option_or_fallback() { 6 | local option_value 7 | option_value="$(tmux show-option -gqv "$1")" 8 | if [ -z "$option_value" ]; then 9 | option_value="$2" 10 | fi 11 | echo "$option_value" 12 | } 13 | 14 | tmux bind-key "$(tmux_option_or_fallback "@t-bind" "T")" run-shell "$CURRENT_DIR/bin/t" 15 | --------------------------------------------------------------------------------