Tmux中的窗格标题


88

在我的本地计算机上,我有3个node.js实例同时运行。每个窗口在称为“服务器”的tmux窗口中都有其自己的窗格。问题在于,要弄清哪个节点在哪个窗格中运行并不容易,因为它们的日志是相似的。

我需要的是每个窗格的标题。据我了解,tmux本身不具备此功能:它仅具有Windows的标题,而没有窗格的标题。在每个窗格中为每个node.js实例启动一个单独的tmux会话看起来像是过分的。

那么,是否有一些小程序启动命令,将其输出包装在指定的状态栏中?

提前致谢


1
从2.3版开始的tmux支持窗格标题,请参阅stackoverflow.com/a/37602055/266453
Dennis G

Answers:


80

tmux支持每窗格标题,但不提供每窗格位置来显示这些标题。

您可以设置一个窗格的标题与转义序列ESC ]2;... ESC \(例如,见一节姓名和头衔TMUX手册页)。您可以像这样从shell中执行此操作:

printf '\033]2;%s\033\\' 'title goes here'

每个窗格的标题默认为系统的主机名。默认情况下,显示在右侧的活动窗格的标题TMUX状态行(会话变量的默认全局值status-right"#22T" %H:%M %d-%b-%y,这显示了窗格的标题,时间和日期的22个字符)。

因此,只要您满意能够看到活动窗格的标题(即愿意切换窗格以查看不活动窗格的标题),就可以使用默认功能。在启动每个窗格的主命令之前,只需发送适当的标题设置转义序列即可。


如果您绝对需要专用的行来显示某些每个窗格的信息,则嵌套的tmux会话可能不会像您首先想到的那样“过多”(不必要)。

在一般情况下,要在某些给定的终端上提供不正常的状态行,您将需要一个位于原始终端和新终端(一个少行的终端)之间的完整终端(重新)仿真器。需要这种(重新)仿真来转换发送到内部终端的控制序列,并将其转换为原始终端。例如,要在外部端子的底部保持状态行,请使用以下命令

移至最后一行。

发送到内部终端必须成为

移至最后一行的下一行。

翻译并发送到外部终端。同样,发送到内部终端的LF必须变为

如果光标位于最后一行的下一行,则将这一行及其上方的所有行向上滚动一行,以提供清晰的倒数第二行(保护最后一行的状态行)。否则,发送LF。

在外部终端。

诸如tmuxscreen之类的程序就是这样的终端重新仿真器。当然,终端仿真器还有很多其他功能,但是您仅需要提供大量终端仿真代码即可提供可靠的状态行。


但是,只要有一个轻量级的解决方案,

  1. 您的程序(Node.js实例)与运行它们的窗格之间的交互作用有限(即,没有光标定位),并且
  2. 您不会在程序运行时调整窗格的大小。

像许多终端仿真器一样,tmux在其窗格中支持“设置滚动区域”终端控制命令。您可以使用此命令将滚动区域限制在终端的N-1行的顶部(或底部),并将某种实例标识文本写入非滚动行。

由于生成输出的程序(例如,Node.js实例)不知道滚动已被限制在特定区域,因此需要限制(不允许光标移动命令,不调整大小)。如果输出生成程序将光标移至滚动区域之外,则输出可能会出现乱码。同样,在调整终端大小时,终端仿真器可能会自动重置滚动区域(因此“非滚动行”可能最终会滚动消失)。

我编写了一个脚本,该脚本tput用于生成适当的控制序列,写入非滚动行并在将光标移至滚动区域后运行程序:

#!/bin/sh

# usage: no_scroll_line top|bottom 'non-scrolling line content' command to run with args
#
#     Set up a non-scrolling line at the top (or the bottom) of the
#     terminal, write the given text into it, then (in the scrolling
#     region) run the given command with its arguments. When the
#     command has finished, pause with a prompt and reset the
#     scrolling region.

get_size() {
    set -- $(stty size)
    LINES=$1
    COLUMNS=$2
}
set_nonscrolling_line() {
    get_size
    case "$1" in
        t|to|top)
            non_scroll_line=0
            first_scrolling_line=1
            scroll_region="1 $(($LINES - 1))"
            ;;
        b|bo|bot|bott|botto|bottom)
            first_scrolling_line=0
            scroll_region="0 $(($LINES - 2))"
            non_scroll_line="$(($LINES - 1))"
            ;;
        *)
            echo 'error: first argument must be "top" or "bottom"'
            exit 1
            ;;
    esac
    clear
    tput csr $scroll_region
    tput cup "$non_scroll_line" 0
    printf %s "$2"
    tput cup "$first_scrolling_line" 0
}
reset_scrolling() {
    get_size
    clear
    tput csr 0 $(($LINES - 1))
}

# Set up the scrolling region and write into the non-scrolling line
set_nonscrolling_line "$1" "$2"
shift 2

# Run something that writes into the scolling region
"$@"
ec=$?

# Reset the scrolling region
printf %s 'Press ENTER to reset scrolling (will clear screen)'
read a_line
reset_scrolling

exit "$ec"

您可以这样使用它:

tmux split-window '/path/to/no_scroll_line bottom "Node instance foo" node foo.js'
tmux split-window '/path/to/no_scroll_line bottom "Node instance bar" node bar.js'
tmux split-window '/path/to/no_scroll_line bottom "Node instance quux" node quux.js'

只要终端支持并发布其和terminfo功能,该脚本也应在tmux之外运行csrcup


您的脚本运行完全符合我的预期;唯一的问题:我应该用谷歌定制“ non_scroll_line”的颜色吗?
Andrey Lushnikov 2012年

1
也许是“ terminfo功能前景背景色”(即,在terminfo联机帮助页中了解了颜色)。您可以用来tput在“行内容”参数中包含适当的控制序列。对于大多数终端,您可以使用将该行设置为“洋红色(5)上的青色(6)和绿色(3)” no_scroll_line top "$(tput setaf 6; tput setab 5)Node: $(tput setaf 3)foo$(tput op)" node foo.jssetaf设置前景,setab设置背景,op重置为终端默认颜色。颜色功能的取值范围为0–7、0–15、0–87或0–255,具体取决于您的终端仿真。
克里斯·约翰森

现在,我们发布了pymux。这将显示窗格标题栏:github.com/jonathanslenders/pymux
Jonathan Slenders,2016年

看来,其行为是窗格标题设置为在外壳程序中运行的命令。因此,除非我们在内部运行一个长期存在的进程(它也知道如何输出标题设置的转义序列),否则它不会“停留”。
史蒂文·卢

4
请在下面进一步查看答案:stackoverflow.com/a/37602055/266453从2.3版开始的tmux支持窗格边框中的标题。
丹尼斯·G

78

此功能已在此commit中添加到tmux 。它不是在2.2版中,但看起来将在2.3版中。

要启用它:

tmux set -g pane-border-status top

或者,如果您喜欢:

tmux set -g pane-border-status bottom

要将自定义文本设置为窗格边框状态行,可以使用pane-border-format,例如,如下所示:

tmux set -g pane-border-format "#{pane_index} #{pane_current_command}"

1
这显示了窗格的编号和默认标题。您如何改变想法?
ADN

我不确定窗格编号,但它的响应就像xterm窗口标题一样,以转义序列。例如,使用bash,我将PS1 ='[\ e] 0; \ u @ \ h:\ w \ a] $'设置为“ user @ host:working dir /”
kevmitch

据我了解,您需要事先设置该顺序。但是没有快捷键或组合键可以更改它们。因此,在tmux外部您需要一些命令tmux来对其进行更改。对?还是里面有什么序列可以更新它?
2016年

是的,您只需要在运行的shell中设置变量,它就会在绘制下一个提示时更新。对我来说,tmux似乎有点粗略,只有在切换到另一个窗格时才真正更新它。
kevmitch '16

实际上,您可以pane-border-format用来设置要显示的窗格的自定义格式字符串(通常的#{...}格式)。我已经编辑了您的答案以包括此内容。
丹尼斯·G

33

由于tmux 2.6您可以:

$ tmux select-pane -t {pane} -T {title}

# Examples:
$ tmux select-pane -T title1          # Change title of current pane
$ tmux select-pane -t 1 -T title2     # Change title of pane 1 in current window
$ tmux select-pane -t 2.1 -T title3   # Change title of pane 1 in window 2

您可以在状态栏中查看每个窗格的标题,其中包括:

$ tmux set pane-border-status bottom      # For current window
$ tmux set -g pane-border-status bottom   # For all windows

通过以下方式禁用状态栏:

$ tmux set pane-border-status off       # For current window
$ tmux set -g pane-border-status off    # For all windows

您是否知道有什么方法可以防止tmux从您的身下更改标题?例如,如果我设置窗格的标题,然后在该窗格中执行某项操作,例如cd $HOME,标题将更改为的值$HOME。(我在tmux 2.8上看到了这一点。)
pdoherty926

1
@ pdoherty926也许您已经得到了答案,但请查看set-window-option automatic-rename off
noname

set-option -g allow-rename off.tmux.conf档案中。
Eyal Levin

1
感谢您的建议。我使用pane-border-format了一个用户提供的变量(我不确定此功能是否有正式名称)来控制显示的内容。这是一个例子。
pdoherty926

14

我正在tmux-票证的窗格状态栏上工作。我的开发分支可以在github上找到:https : //github.com/jonathanslenders/tmux

现在,这已经添加了一个有效的重命名窗格“ title”命令。仍然存在一些错误,API将会得到改善。想法是为每个窗格创建一个状态栏,该状态栏可以具有某些格式,例如会话状态栏。与tmux的其余部分一样,所有内容都应可编写脚本并可自定义。完成并稳定后,它可能会包含在官方tmux中。


当您在其中时,是否可以使窗格标题成为分隔窗格期间的默认窗口标题?
djsadinoff 2015年

该分支从未在tmux中合并。但是我改为创建了pymux,它具有窗格标题栏:github.com/jonathanslenders/pymux
Jonathan Slenders

此命令也不适用于最新版本(提交a24260)。
ADN

14

我使用的是tmux 2.3版,我认为以前的版本不支持边框样式。这对我有用:

为每个窗格设置标题:

printf '\033]2;My Pane Title\033\\'

然后:

tmux set -g pane-border-format "#{pane_index} #T"

9
至少在tmux 2.6之前,您可以在tmux中更改窗格标题:select-pane -T "my title"执行此操作。您甚至可以设置按键绑定,因此只需要提供标题即可:bind-key T command-prompt -p "New title:" 'select-pane -T "%%"'
lucasem

3
@lucasem也许我还没有关注这个话题,但这似乎是答案。
icicleking

@lucasem我不确定100%,但是我相信您的方法(对于最新版本的tmux,该方法在整个线程中是最好的和最简单的IMO)仅在该pane-border-status选项设置为(topbottom)时有效。
cjauvin


7

是的,有这样一个命令:tmux。给您的会话起一个名字,它将显示在内部状态栏中:

TMUX=0 tmux new-session -s my-new-session

2
是的,谢谢您的回答!但是,因此我必须在每个窗格中仅针对其底部的一个标题启动一个新的tmux会话-有点过头了,不是吗?
Andrey Lushnikov 2012年

我不知道。是吗?你试过了吗?额外的会话使用了多少额外的内存?
event_jr 2012年

是的,直到今天我一直在使用嵌套的tmux会话。我不确定内存消耗以及诸如此类的事情-我只是不喜欢这个概念本身,因为它不纯净。
Andrey Lushnikov 2012年

4

这在短期内无济于事,但在tmux中有针对每个窗格标题的功能请求:http : //sourceforge.net/tracker/? func = detail&aid = 3495916&group_id = 200378&atid = 973265#

同时,正如其他人所提到的,嵌套tmux可以正常工作。


0

TL; DR

将以下配置附加到您的tmux配置文件(在我的情况下是~/.tmux.conf.local

# dispaly pane_current_path as the pane title
set -g pane-border-status top
set -g pane-border-format "#{pane_index} #{pane_current_path}"

然后运行:

tmux source-file ~/.tmux.con

好好享受

感谢https://stackoverflow.com/a/37602055/5121972

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.