Как сделать ширину панели tmux фиксированной?

4

Скажем, я разделил окно на 2 панели, правая имеет ширину 20 ячеек. Но когда я изменяю размер внешнего эмулятора терминала, ширина панели изменяется.

Есть ли способ это исправить? Потому что я хочу отображать информацию, которая отформатирована под 20 ячеек

haohaolee
источник

Ответы:

4

Насколько я могу судить, tmux не имеет никаких настроек для фиксации ширины до минимального значения, только до максимального значения. Это связано с тем, что размеры окон терминала могут быть меньше минимального значения tmux, а tmux может не иметь подходящего способа обработки этого.

При этом, если у вас открыты другие панели tmux, вы можете добавить небольшой скрипт в PS1 ( PS1='$(resizePane $id)other-stuff') или PROMPT_COMMAND, чтобы постоянно изменять размер информационной панели, которую вы хотите сохранить на ширине 20c, так как вы используете другие панели в tmux. По сути, 1) вы можете открыть программу, 2) изменить размер терминала, 3) перейти на другую панель, 4) тип Enterи blam, размер панели будет изменен.

Вы должны посмотреть на страницы руководства для

resize-pane [-DLRU] [-t target-pane] [adjustment]

Если вы находитесь на нужной панели, все, что нужно сделать, это уменьшить ширину слева -L или справа -R на x символов, необходимых для достижения 20. По сути, если панель находится напротив стены выше чем панель, используйте ее направление для сжатия и наоборот для увеличения. Если моя панель находится рядом с правой стеной, используйте -R, чтобы уменьшить ширину, и -L, чтобы увеличить ее.

Чтобы получить правильное количество символов, вам нужно знать текущую ширину панели, которую можно найти вместе с идентификатором панели, если вы наберете

tmux list-panes

Я еще не уверен, как определить номер панели, кроме того, что вы Prefix+qнабрали

tmux display-panes

Это даст нам номер идентификатора всех панелей в текущем окне. Если мы знаем 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на другой панели, чтобы продолжить работу на новой панели изменения размера, но я рассмотрел новый вариант, который может работать для вас ...

Я переосмыслил эту идею с момента первоначальной публикации и думаю, что она может быть разумно автоматизирована, если запущенная программа имеет цикл, который может отправлять команды оболочки. Это потому, что мы можем запустить программу, по существу разделив окно. Вот пример того, что я имею в виду. Следующий код

  1. Пользователь бежит runCodeSplit.sh, который
  2. разбивает новую панель по горизонтали (ширина 20c) справа от последней панели и запускает test.sh
  3. Введите цикл
  4. проверяет текущий размер панели и пытается изменить ее размер
  5. Спит 10 секунд (но вы можете изменить это, чтобы сделать все, что вы хотите)
  6. повторяется 3 и 4 раза 10, затем выходит

runCodeSplit.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"

test.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. Проблема в том, что каждый раз, когда вы запускаете его, они собираются рядом друг с другом, что, в свою очередь, приводит к тому, что они конкурируют за место (одно сжимает другое, чтобы расширяться, и наоборот). Возможно, вы сможете обойти эту проблему, но я оставлю это на ваше усмотрение, чтобы выяснить.

scicalculator
источник
Спасибо за подробный ответ. Вы сказали, что для изменения размера панели используйте команду PS или Prompt, значит ли это, что мне нужно переключиться на эту панель и нажать Enter, чтобы изменить размер? Есть ли способ отловить событие смены терминала? так что это может быть автоматическое изменение размера. Поскольку сам tmux может реагировать на изменение размера терминала.
Хаохоли
Извините, что мой предыдущий ответ был менее полезным для вас. Я переосмыслил это и добавил новый раздел выше, который может позволить вам автоматизировать процесс изменения размера. К вашему сведению, это тоже полезно для меня :)
scicalculator
пометить как ответивший Кстати, наконец, я не следовал этому подходу, потому что обнаружил, что используемая мной оболочка - zsh - имеет возможность перезванивать при изменении размера, поэтому я могу использовать tmux resize во времени.
Хаохоли
К вашему сведению: Текущий номер панели можно найти с помощьюtmux display-message -p '#P'
Peter V. Mørch
2

Я выложу свой сорт, так как он никому не повредит, и, возможно, подойдет кому-то лучше как есть.

Я использую его для изменения размера панели в сеансе irssi внутри tmux, который читает выходные данные из nicklist.plскрипта. Размер панели часто изменяется, когда я присоединяюсь к разным терминалам, и для правильной работы FIFO необходимо иметь ширину> 20 столбцов (и нет необходимости иметь ее шире, крадя пространство на экране).

Игнорируйте запутанный CURRENT_PANE_WIDTHрасчет и используйте вместо него grep + sed, если хотите. Текущий был в основном экспериментом, чтобы сохранить скрипт полностью в оболочке (за исключением вызовов 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
Даниэль Андерссон
источник
Благодарю. Ситуация, в которой я нахожусь, точно такая же, как у вас, я тоже использую irssi и tmux. Но кто должен назвать этот сценарий? Должен ли я назвать это на панели 1?
Хаохоли
Вы можете вызывать его из любого места, поскольку оно содержит имя сеанса tmux и т. Д. Лично я переписал вышеупомянутое как плагин irssi вместо этого - см. Раздел «Автообновление размера панели tmux для nicklist.pl» на 510x.se/notes/ posts / Install_and_setup_BitlBee . Я использовал плагин по крайней мере пару недель, и он прекрасно работает здесь.
Даниэль Андерссон
большое спасибо. Я бы проголосовал за твой ответ, когда мне хватит репутации
haohaolee