Dynamic templates with Tmuxinator
Tags: linux, bash, tmux, tmuxinator
Published: 2020-11-23 16:58:19

## Meet Tmuxinator
A while ago, I was using vim + [tmux](https://github.com/tmux/tmux/wiki) just like I would an IDE. For instance, I would split the first window, with a huge left pane for my vim, and a smaller right pane for the tests.

[Tmuxinator](https://github.com/tmuxinator/tmuxinator) is great tool allowing you to define templates. It will take care of opening the needed windows and panes, and run the commands needed inside.

## Limitations
Let's say you have a template called `mytmux`. Then you can run `tmuxinator mytmux`, and the needed windows, panes and command will execute. If you run `tmuxinator mytmux` again, it will attach to the same tmux session.

But what if we want to use a single template on several projects?

I often use the same setups in my terminal based on the language I work with. A few years back, when learning Haskell,  I was working on a lot of small exercises (for instance using [exercism](https://exercism.io/)) which are all structured the same way. Every time I wanted to code on a project, I would use at least two commands, in two panes:

* `vim -p src/Lib.hs test/Spec.hs`
* `stack test --file-watch`

It is easy to setup a tmuxinator file to do this in a specific location: you need to specify the path of your project in the template. But here, we want it to be dynamic. My first attempt was to use `.` as the path of my template. I would just need to move to the project location, and then to run tmuxinator.

At first, it seems to be working well. But as stated earlier, if your template is called `mytmux`, then the session name will be `mytmux`. That means that you won't be able to use the template in two different projects at the same time. Calling `tmuxinator mytmux` would just connect you to the existing session.

So I did some research, and found out you can actually pass arguments from the command line, and use them in the tmuxinator template. You can also access environment variables and use ruby code directly inside the template. Using this, you will be able to create a dynamic template.

## A dynamic template
You'll find below a (simplified) version of my stack template. It will use as root the path given on the command line, or if none is given, the current working directory from the environment variable PWD. It will also split this path to extract the project directory (the project name in my case), and use it as session name.

Thanks to this little trick, if I use twice tmuxinator on the same directory, I will just join the same session, but if directories differs, it will start a new session. The alternative to this would be to generate a random name for the session, which would allow to create different sessions even for the same project.

```rb
# Set var "WDIR" to workdir
<% if @args[0] %>
<% WDIR=@args[0] %> 
<% else %>
<% WDIR=ENV["PWD"] %>
<% end %>

name: <%= WDIR.split('/').last  %>
root: <%= @args[0] %>

windows:
  - editor:
      layout: f5f0,238x64,0,0{166x64,0,0,0,71x64,167,0,1} 
      panes:
        - vim:
          - vim -p src/Lib.hs test/Spec.hs
        - tests:
          - stack test --file-watch
```