How to rename tmux window with current running fish command? - terminal

I wish to rename current tmux window to current running process in current pane with running fish. Here's my command I enter:
tmux rename-window $_
But instead of fish, I getting tmux. The problem, as I understand it - is because tmux itself is a process and $_ outputs it, where I need $_ to output process before using $_ as an argument.
The same behavior here:
echo $_
Outputs echo- because of that behavior I can not even see whats the current process is, all I can see is echo. So my question is I think is how to get $_ "before current command", is there some way I can do that?
Solution:
Solution what I found is using that:
run-shell "tmux rename-window \"#{pane_current_command}\""
Strangely, you can not use rename-window outside of run-shell, because rename-window not interpolating tmux variables if runned inside tmux.conf.

Create functions that are run when the fish_preexec and fish_postexec event is fired. See http://fishshell.com/docs/current/commands.html#function
Also, to get the most recently run command use history -n1.

Related

Display welcome message in new tmux session

In a bash script, a new tmux session is started, several processes are launched in separate panes, then the session is attached to the current terminal. I would like to display a short message that gives a few helpful hints how to navigate panes, exit the session etc.
I tried to just echo, but that is not executed inside the session. Is there a good approach how to do this?
Edit: my use case is to have everything contained in a repository. I want to avoid adding config to dotfiles or anything in the user's home dir.
There are a few ways you could print your message perhaps:
Make tmux enter copy mode with some output, for example: tmux new \; run 'echo hello'
Run a script in a new window that prints the output: tmux neww 'echo hello; sleep 5'
Make one of your panes (if your tmux is new enough) open a popup: tmux new 'tmux popup -KER "echo hello; sleep 5"; exec $SHELL"
You can check to see if there are tmux specific environment variables set in your .bashrc and print a message if they exist
eg. in your .bashrc
if [ ! -z "$TMUX" ]; then
echo "Your message"
fi

tmux: run command in pane and capture result, in bash script

Using tmux, I'd like to run a command from one pane against another pane, and capture the output of the command.
For example, say in pane 7 I have an SSH session running, and I'd like to run a bash script in pane 2 to capture the host name from pane 7.
Is this possible?
I know I can do the send keys like so
$ tmux send-keys -t 7 "hostname" Enter
but I'm not sure how to capture the output from pane 7 into a bash variable.
I don't mind if it displays on the screen either (doesnt have to happen in the background).
EDIT: Note that hostname is just an example - I would like to run other scripts against each pane as well
As an alternative to capture-pane you can similarly use pipe-pane. It is often used for logging. You give it a command to pipe all output into, or no command at all to stop piping. So you end up with something like
tmux pipe-pane -t 7 'cat >/tmp/capture'
tmux send-keys -t 7 'hostname' Enter
sleep 1
tmux pipe-pane -t 7 # stops piping
IT=$(</tmp/capture)
Beware, this capture includes carriage-return characters. You will need to remove the first and last lines of the capture to get just the wanted output. Eg:
IT=$(sed '1d;$d;s/\r//' </tmp/capture)
While not exactly what I was looking for, the tmux capture-pane command seems to capture the displayed output of a pane, which I can run of course after running my command.
example.sh
#/bin/bash
# run the command in another pane
tmux send-keys -t 7 "hostname" Enter
# capture it's output
IT=$(tmux capture-pane -p -t 7)
echo "$IT"

bash script - how to execute command after starting new tmux session

For example: start new tmux session, launch webserver (sends log into console), and launch second tmux window for editor.
I had trying do this by different ways - but nothing works.
Take a look at tmuxify (disclaimer: I wrote it).
It's to automate the launch of tmux sessions by defining a layout file with windows, panes and commands.
For commands executions, take a look at this answer.
But you can also predefining layouts of tmux sessions, try tmuxinator/tmuxinator
.
You can run shell commands from ~/.tmux.conf:
if-shell shell-command export I_AM_USING_TMUX=1
But it often does not seem to work as expected...
The environment variable TMUX is set when you run tmux. Then you can conditionally run shell commands from ~/.bash_profile:
if [[ ! -z "$TMUX" ]]; then
# run shell commands
fi
Or, you can export your own environment variable from ~/.tmux.conf file (as I already exported one from the beginning) and use it for if condition from ~/.bash_profile again:
if [[ ! -z "$GHCHOI_IS_USING_TMUX" ]]; then
# run shell commands
fi

pager (less) -- get current scroll position?

I am scripting the display of the output of a script (well, it is just the program git diff) with tmux: Once a filesystem change is detected the shell script executes tmux send-keys q enter C-l "git diff" enter which has it effectively refresh the git diff view.
You might consider this similar to functionality provided by iTerm's coprocesses.
Problem is, I want it on refresh to scroll back to the same position that it was in.
One of the reasons for using tmux is that the window is actually a totally normal and interactive terminal session that can be interacted with as normal to scroll around to look at the full output.
But I want to obtain the scroll position somehow.
Suppose I want to actually do computation on the text content of the terminal window itself, exactly like iTerm2's coprocess does, but so that I can use it on Linux (over ssh). Does tmux provide this ability?
I'm unsure about capturing this with a script, but less -N will show line numbers.
And -jn or --jump-target=n can jump to a location.
About iTerm's coprocesses,
tmux has a command pipe-pane that can be used to pipe the input and output of a shell command to the output and input of a target pane specified by -t.
So if I have a shell program, ~/script.sh for example:
#!/usr/bin/env bash
while read line; do
if [[ "$line" = "are you there?"* ]]; then
echo "echo yes"
fi
done
Note that read line will read every line printed to the pane, i.e. the prompt as well.
I can connect its stdin and stdout to pane 0 in my-session:my-window like so:
tmux pipe-pane -IO -t my-session:my-window.0 "~/script.sh"
and then at the prompt, type echo are you there?, and it responds:
$ echo are you there?
are you there?
$ echo yes
yes
Be careful using -IO together as it can easily cause a feedback loop (I had to kill the tmux server a few times while experimenting with this feature, lol).

Simply forking and redirecting the output of a command to /dev/null

I frequently execute from a shell (in my case Bash) commands that I want to fork immediately and whose output I want to ignore. So frequently in fact that I created a script (silent) to do it:
#!/bin/bash
$# &> /dev/null &
I can then run, e.g.
silent inkscape myfile.svg
and my terminal will not be polluted by the debug output of the process I just forked.
I have two questions:
Is there an "official" way of doing this?, i.e. something shorter but equivalent to &> /dev/null & ?
If not, is there a way I can make tab-completion work after my silent command as if it weren't there ? To give an example, after I've typed silent inksc, I'd like bash to auto-complete my command to silent inkscape when I press [tab].
aside: probably want to exec "$#" &> /dev/null & in your silent script, to cause it to discard the sub-shell, and the quotes around "$#" will keep spaces from getting in the way.
As for #2: complete -F _command silent should do something like what you want. (I call my version of that script launch and have complete -F launch in my .bash_profile)
It looks like nohup does more or less what you want. The tab-completion problem is because bash thinks that you are trying to complete a filename as an argument to the script, whereas its completion rules know that nohup takes a command as its first argument.
Nohup redirects stout and stderr to nohup.out and will also leave the command running if your shell exits.
Here's a little script I use for launching interactive (and chatty) X apps from e.g. an xterm
#!/bin/bash
exe="$1"
shift
"$exe" "$#" 2>/tmp/$$."$exe".err 1>&2 & disown $!
No output, won't die if the terminal exits, but in case something goes wrong there's a log of all output in /tmp
If you don't want the log just use /dev/null instead.
Also will work from a function if you're script-alergic.
Perhaps if you could 'rebind' the tab key? An example on superuser Stackoverflow with the enter key is shown. Is this the right idea?

Resources