我想使用 tmux 为终端创建一个“焦点模式”,有点像goyo 为 vim 做了什么:
问题 1:调整窗格大小
我的想法是通过将窗口分成三个窗格来实现这一点,然后将中心窗格设置为固定的最大值(可能是 80 列?可能是 100 列?可能根据终端窗口大小设置不同的最大值,例如响应式 Web 布局?)并将侧窗格设置为均匀填充剩余的列。我还希望它能够在不同尺寸的屏幕上工作,以便我可以在笔记本电脑和台式机上使用它。
目前,我能想到的唯一办法就是与 shell 合作(IE,使用 获取终端宽度tput cols
,然后使用 进行数学运算计算每个窗格所需的宽度$(())
。我对此没意见,但如果在 tmux 中有一个内置方法来实现这一点,我会因为错过它而感到非常愚蠢。
那么...有吗?
问题 2:遮挡侧窗格
这不是那么重要;看到一个几乎空白的窗格顶部有一个提示符真的不是那么糟糕。我知道 tmux 有clock-mode
(例如),它会覆盖窗格的内容并显示其他内容。所以我想知道是否有办法完全隐藏非活动窗格的内容。到目前为止,我能想到的最好的办法是将 fg 和 bg 设置为相同的颜色:
:select-pane -t:.1 -P 'fg=black,bg=black'
或者圣杯
如果有设施,这一切都可以更容易地实现边距在 tmux 的窗格上。据我所知,此功能不存在,但我远不是 tmux 专家。有没有可能它就在那里,而我只是不知道?
答案1
这就是我的名字_tmux-margins
:
#!/bin/sh
pane="${2:-$TMUX_PANE}"
[ -n "$pane" ] || exit 1
tmux has-session -t "$pane" 2>/dev/null || exit 0
tool="$0"
width="${TMUX_M_COLUMNS:-80}"
step=10
todo="${TMUX_M_COMMAND:-true}"
action="$1"
pattern=" '$tool' sleep "
pattern_left="$pattern'${pane}' left"
pattern_right="$pattern'${pane}' right"
command_left="TMUX_M_COMMAND='$todo'$pattern_left"
command_right="TMUX_M_COMMAND='$todo'$pattern_right"
tmux display-message -p '#{pane_start_command}' | grep -qF "$pattern" && exit 0
find_margins() {
pane_left="$(tmux list-panes -F "#{pane_id} #{pane_start_command}" | grep -F "$pattern_left" | head -n 1 | cut -d ' ' -f 1)"
pane_right="$(tmux list-panes -F "#{pane_id} #{pane_start_command}" | grep -F "$pattern_right" | head -n 1 | cut -d ' ' -f 1)"
}
find_geometry() {
[ -n "$pane_left" ] && width_left="$(tmux display-message -p -t "$pane_left" '#{pane_width}')" || width_left=0
[ -n "$pane_right" ] && width_right="$(tmux display-message -p -t "$pane_right" '#{pane_width}')" || width_right=0
border=0
[ "$width_left" -gt 0 ] && border=$((border+1))
[ "$width_right" -gt 0 ] && border=$((border+1))
width_center="$(tmux display-message -t "$pane" -p '#{pane_width}')"
width_all="$((width_center+width_left+width_right+border))"
[ "$((width+5))" -ge "$width_all" ] && width="$width_all"
}
destroy() {
[ -n "$pane_left" ] && [ "$pane_left" != "$TMUX_PANE" ] && tmux kill-pane -t "$pane_left"
[ -n "$pane_right" ] && [ "$pane_right" != "$TMUX_PANE" ] && tmux kill-pane -t "$pane_right"
[ "$pane_left" = "$TMUX_PANE" ] || [ "$pane_right" = "$TMUX_PANE" ] && tmux kill-pane -t "$TMUX_PANE"
true
}
create() {
width_left=$(( (width_all-width-2)/2 ))
[ "$width_left" -gt 2 ] || width_left=2
if [ -n "$pane_left" ]; then
tmux resize-pane -t "$pane_left" -x "$width_left"
else
tmux split-window -hdbl "$width_left" -t "$pane" "$command_left"
fi
width_right=$(( width_all-width-width_left-2 ))
[ "$width_right" -gt 2 ] || width_right=2
if [ -n "$pane_right" ]; then
tmux resize-pane -t "$pane_right" -x "$width_right"
else
tmux split-window -hdl "$width_right" -t "$pane" "$command_right"
fi
}
equalize() {
width="$width_center"
[ "$width" -lt "$width_all" ] && create
}
verify() {
tmux has-session -t "$pane" 2>/dev/null || destroy
}
resize() {
width="$((width_center${1}))"
if [ "$((width+5))" -ge "$width_all" ]; then
destroy
else
create
fi
}
main() {
find_margins
find_geometry
case "$action" in
sleep )
trap destroy INT
trap 'verify; kill "$!" 2>/dev/null; $todo &' WINCH
while true; do
$todo &
while sleep 1; do verify; done
done
;;
""|c* )
create
;;
d* )
destroy
;;
e* )
equalize
;;
+ )
resize "+$step"
;;
- )
resize "-step"
;;
+*|-* )
resize "$action"
;;
esac
}
main
有些部分和解决方案我并不满意。但它仍然有效。
像这样使用它(假设它位于您的目录中$PATH
):
- 要创建边距:
_tmux-margins c
- 或者
_tmux-margins create
- 或
_tmux-margins cwhatever
(实际上以 开头的任何内容c
) - 或
_tmux-margins
(创建是默认操作)。
- 销毁边距:
_tmux-margins d
(实际上任何以:d
,,,del
开头的delete
内容)。destroy
dwhatever
- 要均衡边距宽度:
_tmux-margins e
(事实上任何以 开头的事物e
)。
- 要放大中心窗格(缩小边距):
_tmux-margins +
- 或
_tmux-margins +N
(N
如果可能的话,将列添加到中心窗格)。
- 缩小中心窗格(扩大边距):
_tmux-margins -
- 或
_tmux-margins -N
(N
如果可能的话,从中心窗格中减去列)。
第二个参数(上例中未使用)指定窗格。这样,您可以从另一个窗格或从 外部调用该工具tmux
。示例:
_tmux-margins c .1
_tmux-margins - %5
有两个有用的变量:
TMUX_M_COLUMNS
– 创建边距时中心窗格的所需宽度(80
如果未设置)。TMUX_M_COMMAND
– 在边距窗格中运行的命令(true
如果未设置)。如果调整了边距大小,命令将重新启动。我实现此功能的主要原因是:TMUX_M_COMMAND='cmatrix -u 20' _tmux-margins create
我的里面有这个~/.tmux.conf
:
bind-key -T root C-Up run-shell -b 'TMUX_PANE="#{pane_id}" _tmux-margins d "#{pane_id}"'
bind-key -T root C-Down run-shell -b 'TMUX_PANE="#{pane_id}" _tmux-margins c "#{pane_id}"'
bind-key -T root C-Left run-shell -b 'TMUX_PANE="#{pane_id}" _tmux-margins - "#{pane_id}"'
bind-key -T root C-Right run-shell -b 'TMUX_PANE="#{pane_id}" _tmux-margins + "#{pane_id}"'
这些行使Ctrl+ ↑、Ctrl+ ↓、Ctrl+←和Ctrl+分别→调用_tmux-margins d
、… c
和,… -
以… +
当前窗格为目标。
笔记:
- 这些组合键对我来说在 Linux 本地和从
ssh
Linux 到 Linux 都有效。当我在 Windows 上使用 PuTTY 连接到 Linux 时,它们对我不起作用。我还没有尝试修复此问题。也许可以配置 PuTTY 使其工作,我不知道。无论如何,您可以选择其他组合,可能使用前缀键 (bind-key -T prefix …
)。 _tmux-margins e
如果您发现有用的话,请继续绘制地图。通过按键调用的脚本无法访问当前窗格中的 shell 环境(比较这个答案)。这意味着为了使用
TMUX_M_COLUMNS
或TMUX_M_COMMAND
按键,您需要为 tmux 服务器本身设置它们:对于第一个
tmux
(启动服务器的那个):TMUX_M_COMMAND='cmatrix -b' tmux
或者在你的
~/.tmux.conf
:set-environment -g TMUX_M_COMMAND 'cmatrix -b'
(注意
-g
(全局环境)是必须的,因为tmux.conf
它在任何会话开始之前进行解析);或更高版本(当 tmux 服务器正在运行时)如下所示:
tmux set-environment TMUX_M_COMMAND 'cmatrix -b'
(有或没有
-g
;注意如果不在 tmux 内,那么您需要-g
或-t
);或者从 tmux 内部:
prefix:
set-environment TMUX_M_COMMAND 'cmatrix -b'
Enter(再次强调,有或没有
-g
)。
一般注意事项:
- 边距只是窗格。如果您拆分边距或将其与另一个窗格交换或将其从窗口中分离出来,使其看起来不像一个合适的边距,那么这就是您的问题。或者如果您拆分中心窗格等。
- 另一方面,您可以像任何其他窗格一样调整边距的大小(可以使用鼠标);这
_tmux-margins e
很有用。 - 我的脚本尝试不为边距创建边距。
- 销毁一个边距会销毁另一个边距。您可以选择一个边距并点击Ctrl+ c,而不是调用
_tmux-margins d
。 - 销毁窗格会销毁其边距(如果存在)。