├── LICENSE ├── README.md └── bin └── tmuxify /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Lucas Tolchinsky 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | TMUXIFY 2 | ======= 3 | 4 | `tmuxify` is a bash tool inspired in [tmuxinator](https://github.com/tmuxinator/tmuxinator). The big difference is that it doesn't need Ruby. 5 | 6 | ### TL;DR 7 | 8 | Fire up `tmux` with all the windows, panes and commands you need to start hacking at once! 9 | You will need to create a `.tmuxify.layout` file in the root of your project and run `tmuxify`. 10 | 11 | ### The `.tmuxify.layout` file 12 | 13 | Each line of this file tells `tmuxify` what to run, in what window and pane. It uses the following format 14 | 15 | window-name pane-number command 16 | 17 | Yes, separated by a single space. Everything after the `pane-number` will be treated as part of the `command`. 18 | 19 | Say I need two windows, one for `git` and one for `vim`, then my `.tmuxify.layout` file would look like: 20 | 21 | git 1 git pull 22 | vim 1 vim 23 | 24 | Now I want the `git` window to have a pane with a `rack` server running. 25 | 26 | git 1 git pull 27 | git 2 rackup -p 8080 28 | vim 1 vim 29 | 30 | Get the idea? Go crazy. 31 | 32 | You can also select which pane will have focus after attaching the session by adding a `*` after the `pane-number` 33 | 34 | git 1* git pull 35 | git 2 rackup -p 8080 36 | vim 1 vim 37 | 38 | ### Files 39 | 40 | `tmuxify` looks for a layout file in the current directory. If none is found it will default to `~/.tmuxify.layout`. 41 | 42 | ### Caveats 43 | 44 | 1. The `.tmuxify.layout` file will need a `pane-number` even if the window has only one, like the `vim` example up there. 45 | 2. All the `commands` will `cd` to the directory where the `.tmuxify.layout` file is in. 46 | 3. The pane layout is always tiled. 47 | 4. The specified window names in the layout create new windows, so the first one is never used. Closing the first window will not renumber the existing ones. To fix that, add the following option in `~/.tmux.conf` 48 | 49 | set-option -g renumber-windows on 50 | 51 | ### Installation 52 | 53 | With Homebrew 54 | 55 | ```shell 56 | brew tap tonchis/goodies && brew install tmuxify 57 | ``` 58 | 59 | Or standalone. Here's a oneliner. 60 | 61 | ```shell 62 | $ wget https://raw.githubusercontent.com/tonchis/tmuxify/v1.2.1/bin/tmuxify && chmod +x tmuxify && sudo mv tmuxify /usr/local/bin 63 | ``` 64 | You can pass options to tmux with the `TMUX_OPTS` environment variable if you need. 65 | 66 | ### Why? 67 | 68 | I love `tmux` and the automation that `tmuxinator` offers to speed up my development, yet I find that needing Ruby and YAML is a bit cumbersome, given the powerful CLI tools that `tmux` offers. 69 | 70 | ### Thanks 71 | 72 | To [inkel](https://github.com/inkel) and [djanowski](https://github.com/djanowski) for all their feedback :D 73 | -------------------------------------------------------------------------------- /bin/tmuxify: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | 3 | for file in {$PWD,$HOME}/.tmuxify.layout; do 4 | test -f $file && layout=$file && break 5 | done 6 | 7 | if [[ ! -f $layout ]]; then 8 | echo "Aborting. No $PWD/.tmuxify.layout nor $HOME/.tmuxify.layout found." 9 | exit 1 10 | fi 11 | 12 | session=${1:-$(basename $PWD | tr . -)} 13 | 14 | if [[ -z $(tmux ls -F "#{session_name}" 2>/dev/null | grep "^$session$") ]]; then 15 | tmux $TMUX_OPTS new-session -s $session -d 16 | else 17 | tmux $TMUX_OPTS attach -t $session 18 | exit 0 19 | fi 20 | 21 | while read window pane command; do 22 | 23 | [ -z "$window" -o -z "$pane" -o -z "$command" ] && continue 24 | 25 | pane_number=${pane//[^0-9]*} 26 | active=${pane//[^*]} 27 | 28 | if [[ -n $active ]]; then 29 | active_window=$window 30 | active_pane=$pane_number 31 | fi 32 | 33 | if [[ -z $(tmux list-windows -t $session -F "#{window_name}" | grep "^${window}$") ]]; then 34 | tmux new-window -a -t $session -n $window -c $PWD 35 | fi 36 | 37 | if [[ -z $(tmux list-panes -t $session:$window -F "#{pane_index}" | grep "^${pane_number}$") ]]; then 38 | tmux split-window -t $session:$window 39 | fi 40 | 41 | tmux select-layout -t $session:$window tiled > /dev/null 42 | 43 | tmux send-keys -t $session:$window.$pane_number "$command" C-m 44 | done < $layout 45 | 46 | # The first window is never used. The specified window names in the layout create new windows. 47 | # Closing the first window will not renumber the existing ones. To fix that, add the following option in ~/.tmux.conf 48 | # 49 | # set-option -g renumber-windows on 50 | # 51 | 52 | tmux kill-window -t $session:$( tmux list-windows -t $session -F "#{window_index}" | head -n 1 ) 53 | 54 | tmux select-window -t $session:$active_window 55 | 56 | tmux select-pane -t $session:$active_window.$active_pane 57 | 58 | tmux $TMUX_OPTS attach-session -t $session 59 | --------------------------------------------------------------------------------