Терминал: отправьте escape-последовательность без контроля или управляющий символ - PullRequest
0 голосов
/ 02 июля 2019

Мне нужно, чтобы мой терминал отправлял неиспользуемый управляющий символ или 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

Это моя дилемма, и в настоящее время я рассматриваю несколько альтернатив:

  1. Пусть терминал передает управляющий символ, а не escape-последовательность. Управляющие символы всегда поддерживаются. Я бы хотел, чтобы там существовал символ «ничего не делать», и он надеялся на Control- @ (NUL или ASCII 0), но этот символ отображается в оболочке и имеет существенный эффект в режиме вставки в vim. Если такого символа не существует, см. № 3. Возможно, я мог бы присвоить необычный управляющий символ, но он также должен был бы быть настроен так, чтобы ничего не делать, на всех уровнях: xterm, bash, readline, vim и т. Д.

  2. Пусть терминал отправит неиспользованную или неиспользуемую escape-последовательность, а не последовательность фиксаторов Control-Shift-c. Последовательность должна игнорироваться на всех уровнях: игнорируется оболочками (bash, ...), игнорируется линейными редакторами (readline, ...) и игнорируется всеми приложениями (vim, less, mutt, ...) , См. № 3.

  3. Измените запись terminfo для моего терминала, чтобы гарантировать, что по крайней мере один из вышеперечисленных (управляющий код, стандартная escape-последовательность или escape-последовательность fixterms) игнорируется на всех уровнях согласно [10]. Затем свяжите эту измененную последовательность в tmux.

  4. Вызовите 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.


  1. https://stackoverflow.com/a/14876639
  2. https://unix.stackexchange.com/a/116630
  3. http://www.leonerd.org.uk/hacks/fixterms/
  4. https://github.com/tmux/tmux/blob/master/xterm-keys.c
  5. http://www.leonerd.org.uk/code/libtermkey/
  6. https://stackoverflow.com/a/2179779
  7. http://man7.org/linux/man-pages/man3/tcgetpgrp.3.html
  8. https://github.com/tmux/tmux/blob/master/osdep-linux.c
  9. https://invisible -island.net / Xterm / страница руководства / xterm.html # h2-KEY-ПРИВЯЗКИ
  10. Связать Ctrl + Tab и Ctrl + Shift + Tab в tmux
  11. https://man.openbsd.org/ssh#ESCAPE_CHARACTERS

edit, новая идея: SSH имеет собственный эмулятор терминала или, по крайней мере, подключен к паре pts [11]. Означает ли это, что он может обрабатывать входящие escape-последовательности и, возможно, выполнять внешнюю удаленную команду, например, команду tcgetpgrp? Или это будет небезопасно? Вместо того, чтобы настраивать, возможно, бесконечную серию терминальных приложений, чтобы игнорировать escape-последовательность, я бы предпочел настроить только SSH, как я бы использовал tmux.

1 Ответ

0 голосов
/ 03 июля 2019

Все доступные последовательности потенциально будут выглядеть как ключ некоторого вида для приложения, получающего его (например, 0 - это C- @ и C-Space), нет последовательности, которую приложения гарантированно игнорируют.

Если бы я был вами, я бы просто отправил escape-последовательность для F20 или чего-то еще и связал этот ключ, чтобы ничего не делать в других приложениях, которые вы часто используете.

...