Tmux: Switch the split style of two adjacent panes - tmux

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.

Prefix + Space is bound to next layout

# 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).

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

#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

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)

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:
If your mouse support is not already turned on, turn it on with:
CTRL+B :set-option -g mouse on ENTER
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.)
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.)
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

Combine your prefix (usually crtl+b) and then space.
When you have 2 panes, it will switch between horizontal to vertical mode.

Related

QGraphicsItem under cursor at leaving object while over another item

I have a QGraphicsScene, QGraphicsView and some QGraphicsItems subclassed.
I want to track which item is under the cursor topmost visible.
It works fine using hoverEnterEvent in most situations, but if I have two Objects where one is on top of another it does work on entering both but not on leaving the inner object (and re-entering the outer, since it never left the outer in the first place).
+-------------------------------------+
outside | |
| outer |
| |
| |
| +-------------+ | +-------------+
| | | | | |
| | | | | another |
| | inner | | | |
| | | | | |
| | | | +-------------+
| +-------------+ |
| |
| |
| |
| |
+-------------------------------------+
outside -> outer : works, outer is selected
outside -> outer -> outside -> another : works, first outside is selected, than nothing, than another
outer -> inner : works, inner is seletected
outside -> outer -> inner -> outer: does not work, first outside is selected, than inner, but than nothing (should be outer again)
What can I do, besides looping trough all graphicitems triggered via a slight delayed singleshot on hoverLeaveEvent?
Edit:
I found a temporary solution:
I added a global QList < MyQGraphicsItem *> where on MyQGraphicsItem::hoverEnterEvent I add "this", and on MyGraphicsItem::hoverLeaveEvent I remove the last item in the List. So the myGlobalQList.last() always contains the topmost item visible under the cursor.
I assume this is not the best solution since QList is not threadsafe, therefor I am still interested in other solutions.
Your QGraphicsItems live in a QGraphicsScene which can be displayed by one or more QGraphicsViews.
I know that the model-view mapping usually is 1:1.
Still I suggest to implement mouse handling like this in your view, not in the scene:
Install an eventFilter on your graphicsView->viewport().
Override the eventFilter() function in your filter class.
Watch for QEvent::MousePress, MouseMove, MouseRelease, maybe Enter and Leave, depending on what you need.
Probably you need to setMouseTracking(true) on the viewport.
Then, in the event filter function, use QGraphicsView::mapToScene() and QGraphicsScene::itemAt() to find the topmost item, or ::items() to find all items under the cursor.
I recently used this to decorate the topmost item with a border by painting over the view (QGraphicsView::drawForeground()).

How do I merge four windows in to four evenly-spaced panes?

I have four windows called PP1, PP2, PP3, and PP4. I would like to join them so that they would look something like this:
-----------------
| | | | |
|PP1|PP2|PP3|PP4|
| | | | |
-----------------
Currently I'm using join-pane, but I am unsure of how to make them evenly spaced.
tmux join-pane -h -s PP2 -t PP1
tmux join-pane -h -s PP3 -t PP1
tmux join-pane -h -s PP4 -t PP1
I've also tried adding this to the end of the script, but to no avail:
tmux select-layout -t PP1 even-horizontal
Using the keyboard, you can press your activation key (Ctrl + B by default) and then press Alt + 1. Alternatively, repeated Ctrl + B, Space will cycle through the common layout options.

tmux resize on focus

I'd like to be able to specify a secondary size parameter for a particular pane so that it assigns the new size upon focusing the pane, and returns it upon exiting. So e.g.
(Note [] represents focused terminal cursor)
________________
|$ ls | |
|a's | |
|dir | |
|$ |$ [] |
|______|_______|
Swap pane focus
_______________
| | |
|$ ls | |
|a's dir | |
|$ [] |$ |
|________|____|
And so on. Especially gonna be cool since resizing panes in recent tmux versions has it do a great job re-flowing the content rather than slicing it off.
In the example, the left pane has its width set to automatically switch to being 8 columns when it is focused, and it got squished thinner when it lost focus. Notice how the content is still visible (this is afterall why we love tmux) but we can still eat our cake too by letting the currently focused pane expand itself automatically so it's always big enough to do work in!
I can probably come up with some elaborate binds to automate the application of resize-pane commands to do this, and make it just the right amount of elaborate to suit my wishes. But I was hoping there was some kind of built-in feature for this.
It would be practical to track and allow the modification of an auxiliary 4-tuple of integers for each pane. These specify the amount of resize-pane -L/D/U/R operations to do upon that pane's focusing, and the reverse direction upon that pane's defocusing.
There may be other, more reasonable formulations of this.
Found a partial solution...
Ive got my pane switching synced with vim, so whenever I switch switch panes, I also resize tmux.
This is not optimal because tmux is not verifying the current pane size and resizing it accordingly. Anyway, it works pretty well since you can do ctr-h or ctrl-k twice to resize the panes size.
The relevant config is the following:
# Sync panes with vi
bind -n C-h run "(tmux display-message -p '#{pane_current_command}' | grep -iqE '(^|\/)vim(diff)?$' && tmux send-keys C-h) || tmux select-pane -L && tmux resize-pane -R 30"
bind -n C-l run "(tmux display-message -p '#{pane_current_command}' | grep -iqE '(^|\/)vim(diff)?$' && tmux send-keys C-l) || tmux select-pane -R && tmux resize-pane -L 30"
bind -n C-j run "(tmux display-message -p '#{pane_current_command}' | grep -iqE '(^|\/)vim(diff)?$' && tmux send-keys C-j) || tmux select-pane -D"
# Move panes up and down, wont resize
bind -n C-k run "(tmux display-message -p '#{pane_current_command}' | grep -iqE '(^|\/)vim(diff)?$' && tmux send-keys C-k) || tmux select-pane -U"
Sorry, this only amounts to speculation so far, but I thought about it some, and I think there is functionality that is built in to tmux that can support this but it'll require some/a lot of scripting.
See this question I posted.
http://sourceforge.net/p/tmux/mailman/message/31221459/
Essentially it looks like the select-layout command can (possibly!??!) be used to apply an arbitrary mutation to the layout. I've not tested if it works, though.
Thomas Adam suggested to look in the layout-custom.c source to find out more about what's going on. That's about as far as I got. But if indeed it is possible to programmatically mutate the layout and generate working strings to pass to select-layout, then this would be a very good approach.
Update: Now I have asked this directly (whether just generating a suitable string can indeed achieve resizing to arbitrary layouts), but not yet received a response, from Mr. Adam himself, but the reason why I suspect that this can work if we can generate a string that passes the checksum is that I am able to resize my panes any which way, and change them away once I record the string (yielded by the list-windows command), and then afterwards restore to the recorded layout with the string. This means that there is not some sort of explicit action that must be taken to like "save" the layout or anything, it seems like the checksum is just some kind of clever way to help prevent garbage/pathological strings from wreaking havoc with the string interpreter that does the pane layout rearrangement.
You definitely need to pass a string that is nontrivial to construct in order for this to work. However, the code for computing the checksum and the rest is plain to see in layout-custom.c. One day I'll probably be back with a shell script (or just a C program, if it's possible to lift out the code) that implements suitable transformations. Should be fun.
Yes it would be awesome for me to crank this out and pick up that nice little bounty, but I have Real WorkTM waiting for me tonight unfortunately.

Get just the staus of autosys (main) job/box

I have a main autosys box (first_start_main_job)that has 2 different sub box.
When I enter autorep -j first_start_main_job -d I get something like:
JOb Name | Last Start | Last Run | ST | RUN | Pri/Xtx
first_start_main_job | some_time | some_time | SU | some_text
first_start_sub_job | some_time | some_time | SU | some_text
second_start_sub_job | some_time | some_time | SU | some_text
I just want ST(status) of first_start_main_job and store that in a variable.
Please let me know how to accomplish this.
Thanks in advance..
Use the print level switch -L, with level 0, (zero) to list only the outermost box. Then use your favorite script tool to get and store the ST value.
For example:
autorep -J main_job_box -d -L0
man autorep from a AutoSys command prompt will give you more information if you need it.
Just adding up to above posted answer.
To get the Status of Job in a variable we can filter out the status using awk.
e.g.
autorep -J first_start_main_job -d -L0 | awk '/SU /{print $6}'
It will check for the first line and if it contains "SU ", than the status will be printed.

Can ECB be restricted to "take over" only the current buffer when it's activated?

From the get go: sorry if I'm not using the proper emacs terminology -- I'm relatively wet behind the ears in the emacs world.
Most of my work in emacs is for programming R, and I'm using ESS and ECB to do so quite happily. I'd like to build a custom ECB layout which uses the entire bottom of the screen as my R console, while putting some ECB-specific buffers on the left.
Using ECB-esque layout diagrams, I'd like my layout to look like pretty much exactly like "left13", except I'd like the entirety of the "compilation" buffer to be my running R console (or any shell, for that matter):
-------------------------------------------------------
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| Directories | Edit |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
-------------------------------------------------------
| |
| R Console |
| |
-------------------------------------------------------
If I can just split my buffer in two (vertically), then call ecb-activate from the top buffer (and not allow it to touch my bottom buffer), I'm imagining it could work (hence the subject of my question).
That doesn't work, though, and I don't know how to get an entier "bottom pane" out of a layout to work in the way I like using trying to use ECB's customize layout functionality.
Does anybody know if/how I can do this?
Short answer: No.
Longer answer: Unfortunately, ECB completely takes over Emacs "window" management at a very low level. So it's all or nothing. You can't comfortably combine it with regular window splitting. What you might be able to do, is to adjust the layout ECB gives you or to program a custom layout. (Some assembly required.)

Resources