Мне нужно, чтобы мой терминал отправлял неиспользуемый управляющий символ или escape-последовательность, которая не действует на всех уровнях: игнорируется оболочками (bash, ...), игнорируется линейными редакторами (readline, ...), и игнорируется всеми приложениями (vim, less, mutt, ...). Затем я свяжу этот ключ в tmux, с определяемой пользователем escape-последовательностью ключа, если это необходимо. Какой управляющий символ или escape-последовательность я использую? Более подробная информация ниже:
Я хочу, чтобы аккорд клавиш Control-Shift-c в tmux был привязан к действию, которое скопирует выделение tmux в буфер выбора X буфера обмена. Это и продолжает иметь Control-Shift-c копировать выбор терминала в буфер выбора буфера обмена X, когда tmux не работает. Эмуляторы терминала генерируют один и тот же выход для входов Control-Shift-key и Control-key, см. [1] [2]. Первый шаг должен изменить это:
# Enable fixterms (I think) sequences for all keys:
xterm -xrm "XTerm.vt100.modifyOtherKeys: 2" -xrm "XTerm.vt100.formatOtherKeys: 1"
Это инструктирует xterm создать escape-последовательность для всех ключей, измененных Control, Alt или Meta. Насколько я могу сказать, ничто не поддерживает эти escape-последовательности, независимо от того, отформатированы ли они с использованием исходных последовательностей xterm или с помощью новых спецификаций fixterms [3]. Даже tmux поддерживает только подмножество этих последовательностей [4], а не полноценный парсер CSI-последовательностей [5].
Самый простой обходной путь состоит в том, чтобы только Control-Shift-c отправлял последовательность исправлений согласно [6]. Поскольку эта последовательность не поддерживается tmux, ее нужно будет определять вручную с помощью опции user-keys
. Он также должен быть привязан к таблице корневых ключей tmux, а не к одной из таблиц режима копирования; в противном случае, если tmux не находится в режиме копирования, привязка будет проигнорирована и передана через tmux одному из терминальных приложений.
# Configure only Control-Shift-c to send a fixterms sequence:
xterm -xrm "XTerm*vt100.translations: #override \n\
Ctrl Shift <Key>c: string(0x1b) string ([67;6u)"
# Recognize (but don't handle) the Control-Shift-c fixterms sequence:
tmux set-option -s user-keys[0] "\e[67;6u"
# Copy the selection to the clipboard buffer only when in copy-mode. If
# there is no selection, nothing will be copied:
tmux bind-key -T root User0 if-shell -Ft= "#{pane_in_mode}"
"send-keys -X copy-pipe 'xsel -i -b'"
Все другие приложения, которые не поддерживают последовательности исправлений, получат входной мусор. Хуже того, неизвестные escape-последовательности могут быть неправильно истолкованы и вызывать специфичные для приложения команды. Изначально я думал об использовании tcgetpgrp(3)
[7] для получения имени команды, которая в данный момент выполняется в терминале, очень похоже на #{pane_current_command}
в tmux [8].
xterm <-> bash <-> command
Привязка терминала для Control-Shift-c сначала скопирует выделение терминала в буфер буфера обмена, как обычно; затем вызовите мою внешнюю программу [9]. Если команда терминала в настоящее время не tmux, ничего не происходит; в противном случае внешняя команда записывает последовательность Control-Shift-c fixterms в pts
терминала. Когда tmux получит эту последовательность, он перезапишет буфер буфера обмена с собственным выбором.
xterm -xrm "XTerm*vt100.translations: #override \n\
Ctrl Shift <Key>c: copy-selection(PRIMARY) \n\
exec-formatted("~/send_fixterms_sequence_if_tmux.py")
Не удается обработать вложенные эмуляторы терминала, как при запуске tmux через ssh - что очень часто встречается.
xterm <-> bash <-> ssh <-> bash <-> tmux <-> bash <-> command
Это моя дилемма, и в настоящее время я рассматриваю несколько альтернатив:
Пусть терминал передает управляющий символ, а не escape-последовательность. Управляющие символы всегда поддерживаются. Я бы хотел, чтобы там существовал символ «ничего не делать», и он надеялся на Control- @ (NUL или ASCII 0), но этот символ отображается в оболочке и имеет существенный эффект в режиме вставки в vim. Если такого символа не существует, см. № 3. Возможно, я мог бы присвоить необычный управляющий символ, но он также должен был бы быть настроен так, чтобы ничего не делать, на всех уровнях: xterm, bash, readline, vim и т. Д.
Пусть терминал отправит неиспользованную или неиспользуемую escape-последовательность, а не последовательность фиксаторов Control-Shift-c. Последовательность должна игнорироваться на всех уровнях: игнорируется оболочками (bash, ...), игнорируется линейными редакторами (readline, ...) и игнорируется всеми приложениями (vim, less, mutt, ...) , См. № 3.
Измените запись terminfo для моего терминала, чтобы гарантировать, что по крайней мере один из вышеперечисленных (управляющий код, стандартная escape-последовательность или escape-последовательность fixterms) игнорируется на всех уровнях согласно [10]. Затем свяжите эту измененную последовательность в tmux.
Вызовите readline, чтобы сделать что-то волшебное. В конечном итоге это вряд ли повлияет на терминальные приложения в альтернативном режиме.
Идея состоит в том, чтобы, как и прежде, скопировать выделение терминала в буфер буфера обмена. Затем введите <STRING>
, как если бы он был напечатан. Когда tmux получает <STRING>
, он перезаписывает буфер буфера обмена своим собственным выбором. Любое другое приложение будет игнорировать это: включая и, в особенности, ничего не печатать на терминале.
xterm -xrm "XTerm*vt100.translations: #override \n\
Ctrl Shift <Key>c: copy-selection(PRIMARY) string(<STRING>)
Я также планирую расширить это на gnome-терминал, так что пример записи escape-последовательности или управляющего символа в pts
терминала будет полезен. Я использую только xterm в качестве рабочего примера - этот вопрос определенно не относится к xterm.
- https://stackoverflow.com/a/14876639
- https://unix.stackexchange.com/a/116630
- http://www.leonerd.org.uk/hacks/fixterms/
- https://github.com/tmux/tmux/blob/master/xterm-keys.c
- http://www.leonerd.org.uk/code/libtermkey/
- https://stackoverflow.com/a/2179779
- http://man7.org/linux/man-pages/man3/tcgetpgrp.3.html
- https://github.com/tmux/tmux/blob/master/osdep-linux.c
- https://invisible -island.net / Xterm / страница руководства / xterm.html # h2-KEY-ПРИВЯЗКИ
- Связать Ctrl + Tab и Ctrl + Shift + Tab в tmux
- https://man.openbsd.org/ssh#ESCAPE_CHARACTERS
edit, новая идея: SSH имеет собственный эмулятор терминала или, по крайней мере, подключен к паре pts
[11]. Означает ли это, что он может обрабатывать входящие escape-последовательности и, возможно, выполнять внешнюю удаленную команду, например, команду tcgetpgrp
? Или это будет небезопасно? Вместо того, чтобы настраивать, возможно, бесконечную серию терминальных приложений, чтобы игнорировать escape-последовательность, я бы предпочел настроить только SSH, как я бы использовал tmux.