Спасибо всем, кто пришел высказаться в комментарии к моей вечерашней статье про перенос по словам в far2l. Получилась интересная дискуссия о том, что такое современный менеджер файлов, и куда ему стоит двигаться. Решил заодно написать про ещё одну недавно добавленную «фишку»: ускоренную вставку из буфера терминала. Технически это может показаться очень локальной оптимизацией, но по ощущениям во многих кейсах меняет качество жизни кардинально.

Поговорим о скорости. А точнее — о том, как мы заставили far2l мгновенно «проглатывать» большие объемы текста из буфера обмена терминала, даже если вы сидите через медленный SSH на сервере, где нет иксов.

Три пути к буферу обмена

Одной из главных болей при переходе с Windows на Linux-консоль для многих становится буфер обмена. В консольных Windows приложениях он просто работает и всё, консольный API это позволяет. В мире терминалов, работающих через ESC последовательности, всё сложнее. В far2l мы реализовали три механизма работы с ним, чтобы покрыть все сценарии:

  1. Интеграция с X11. Это «тяжелая артиллерия». Если в системе есть библиотеки X11, far2l попробует напрямую общаться с буфером обмена вашего десктопа. Это работает идеально, но не всегда осуществимо, требует настройки (для работы через ssh понадобится настроить X11 Forwarding, который может быть отключён на сервере) и тянет зависимость от иксовой библиотеки.

  2. OSC 52 (только copy). Современный и элегантный метод. Приложение (в нашем случае far2l) с помощью специальной ESC последовательности просит терминал: «пожалуйста, запиши этот текст пользователю в буфер обмена». Это работает даже вложенно через несколько SSH-сессий и tmux, но поддерживается не во всех терминалах (например, Konsole из KDE это умеет, а терминал GNOME пока нет, мы с мейнтейнером сейчас пилим реализацию). Но эта штука, если и поддерживается терминалами, то почти всегда только на запись, а не на чтение из буфера (стандарт читать из буфера позволяет тоже, но чтение почти никогда не реализуют из соображений безопасности).

  3. Эмуляция ввода (только paste). Самый древний и «железобетонный» способ. Терминал просто посылает текст приложению так, будто пользователь очень быстро набрал его на клавиатуре.

Проблема: Эффект «машинистки-призрака»

Представьте: вы подключились по SSH к серверу, где X11 Forwarding запрещен админом, и вам нужно вставить конфиг на 500 строк в редактор. Вы жмете Ctrl+V. Терминал начинает «печатать» этот текст в поток ввода, и тут начинается боль. Для того, чтобы дойти до редактора, символ проходит через несколько слоёв абстракции, в частности, под него создаётся «виртуальное» событие нажатия клавиши. В итоге на каждую букву в редакторе запускается лавина процессов:

  • Обработка макросов (а вдруг это хоткей?)

  • Пересчет подсветки синтаксиса (Colorer)

  • Обновление undo-буфера

  • И, самое страшное, перерисовка экрана

Если пинг до сервера хотя бы 50-100 мс, вставка превращается в медитативное созерцание бегущих строк, можно успеть сходить за кофе. Этим грешат многие: например, mc (mcedit) на больших файлах в таких условиях ведет себя точно так же.

Bracketed paste: спасательный круг, который... тормозил

Вообще-то, в современных терминалах консольное приложение может узнать, приходят нам символы в процессе вставки из буфера или в результате нажатия клавиш. Для этого нужно включить режим Bracketed paste, в нём терминал оборачивает вставляемый текст в специальные escape-последовательности (\e[200~ в начале и \e[201~ в конце). Изначально это было сделано для того, чтобы в режиме Auto indent в редакторах не получалась «лесенка» из вставленных строк вместо правильных отступов. far2l этот режим поддерживает, так что никакой лесенки у нас давно нет, но до недавнего времени обработка всё равно шла посимвольно! Мы знали, что происходит вставка, но обрабатывали её неэффективно, как обычный ввод.

Решение: Буферизация и пакетная вставка

В недавнем обновлении мы пересмотрели архитектуру обработки ввода с учётом этой проблемы. Теперь логика работает так:

  1. Как только TTYInputSequenceParser видит маркер начала вставки (\e[200~), far2l переходит в режим накопления.

  2. Все последующие символы не отправляются в ядро обработки клавиш. Они складываются в отдельный буфер памяти. Отключаются все проверки макросов и лишние хуки.

  3. Как только приходит маркер конца (\e[201~), мы получаем готовый кусок текста.

  4. В редактор отправляется одно-единственное событие: макрокоманда KEY_OP_PLAINTEXT, вставляющая в редактор произвольный текст целиком.

Результат: вместо 1000 операций вставки и 1000 перерисовок экрана происходит ровно одна. Текст появляется мгновенно, целиком (и отменить операцию, вслучае чего, теперь можно одним нажатием Ctrl+Z, а не десятками-сотнями). Даже если вы сидите через мобильный интернет где-то в роуминге.

Особенно круто это работает в связке с OSC 52. Например, в той же KDE Konsole (которая поддерживает и Bracketed paste, и OSC 52) вы получаете полноценный буфер обмена по ssh без необходимости пробрасывать иксы, и теперь это работает молниеносно.

Бонус: безопасность в командной строке

Ускорение — это хорошо, но мы решили улучшить и UX тоже.

Раньше, если вы случайно вставляли в командную строку многострочный bash-скрипт, far2l (как и многие другие шеллы) начинал исполнять его строчку за строчкой. Если в середине скрипта была команда rm -rf ..., а вы передумали и начали судорожно жать Ctrl+C — могло быть уже поздно.

Теперь, благодаря механизму пакетной вставки, far2l видит весь вставляемый фрагмент целиком. Если в нём есть переводы строк, вместо немедленного исполнения вы увидите диалоговое окно:

Диалог многострочной вставки в командую строку
Диалог многострочной вставки в командую строку

Вы можете просмотреть, что именно вставляется, отредактировать это прямо в поле ввода и только потом нажать «Выполнить»: конкретно спасает нервные клетки DevOps'ов.

Как получить обновление?

Оптимизация уже влита в master-ветку и доступна в свежих сборках.

Ubuntu/Debian (PPA) (upd: пока не работает, ждем когда починят):

sudo add-apt-repository ppa:far2l-team/ppa
sudo apt update
sudo apt install far2l

Есть и portable Linux-сборка.

macOS (Homebrew):

brew install far2l

Для Arch Linux, Fedora, openSUSE и других систем ссылки на пакеты можно найти здесь, на гитхабе проекта. И обязательно приходите в наш Telegram-чат, там мы обсуждаем развитие проекта, помогаем с настройкой и просто общаемся. Удачи с редактированием!