I just update to tmux 1.7 and in the man pages there is a new option for using movew: -r which says
move-window [-rdk] [-s src-window] [-t dst-window]
(alias: movew)
This is similar to link-window, except the window at src-window is moved to dst-window. With -r, all windows in the session are renumbered in sequential order, respecting the base-index
option.
If I am having 3 windows in the session: 1 2 3 and I try this command from window 1:
prefix : movew -r -t 4
it gives the error:
session not found: 4
Doesn't this just move window 1 to window 4 and rename the windows? I'm not trying to move it to a new session, just a new window in the same one.
The documentation does not explicitly say this, but when you use -r, the argument to -t is interpreted as a session specifier, not a window specifier.
Thus, move-window -r -t 4 tells tmux to renumber all the windows in the session named/matching the string “4”.
It sounds like you can accomplish what you want* with two commands (assuming that you have base-index set to 1):
move-window -t 4 ; move-window -r
You can bind a sequence of commands to a key, but you need to escape the semicolon (so that the second command is not simply executed immediately after the initial bind command):
bind-key : move-window -t 4 \; move-window -r
Also, if you normally maintain a “gapless” sequence of window numbers (e.g. you have the renumber-windows option enabled), then you can replace the 4 with : and the command pair will work for any number of windows (not just 3 or fewer): : as a destination window specifier means “the first unused window number in the current session” (i.e. 4 if you already have windows 1–3).
* If I understand correctly that you want to transform a set of windows like 1:A, 2:B, 3:C to 1:B, 2:C, 3:A (i.e. move window #1 (“A”) to the end and renumber them all so that you have 1–3 again instead of 2–4).
Related
I often use ^Z to make sleep a process, possibly open a new one, make this one sleep too, and so on, also moving between different Tmux windows.
So what I would like, is that the Tmux status bar update relevantly to indicate me how many processes are sleeping in the currently focused window.
Is that possible?
This is a common question - how to pass information from a shell inside tmux to tmux. The easiest way to do this is to have your shell do it as part of PS1 or some other variable that is evaluated when the prompt is printed.
There are two things you can do:
1) Set a user option with tmux set -w #myoption xyz, then you can use it in the status line with #{#myoption}. This has the disadvantage that it cannot work over ssh.
2) Set the pane title using the escape sequence, for example: printf "\033]2;xyz\033\\". It is then available in #{pane_title}. This works over ssh but had the disadvantage that there is no way to prevent applications also changing the title if they want.
In either case you will only want to run this when TMUX is set, so something like:
[ -n "$TMUX" ] && tmux set -w #myoption $(jobs|wc -l)
I am running a lot of tmux session like
Each tmux session is started as:
today=`date +%Y-%m-%d-%H_%M_%S_%N`
tmux new-session -d -s "$today" zsh /home/path/to/script.sh "with_params"
If i want to only view the list of tmux sessions. I can do by
tmux ls | awk '{print $1}';
Now what i want is to monitor their output using the while loop to show the session name and the recent output:
while true;
do;
echo "##########################################"
??? For list of tmux session; do
sleep 1;
??? session name
??? recent last 5 lines of output
done
echo "##########################################"
done;
??? : What commands should i use
You can use capture-pane to show the last five lines of output:
tmux capture-pane -p -S- -E-|sed '/^$/d'|tail -5
Add -t to specify the pane you want to see - if you just give a session it will use the active pane in the current window.
Add -e if you want colour sequences included.
(Disclaimer: I am fully aware that there are solutions to the problem I describe below that involve writing and calling shell scripts that interact with a running tmux server, or set the necessary environment variables before starting the tmux server. I am specifically posting this questions to see if it possible to solve this problem without the use of such scripts.)
Problem Summary
In my .tmux.conf file, I am trying to set a local variable VALUE to different values depending on whether an environment variable FOO has been set before invoking tmux or not. I then want to use VALUE in other tmux commands. Unfortunately, I either cannot set VALUE correctly or access it after it has been set.
Previous Attempts
According to what I have found in the manpage and in other Q&A posts that contain sample tmux code, there are several ways to implement the above.
Attempt 1
I first tried using the if-shell command. I attempted using this command both with and without the -b flag; the result was the same in either case.
I have seen from examples that I can assign variables with the syntax VALUE=bar. Given that, here is a minimal example of my configuration:
if-shell '[ -z "$FOO" ]' \
'VALUE=bar' \
'VALUE=baz'
set-environment -g RESULT $VALUE
Terminal session:
$ echo $FOO
$ tmux
[detached (from session 0)]
$ tmux showenv -g VALUE
VALUE=bar
$ tmux showenv -g RESULT
RESULT=
$ killall tmux
$ export FOO=foo
$ echo $FOO
foo
$ tmux
[detached (from session 0)]
$ tmux showenv -g VALUE
VALUE=baz
$ tmux showenv -g RESULT
RESULT=
So while VALUE seems to have been set correctly, RESULT does not seem to able to access VALUE.
Attempt 2
The manpage also mentions that commands can be conditionally executed using %if statements. Using this format, I tried the following configuration:
%if #{#(if [ -z "$FOO" ]; then echo 1; else echo 0)}
VALUE=bar
%else
VALUE=baz
%endif
set-environment -g RESULT $VALUE
For the expression in the %if statement, I tried several variations, such as
#{#([ -z "$FOO" ])} (I believe this shouldn't work since this command does not produce any output, but it was worth a try.)
#{==:#(if [-z "$FOO" ]; then echo 1; else echo 0),1} (Just in case an explicit comparison would work)
Even with these variations, regardless of whether FOO was set or not, I got the following:
$ tmux
[detached (from session 0)]
$ tmux showenv -g VALUE
VALUE=baz
$ tmux showenv -g RESULT
RESULT=baz
Thus while VALUE was accessible, it was always baz.
Unfortunately, I have been able to find no useful examples regarding the formats used in conditional statements. The manpage describes how to access tmux variables and some formatting hints; however, regarding accessing environment variables, all I could find was a way to use shell commands:
In addition, the first line of a shell command's output may be inserted using #(). For example, #(uptime) will insert the system's uptime. When constructing formats, tmux does not wait for #() commands to finish; instead, the previous result from running the same command is used, or a placeholder if the command has not been run before.
I am unsure of whether this means I need to call commands in #() twice to avoid using a placeholder value, which may be a possible error on my part.
I was also unable to find a way to print the result of #{} commands easily to debug this part of the statement.
Summary of Questions
While I would appreciate any pointers to information that may help me solve this problem, the most pressing questions for me are:
Why is VALUE being set correctly, yet not accessible to RESULT in Attempt 1?
How should my conditional be written in Attempt 2 to ensure that VALUE is set correctly?
The way tmux runs the config is by parsing the config file into a set of commands, and then executing them (there is a command queue, so the config file is parsed and appended to the queue and then executed from the queue). So there are distinct parse and execution steps.
The problem you are running into with attempt 1, is that the if-shell is run at execution time, but the $VALUE expansion happens at parse time. VALUE is not set when the set-environment command is parsed.
In attempt 2, #() is not processed inside %if so that won't work. However, you can use the variable directly in formats (if it is set). %if happens at parse time.
So you need to make sure assignment and expansion happen in the right order. You have a couple of choices.
You could make tmux expand the variable at command execution time rather than parse time. You can do this by wrapping the setenv inside run-shell, so something like:
if-shell '[ -z "$FOO" ]' \
'VALUE=bar' \
'VALUE=baz'
run 'tmux setenv -g RESULT $VALUE'
Or you could do the assignment at parse time like you tried in attempt 2, but you can't use #() - you need to use a format instead:
%if #{==:#{FOO},}
VALUE=bar
%else
VALUE=baz
%endif
setenv -g RESULT $VALUE
(Note that X=Y in the config file is equivalent to setenv -g X=Y except it happens when parsing rather than executing - both set the global environment. So you could get rid of VALUE and do either RESULT=bar or setenv -g RESULT bar inside the %if.)
Also you can use display -p to print formats. In master and 2.9 you can add -v to see how they are parsed:
$ tmux setenv -g FOO bar
$ tmux display -pv '#{==:#{FOO},baz}'
# expanding format: #{==:#{FOO},baz}
# found #{}: ==:#{FOO},baz
# modifier 0 is ==
# expanding format: #{FOO}
# found #{}: FOO
# format 'FOO' found: bar
# replaced 'FOO' with 'bar'
# result is: bar
# expanding format: baz
# result is: baz
# compare == left is: bar
# compare == right is: baz
# replaced '==:#{FOO},baz' with '0'
# result is: 0
0
I'd like to be able to issue a command like this:
tmux new-window -n irc ssh -t eco /usr/bin/weechat
and have the title of the new window be "irc". Instead, as soon as weechat launches, the title changes to weechat.
I had been under the impression based on the tmux man page that if you set a window title explicitly, automatic-rename would be disabled for you:
automatic-rename
[...] This flag is automatically disabled for an individual window when a
name is specified at creation with new-window or new-session, or later
with rename-window, or with a terminal escape sequence.
But that seems to not be the case. What am I missing here? I do want automatic-rename in most cases - I just want to also be able to specify -n windowname and have it take precedence.
I use vim, and so I wanted to change a couple of tmux's default bindings. In particular I wanted to change the resizing commands so that e.g. ctrl-b ctrl-k resize the split up by one position. I entered the following into my .tmux.conf:
bind-key C-k resizep -U
and it works, except that it only allows me to resize by one unit at a time before I have to hit ctrl again. In other words, I can't hold down ctrl and press b followed by k a bunch of times (while still holding down ctrl), whereas I can hold down ctrl, press b, and then press the up arrow key a bunch of times.
Does anyone know exactly why this is, or how I might replicate my desired behavior?
You need to specify the -r parameter in your command:
bind-key -r C-k resizep -U
As explained in tmux man page:
bind-key [-cnr] [-t mode-table] key command [arguments]
(alias: bind)
Bind key key to command. By default (without -t) the primary
key bindings are modified (those normally activated with the
prefix key); in this case, if -n is specified, it is not neces‐
sary to use the prefix key, command is bound to key alone. The
-r flag indicates this key may repeat, see the repeat-time
option.