在 tmux 中转置窗格

在 tmux 中转置窗格

我在 tmux 窗口中打开了 6 个窗格。

Prefix:select-layout tiled将它们排列如下:

+---------+---------+
|    1    |    2    |
+---------+---------+
|    3    |    4    |
+---------+---------+
|    5    |    6    |
+---------+---------+

这很好,但是我的显示器又宽又短,对于我正在运行的进程来说,这浪费了大量的水平空间。

我更愿意这样安排它们:

+-----+-----+-----+
|  1  |  2  |  3  |
+-----+-----+-----+
|  4  |  5  |  6  |
+-----+-----+-----+

假设窗格本身的数字顺序并不重要,并且关键的是不会停止任何正在运行的进程,我如何从第一个布局切换到第二个布局?

答案1

您可以使用tmuxlayout这是一个 perl 脚本,您只需在另一个窗口中运行它,tmuxlayout 123 456它就会将适当的命令发送到正在运行的 tmux。

安装起来可能会有点困难,因为它可能不在您的发行版的存储库中。


如果您想tmuxlayout在本地安装,无需成为 root 或弄乱您的/usr/lib等等,您可以在安装cpan命令后执行此操作,该命令应该在您的存储库中。

然后,您可以cpan像下面这样以交互方式运行,只需输入 3 行。它将在您的$HOME:perl5/和中仅创建 2 个目录.cpan

下面我删除了大量的输出,因此当要求自动配置时只需按回车键yes,当要求选择时按回车键local::lib,然后输入命令install Term::Tmux::Layout

$ cpan
Would you like to configure as much as possible automatically? [yes] 
What approach do you want?  (Choose 'local::lib', 'sudo' or 'manual')
 [local::lib] 
cpan[1]> install Term::Tmux::Layout

如果它说安装正确,请在下一个提示符下输入 control-D 退出,并记下它要求您设置的值:

cpan[2]> ^D
*** Remember to add these environment variables to your shell config
and restart your shell before running cpan again ***
PATH="/home/meuh/perl5/bin${PATH:+:${PATH}}"; export PATH;
PERL5LIB="/home/meuh/perl5/lib/perl5${PERL5LIB:+:${PERL5LIB}}"; export PERL5LIB;
PERL_LOCAL_LIB_ROOT="/home/meuh/perl5${PERL_LOCAL_LIB_ROOT:+:${PERL_LOCAL_LIB_ROOT}}"; export PERL_LOCAL_LIB_ROOT;
PERL_MB_OPT="--install_base \"/home/meuh/perl5\""; export PERL_MB_OPT;
PERL_MM_OPT="INSTALL_BASE=/home/meuh/perl5"; export PERL_MM_OPT;

使用上述 5 行创建一个小的 shell 脚本,并在末尾添加

tmuxlayout 123 456

并运行脚本。

答案2

我编写了以下脚本,以便轻松地将窗格放置在网格中。它使用来自Sleep_Walker 的博客。我不清楚许可证是什么。为了安全起见,我从代码中删除了该函数,并将其作为正确引用单独发布。

您需要通过将函数粘贴到脚本中来编写完整的脚本。

#!/bin/bash

# number of rows
m="$2"
# number of columns
n="$1"

target="${3:-$TMUX_PANE}"
set -- $(tmux list-panes -t "$target" -F '#{pane_id}')

n="${n:-$(($#/m))}"
m="${m:-$(($#/n))}"

if [ "$#" -ne "$((m*n))" ]; then
    printf '%s: panes needed for %sx%s layout: %s; panes detected: %s. Aborting.\n' "$0" "$n" "$m" "$((m*n))" "$#" >&2
    exit 1
fi

if [ "$m" -eq 1 ]; then
   layout=even-horizontal
elif [ "$n" -eq 1 ]; then
   layout=even-vertical
else

# ---------- IMPORTANT ----------
# Visit http://sleepwalker-hnd.blogspot.com/2016/07/tmux-layout-checksum.html
# and paste tmux_layout_checksum function here.

   create_row() {
      row="${n}x1,0,${1}{"
      shift
      for j in $(seq 0 "$((n-1))"); do
         row="${row}1x1,${j},0,${1#%},"
         shift
      done
      row="${row%,}},"
   }

   layout="${n}x${m},0,0["
   for i in $(seq 0 "$((m-1))"); do
      create_row "$i" "$@"
      shift "$n"
      layout="${layout}${row}"
   done
   layout="${layout%,}]"
   layout="$(tmux_layout_checksum "$layout"),${layout}"

fi

tmux select-layout -t "$target" "$layout"

所提到的函数:

tmux_layout_checksum() {
    local layout="$1"
    local csum=0
    local i
    for i in $(seq 0 $((${#layout} - 1))); do
        let csum=$(((csum >> 1) + ((csum & 1) << 15)))
        let csum=$((csum + $(LC_CTYPE=C printf '%d' "'${layout:$i:1}")))
    done
    printf '%x' "$((csum & 0xffff))"
}

来源:Sleep_Walker 的博客


用法

假设你将脚本命名为tmux-grid。用法如下:

tmux-grid columns [rows [target]]

target正是所tmux … -t期望的。有了它,您可以定位任何 tmux 窗口。如果省略或为空,$TMUX_PANE则将被使用。这样,您无需target从窗口本身内部更改当前窗口的布局。

rows是所需的行数。如果省略或为空,脚本将尝试根据现有窗格的数量和指定的 来计算此数字columns

columns是所需的列数。如果为空,脚本将尝试根据现有窗格的数量和指定的 来计算此数字rows

在您的情况下,从相关的6个窗格之一中调用其中一个:

tmux-grid 3      # exactly 3 columns
tmux-grid '' 2   # exactly 2 rows
tmux-grid 3 2    # exactly 3 columns and exactly 2 rows

注意一般tmux-grid 2需要偶数个窗格;tmux-grid 3需要数字可以被 3 整除;tmux-grid 3 2需要恰好 6 个窗格。

如果每个窗格都很忙,您可以从另一个窗口调用该命令。在这种情况下,您需要指定target。这可能很方便:

tmux-grid 3 '' {marked}

(对于不熟悉标记窗格概念的用户:这是我的另一个答案


怎么运行的

该脚本构建了每个尺寸为 1x1 的窗格布局。由于重新tmux select-layout计算布局以匹配窗口大小,因此窗格会自动调整大小。

注意:我后来的测试在大小为 0x0 的窗格上成功了。但我保留了原始脚本。

相关内容