I wrote an addon for tmux, tmux-gitbar. It shows some information about Git status of current directory in tmux status bar. The status bar must be updated each time the user runs a command, to do this I added a function, called from the$PROMPT_COMMAND
variable.
.bashrc
:
source ~/.tmux-gitbar/tmux-gitbar.sh;
tmux-gitbar.sh
:
update_gitbar() {
#
# update tmux status bar
#
}
PROMPT_COMMAND="update_gitbar; $PROMPT_COMMAND"
I'd like to achieve the same result without adding a line to .bashrc
. All should be performed intmux.conf
file. I already managed to modify $PROMPT_COMMAND
by doing this in tmux.conf
:
PROMPT_COMMAND="update_gitbar; $PROMPT_COMMAND"
Now my problem is to export update_gitbar
function into the environment
I tried various ways to source the script, but with no luck:
run-shell "source ~/.tmux-gitbar/tmux-gitbar.sh"
run-shell "eval $(~/.tmux-gitbar/tmux-gitbar.sh)"
run-shell "eval $(cat ~/.tmux-gitbar/tmux-gitbar.sh)"
I always get :
update_gitbar: command not found
How can I, from tmux.conf file, export a function (declared in another file) and make that function available to the environment?
If that can help, current code is available on github
Trying to solve it via run-shell is futile. By definition, anything run using run-shell is in a sub-shell/child process, and will not be able to affect tmux's environment.
Honestly, I highly recommend that you use an external shell script, instead of a function. Among other things, this will allow you to make changes to update_gitbar
that take effect instantly everywhere. It's slightly less efficient, of course, but I don't think you're likely to notice the difference. Just throw it in ~/bin
, say, and make PROMPT_COMMAND
be "$HOME/bin/update_gitbar; $PROMPT_COMMAND"
.
However, if you must insist on using shell functions – which I must point out, are a bash-only feature, and was also the source of major security vulnerabilities last year ("ShellShock"; note: not the use of the feature, just its actual existence, and very broken implementation, which has since been fixed in newer versions), there are two solutions I can offer.
The first, and simplest way, is just to make sure you do the export in the environment that starts the tmux session, and not after or within it. If you start tmux versus a shell script, say, you'd just do:
export -f update_gitbar
tmux
As part of that startup, you'd also probably want to put the definition of update_gitbar
, and your PROMPT_COMMAND
setting. Note that once tmux is started, you wouldn't be able to change update_gitbar
and have it propagate to everywhere it's being used – that's why I recommended a shell script instead. You would however still be able to modify its meaning for new shells (in new tmux panes, say) using the method described below.
The final method, the hardest and least-portable, is to use tmux's setenv
, or the same VAR=value
syntax in .tmux.conf
. Bash implements its unique "export function" feature just by using a normal export variable, with a special format.
The exact nature of that format is different between different distributions and versions of bash, due to fixing the "ShellShock" security vulnerabilities mentioned above, so (a) what you do in one environment may not work in another, and (b) I can't tell you the exact exported variable name you need to do what you want.
In order to find out what variable format you need, in a regular shell that has update_gitbar
, run:
env | sed -n '/^[^=]*update_gitbar/,/^}/p' |
perl -ne 'chomp; $a .= $a? "; $_" : $_; END{$a=~s/=(.*)/='\''$1'\''/; print "$a\n"}'
That complicated command just looks in the environment for the exported shell function and prints its value. Bash includes newlines in the value of the exported variable, so it continues grabbing from the environment until it sees a single line with a closing brace alone. Then it replaces all those newlines with semicolons so that you can put it all on one line. Finally, it replaces the value of the variable inside single quotes, to avoid special meanings of characters. If you have trouble getting a usable value from that command for some reason, you could do that process yourself.
For me, with an example like below illustrates the format on my particular distribution and bash version (notice in the command I changed update_gitbar
to hello
). As I mentioned, your results may vary, so be sure to try it out on your system.
After you get the variable you want, just plug it into your .tmux.conf
, or use the setenv
version.
hello() {
echo hi;
}
export -f hello
hello
>>>> hi
env | sed -n '/^[^=]*hello/,/^}/p' |
perl -ne 'chomp; $a .= $a? "; $_" : $_; END{$a=~s/=(.*)/='\''$1'\''/; print "$a\n"}'
>>>> BASH_FUNC_hello%%='() { echo hi\!; }'
(The >>>>
-prefixed lines are output, not part of the script in the example.)
tmux's set-environment
looks promising and might be of help to you.
Let me quote the relevant section from man tmux
:
set-environment [-gru] [-t target-session] name [value] (alias: setenv) Set or unset an environment variable. If -g is used, the change is made in the global environment; otherwise, it is applied to the session environment for target-session. The -u flag unsets a variable. -r indicates the variable is to be removed from the environment before starting a new process.
You might want to use set-environment -g PROMPT_COMMAND update_gitbar
as an instruction inside your tmux-gitbar.conf which will be sourced from .tmux.conf via source /path/to/tmux-gitbar.conf
EDIT:
Forgot to mention that update_gitbar
should be an exectuable file somewhere in PATH
.
P.S.
Cool plugin! :-)
Whereas I have to point out that there are already viable answers, I want to mention one more solution to your problem.
There's a mod adding full-fledged scripting to tmux: http://ershov.github.io/tmux/ (I'm the author).
It not only allows to create new commands:
proc update_gitbar {} { run-shell "source ~/.tmux-gitbar/tmux-gitbar.sh" }
(for your case)
... but also allows you to bind several actions to 'mode' keystrokes.
It's also usable for writing complete plugins in that language without a need to spawn a shell at all.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With