49

I realize that reshaping pane layout in general is not trivial to describe, but I'm interested in at least being able to swap the layout of two adjacent panes.

Suppose I've got these panes laid out like this

 _____________
|    |        |
|    |   2    |
|    |________|
| 0  |        |
|    |        |
|    |        |
|    |   3    |
|____|        |
| 1  |        |
|____|________|

And I now discover that I want even more vertical space with pane 3. It's clearly not trivial to consider how I could rearrange it with pane 0 or 1 but it would be really nice if I could tell 3 and 2 to flip splitting axis:

 _____________
|    |     |  |
|    |     |  |
|    |     |  |
| 0  |     |  |
|    |  3  |2 |
|    |     |  |
|    |     |  |
|____|     |  |
| 1  |     |  |
|____|_____|__|

(note here tmux will most likely reorder it so the old 3 becomes the new pane #2)

Currently when I try to run join-pane -h to reorganize it it tells me "cannot join pane to its own window". Yeah, well, I'm just trying to shuffle it without disrupting the entire layout.

I guess a workaround is to break it out to its own named window and then immediately join it back, though it looks like it won't be able to determine the orientation to switch to (horizontal vs vertical).

Note this is different from the operation of swapping the locations of two panes, for which there exists a command ready to use. I'm looking to swap the splitting axis.

Steven Lu
  • 41,389
  • 58
  • 210
  • 364

7 Answers7

76

Prefix + Space is bound to next layout

Brandon
  • 3,573
  • 6
  • 19
  • 21
29
# Here is a jewel of a bind which does the task of flipping the
# orientation of the current pane with the pane before it (in the
# ordering) -- I had a SO question on this and nobody answered.
bind -n M-f move-pane -t '.-'
bind M-f move-pane -t '.-'
bind -n M-r move-pane -h -t '.-'
bind M-r move-pane -h -t '.-'

The comment is a lie, this functionality is not intuitive and frankly sucks, but it does work in a pinch.

Update: I have since updated this to remove the -n binds in my config, basically you do want to leave open the ability to "pass through" the keystroke through tmux. For example after a while I desired the same exact functionality inside Vim, which I bound to the same combination.


UPDATE: Can combine with the great solution here: https://stackoverflow.com/a/70024796/340947

This allows you to grab a pane and walk it all around. Makes my binds obsolete but both could be kept (like I will) for the familiar behaviors. I don't really like that mine will do something confusing if you happen to run it on the first pane ('.-' would pick the bottom right pane in this case).

Steven Lu
  • 41,389
  • 58
  • 210
  • 364
  • 11
    For future travelers, here's an explanation of what Steven has done: `bind M-f move-pane -t '.-'` This makes a bind for the key command (M)eta+f. Your meta key is typically your `alt` key. The -t selects a target, and the target is presented in the format `'A.B'` A is the target window and B is the pane index of that window. In Steven's example, the target window is omitted, so the currently active window is used. The `-` given for a pane index means "the previous pane by number". By default, panes are split vertically, but the addition of `-h` in the later bind splits horizontally – Taylor Liss May 18 '18 at 23:49
15

C-b space (bound to next-layout by default) cycles through available layouts

R.F
  • 335
  • 3
  • 8
  • 6
    I will refrain from downvoting this answer for two reasons: 1. I did not make clear in my question that i am not interested at all in switching to or cycling through the predefined layouts, as you mention, and 2. This is an answer that may be beneficial to another reader who stumbles on this question and who may be interested in learning how to use the predefined layouts. – Steven Lu Nov 12 '17 at 22:01
  • but all of that is invalidated by how someone already provided your answer in 2013 – Steven Lu Nov 24 '17 at 17:21
  • 4
    I'm upvoting your non-downvote because `C-b space` was exactly what I needed. ;) – Mark Birbeck Dec 05 '18 at 09:44
  • 1
    Mark, then you will probably find useful `C-B M-1`, `C-B M-2`, etc. – Yuriy Ershov Jul 09 '20 at 20:39
  • I quite like C-B M-1, C-B M-2 solution (in which M is Alt key for future travelers). Most often I run tmux on a system that is just set up (not mine) and thus I prefer a solution out of the box, unlike binding keys (that is hard to memorize and needs a copy paste from a Google search). – dashesy Nov 12 '20 at 19:45
9
#flipping the orientation of the current pane with the pane <arrow-way>-of

    bind -n S-Up move-pane -h -t '.{up-of}'
    bind -n S-Right move-pane -t '.{right-of}'
    bind -n S-Left move-pane -t '.{left-of}'
    bind -n S-down move-pane -h -t '.{down-of}'

here are my example to change the otiantation with the pane in the way of the arrow only Press Shift and Arrow-key or rebind the command how you want

Daniel Mueller
  • 106
  • 1
  • 1
  • Phenomenal first post. This is great. Not sure when these target pane tokens got added but THIS IS THE TICKET RIGHT HERE. Also excellent choice of bind, I was previously using shift+arrow to move by word or paragraph in vim but it would never get used. – Steven Lu Nov 18 '21 at 19:59
2

If you really want to do exactly what you said, I would recommend breaking the pane out to a new window, then joining it back in.

For example...

Make sure you have one of the two panes active and break it out:

prefix break-pane

Go back into the main window (prefix w) and Perform any operations on the remaining panes to get it to the layout you want

Make sure you have the pane active you want the other pane to come in adjacent to

Make sure window is named (or assigned name is known)

Go to the new window that pane was broken out into (prefix w again)

join-pane -t <Main Window Name> -h (or -v if you want a vertical split)

Steve
  • 21
  • 1
1

To reiterate:

You have panes
laid out like
this:

 _____________                    _____________
|    |        |                  |    |     |  |
|    |   2    |                  |    |     |  |
|    |________|                  |    |     |  |
| 0  |        |   but you want   | 0  |     |  |
|    |        |   them to look   |    |  3  |2 |
|    |        |   like this:     |    |     |  |
|    |   3    |                  |    |     |  |
|____|        |                  |____|     |  |
| 1  |        |                  | 1  |     |  |
|____|________|                  |____|_____|__|

Since you know all the pane numbers (particularly the pane numbers of the panes you want to rearrange), the short answer is to type:

CTRL+B :move-pane -s 3 -t 2 -h ENTER


But if you don't know all the pane numbers, here is a simple way to reposition a pane:

  1. If your mouse support is not already turned on, turn it on with:
    CTRL+B :set-option -g mouse on ENTER
  2. Using your mouse, click on the pane that you want to tear off -- that is, click on the pane that you want to reposition to be to the right or below another pane. (In your example, this will be pane 2, because you want to tear it off an reposition it to the right of pane 3.)
  3. Next, click on the pane to which you want to attach/reposition the torn-off pane. (In your example, this will be pane 3, as you want to attach pane 2 to the right of it.)
  4. Finally, type:
    CTRL+B :move-pane -s ! -h ENTER

Explanation:

  • The magic is mostly happening in step 4, with the -s ! switch. It tells tmux to move the next-to-last pane you clicked on to the last pane you clicked on.
  • The -h switch in step 4 tells tmux to reattach the pane horizontally -- that is, to the right. If you want to attach it below, either use the -v switch instead, or leave out the -h switch altogether.

Notes:

  • These steps will place pane 2 to the right of pane 3. If you want pane 2 to the left of pane 3, then simply run through the steps with pane 3 as the "tear-off" panel, and pane 2 as the panel to attach to. (Or you can swap the panels; you can read through man tmux to figure out how.)
  • If you run step 4 via the Unix shell prompt, remember to quote the !, like this:
    tmux move-pane -s '!' -h
  • The line:
    set-option -g mouse on
    is a great line to put inside your ~/.tmux.conf file, if you don't already have it in there.
  • As you said above, tmux will assign new pane numbers after you reorder them.
  • To see the pane number of a particular pane, click on the page you want (to make it current), and type:
    CTRL+B   i
    If the status message that shows you the pane number disappears too fast for you, you can lengthen the time it is visible with:
    CTRL+B :set-option -g display-time 4000 ENTER
  • To quickly see the pane number/index of all the panes, type:
    CTRL+B   Q
    If the pane numbers disappear too fast for you, you can lengthen the time they are visible with:
    CTRL+B :set-option -g display-panes-time 4000 ENTER

J-L
  • 1,786
  • 10
  • 13
  • 1
    Thank you for this answer. I didn't have a chance to review it till now. I think that this mouse based functionality can be very powerful but depending on what type of computer I'm using I may prefer to stick with keyboard-only, on the other hand I do believe that this exact use case is one of the few ones where mouse can theoretically be unequivocally superior due to its precision capabilities. I think this could be really good but it will be slightly painful when you cannot get a live preview. I hope it might be possible. I have not explored mouse mapping very deeply yet. – Steven Lu Dec 20 '21 at 19:50
  • *i believe* tmux's built in right mouse click menu is built entirely using binds, which is impressive. I think something could be done to basically use the mouse to drag panes around and rearrange them in ways akin to modern tiling interfaces. It would be phenomenal. As for the keyboard based interface, the other answer which I have accepted is great, it can work a little bit confusingly but never puts you into an unrecoverable state since it's always the same pane you stay focused on. – Steven Lu Dec 20 '21 at 19:52
  • 1
    Thank you for this nicely explained answer with default tmux keybindings. – Arthur Bowers Mar 03 '22 at 09:40
1

Combine your prefix (usually crtl+b) and then space.

When you have 2 panes, it will switch between horizontal to vertical mode.

  • 1
    This is fine when the number of panes you have is 4 or less. This feature is indeed useful but you have to realize that it does not cycle through *every possible* layout you can have. It cycles through the exact sequence of the following: (1) all vertical splits, (2) all horizontal splits, (3) first pane at top and the rest vertically split on the bottom, (4) first pane at left and the rest horizontally split on the right, (5) a fairly reasonable grid layout. *There are only 5 layouts cycled through with `next-layout`*. – Steven Lu Dec 20 '21 at 19:19
  • Thanks for you information, I edited my answer. – Maria Clara Bezerra Dec 20 '21 at 19:28
  • 1
    Thanks! Furthermore, I'd like to mention that the way that tmux handles tiling is probably with a binary tree. in a situation like all horizontal splits for example, the exact layout of the tree is irrelevant, but once you combine different types of splits it has an important effect on the layout. When you have a grid layout, either the horizontal or vertical bar is the "parent" split and can't be "split". Let me know if this is confusing for you. For example in the first diagram in my question, the grid layout is a vertical main split. You can also have a grid with a horizontal main split. – Steven Lu Dec 20 '21 at 19:53
  • 1
    So i think you can start to see where i am coming from. Even if i were to only use 4 panes (ha!!! sometimes I have nearly 20 panes), i would like to be able to e.g. swap from a vertical main split layout to a horizontal main split layout. And `next-layout` sure as hell ain't going to give that to me as an option. – Steven Lu Dec 20 '21 at 19:54