为 tmux 创建“焦点模式”?(一个居中的窗格两侧是两个空白窗格?)

Rya*_*Lue 6 terminal bash tmux

我想使用 tmux 为终端创建一个“焦点模式”,有点像goyo 为 vim 所做的

goyo 截图

问题 1:调整窗格大小

我的想法是通过将窗口分成三个窗格来实现这一点,然后将中心窗格设置为固定的最大值(可能是 80 列?可能是 100?可能根据终端窗口大小不同的最大值,例如响应式 Web 布局?)并设置侧窗格以平均填充剩余的列。我还希望它可以在不同尺寸的屏幕上工作,这样我就可以在我的笔记本电脑和台式机上使用它。

目前,我能想到的唯一方法是与 shell 合作(即,获取终端宽度,tput cols然后使用数学运算计算每个窗格所需的宽度$(()))。我对此没有意见,但是如果在 tmux 中有一种内置方法可以完成此操作,我会因为错过它而感到非常愚蠢。

所以……有吗?

问题 2:消隐侧窗格

这不太重要;看到顶部有提示的大部分空白窗格确实还不错。我知道 tmux 有clock-mode(例如),它会覆盖窗格的内容并显示其他内容。所以我想知道是否有办法完全隐藏非活动窗格的内容。到目前为止,我能想到的最好的方法是将 fg 和 bg 设置为相同的颜色

:select-pane -t:.1 -P 'fg=black,bg=black'
Run Code Online (Sandbox Code Playgroud)

或者,圣杯

如果tmux 中的窗格有边距功能,那么这一切都可以更轻松地完成。据我所知,此功能不存在,但我远非 tmux 专家。有没有可能它在那里而我只是不知道它?

Kam*_*ski 5

这就是我的名字_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
Run Code Online (Sandbox Code Playgroud)

有一些片段和解决方案我并不引以为豪。仍然有效。


像这样使用它(前提是它在您的 目录中$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 +NN如果可能,将列添加到中心窗格)。
  • 要缩小中心窗格(扩大边距):
    • _tmux-margins -
    • _tmux-margins -NN如果可能,从中心窗格中减去列)。

第二个参数(未在上述示例中使用)指定窗格。通过这种方式,您可以从另一个窗格或从tmux. 例子:

_tmux-margins c .1
_tmux-margins - %5
Run Code Online (Sandbox Code Playgroud)

有两个有用的变量:

  • TMUX_M_COLUMNS– 创建边距时中心窗格的所需宽度(80如果未设置)。
  • TMUX_M_COMMAND– 在边距窗格中运行的命令(true如果未设置)。如果调整了边距,该命令将重新启动。我实施这个的主要原因:

    TMUX_M_COMMAND='cmatrix -u 20' _tmux-margins create
    
    Run Code Online (Sandbox Code Playgroud)

我有这个~/.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}"'
Run Code Online (Sandbox Code Playgroud)

这些线使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_COLUMNSTMUX_M_COMMAND使用击键,您需要为 tmux 服务器本身设置它们:

    • 对于第一个tmux(启动服务器的那个):

      TMUX_M_COMMAND='cmatrix -b' tmux
      
      Run Code Online (Sandbox Code Playgroud)
    • 或在您的~/.tmux.conf

      set-environment -g TMUX_M_COMMAND 'cmatrix -b'
      
      Run Code Online (Sandbox Code Playgroud)

      (注意-g(全局环境)是必须的,因为tmux.conf在任何会话开始之前都会被解析);

    • 或以后(当 tmux 服务器运行时)像这样:

      tmux set-environment TMUX_M_COMMAND 'cmatrix -b'
      
      Run Code Online (Sandbox Code Playgroud)

      (有或没有-g;请注意,如果不在 tmux 内,则您需要-g-t);

    • 或从 tmux 内部:

      prefix:set-environment TMUX_M_COMMAND 'cmatrix -b'Enter

      (同样,有或没有-g)。


一般注意事项:

  • 边距只是窗格。如果您拆分边距或将其与另一个窗格交换或将其从窗口中分离出来,因此它看起来不像是适当的边距,那么这是您的问题。或者,如果您拆分中心窗格等。
  • 另一方面,您可以像任何其他窗格一样调整边距(可能使用鼠标);那么_tmux-margins e有用。
  • 我的脚本尽量不为边距创建边距。
  • 破坏一个边距会破坏另一个边距。您可以选择边距并点击Ctrl+c而不是调用_tmux-margins d.
  • 销毁窗格会破坏其边距(如果存在)。