假设我将窗口拆分为两个窗格,右侧窗格的宽度为 20 个单元格。但是当我调整外部终端仿真器的大小时,窗格的宽度会发生变化。
有什么办法可以解决这个问题吗?因为我想显示格式化为适合 20 个单元格的信息
答案1
据我所知,tmux 没有任何将宽度固定为最小值的设置,只有最大值。这是因为终端窗口可以调整为小于 tmux 的最小值,而 tmux 可能没有合适的方法来处理这种情况。
话虽如此,如果您打开了其他 tmux 窗格,则可以向 PS1 ( PS1='$(resizePane $id)other-stuff'
) 或 PROMPT_COMMAND 添加一个小脚本,以便在使用 tmux 内的其他窗格时不断调整信息窗格的大小,使其保持 20c 的宽度。本质上,1) 您可以打开程序,2) 调整终端大小,3) 移动到另一个窗格,4) 键入Enter
并砰的一声,窗格就调整大小了。
你应该看看
resize-pane [-DLRU] [-t target-pane] [adjustment]
如果您位于所需的窗格中,则必须执行的所有操作都是将宽度从左侧 -L 或从右侧 -R 缩小 x 个字符,以达到 20。本质上,如果窗格靠在比窗格高的墙上,则使用其方向进行缩小,反之则进行放大。如果我的窗格紧挨着右墙,则使用 -R 减小宽度并使用 -L 放大它。
要获取正确数量的字符,您需要知道窗格的当前宽度,如果您输入,可以与窗格 ID 一起找到它
tmux list-panes
除了通过Prefix+q
或输入
tmux display-panes
这将为我们提供当前窗口中所有窗格的 ID 号。如果我们知道 id# ($id) 并假设它靠在右墙上,我们可以通过以下方式将窗格的大小调整为 20 个字符宽:
paneWidths=$(tmux list-panes | awk '{print $2}' | cut -c 2- | cut -f 1 -d'x')
currentWidth=$(echo $paneWidths | sed $id'q;d')
resizeNum=$(expr $currentWidth - 20)
tmux resize-pane -R -t $id $resizeNum
请注意,resizeNum 不能为负数。如果为负数,则使用另一边调整大小为 resizeNum 的绝对值(这可以自动完成,但我将把这留给您自己决定)。此外,如果您将其合并到程序代码中,则可以忽略“-t $id”部分,但我不知道如何在程序中自动查找 $id。
您可能还需要查看tmux setw main-pane-width
tmux setw other-pane-width
,如果您重新加载新的图块格式,它将设置特定的窗格宽度。要循环格式,请使用Prefix+space
希望这可以帮助!
--- 编辑以添加有关自动化的更多信息 ---
我以前的想法是,让您转到一个新窗格并运行PS1="$(resizePane $id)${PS1}"
,然后点击ENTER
另一个窗格,以便您可以继续在新调整大小的窗格中工作,但我已经考虑了一个可能适合您的新选项......
自从最初发布以来,我重新考虑了这个想法,我认为如果运行的程序有一个可以发送 shell 命令的循环,那么它可以合理地实现自动化。这是因为我们可以通过本质上分割窗口来运行程序。下面是我所指的一个例子。以下代码
- 用户
runCodeSplit.sh
运行 - 在最后一个窗格的右侧水平拆分一个新窗格(20c 宽度),并运行
test.sh
- 进入循环
- 检查当前窗格大小并尝试调整大小
- 休眠 10 秒(但你可以根据需要更改此时间)
- 重复 3 和 4 10 次,然后退出
运行CodeSplit.sh:
#!/bin/bash
# runCodeSplit.sh
paneID=$(tmux list-panes | wc -l)
echo "pane: $paneID"
echo $(expr $paneID - 1)
# now, open a new pane and run the func
tmux split-window -h -l 20 -t $(expr $paneID - 1 ) "~/test.sh $paneID"
测试.sh:
#!/bin/bash
# test.sh
if [[ $# -lt 1 ]] ; then
echo "please provide the pane-number"
exit
fi
paneID=$1
i=0
while [[ i -lt 10 ]] ; do
# find the current width and resize it at every loop
width=$(tmux list-panes | awk '{print $2}' | cut -c 2- | cut -f 1 -d'x' | sed $(expr $paneID + 1)'q;d')
resizeNum=$(expr $width - 20)
echo "$paneID : w $width r $resizeNum"
if [[ $resizeNum -gt 0 ]] ; then
tmux resize-pane -R -t $paneID $resizeNum
elif [[ $resizeNum -lt 0 ]] ; then
tmux resize-pane -L -t $paneID $(expr 0 - $resizeNum)
fi
#now, we can do stuff ...
let i++
echo "i= $i / 10"
sleep 10
done
read -p "Press any key to close this pane ... " -n1 -s
笔记:不幸的是,按照我上面的实现方式,您实际上只能在每个 tmux 窗口中运行一次。问题是,每次运行它时,它们都会挤在一起,这反过来又会导致它们争夺空间(一个会缩小另一个以扩大空间,反之亦然)。您也许可以解决这个问题,但我留给您自己去解决。
答案2
我会发布我的版本,因为它不会伤害任何人,并且可能更适合某些人。
我使用它来调整 tmux 中 irssi 会话中窗格的大小,该会话读取来自nicklist.pl
脚本。当我连接到不同的终端时,窗格经常会调整大小,并且它需要>20列宽才能使FIFO正常工作(并且没有必要让它更宽,这会占用我的屏幕空间)。
忽略复杂的CURRENT_PANE_WIDTH
计算,如果需要,可以使用 grep+sed 来代替。当前版本主要是将脚本完全保留在 shell 中的实验(当然,tmux 调用除外)。它很可能更快,这对于脚本频繁运行的自动化来说可能很有趣(不过,我目前将其作为特定调用运行)。
#!/bin/sh
TMUX="/usr/bin/tmux"
TMUX_SESSION="irssi"
TMUX_WINDOW="0"
TMUX_WINDOW_PANE="1"
DESIRED_PANE_WIDTH="20"
error()
{
printf '%s: error: %s\n' "${0##*/}" "${1}" 1>&2
exit ${2}
}
# Find with grep and sed. More readable and easier to modify.
#CURRENT_PANE_WIDTH="$(${TMUX} list-panes -t "${TMUX_SESSION}:0 | grep "^${TMUX_WINDOW_PANE}: " | sed 's/^'"${TMUX_WINDOW_PANE}"': \[\([^x]\+\).*/\1/')"
# Find with shell expansion. Because it can be done!
CURRENT_PANE_WIDTH=$(${TMUX} list-panes -t "${TMUX_SESSION}:${TMUX_WINDOW}" |\
while read line; do
PANE_MATCH="${line#${TMUX_WINDOW_PANE}:\ \[}"
if [ "${line}" != "${PANE_MATCH}" ]; then
CURRENT_PANE_WIDTH="${PANE_MATCH%%x*}"
printf "${PANE_MATCH%%x*}"
break;
fi
done)
if [ -z "${CURRENT_PANE_WIDTH}" ]; then
error 'no matching pane found.' 1
fi
if ! [ "${CURRENT_PANE_WIDTH}" -eq "${CURRENT_PANE_WIDTH}" ]; then
error 'could not get integer width.' 1
elif ! [ "${CURRENT_PANE_WIDTH}" -eq "${DESIRED_PANE_WIDTH}" ]; then
RESIZE_NUMBER=$((${CURRENT_PANE_WIDTH} - ${DESIRED_PANE_WIDTH}))
if [ ${RESIZE_NUMBER} -ge 0 ]; then
DIRECTION="R"
else
DIRECTION="L"
RESIZE_NUMBER=$((-${RESIZE_NUMBER}))
fi
${TMUX} resize-pane -t "${TMUX_SESSION}:${TMUX_WINDOW}" -${DIRECTION} ${RESIZE_NUMBER}
fi
答案3
从 2.1 版开始,tmux 支持钩子(在手册中查找^HOOKS
)。手册中给出了示例(我只有 3.1 版):
A command's after hook is run after it completes, except when the command is run as part of a hook
itself. They are named with an ‘after-’ prefix. For example, the following command adds a hook to
select the even-vertical layout after every split-window:
set-hook -g after-split-window "selectl even-vertical"
当钩子触发时执行的命令与set-hook
使用的格式相同bind-keys
。
除了 HOOKS 部分列出的钩子之外,您还可以使用 CONTROL MODE 部分中描述的所有事件(在手册中搜索^CONTROL
)。在以下情况下,您可以使用以下钩子来调整窗格大小:有趣的事情发生的事情是client-resized
,pane-exited
和layout-change
(不是“改变”!)。继续阅读,在钩子前加上前缀after-
,如上面引用的示例所示。
resize-pane
手册的“命令”部分列出了可用于该命令的引用窗格的不同方法。不完整的列表包括窗格编号、偏移编号和类似{top-right}
或 的标记{left-of}
。该命令接受字符单元格中的绝对和相对大小以及窗口宽度的百分比。