support putty's terminal better
unxed opened this issue · comments
What currently works:
- correct border lines (with UTF-8 set as Translation)
- f* hotkeys
- alt+character quick search
- ctrl+character hotkeys
What does not:
- alt+f1 / alt+f2 (produce [11~ and [12~)
- shift+f* (wrong action or no action at all)
- shift+arrows (shift ignored)
- ctrl+arrows (ctrl ignored)
That's how far2l behaves in putty's "xterm" mode. Putty's "linux" mode gives almost same results, but command line characters generated on unsupported key combinations differs.
Tested with recent vanilla putty from official website.
UPD: Putty version supporting far2l perfectly: https://github.com/unxed/putty4far2l
Until this is fixed (if even possible), alternative options are:
- far2l+netrocks on cygwin
- far2l+netrocks on WSL
- ttyd (all tried hotkeys work perfectly, except for the need to press ESC twice)
- electron/xterm.js-based terminals like hyper (uses the same lib as ttyd)
If we can't support PuTTY terminal better, maybe we can make PuTTY terminal support us? :) Here is PuTTY with far2l terminal extensions support. Only full keyboard support for now, though (as I am not a C guru :)
https://github.com/unxed/putty4far2l
UPD: clipboard sync added
@elfmz а можно какую-нибудь минимальную доку на сами far2l terminal extensions? Там в целом вроде всё довольно понятно по исходникам, но вот, например, при работе с clipboard я не понял, зачем нужно поле id и как оно используется (которое id сообщения, а не id клиента - опять же, если я правильно понял). И ещё почему часть последовательностей идет с префиксом \x1b_far2l, а часть - с \x1b_f2l?
id сообщения нужно для того чтобы сопоставить запрос и ответ с ответом на запрос. Если id = 0 то запрос не требует ответа.
\x1b_far2l - это именно запросы от "той" стороны к терминал-хосту
\x1b_f2l - это для input event-ов - клава, мышь. Которые терминал-хост самостоятельно генерит.
Логика тут простая - \x1b_far2l более длинное но и более уникальное, меньше риска. Оно изначально юзалось для negotiate, чтобы минимизировать коллизию с каким нить другим, таким же хитрым, терминалом. Ну а потом я стал его юзать и для всех запросов, так как они достаточно редкие и обычно несут в себе достаточно жирые данные чтобы двумя байтами можно было пренебречь.
А input event'ы - это достаточно плотный траффик, где неплохо бы сэкономить байты.
Кстати сами по себе данные пакуются казалось бы не эффективно - много нулей и т.п. Но SSH по дефолту (а SSH2 AFAIK неотключаемо) юзает компрессию траффика, так что длинные последовательности повторяющихся байт по идее должны хорошо сжиматься.
А вот для telnet'ов всяких, где нет сжатия, решение не овчэффективное получилось:)
О, спасибо, уже понятнее. Ну, устаивать оверинжениринг ради телнета, имхо, рано пока :)
id сообщения нужно для того чтобы сопоставить запрос и ответ с ответом на запрос.
Вот я эту часть и не понял как раз. Как может возникнуть ситуация, когда ответ не сопоставить с запросом? Вот с буфером обмена, например: запросили авторизацию и сидим ждем, авторизуют или нет. По идее, там ничего, кроме ответа по поводу авторизации, придти и не может ведь, другие запросы-то не отправляются? А в какой ситуации может?
Там нет такой жесткой синхронизации. TTYBackend::Far2lInterract посылает запрос, запрос посылается в stdin, ид запроса кладется в список ожидающих ответа, и когда придет ответ совпадающим ид - Far2lInterract раздупляется и выходит.
НО при этом другой поток может сделать параллельный TTYBackend::Far2lInterract, и от терминала вовсе не требуется отвечать один за одним, мало ли... Более того - пока запрос обрабатывается гипотетически может другой инпут ходить туда сюда. Правда посколько id восьмибитный, то таких одновременных запросов может быть макс 255 штук, если в очереди окажется больше - лишние поскипаются (не зависнут, просто завершатся без ответа). Такой себе протокол асинхронных запросов через терминал.
Вощем не надо мне рассказывать про оверинжиниринг :)
Спасибо за разъяснения)) Да, меня тоже немножко восьмибитность id смутила :)
В общем, запилил я clipboard, вроде работает. Только с форматами не разбирался пока, впрочем, кажется, CF_UNICODETEXT вполне хватает.
у фара есть еще свой кастомный формат для красивого копипаста вертикальных блоков выделения в едиторе, если поддерживать только CF_UNICODETEXT то он отвалится
И ещё обнаружилась забавность: редактор обрезает строки по 0x00, если такие символы в строках исходного файла есть. И "копировать-вставить" тоже (это фундаментальное ограничение WinAPI, потому что аргументы функций - null-terminated, да?).
Ага, и правда вертикальные блоки отвалились. Ок, добавил поддержку кастомных форматов.
Только наблюдаяется забавная фишка: внутри и между экземплярами putty всё работает как надо, а вот когда я из putty в wx'овый far копирую (я под wine тестирую, чтоб виртуалку зря не гонять), приходит обычный юникодный блок.
Я правильно понимаю, что запрос на регистрацию формата передает utf8-строку, которая в данном вырожденном случае суть ASCII строка, и я могу юзать RegisterClipboardFormatA и не выпендриваться с перекодированием? Хочу понять, это я идентификатор формата отдаю в WinAPI криво, или рассчитывать на интероперабельность между иксами и wine по части кастомных форматов буфера обмена в принципе утопия.
UPD: Проверил под виндой - та же история, между экземплярами putty кастомный формат работает, а в виндовый фар приходит обычный юникодный текст.
Проверил и cygwin'овый far2l для интересу - там тоже нет интероперабельности по кастомному формату буфера обмена с нативным виндовым far'ом, тоже обычный юникодный текст приходит.
О, в пропатченной putty поиск по Alt+русские_буквы нормально работает :)
у фара есть еще свой кастомный формат для красивого копипаста вертикальных блоков
Ага, только на винде там UTF16, а на wx, судя по всему, UTF32. И поэтому копипаста вертикальных блоков из putty4far2l под wine в far2l wx и обратно работает криво( CF_UNICODETEXT-то конвертится на лету, надо полагать, а свой формат - фиг.
А вот на винде удалось таки сделать интероперабельность putty с виндовым фаром (правда, она пока только в одну сторону работает - из putty в виндовый фар вертикальные блоки норм прилетают, а обратно - пустая строка почему-то и фоллбек на CF_UNICODETEXT срабатывает; да, я проверил, id формата правильно приходит и правильно парсится). Причем прилетает именно хэндл пустой строки, а не NULL.
А input event'ы - это достаточно плотный траффик, где неплохо бы сэкономить байты.
@elfmz а зачем в vt extensions шлётся wVirtualScanCode? Он же, во-первых, в wx-ах всегда нулевой, а во-вторых, в TTY всё равно автоопределяется по wVirtualKeyCode.
ну да, избыточненько получилось.. завернул просто всю структуру как есть
alt+f1 / alt+f2 (produce [11~ and [12~)
— Works now
shift+f* (wrong action or no action at all)
— Vanilla putty sends Shift+F1 as F11, Shift+F2 as F2, etc. Can do nothing with it.
shift+arrows (shift ignored)
— Vanilla putty sends equal esc sequences with Shift pressed and without it, so can nothing to do with it.
ctrl+arrows (ctrl ignored)
— Vanilla putty sends \x1b[OC
with Control and \x1b[C
without Control. This probably can be distinguished on the far2l's side (see
void TTYInputSequenceParser::AddStrCursors(WORD vk, const char *code)
{
AddStr(vk, 0, "O%s", code);
AddStr(vk, 0, "[%s", code);
AddStr_ControlsThenCode(vk, "[%d%s", code);
AddStr_ControlsThenCode(vk, "[1;%d%s", code);
}
), but I am not sure sending Control+Arrows such way it is standards-compatible behavior, and anyway far2l UX would not be so great without Shift+F* and Shift+Arrows. So it's better to offer users to use one putty's forks supporting far2l terminal extensions:
https://github.com/unxed/putty4far2l
https://github.com/cyd01/KiTTY
or to use Windows Terminal which now has win32-input-mode that far2l understands great.
Closing.