Заголовок панели в Tmux

88

На моем локальном компьютере одновременно работают 3 экземпляра node.js. У каждого есть своя собственная панель в окне tmux, которая называется «серверы». Проблема в том, что не так просто определить, какой узел на какой панели работает, потому что их журналы похожи.

Мне нужно название для каждой панели. Как я понял, сам tmux не имеет такой функции: у него есть только заголовки для окон, а не для панелей. Запуск отдельного сеанса tmux внутри каждой панели для каждого экземпляра node.js выглядит как излишество.

Так есть ли небольшая программа, которая запускает команду, заключая ее вывод в указанную строку состояния?

заранее спасибо

Андрей Лушников
источник
1
tmux начиная с версии 2.3 поддерживает заголовки панелей, см. stackoverflow.com/a/37602055/266453
Dennis G

Ответы:

80

tmux поддерживает заголовки для каждой панели, но не обеспечивает расположение для каждой панели для отображения этих заголовков.

Вы можете установить заголовок панели с помощью escape-последовательности ESC ]2;… ESC \(например, см. Раздел « Имена и заголовки» на странице руководства tmux ). Вы можете сделать это из оболочки следующим образом:

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

Заголовок каждой панели по умолчанию соответствует имени хоста системы. По умолчанию заголовок активного окна выводится на дисплее на правой стороне tmux строки состояния ( по умолчанию глобального значения переменного сеанса status-rightявляется "#22T" %H:%M %d-%b-%y, которая показывает 22 символов из заголовке панели, времени и даты).

Итак, до тех пор, пока вы удовлетворены тем, что можете видеть заголовок активной панели (т.е. желаете переключить панели, чтобы увидеть заголовок неактивной панели), вы можете обойтись функциональностью по умолчанию. Просто отправьте соответствующую escape-последовательность для установки заголовка перед запуском основной команды для каждой панели.


Если вам абсолютно необходима выделенная строка для отображения некоторой информации о каждой панели, то вложенные сеансы tmux могут быть не такими (ненужными) «излишними», как вы могли сначала подумать.

В общем случае, чтобы обеспечить нерушимую строку состояния на каком-либо данном терминале, вам понадобится полный (пере) эмулятор терминала, который находится между исходным терминалом и новым терминалом (один с на одну строку меньше). Такая (повторная) эмуляция необходима для трансляции управляющих последовательностей, отправленных на внутренний терминал, и их трансляции для исходного терминала. Например, чтобы поддерживать строку состояния в нижней части внешнего терминала, команда

Перейти к последней строке.

отправлено на внутренний терминал должен быть

Перейти к предпоследней строке.

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

Если курсор находится на предпоследней строке, прокрутите эту строку и все строки над ней на одну строку вверх, чтобы очистить предпоследнюю строку (защищая строку состояния на последней строке). В противном случае отправьте LF.

во внешнем терминале.

Такие программы, как tmux и screen, являются такими эмуляторами терминала. Конечно, эмулятор терминала обладает множеством других функций, но вам понадобится большой кусок кода эмуляции терминала, чтобы обеспечить надежную строку состояния.


Однако есть облегченное решение, если

  1. ваши программы ( экземпляры Node.js ) имеют ограниченное взаимодействие терминала с панелями, в которых они работают (т.е. без позиционирования курсора), и
  2. вы не изменяете размер панелей во время работы ваших программ.

Как и многие эмуляторы терминала, tmux поддерживает команду управления терминалом «установить область прокрутки» на своих панелях. Вы можете использовать эту команду, чтобы ограничить область прокрутки верхними (или нижними) строками N-1 терминала и записать какой-то текст, идентифицирующий экземпляр, в строку без прокрутки.

Ограничения (запрещение команд перемещения курсора, отсутствие изменения размера) необходимы, поскольку программа, генерирующая вывод (например, экземпляр Node.js ), не знает, что прокрутка была ограничена определенной областью. Если программа, генерирующая вывод, переместила курсор за пределы области прокрутки, то вывод может стать искаженным. Точно так же эмулятор терминала, вероятно, автоматически сбрасывает область прокрутки при изменении размера терминала (так что «строка без прокрутки», вероятно, закончится прокруткой).

Я написал сценарий, который использует tputдля генерации соответствующих управляющих последовательностей, записи в строку без прокрутки и запуска программы после перемещения курсора в область прокрутки:

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

Вы можете использовать это так:

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'

Сценарий также должен работать вне tmux, если терминал поддерживает и публикует свои возможности csrи cupterminfo.

Крис Джонсен
источник
ваш сценарий работает именно так, как я ожидал; единственный вопрос: что мне гуглить, чтобы настроить цвет "non_scroll_line"?
Андрей Лушников
1
Возможно, «цвет фона переднего плана возможностей terminfo» (т.е. читайте о цвете в man-странице terminfo). Вы можете использовать tputдля включения соответствующих управляющих последовательностей в аргумент «содержимое строки». На большинстве терминалов вы можете сделать линию «голубой (6) и зеленой (3) на пурпурной (5)» с помощью no_scroll_line top "$(tput setaf 6; tput setab 5)Node: $(tput setaf 3)foo$(tput op)" node foo.js. setafустанавливает передний план, setabустанавливает фон, opсбрасывает цвета терминала по умолчанию. Возможности цвета принимают числа от 0–7, 0–15, 0–87 или 0–255, в зависимости от эмуляции вашего терминала.
Крис Йонсен
Мы выпустили pymux. Это отображает строки заголовка панели: github.com/jonathanslenders/pymux
Джонатан Слендерс,
Кажется, что поведение таково, что заголовок панели установлен на команду, выполняемую в оболочке. Таким образом, он не будет «прилипать», если мы не запустим один долговечный процесс (который также знает, как выводить escape-последовательность установки заголовка) внутри.
Стивен Лу
4
Взгляните на ответ ниже: stackoverflow.com/a/37602055/266453 tmux начиная с версии 2.3 поддерживает заголовки в границах панели.
Dennis G
78

Эта функция была добавлена ​​в tmux в этом коммите . Его нет в версии 2.2, но похоже, что он будет в версии 2.3.

Чтобы включить его:

tmux set -g pane-border-status top

или, если хотите:

tmux set -g pane-border-status bottom

Чтобы установить собственный текст в качестве строки состояния границы панели, вы можете использовать pane-border-format, например, вот так:

tmux set -g pane-border-format "#{pane_index} #{pane_current_command}"
Кевмитч
источник
1
Здесь отображается номер панели и заголовок по умолчанию. Как изменить это мышление?
ADN
Я не уверен насчет номеров панелей, но он реагирует как заголовок окна xterm на escape-последовательности. Например, в bash я установил PS1 = '[\ e] 0; \ u @ \ h: \ w \ a] $', чтобы получить «user @ host: working dir /»
kevmitch
Насколько я понимаю, вы заранее устанавливаете эту последовательность. Но нет сочетания клавиш или сочетания клавиш, которое их изменяет. Итак, tmuxвам нужна какая-то команда извне, tmuxчтобы изменить это. Правильно? Или есть какая-то последовательность внутри, которая может его обновить?
adn
Да, вы просто устанавливаете переменную в работающей оболочке, и она обновляется, когда отображается следующее приглашение. Мне кажется, что tmux немного схематичен и фактически обновляет его только при переключении на другую панель.
kevmitch
Фактически вы можете использовать pane-border-formatдля установки строки настраиваемого формата для отображения панели (обычный #{...}формат). Я отредактировал ваш ответ, чтобы включить это.
Dennis G
33

Поскольку tmux 2.6вы можете:

$ 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

Вы можете увидеть заголовок каждой панели в строке состояния с помощью:

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

Отключить строку состояния с помощью:

$ tmux set pane-border-status off       # For current window
$ tmux set -g pane-border-status off    # For all windows
Эяль Левин
источник
Вы знаете, есть ли способ предотвратить изменение заголовка tmux из-под вас? Например, если я устанавливаю заголовок панели, а затем делаю что-то в этой панели, например cd $HOME, заголовок изменяется на значение $HOME. (Я вижу это на tmux 2.8.)
pdoherty926
1
@ pdoherty926 Может быть, вы уже получили ответ, но проверьте set-window-option automatic-rename off.
noname
У меня set-option -g allow-rename offв .tmux.confдосье.
Эяль Левин,
1
Спасибо за предложения. Я закончил использовать pane-border-formatпеременную, предоставленную пользователем (я не уверен, есть ли у этой функции официальное название), чтобы контролировать то, что отображается. Вот пример.
pdoherty926,
14

Я работаю над панелью состояния панели для tmux - ticket. Мою ветку разработки можно найти здесь, на github: https://github.com/jonathanslenders/tmux

Прямо сейчас это уже добавляет рабочую команду заголовка панели переименования . Есть еще некоторые ошибки, и API будет улучшаться. Идея состоит в том, чтобы создать строку состояния для каждой панели, которая может иметь некоторое форматирование, например строку состояния сеанса. Как и в остальном tmux, все должно быть скриптовым и настраиваемым. После завершения и стабильной работы он, вероятно, будет включен в официальный tmux.

Джонатан Слендерс
источник
Пока вы там, можете ли вы сделать так, чтобы заголовок панели стал заголовком окна по умолчанию во время разбиения панели?
djsadinoff
Эта ветка никогда не была объединена в tmux. Но вместо этого я создал pymux, у которого есть строки заголовков панелей: github.com/jonathanslenders/pymux
Джонатан Слендерс,
Эта команда также не работает в последней сборке (зафиксируйте a24260).
ADN
14

Я использую tmux версии 2.3, я думаю, что стиль границы не поддерживается в предыдущих версиях. вот что сработало для меня:

Для каждой панели установите заголовок:

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

Затем:

tmux set -g pane-border-format "#{pane_index} #T"
OriG
источник
9
По крайней мере, так же недавно, как tmux 2.6, вы можете изменить заголовок панели в tmux: select-pane -T "my title"делает это. Вы даже можете настроить привязку клавиш, так что вам просто нужно указать заголовок:bind-key T command-prompt -p "New title:" 'select-pane -T "%%"'
lucasem
3
@lucasem, возможно, я не следил за этой веткой, но это похоже на ответ.
icicleking
@lucasem Я не уверен на 100%, но я считаю, что ваш метод (какой IMO является лучшим и самым простым во всем этом потоке для последних версий tmux) работает только в том случае, если для pane-border-statusпараметра установлено что-то ( topили bottom).
cjauvin
11

Гифка стоит тысячи слов. ( источник )

tmux-xpanes - это разделитель терминала на основе tmux, который поддерживает отображение заголовка для каждой панели с помощью недавно добавленной -tопции.

навигация
источник
1
Гифка стоит тысячи слов, но если когда-нибудь ссылка испортится, то ничего не стоит.
Иск Фонда Моники
7

Да , есть такая команда: tmux. Дайте вашей сессии имя, и оно будет отображаться во внутренней строке состояния:

TMUX=0 tmux new-session -s my-new-session
event_jr
источник
2
Да, спасибо за ответ! Но, таким образом, мне придется запускать новый сеанс tmux в каждой панели только для одного заголовка внизу - своего рода перебор, не так ли?
Андрей Лушников
Я не знаю. Это? Ты это пробовал? Сколько дополнительной памяти используется дополнительным сеансом?
event_jr
да, до сегодняшнего дня я использовал вложенные сеансы tmux. Я не уверен в потреблении памяти и тому подобном - мне просто не нравится сама концепция, потому что она не чистая.
Андрей Лушников
0

TL; DR

Добавьте следующие конфигурации в свой файл конфигурации tmux (в моем случае ~/.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}"

затем запустите:

tmux source-file ~/.tmux.con

наслаждайся этим

Благодаря https://stackoverflow.com/a/37602055/5121972

структура
источник