Como fazer uma largura de painel do tmux fixa?

4

Digamos que eu divida uma janela em 2 painéis, a da direita tenha 20 células de largura. Mas quando eu redimensiono o emulador de terminal externo, a largura do painel muda.

Existe alguma maneira de corrigir isso? Porque eu quero mostrar informações formatadas para caber 20 células

    
por haohaolee 13.08.2011 / 07:14

2 respostas

4

Tanto quanto eu posso dizer, o tmux não possui configurações para fixar a largura a um valor mínimo, apenas para um valor máximo. Isso ocorre porque as janelas de terminal podem ser redimensionadas para um valor menor que o mínimo do tmux e o tmux pode não ter uma maneira adequada de lidar com isso.

Dito isso, se você tiver outros painéis tmux abertos, você pode adicionar um script pequeno ao PS1 ( PS1='$(resizePane $id)other-stuff' ) ou PROMPT_COMMAND para redimensionar constantemente o painel de informações que deseja manter na largura de 20c à medida que você usa outros painéis dentro do tmux. Essencialmente, 1) você pode abrir o programa, 2) redimensionar o terminal, 3) mover para outro painel, 4) digite Enter e blam, o painel é redimensionado.

Você deve olhar as páginas do manual para

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

Se você estiver no painel desejado, tudo o que deve ser feito é reduzir a largura da esquerda -L ou da direita -R por x caracteres necessários para chegar a 20. Essencialmente, se o painel for contra uma parede mais alta que a vidraça, use a direção para encolher e o oposto para aumentar. Se meu painel estiver ao lado da parede da direita, use -R para reduzir a largura e -L para ampliá-lo.

Para obter a quantidade certa de caracteres, você precisa saber a largura atual do painel, que pode ser encontrado junto com o ID do painel se você digitar

tmux list-panes

Ainda não tenho certeza de uma maneira de saber em qual painel você está, exceto por Prefix+q ou digitando

tmux display-panes

Isso nos dará o número de identificação de todos os painéis na janela atual. Se soubermos o id # ($ id), assumindo que é contra a parede direita, podemos redimensionar o painel para 20 caracteres de largura:

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

Observe que o resizeNum não pode ser negativo. Se for negativo, use o outro lado para redimensionar para o valor absoluto de resizeNum (isso pode ser automatizado, mas vou deixar isso para você). Além disso, se você incorporar isso no código do seu programa, poderá negligenciar a parte "-t $ id", mas não sei como automatizar a localização do $ id a partir do seu programa.

Também pode ser útil ver tmux setw main-pane-width tmux setw other-pane-width , que definirá a largura específica do painel se você recarregar um novo formato de bloco. Para ciclos de formatos, use Prefix+space

Espero que isso ajude!

--- editada para adicionar mais informações sobre automação ---

Meu pensamento anterior era que você fosse para um novo painel e executasse PS1="$(resizePane $id)${PS1}" e, em seguida, atingisse ENTER dentro do outro painel para continuar trabalhando no novo painel de redimensionamento, mas considerei uma nova opção que pode funcionar para você ...

Eu tenho repensado essa ideia desde o lançamento original e acho que pode ser razoavelmente automatizado se o programa rodando tiver um loop que possa enviar comandos shell. Isso ocorre porque podemos executar o programa basicamente dividindo a janela. Aqui está um exemplo do que quero dizer. O seguinte código

  1. O usuário executa runCodeSplit.sh , que
  2. divide um novo painel horizontalmente (20c de largura) à direita do painel final e executa test.sh
  3. Insira o loop
  4. verifica o tamanho atual do painel e tenta redimensionar
  5. Dorme por 10 segundos (mas você pode mudar isso para fazer o que quiser)
  6. repete 3 & 4 10 vezes e, em seguida, sai

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

NOTA: Infelizmente, da maneira como eu o implementei acima, você só deve executá-lo uma vez por janela do tmux. O problema é que cada vez que você executá-lo, eles irão se agrupar próximos um do outro, o que, por sua vez, os colocará competindo pelo espaço (um irá encolher o outro para expandir e vice-versa). Você pode resolver esse problema, mas deixo isso para você descobrir.

    
por 14.08.2011 / 09:27
2

Eu vou postar a minha variedade, uma vez que não vai machucar ninguém, e talvez se encaixe melhor para alguém como está.

Eu uso para redimensionar um painel em uma sessão irssi dentro do tmux que lê a saída do script nicklist.pl . O painel frequentemente é redimensionado quando eu conecto terminais diferentes, e é necessário ter 20 colunas de largura para que o FIFO funcione corretamente (e é desnecessário tê-lo mais largo, roubando meu espaço de tela).

Ignore o cálculo de CURRENT_PANE_WIDTH complicado e use o grep + sed em vez disso, se desejar. O atual foi principalmente uma experiência para manter o script totalmente em shell (exceto as chamadas do tmux, é claro). É mais provável que seja mais rápido, o que pode ser interessante para a automação em que o script é executado com frequência (atualmente o executo como uma chamada específica).

#!/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]\+\).*//')"

# 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
    
por 12.02.2012 / 17:23

Tags