Título do painel em Tmux

88

Em minha máquina local, tenho 3 instâncias de node.js em execução simultaneamente. Cada um tem seu próprio painel em uma janela do tmux chamada "servidores". O problema é que não é tão fácil descobrir qual nó está sendo executado em qual painel, porque seus logs são semelhantes.

O que preciso é de um título para cada painel. Como descobri, o tmux em si não tem esse recurso: ele só tem títulos para janelas e não para painéis. Lançar uma sessão tmux separada dentro de cada painel para cada instância do node.js parece um exagero.

Então, há algum pequeno programa que inicia um comando, envolvendo sua saída com uma barra de status especificada?

desde já, obrigado

Andrey Lushnikov
fonte
1
tmux a partir da versão 2.3 suporta títulos de painel, consulte stackoverflow.com/a/37602055/266453
Dennis G

Respostas:

80

O tmux oferece suporte a títulos por painel, mas não fornece uma localização por painel para exibir esses títulos.

Você pode definir o título de um painel com a sequência de escape ESC ]2;… ESC \(por exemplo, consulte a seção chamada Nomes e títulos na página de manual do tmux ). Você poderia fazer isso a partir do shell assim:

printf '\033]2;%s\033\\' 'title goes here'

O título de cada painel é padronizado para o nome do host do sistema. Por padrão, o título do painel ativo é exibido no lado direito da linha de status do tmux (o valor global padrão da variável de sessão status-righté "#22T" %H:%M %d-%b-%y, que mostra 22 caracteres do título do painel, a hora e a data).

Portanto, contanto que você esteja satisfeito em poder ver o título do painel ativo (ou seja, disposto a alternar os painéis para ver o título de um painel inativo), você pode continuar com a funcionalidade padrão. Basta enviar a sequência de escape de definição de título apropriada antes de iniciar o comando principal para cada painel.


Se você precisa absolutamente de uma linha dedicada para exibir algumas informações por painel, então as sessões aninhadas do tmux podem não ser tão (desnecessárias) “exageradas” como você pode pensar.

No caso geral, para fornecer uma linha de status inviolável em algum terminal determinado, você precisará de um (re) emulador de terminal completo que fica entre o terminal original e um novo terminal (um com menos linhas). Essa (re) emulação é necessária para traduzir as sequências de controle enviadas para o terminal interno e traduzi-las para o terminal original. Por exemplo, para manter uma linha de status na parte inferior do terminal externo, o comando

Vá para a última linha.

enviado para o terminal interno deve ser tornado

Vá para a próxima à última linha.

quando traduzido e enviado para o terminal externo. Da mesma forma, um LF enviado para o terminal interno deve se tornar

Se o cursor estiver na penúltima linha, role esta linha e todas as linhas acima uma linha acima, para fornecer uma linha próxima à última clara (protegendo a linha de status na última linha). Caso contrário, envie um LF.

no terminal externo.

Programas como tmux e screen são apenas esses reemuladores de terminal. Claro, há muitas outras funcionalidades envolvidas no emulador de terminal, mas você precisaria de um grande pedaço de código de emulação de terminal apenas para fornecer uma linha de status confiável .


Existe, no entanto, uma solução leve, desde que

  1. seus programas ( instâncias de Node.js ) têm interações de terminal limitadas com os painéis em que estão sendo executados (ou seja, sem posicionamento do cursor), e
  2. você não redimensiona os painéis enquanto seus programas estão em execução.

Como muitos emuladores de terminal, o tmux suporta um comando de controle de terminal “set scrolling region” em seus painéis. Você pode usar este comando para limitar a região de rolagem às N-1 linhas superiores (ou inferiores) do terminal e escrever algum tipo de texto de identificação de instância na linha não rolante.

As restrições (nenhum comando de movimento do cursor permitido, nenhum redimensionamento) são necessárias porque o programa que está gerando a saída (por exemplo, uma instância do Node.js ) não tem ideia de que a rolagem foi limitada a uma região específica. Se o programa de geração de saída mover o cursor para fora da região de rolagem, a saída pode ficar distorcida. Da mesma forma, o emulador de terminal provavelmente redefine automaticamente a região de rolagem quando o terminal é redimensionado (então a “linha não rolante” provavelmente acabará rolando para longe).

Eu escrevi um script que usa tputpara gerar as sequências de controle apropriadas, escrever na linha não rolante e executar um programa depois de mover o cursor para a região de rolagem:

#!/bin/sh

# usage: no_scroll_line top|bottom 'non-scrolling line content' command to run with args
#
#     Set up a non-scrolling line at the top (or the bottom) of the
#     terminal, write the given text into it, then (in the scrolling
#     region) run the given command with its arguments. When the
#     command has finished, pause with a prompt and reset the
#     scrolling region.

get_size() {
    set -- $(stty size)
    LINES=$1
    COLUMNS=$2
}
set_nonscrolling_line() {
    get_size
    case "$1" in
        t|to|top)
            non_scroll_line=0
            first_scrolling_line=1
            scroll_region="1 $(($LINES - 1))"
            ;;
        b|bo|bot|bott|botto|bottom)
            first_scrolling_line=0
            scroll_region="0 $(($LINES - 2))"
            non_scroll_line="$(($LINES - 1))"
            ;;
        *)
            echo 'error: first argument must be "top" or "bottom"'
            exit 1
            ;;
    esac
    clear
    tput csr $scroll_region
    tput cup "$non_scroll_line" 0
    printf %s "$2"
    tput cup "$first_scrolling_line" 0
}
reset_scrolling() {
    get_size
    clear
    tput csr 0 $(($LINES - 1))
}

# Set up the scrolling region and write into the non-scrolling line
set_nonscrolling_line "$1" "$2"
shift 2

# Run something that writes into the scolling region
"$@"
ec=$?

# Reset the scrolling region
printf %s 'Press ENTER to reset scrolling (will clear screen)'
read a_line
reset_scrolling

exit "$ec"

Você pode usá-lo assim:

tmux split-window '/path/to/no_scroll_line bottom "Node instance foo" node foo.js'
tmux split-window '/path/to/no_scroll_line bottom "Node instance bar" node bar.js'
tmux split-window '/path/to/no_scroll_line bottom "Node instance quux" node quux.js'

O script também deve funcionar fora do tmux , desde que o terminal suporte e publique seus recursos csre do cupterminfo.

Chris Johnsen
fonte
seu script funciona exatamente como eu esperava; a única pergunta: o que devo google para personalizar a cor de "non_scroll_line"?
Andrey Lushnikov
1
Talvez "capacidade do terminfo cor de fundo do primeiro plano" (ou seja, leia sobre cor na página de manual do terminfo). Você pode usar tputpara incluir as sequências de controle apropriadas no argumento “conteúdo da linha”. Com a maioria dos terminais, você pode fazer com que a linha seja “ciano (6) e verde (3) em magenta (5)” com no_scroll_line top "$(tput setaf 6; tput setab 5)Node: $(tput setaf 3)foo$(tput op)" node foo.js. setafdefine o primeiro plano, setabdefine o plano de fundo, oprestaura as cores padrão dos terminais. Os recursos de cores variam de 0–7, 0–15, 0–87 ou 0–255, dependendo da emulação do terminal.
Chris Johnsen
Agora lançamos o pymux. Isso exibe as barras de título do painel: github.com/jonathanslenders/pymux
Jonathan Slenders
Parece que o comportamento é que o título do painel está definido para o comando que está sendo executado no shell. Portanto, ele não "grudará" a menos que estejamos executando um processo de longa duração (que também sabe como gerar a sequência de escape de definição de título) dentro.
Steven Lu
4
Por favor, dê uma olhada na resposta mais abaixo: stackoverflow.com/a/37602055/266453 tmux a partir da versão 2.3 suporta títulos nas bordas do painel.
Dennis G,
78

Esta funcionalidade foi adicionada ao tmux neste commit . Não está na versão 2.2, mas parece que estará na 2.3.

Para habilitá-lo:

tmux set -g pane-border-status top

ou se preferir:

tmux set -g pane-border-status bottom

Para definir um texto personalizado como a linha de status da borda do painel, você pode fazer uso pane-border-format, por exemplo:

tmux set -g pane-border-format "#{pane_index} #{pane_current_command}"
Kevmitch
fonte
1
Mostra o número do painel e um título padrão. Como você muda esse pensamento?
adn
Não tenho certeza sobre os números do painel, mas ele responde como um título de janela xterm para sequências de escape. Por exemplo, com bash, configurei PS1 = '[\ e] 0; \ u @ \ h: \ w \ a] $' para obter "usuário @ host: diretório de trabalho /"
kevmitch
Pelo que eu entendo, você definiu essa sequência de antemão. Mas não há atalho ou combinação de teclas que os altere. Então, tmuxvocê precisa de algum comando externo tmuxpara alterá-lo. Direito? Ou existe alguma sequência interna que pode atualizá-lo?
adn
Sim, você apenas define a variável no shell em execução e ela atualiza quando o próximo prompt é desenhado. Para mim, parece que o tmux é um pouco incompleto e só o atualiza quando você muda para outro painel.
kevmitch
Você pode realmente usar pane-border-formatpara definir uma string de formato personalizado para o painel exibir (o #{...}formato normal ). Eu editei sua resposta para incluir isso.
Dennis G,
33

Já que tmux 2.6você pode fazer:

$ tmux select-pane -t {pane} -T {title}

# Examples:
$ tmux select-pane -T title1          # Change title of current pane
$ tmux select-pane -t 1 -T title2     # Change title of pane 1 in current window
$ tmux select-pane -t 2.1 -T title3   # Change title of pane 1 in window 2

Você pode ver o título por painel em uma barra de status com:

$ tmux set pane-border-status bottom      # For current window
$ tmux set -g pane-border-status bottom   # For all windows

Desative a barra de status com:

$ tmux set pane-border-status off       # For current window
$ tmux set -g pane-border-status off    # For all windows
Eyal Levin
fonte
Você sabe se existe alguma maneira de evitar que o tmux mude o título sob você? Por exemplo, se eu definir o título de um painel e fizer algo nesse painel, como cd $HOME, o título é alterado para o valor de $HOME. (Estou vendo isso no tmux 2.8.)
pdoherty926
1
@ pdoherty926 Talvez você já tenha a resposta, mas confira set-window-option automatic-rename off.
noname
Eu tenho set-option -g allow-rename offem meu .tmux.confarquivo.
Eyal Levin
1
Obrigado pelas sugestões. Acabei usando pane-border-formatuma variável fornecida pelo usuário (não tenho certeza se existe um nome oficial para esse recurso) para controlar o que é exibido. Aqui está um exemplo.
pdoherty926
14

Estou trabalhando na barra de status do painel para tmux - ticket. Meu branch de desenvolvimento pode ser encontrado aqui no github: https://github.com/jonathanslenders/tmux

No momento, isso já adiciona um comando "título" de painel de renomeação funcional . Ainda existem alguns bugs e a API irá melhorar. A ideia é criar uma barra de status por painel, que pode ter alguma formatação, como a barra de status da sessão. Como o resto do tmux, tudo deve se tornar programável e personalizável. Quando finalizado e estável, provavelmente será incluído no tmux oficial.

Jonathan Slenders
fonte
Enquanto você está lá, você pode fazer com que o título do painel se torne o título da janela padrão durante uma pausa no painel?
djsadinoff
Este branch nunca foi fundido no tmux. Mas eu criei pymux em vez disso, que tem barras de título de painel: github.com/jonathanslenders/pymux
Jonathan Slenders
Este comando também não funciona na última compilação (commit a24260).
adn
14

Estou usando o tmux versão 2.3, acho que o estilo de borda não é suportado nas versões anteriores. Isto é o que funcionou para mim:

Para cada painel, defina o título:

printf '\033]2;My Pane Title\033\\'

Então:

tmux set -g pane-border-format "#{pane_index} #T"
OriG
fonte
9
Pelo menos tão recente quanto o tmux 2.6, você pode alterar o título do painel dentro do tmux: select-pane -T "my title"faça isso. Você pode até configurar uma vinculação de chave, portanto, basta fornecer o título:bind-key T command-prompt -p "New title:" 'select-pane -T "%%"'
lucasem
3
@lucasem talvez eu não tenha seguido este tópico, mas esta parece ser a resposta.
icicleking
@lucasem Não tenho 100% de certeza, mas acredito que seu método (que IMO é o melhor e mais simples em todo este tópico, para versões recentes do tmux) só funciona se a pane-border-statusopção for definida como algo ( topou bottom).
cjauvin
11

Um gif vale mais que mil palavras. ( fonte )

tmux-xpanes é um divisor de terminal baseado em tmux, que suporta a exibição de títulos para cada painel por meio da -topção recém-adicionada .

navigaid
fonte
1
Um gif vale mais que mil palavras, mas se algum dia ele apodrecer, não vale nada.
Processo de Fundo Monica
7

Sim, existe tal comando a: tmux. Dê um nome à sua sessão e ele será exibido em uma barra de status interna:

TMUX=0 tmux new-session -s my-new-session
event_jr
fonte
2
Sim, obrigado pela sua resposta! Mas, portanto, terei que lançar uma nova sessão do tmux em cada painel apenas para um título na parte inferior - meio que um exagero, não é?
Andrey Lushnikov
Eu não sei. É isso? Tentaste? Quanta memória extra a sessão extra está usando?
event_jr
sim, tenho usado sessões aninhadas do tmux até hoje. Não tenho certeza sobre o consumo de memória e coisas assim - eu simplesmente não gosto do conceito em si porque não é puro.
Andrey Lushnikov
0

TL; DR

Anexe as seguintes configurações ao seu arquivo de configuração tmux (no meu caso é ~/.tmux.conf.local)

# dispaly pane_current_path as the pane title
set -g pane-border-status top
set -g pane-border-format "#{pane_index} #{pane_current_path}"

então corra:

tmux source-file ~/.tmux.con

Aproveite

Graças a https://stackoverflow.com/a/37602055/5121972

estrutura
fonte