如何导出函数,来自 tmux.conf

How to export a function, from tmux.conf

我为 tmux 写了一个插件,tmux-gitbar。它在 tmux 状态栏中显示有关当前目录的 Git 状态的一些信息。每次用户运行命令 时,状态栏必须 更新,为此我添加了一个函数,从 $PROMPT_COMMAND 变量调用。

我现在在做什么:

在文件 .bashrc:

source ~/.tmux-gitbar/tmux-gitbar.sh;

在文件 tmux-gitbar.sh:

update_gitbar() {
    #
    # update tmux status bar
    #
}
PROMPT_COMMAND="update_gitbar; $PROMPT_COMMAND"


我想在不向 .bashrc
添加一行的情况下获得相同的结果 。都应该在tmux.conf文件中执行。我已经通过在 tmux.conf:

中这样做来修改 $PROMPT_COMMAND
PROMPT_COMMAND="update_gitbar; $PROMPT_COMMAND"

现在我的问题是将 update_gitbar 函数导出到环境中

我尝试了多种获取脚本源的方法,但没有成功:

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)"

我总是得到:

update_gitbar: command not found

问题:

我如何从 tmux.conf 文件 导出函数(在另一个文件中声明)并使该函数对环境可用?

如果有帮助,可以在 github

上找到当前代码

tmuxset-environment 看起来很有前途,可能对您有所帮助。 让我引用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.

您可能想在 tmux-gitbar.conf 中使用 set-environment -g PROMPT_COMMAND update_gitbar 作为指令,它将源自 .tmux.conf 通过 source /path/to/tmux-gitbar.conf

编辑: 忘了说 update_gitbar 应该是 PATH.

中某处的可执行文件

P.S.

很酷的插件! :-)

试图通过运行-shell解决它是徒劳的。根据定义,任何使用 运行-shell 的 运行 都在 sub-shell/child 进程中,并且不会影响 tmux 的环境。

外部 shell 脚本

老实说,我强烈建议您使用外部 shell 脚本,而不是函数。除其他外,这将允许您对 update_gitbar 进行更改,这些更改会在任何地方立即生效。当然,它的效率稍低,但我认为您不太可能注意到其中的区别。把它扔进 ~/bin,然后让 PROMPT_COMMAND 变成 "$HOME/bin/update_gitbar; $PROMPT_COMMAND".

但是,如果您必须坚持使用 shell 函数——我必须指出,这只是 bash- 的一个特性,并且也是去年 主要 安全漏洞的来源("ShellShock";注意:不是使用 功能,只是它的实际 存在,以及非常糟糕的实现,此后已在较新版本中修复),我可以提供两种解决方案。

在 运行ning tmux

之前导出

第一种也是最简单的方法就是确保在启动 tmux 会话的环境中进行导出,而不是在它之后或之中。如果你启动 tmux 而不是 shell 脚本,比如说,你会这样做:

export -f update_gitbar
tmux

作为该启动的一部分,您可能还想放置 update_gitbar 的定义和您的 PROMPT_COMMAND 设置。请注意,一旦 tmux 启动,您将无法更改 update_gitbar 并将其传播到任何使用它的地方——这就是为什么我建议使用 shell 脚本。但是,您仍然可以使用下面描述的方法修改 new shells(例如,在新的 tmux 窗格中)的含义。

不可移植的变量导出

最后一种方法,也是最难和最不便携的,是使用 tmux 的 setenv,或 .tmux.conf 中相同的 VAR=value 语法。 Bash 仅通过使用具有特殊格式的普通导出变量来实现其独特的 "export function" 功能。

由于修复了上述 "ShellShock" 安全漏洞,bash 的不同发行版和版本之间该格式的确切性质不同,因此 (a) 您在一个环境中所做的可能不能在另一个中工作,并且 (b) 我不能告诉你确切的导出变量名,你需要做你想做的事。

为了找出您需要的变量格式,在具有 update_gitbar、运行:

的常规 shell 中
env | sed -n '/^[^=]*update_gitbar/,/^}/p' |
perl -ne 'chomp; $a .= $a? "; $_" : $_; END{$a=~s/=(.*)/='\'''\''/; print "$a\n"}'

那个复杂的命令只是在环境中查找导出的 shell 函数并打印它的值。 Bash 在导出变量的值中包含换行符,因此它会继续从环境中抓取,直到它看到只有一个右括号的单行。然后它将所有这些换行符替换为分号,以便您可以将它们全部放在一行中。最后,它替换单引号内的变量值,以避免字符的特殊含义。如果您出于某种原因无法从该命令获取可用值,您可以自己执行该过程。

对我来说,下面的例子说明了我的特定发行版和 bash 版本的格式(注意命令中我将 update_gitbar 更改为 hello)。正如我提到的,您的结果可能会有所不同,因此请务必在您的系统上进行尝试。

获得所需变量后,只需将其插入 .tmux.conf,或使用 setenv 版本。

hello() {
    echo hi;
}
export -f hello
hello
>>>> hi
env | sed -n '/^[^=]*hello/,/^}/p' |
perl -ne 'chomp; $a .= $a? "; $_" : $_; END{$a=~s/=(.*)/='\'''\''/; print "$a\n"}'
>>>> BASH_FUNC_hello%%='() {  echo hi\!; }'

>>>>前缀的行是输出的,不是示例中脚本的一部分。)

虽然我必须指出已经有可行的答案,但我想再提一个解决你问题的方法。

有一个 mod 向 tmux 添加完整的脚本:http://ershov.github.io/tmux/(我是作者)。

它不仅允许创建新命令:

proc update_gitbar {} { run-shell "source ~/.tmux-gitbar/tmux-gitbar.sh" }

(针对您的情况)

...但也允许您将多个操作绑定到 'mode' 击键。

它也可用于用该语言编写完整的插件,根本不需要生成 shell。