Tytuł okienka w Tmux

88

Na moim komputerze lokalnym mam jednocześnie uruchomione 3 instancje node.js. Każdy ma swój własny panel w oknie tmux o nazwie „serwery”. Problem polega na tym, że nie jest łatwo dowiedzieć się, który węzeł działa w którym okienku, ponieważ ich dzienniki są podobne.

Potrzebuję tytułu każdego okienka. Jak dostałem, sam tmux nie ma tej funkcji: ma tylko tytuły dla okien, a nie dla okienek. Uruchomienie oddzielnej sesji tmux w każdym okienku dla każdej instancji node.js wygląda na przesadę.

Czy jest więc jakiś mały program, który uruchamia polecenie, zawijając swoje dane wyjściowe określonym paskiem stanu?

Z góry dziękuję

Andrey Lushnikov
źródło
1
tmux od wersji 2.3 obsługuje tytuły paneli, patrz stackoverflow.com/a/37602055/266453
Dennis G

Odpowiedzi:

80

tmux obsługuje tytuły dla okienka, ale nie zapewnia lokalizacji dla okienka do wyświetlania tych tytułów.

Możesz ustawić tytuł panelu za pomocą sekwencji ucieczki ESC ]2;… ESC \(np. Zobacz sekcję o nazwie Nazwy i tytuły na stronie podręcznika tmux ). Możesz to zrobić z powłoki w następujący sposób:

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

Tytuł każdego okienka jest domyślnie nazwą hosta systemu. Domyślnie tytuł aktywnego panelu jest wyświetlany po prawej stronie wiersza stanu tmux (domyślna wartość globalna zmiennej sesji status-rightto "#22T" %H:%M %d-%b-%y, która pokazuje 22 znaki tytułu panelu, czas i datę).

Tak więc, o ile jesteś w stanie zobaczyć tytuł aktywnego panelu (tj. Chcesz przełączyć okienka, aby zobaczyć tytuł nieaktywnego panelu), możesz skorzystać z domyślnej funkcjonalności. Po prostu wyślij odpowiednią sekwencję włączającą ustawienie tytułu przed uruchomieniem głównego polecenia dla każdego okienka.


Jeśli absolutnie potrzebujesz dedykowanej linii do wyświetlania niektórych informacji dla poszczególnych okienek, zagnieżdżone sesje tmux mogą nie być tak dużym (niepotrzebnym) „przesadą”, jak mogłoby się początkowo wydawać.

W ogólnym przypadku, aby zapewnić nienaruszoną linię statusu na jakimś podanym terminalu, będziesz potrzebował pełnego (re) emulatora terminala, który znajduje się pomiędzy oryginalnym terminalem a nowym terminalem (jeden z jedną linią mniej). Taka (re) emulacja jest potrzebna do przetłumaczenia sekwencji sterujących wysyłanych do terminala wewnętrznego i przetłumaczenia ich na oryginalny terminal. Na przykład, aby utrzymać linię stanu na dole zewnętrznego terminala, polecenie

Przejdź do ostatniej linii.

wysłane do terminala wewnętrznego musi zostać

Przejdź do następnego wiersza do ostatniego.

po przetłumaczeniu i wysłaniu do terminala zewnętrznego. Podobnie musi zostać wysłany LF do wewnętrznego terminala

Jeśli kursor znajduje się na przedostatniej linii, przewiń tę linię i wszystkie linie nad nią o jedną linię w górę, aby zapewnić wyraźną linię przedostatnią (chroniąc linię stanu w ostatniej linii). W przeciwnym razie wyślij LF.

w zacisku zewnętrznym.

Programy takie jak tmux i screen są po prostu takimi reemulatorami terminala. Jasne, istnieje wiele innych funkcji owiniętych wokół emulatora terminala, ale potrzebujesz dużego fragmentu kodu emulacji terminala, aby zapewnić niezawodną linię stanu.


Istnieje jednak lekkie rozwiązanie, o ile

  1. Twoje programy ( instancje Node.js ) mają ograniczone interakcje terminala z panelami, w których są uruchomione (tj. bez pozycjonowania kursora), i
  2. nie zmieniasz rozmiaru okienek podczas działania programów.

Podobnie jak wiele emulatorów terminali, tmux obsługuje w swoich panelach polecenie sterowania terminalem „ustaw obszar przewijania”. Możesz użyć tego polecenia, aby ograniczyć obszar przewijania do górnych (lub dolnych) N-1 linii terminala i wpisać jakiś rodzaj tekstu identyfikującego instancję w nie przewijanej linii.

Ograniczenia (niedozwolone polecenia ruchu kursora, brak zmiany rozmiaru) są wymagane, ponieważ program generujący dane wyjściowe (np. Instancja Node.js ) nie ma pojęcia, że ​​przewijanie zostało ograniczone do określonego regionu. Jeśli zdarzyło się, że program generujący dane wyjściowe przesunął kursor poza obszar przewijania, dane wyjściowe mogą zostać zniekształcone. Podobnie, emulator terminala prawdopodobnie automatycznie resetuje obszar przewijania, gdy zmieniany jest rozmiar terminala (więc „wiersz bez przewijania” prawdopodobnie skończy się przewijaniem).

Napisałem skrypt, który używa tputdo wygenerowania odpowiednich sekwencji sterujących, wpisania do linii nie przewijającej się i uruchomienia programu po najechaniu kursorem na obszar przewijania:

#!/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"

Możesz go użyć w ten sposób:

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'

Skrypt powinien również działać poza tmux, o ile terminal obsługuje i publikuje swoje możliwości csri cupterminfo.

Chris Johnsen
źródło
twój skrypt działa dokładnie tak, jak się spodziewałem; jedyne pytanie: co mam wygooglować, aby dostosować kolor „non_scroll_line”?
Andrey Lushnikov
1
Może „kolor tła pierwszego planu funkcji terminfo” (np. Przeczytaj o kolorze na stronie podręcznika terminfo). Możesz użyć, tputaby dołączyć odpowiednie sekwencje sterujące do argumentu „zawartość wiersza”. W przypadku większości terminali można ustawić wiersz „cyjan (6) i zielony (3) na magenta (5)” za pomocą no_scroll_line top "$(tput setaf 6; tput setab 5)Node: $(tput setaf 3)foo$(tput op)" node foo.js. setafustawia pierwszy plan, setabustawia tło,op resetuje do domyślnych kolorów terminala. Możliwości koloru przyjmują liczbę z zakresu 0–7, 0–15, 0–87 lub 0–255, w zależności od emulacji terminala.
Chris Johnsen
Teraz wydaliśmy pymux. Spowoduje to wyświetlenie pasków tytułu okienka: github.com/jonathanslenders/pymux
Jonathan Slenders
Wydaje się, że zachowanie polega na tym, że tytuł panelu jest ustawiony na polecenie uruchamiane w powłoce. Więc nie będzie się „przyklejać”, chyba że uruchomimy jeden długotrwały proces (który również wie, jak wyprowadzić sekwencję ucieczki ustawienia tytułu) wewnątrz.
Steven Lu
4
Spójrz na odpowiedź poniżej: stackoverflow.com/a/37602055/266453 tmux od wersji 2.3 obsługuje tytuły w obramowaniach okienek.
Dennis G
78

Ta funkcja została dodana do tmux w tym zatwierdzeniu . Nie ma go w wersji 2.2, ale wygląda na to, że będzie w wersji 2.3.

Aby to włączyć:

tmux set -g pane-border-status top

lub jeśli wolisz:

tmux set -g pane-border-status bottom

Aby ustawić niestandardowy tekst jako linię stanu obramowania okienka, możesz użyć na pane-border-formatprzykład:

tmux set -g pane-border-format "#{pane_index} #{pane_current_command}"
kevmitch
źródło
1
Pokazuje numer okienka i domyślny tytuł. Jak to zmienić?
wyniki
Nie jestem pewien co do numerów okienka, ale na sekwencje ucieczki reaguje jak tytuł okna xterm. Na przykład w przypadku basha ustawiłem PS1 = '[\ e] 0; \ u @ \ h: \ w \ a] $', aby uzyskać „user @ host: working dir /”
kevmitch
O ile rozumiem, ustawiłeś tę sekwencję wcześniej. Ale nie ma skrótu ani kombinacji klawiszy, która je zmienia. Więc tmuxpotrzebujesz jakiegoś polecenia z zewnątrz, tmuxaby to zmienić. Dobrze? Czy jest w środku jakaś sekwencja, która może ją zaktualizować?
wyniki
Tak, po prostu ustaw zmienną w działającej powłoce i zaktualizuje się, gdy zostanie narysowany następny monit. Wydaje mi się, że tmux jest trochę szkicowy i faktycznie aktualizuje go tylko po przejściu do innego panelu.
kevmitch
W rzeczywistości możesz użyć, pane-border-formataby ustawić niestandardowy ciąg formatu dla panelu do wyświetlenia (zwykły #{...}format). Zredagowałem Twoją odpowiedź, aby to uwzględnić.
Dennis G
33

Ponieważ tmux 2.6możesz:

$ 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

Możesz zobaczyć tytuł w okienku na pasku stanu z:

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

Wyłącz pasek stanu za pomocą:

$ tmux set pane-border-status off       # For current window
$ tmux set -g pane-border-status off    # For all windows
Eyal Levin
źródło
Czy wiesz, czy istnieje sposób, aby zapobiec zmianie tytułu przez tmux spod Ciebie? Na przykład, jeśli ustawię tytuł panelu, a następnie zrobię coś w tym panelu, na przykład cd $HOMEtytuł zostanie zmieniony na wartość $HOME. (Widzę to na tmux 2.8.)
pdoherty926
1
@ pdoherty926 Może już masz odpowiedź, ale sprawdź set-window-option automatic-rename off.
noname
Mam set-option -g allow-rename offw swoich .tmux.confaktach.
Eyal Levin
1
Dzięki za sugestie. pane-border-formatSkończyło się na użyciu zmiennej dostarczonej przez użytkownika (nie jestem pewien, czy istnieje oficjalna nazwa tej funkcji), aby kontrolować, co jest wyświetlane. Oto przykład.
pdoherty926
14

Pracuję nad paskiem stanu panelu dla tmux - bilet. Moją gałąź rozwoju można znaleźć tutaj na github: https://github.com/jonathanslenders/tmux

W tej chwili to już dodaje działające polecenie „tytuł” ​​panelu zmiany nazwy . Wciąż jest kilka błędów, a API zostanie ulepszone. Pomysł polega na utworzeniu paska stanu dla każdego panelu, który może mieć pewne formatowanie, takie jak pasek stanu sesji. Podobnie jak reszta tmux, wszystko powinno stać się skryptowalne i konfigurowalne. Ukończony i stabilny prawdopodobnie zostanie uwzględniony w oficjalnym tmuxie.

Jonathan Slenders
źródło
Skoro już tam jesteś, czy możesz sprawić, by tytuł panelu stał się domyślnym tytułem okna podczas przerwania panelu?
djsadinoff
Ta gałąź nigdy nie została włączona do tmux. Ale zamiast tego stworzyłem pymux, który ma paski tytułowe okienka: github.com/jonathanslenders/pymux
Jonathan Slenders
To polecenie nie działa również w najnowszej kompilacji (zatwierdzenie a24260).
wyniki
14

Używam tmux w wersji 2.3, myślę, że styl obramowania nie jest obsługiwany w poprzednich wersjach. to działa dla mnie:

Dla każdego panelu ustaw tytuł:

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

Następnie:

tmux set -g pane-border-format "#{pane_index} #T"
OriG
źródło
9
Co najmniej tak niedawno jak tmux 2.6, możesz zmienić tytuł panelu w tmux: select-pane -T "my title"robi to. Możesz nawet ustawić przypisanie klawisza, więc wystarczy podać tytuł:bind-key T command-prompt -p "New title:" 'select-pane -T "%%"'
lucasem,
3
@lucasem może nie śledziłem tego wątku, ale wydaje się, że to odpowiedź.
icicleking
@lucasem Nie jestem pewien w 100%, ale wierzę, że twoja metoda (która IMO jest najlepsza i najprostsza w całym tym wątku, dla najnowszych wersji tmux) działa tylko wtedy, gdy pane-border-statusopcja jest ustawiona na coś ( toplub bottom).
Cjauvin
11

GIF jest wart tysiąca słów. ( źródło )

tmux-xpanes to dzielnik terminala oparty na tmux, który obsługuje wyświetlanie tytułu dla każdego okienka za pomocą nowo dodanej -topcji.

nawigacja
źródło
1
GIF jest wart więcej niż tysiąc słów, ale jeśli kiedykolwiek link zepsuje się, to nie będzie nic wart.
Sfinansuj pozew Moniki
7

Tak istnieje taka komenda a: tmux. Nadaj swojej sesji nazwę, a zostanie ona wyświetlona na wewnętrznym pasku stanu:

TMUX=0 tmux new-session -s my-new-session
event_jr
źródło
2
Tak, dziękuję za odpowiedź! Ale w związku z tym będę musiał uruchomić nową sesję tmux w każdym okienku tylko dla jednego tytułu na dole - rodzaj przesady, prawda?
Andrey Lushnikov
Nie wiem Czy to jest? Próbowałeś tego? Ile dodatkowej pamięci zużywa dodatkowa sesja?
event_jr
tak, do dziś używam zagnieżdżonych sesji tmux. Nie jestem pewien co do zużycia pamięci i takich rzeczy - po prostu nie podoba mi się sama koncepcja, ponieważ nie jest czysta.
Andrey Lushnikov
0

TL; DR

Dołącz następujące konfiguracje do pliku konfiguracyjnego tmux (w moim przypadku jest ~/.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}"

następnie uruchomić:

tmux source-file ~/.tmux.con

ciesz się tym

Dzięki https://stackoverflow.com/a/37602055/5121972

sstruct
źródło