Двухпанельный файловый менеджер на Delphi. Из NDN с любовью…

Знаете это царапающее чувство, когда в 2026 году открываешь проводник Windows с вкладками, ждешь пару секунд, пока он сообразит отобразить сетевой диск или каталог с громадным репозиторием, и ловишь себя на каком-то тихом раздражении? Где нужный файл? А вот он! И что? Щелкаешь на него и ждешь еще 1-2 секунды для запуска сторонней программы для работы с этим. А еще... Где это нужное сейчас окно проводника? А вот оно! Так, а где предыдущее окно? Так, закрываем все и переоткрываем только нужные окна! Тааак....
Информационный шум вокруг уверяет, что будущее уже тут: всё давно переехало в веб, десктопные интерфейсы – в браузерных движках, а консольные утилиты – на современных системных языках. Но когда наступает реальность – нужно за полминуты разгрести хаос на дисках, сравнить два каталога по контрольным суммам, быстро заглянуть в многомегабайтный лог или быстро поправить конфиг на сервере – руки сами собой, на безусловных рефлексах, тянутся к двум панелям и функциональным клавишам от F3 до F8.
Я пользуюсь двухпанельными менеджерами прямо-таки с момента появления в России Нортона (ну и потом безусловной замены на Волкова) и как программист всегда искал подобные инструменты по ходу развития операционных сред.
И в конце концов, наверное, вынужденно, пришел к мысли: хочешь получить что-то, что тебе нравится – делай сам.
Сейчас понятно, что двухпанельные менеджеры – инструмент исключительно нишевый. Массовый пользователь вообще перестал взаимодействовать с файловой системой напрямую – мобильные ОС спрятали её внутри, в вебе всё размазано по облакам, а большинство разработчиков не выходит за пределы бокового дерева файлов в IDE. Двухпанельники остались инструментом сравнительно узкой, консервативной, но требовательной аудитории – системных инженеров, DevOps, системных программистов и тех, кому жизненно необходим контроль над машиной и скорость навигации «только с клавиатуры» без отвлечения на мышь.
У каждого из классических инструментов прошлого и настоящего свои уникальные возможности (можно сказать – инженерный почерк). DOS Navigator (DN) – это исключительно аккуратный псевдографический интерфейс. Оу! Эти объемные тени, спокойная палитра и компоновка окон. Выглядел DN для своего времени как межконтинентальный авиалайнер, продуманный до мелочей. О Necromancer's DOS Navigator (NDN) – чуть ниже.
FAR Manager, прямой наследник идей Norton и Volkov Commander, дал надежность, эталонную клавиатурную раскладку (как продолжение, но и как уменьшение богатства клавишных комбинаций – в свое время при переходе с DN пришлось переучиваться, раздражало) и целую экосистему расширений. Но визуально он всегда оставался консервативным – классический монохромный терминал по умолчанию. Надежно, практично, но ориентировано исключительно на консольный формат. Да и ограничения в связи с этим.
Total Commander – признанный универсальный инструмент в мире двухпанельников. Всё, что хочешь: любой поиск, любые архивы, FTP, экосистема плагинов и вкладки над панелями (Ctrl+T), избавившие от необходимости плодить копии окон. Но это представитель другой инженерной школы – классического оконного GUI (Win32). Даже если тонко настроить его под себя, убрать панели инструментов (в экстремальном случае) и переключиться на моноширинный шрифт, внутри он остается набором стандартных графических элементов управления Windows с пропорциональными диалогами. В нем живет другая идея взаимодействия, в отличие от математической матрицы знакомест, где всё пространство экрана – единая символьная сетка. Честно, пробовал. С десяток раз. Так и не прижилось.
В этом и заключается существующий (ну и давний) раскол во взглядах – одни выбирают гибкий оконный GUI (Total Commander, Double Commander), другие – строгий минимализм символьной сетки (Far Manager, Midnight Commander, Yazi).
Затеянный проект – MTN2 – создается в первую очередь для себя. Это попытка собрать в одном месте все необходимые мне рабочие инструменты, получить приятное визуальное представление в стиле Necromancer's DOS Navigator (ну почти), а главное – держать всё под собственным контролем с возможностью расширять функциональность в любую сторону. Строго матричный, моноширинный интерфейс с объемными тенями, рамками и четким порядком здесь перенесен из тесной консоли на современный графический GPU-конвейер с масштабированием шрифтов, полноценным 32-битным цветом (RGBA с поддержкой полупрозрачности) и перекрывающимися окнами (MDI).
В основе гипотеза – можно ли взять стиль NDN (насколько это возможно, там же Turbo Vision), клавиатурную раскладку FAR (как основу) и удобство вкладок Total Commander и ConEmu – и собрать надежный инструмент под свои повседневные задачи, в котором будет комфортно жить и работать каждый день? То есть – закрытие ежедневных функциональных потребностей.
Я следил за разработкой NDN, скачивал и тестировал каждую новую сборку вплоть до того момента, когда разработка проекта окончательно прекратилась. Но это всегда сопровождалось разочарованием – практически в каждом релизе находились баги. То внезапно отказывала какая-то нужная функция, то сбоили базовые файловые операции, которыми я пользовался непрерывно. Ощущение, когда перед тобой отличная архитектурная идея, но ты постоянно натыкаешься на недоработки в повседневных сценариях. Бесит!
Первая попытка родилась на волне всеобщего увлечения современным системным стеком – я сел писать проект MTN 1.0 на Rust (связка crossterm + ratatui + tokio). Попался на маркетинг – максимальная безопасность и скорость, честный TUI прямо в консоли.
Но на практике разработка быстро уперлась в ограничения стандартной консоли Windows (conhost и Windows Terminal). Внутри системного псевдотерминала – бесконечные компромиссы:
Плавное масштабирование шрифта колесом мыши с зажатым Ctrl – не выйдет: в консоли – дискретные знакоместа фиксированного кегля.
Свободное изменение размеров окна мышью без пересборки буфера и мерцания – архитектура буфера WinAPI-консоли на это просто не рассчитана.
Отрисовка нормальных системных значков файлов рядом с именами – в текстовой консоли это упирается в проблему. Либо ставить патченные шрифты Nerd Fonts с ограниченным набором глифов, либо пытаться вешать прозрачные дочерние WinAPI-окна поверх терминала с постоянными микролагами при скролле.
А последней каплей стало то, что драйвер консоли Windows периодически теряет сложные клавиатурные комбинации вроде
Ctrl+Alt+InsилиShift+F2. Может, я чего-то не досмотрел. Но бороться с такими мелочами – не цель.
Ну конечно, были варианты и обойти это путем низкоуровневых решений. На Rust можно было бы подключить крейт windows-sys, внедрить глобальный хук клавиатуры (WH_KEYBOARD_LL) или читать события через Raw Input API, обходя конвейер ввода, а поверх консоли добавить прозрачные оверлеи (жуть, правда?). Но в этот момент концепция чистого TUI ушла куда-то за горизонт. Архитектура быстро обрастала сложными платформозависимыми обходными путями, конфликтовавшими с системными обновлениями терминала, а ощущения легкого, цельного и надежного инструмента так и не появлялось.
Конечно, есть же связка Far Manager и ConEmu. Да, и я на ней сижу (сидел) уже не помню сколько лет. Действительно, ConEmu в свое время предложил прямо-таки отличное инженерное решение. Обернув консоль в графическое окно, проект добавил в консоль удобство вкладок. Можно было в одном контейнере держать открытыми сразу несколько экземпляров Far, сессию PowerShell и сборку в WSL, переключаясь между ними и забыв о куче из десятка окон на панели задач. Кроме этого, ConEmu дал произвольное масштабирование, поддержку 24-битного TrueColor задолго до появления Windows Terminal и даже позволил плагинам Far выводить графический предпросмотр файлов.
Но при всей продуманности, внутри лежит сложная многослойная архитектура. Чтобы перехватывать ввод-вывод и управлять процессами, ConEmu внедряет свои библиотеки-перехватчики (ConEmuHk.dll) прямо в адресное пространство Far и дочерних утилит через системные хуки. Из-за этого мы получаем два раздельных буфера экрана (один внутри системного conhost.exe, второй – в GUI-хосте), неизбежные накладные расходы синхронизации при интенсивном выводе. Поговаривают, что на ранних этапах периодически были срабатывания корпоративных антивирусов на инъекцию стороннего кода. Мне же хотелось чистой монолитной архитектуры, где приложение изначально само является полноценным графическим окном, а не хостом над внешними консольными процессами.
Была (недолго) идея взять Electron. Завернуть туда Chromium, Node.js, нарисовать интерфейс на Canvas или HTML/CSS – и забыть обо всех проблемах со шрифтами и окнами. Но сама мысль отдавать 100 мегабайт памяти браузерному движку ради простой навигации по дискам – нет уж... Файловый менеджер – это базовый рабочий инструмент. Он должен запускаться за доли секунды (ну ладно, за секунду), потреблять скромные ресурсы и мгновенно откликаться на клавиши, а не зависать в очередях межпроцессного взаимодействия и сборщика мусора, например JavaScript.
В какой-то момент стало ясно, что мириться с ограничениями стандартного терминала нельзя. Выход один – создать собственное графическое окно, а внутри него отрисовывать виртуальную символьную сетку напрямую на видеокарте через аппаратный GPU-конвейер.
В плане графики я воспользовался тем же подходом, который применяют современные эмуляторы терминалов вроде Alacritty или WezTerm – не полагаться на стандартную консоль ОС, а создать графическое окно и выводить символьную сетку силами GPU. Но вместо того чтобы ограничиться простым терминалом, реализовал двухпанельный файловый менеджер с многооконным MDI.
Когда концепция определилась, встал вопрос выбора компилируемого языка. Помимо Object Pascal, рассматривались варианты:
C++ – как бы классика (на нем написаны Far Manager и ключевые системные утилиты). Но под Windows на C++ разработка GUI неизбежно упирается либо в кроссплатформенный Qt с десятками мегабайт сторонних DLL, либо в многострочный низкоуровневый Win32/WTL, плюс длительность компиляции и линковки.
Продолжить на Rust. Прекрасный, надежный язык, на котором я и начинал первую версию проекта. Но для быстрого макетирования десктопного интерфейса со сложной перерисовкой и перекрывающимися окнами MDI графическая экосистема Rust все еще слабовата (как мне показалось), а борьба с зависимостями отнимает слишком много времени от самой задачи.
Go/Zig – Go тащит собственную среду выполнения со сборщиком мусора, что для мгновенной отзывчивости UI показалось не лучшим выбором, а для Zig это пока только начало.
Сейчас выбор Object Pascal для полусистемного софта воспринимается как нишевая экзотика. В спорах вокруг языка обычно приводят традиционный набор аргументов – высокая скорость компилятора dcc64.exe (2–3 секунды на весь проект), монолитный бинарник без виртуальных машин и сборщика мусора, готовые потоки PPL и аппаратный рендеринг через FireMonkey и Skia. Всё это известные факты, и спорить с ними бессмысленно. На деле такая нишевость проекта дает преимущество. Для меня первична вовсе не приверженность конкретному бренду или языку – совершенно неважно, на какой платформе написан проект, если в итоге ты получаешь инструмент с теми эксплуатационными характеристиками, которые требовались изначально. И в этот момент сработал простой практический принцип: «Знакомая дорога – самая короткая».
Когда стоит задача получить рабочий, стабильный инструмент под свои требования, а не экспериментировать с новым синтаксисом по вечерам, решающим фактором стала глубина владения платформой. Я использую Pascal со времен Turbo Pascal 5.0, и на Object Pascal у меня реализовано много проектов еще задолго до наступления современной эпохи вайбкодинга. Когда ты знаешь среду досконально – как работает диспетчер памяти, во что компилятор разворачивает структуры, как напрямую работать с системным WinAPI без внешних оберток – скорость разработки оказывается на порядок выше.
Так родился проект MTN2 (Modern Turbo Navigator 2), написанный на Object Pascal в среде Delphi с использованием связки FireMonkey и Skia.
Схематично – как-то так:


Дальше по цепочке – базовый механизм отрисовки, перекрывающиеся окна MDI, «живая» консоль Windows ConPTY с поддержкой xterm TrueColor прямо под панелями, встроенный просмотрщик форматированного Markdown (с ним много работаю) и шестнадцатеричных дампов. Ну и пошло-поехало...
Сразу обозначу – я не пытаюсь заменить Far, не соревнуюсь с Total Commander и не строю коммерческий продукт. MTN2 – это осознанно нишевый проект для самого себя, пример программного инструмента и штучной разработки. В нем нет и не планируется AI в каждой кнопке, маркетинговых компромиссов, облачной телеметрии или попыток понравиться всем подряд за счет размытия функционала. Проект создавался и развивается ради собственного инженерного удовольствия и для личной ежедневной работы. Когда делаешь вещь для себя, нет нужды оглядываться на чужие правила оформления, требования начальства и тренды – можно сосредоточиться строго на ключевых сценариях и спокойно допиливать необходимые эксплуатационные характеристики.
Отдельно скажу об использовании нейросетей. Я спокойно отношусь к современным инструментам и задействовал возможности ИИ на этапе исследований для проверки сценариев, структурирования предпроектных заметок, подготовки итоговой технической документации, а также для реорганизации тестов при переходе на DUnitX (когда временных проверочных программок накопилось столько, что разбирать эти завалы в одиночку стало слишком трудоемко). В роли редактора, аналитика и ассистента модели действительно снимают массу рутины.
Но проект далек от «вайбкодинга». Вся системная архитектура, многопоточность VFS, низкоуровневая интеграция с WinAPI, отлов гонок в ConPTY, оптимизация GPU-рендерера – это ручное программирование и отладка (ну если честно – на 98%). Ну что еще... Перед размещением на GitHub попросил ИИ перевести на английский язык и структурировать комментарии в коде. По крайней мере каждая строчка написана с четким пониманием того, во что она превратится в машинных инструкциях. Тем более не хотелось упускать удовольствие от процесса разработки ("О! Заработало! Класс!"). Как говорится – кто сам колет дрова, тот согревается дважды.
План развития выглядит так:
Основная рабочая среда – Windows x64. Под нее всё отлажено, оптимизировано и работает каждый день.
Для Linux архитектура ядра, VFS и графический конвейер уже платформонезависимы. Следующий шаг – реализация терминального слоя на базе POSIX PTY (
forkptyиtermios) вместо Windows ConPTY.Адаптация под экосистему Apple (macOS) – при наличии свободного времени после завершения версии под Linux.
Наверное, самое интересное будет про Free Pascal (Lazarus / FPC). В планах также есть задача попробовать собрать кодовую базу ядра: отвязать сборку от коммерческой IDE и упростить жизнь сборщикам пакетов под альтернативные дистрибутивы и архитектуры. Ха! Если такие появятся.
Как в конечном итоге хотелось бы реализовать, что получить:
Мгновенный холодный старт, никаких секундных пауз на инициализацию среды выполнения;
Мало памяти, не более 20–40 МБ в реальной работе, а не сотни мегабайт браузерных движков;
Плавная отрисовка на GPU без лагов и пауз на сборку мусора;
Автономность, портативность, один исполняемый файл без внешних сред исполнения, инсталляторов и привязки к системному реестру.
В данном случае, если связка Delphi и Skia позволяет достичь этих характеристик в кратчайшие сроки и без лишней борьбы со сборочным окружением – значит, выбор платформы полностью себя оправдывает.
Еще одно требование – портативность и отсутствие цифровых следов в системе. Программа не требует инсталлятора и ничего не пишет в реестр Windows. Все конфигурации, раскладки клавиш, цветовые схемы и сессии хранятся в формате JSON. В стандартном режиме настройки лежат в %APPDATA%\MTN2\, но если создать рядом с исполняемым файлом пустой маркер portable.dat, ядро (uConfigLocation.pas) автоматически переключается в портативный режим. В этом случае все данные пишутся строго в каталог программы (например, на USB-флешку). Вынул накопитель – и на чужой рабочей станции не остается цифровых следов.
И, наверное, самое главное требование по эргономике повседневного использования – работа без отрыва рук от клавиатуры. В двухпанельном менеджере весь процесс завязан на горячие клавиши. Навигация по каталогам, выбор накопителей, быстрый поиск, вызов терминала, операции с файлами и просмотр содержимого. Со временем управление доводится до автоматизма – точно так же, как переключение передач или выжим сцепления на «механике» в автомобиле. Руки и пальцы действуют сами по себе, на уровне мышечной памяти, пока голова сосредоточена на задаче. И когда в такой отточенный рабочий поток вклинивается необходимость оторвать руку от клавиатуры, шарить по столу в поисках мыши и прицеливаться курсором – это просто раздражает.
В MTN2 практически всё управление спроектировано под быстрый клавиатурный ввод. Базовую раскладку я специально перенес из классического Far Manager (F1–F10, Tab, Insert, Alt+F1/Alt+F2, Ctrl+O, Ctrl+Q и т.д.) – ломать устоявшиеся привычки не имело никакого смысла. Руки-то помнят. Для новых команд (сравнение папок Ctrl+Shift+C, расчет контрольных сумм Ctrl+Alt+H, история файлов Alt+F11, панель атрибутов и дат Ctrl+Shift+A, синхронизация каталога терминала Ctrl+Shift+O) я подбирал наиболее удобные из свободных комбинаций. Но никакого навязывания нет: вся конфигурация привязок вынесена в файл keymap.json, есть встроенный редактор горячих клавиш (uDualPanelKeymapDialog.pas), и любое действие можно перенастроить под собственные привычки.
В классической разработке интерфейсов под Windows обычно мыслят иерархией визуальных компонентов. Это панели, списки, кнопки, метки. Но если попробовать построить сложный файловый менеджер на стандартных компонентах (вроде TListBox или TStringGrid), проект быстро упрется в накладные расходы. Тысячи объектов в памяти, медленный скролл и постоянные пересчеты верстки. Плавали, знаем. У меня было около десятка попыток реализации на стандартных компонентах. В MTN2 применен другой подход, так же, как у эмуляторов терминалов. Вместо дерева компонентов всё окно представляет собой единый двумерный массив плоских структур-ячеек:
type
TCharCellAttribute = (ccaBold, ccaItalic, ccaUnderline, ccaBlink, ccaReverse);
TCharCellAttributes = set of TCharCellAttribute;
TCharCell = record
CharValue: Char; // Символ Юникода (UTF-16)
FgColor: TAlphaColor; // Цвет текста (32-битный RGBA)
BgColor: TAlphaColor; // Цвет фона (32-битный RGBA)
Attributes: TCharCellAttributes;
IconId: Integer; // Системный индекс иконки файла
end;
TTerminalRow = array of TCharCell;
TTerminalGrid = array of TTerminalRow;Ключевая архитектурная деталь – тип данных. Это компактная запись (record), а не класс. Вся сетка экрана размещается в непрерывном блоке оперативной памяти без единой динамической аллокации в куче на отдельный символ. При изменении размеров окна или масштабировании шрифта колесиком мыши ядро просто динамически пересчитывает число строк и колонок под текущую геометрию.
Когда окнам требуется перерисовка, оконный компоновщик (у меня как композитор) (uMdiCompositor.pas) собирает результирующую матрицу видимых символов с учетом их Z-порядка и теней, а графический конвейер Skia за один проход нарезает и отправляет текстуры глифов напрямую в видеокарту.
Что с производительностью?
Когда речь заходит о скорости графического конвейера, обычно возникает вопрос про FPS. Но в терминальном интерфейсе мерить обычный FPS неправильно:
В состоянии покоя интерфейс показывает ровно 0 кадров в секунду (не считая редких всплесков пару раз в секунду, когда тикает таймер мигания курсора). Зачем крутить графический цикл вхолостую и напрягать видеокарту, если на экране ничего не изменилось?
При непрерывном потоке вывода в консоль частоту кадров пришлось ограничивать
cMinNotifyMs = 50(около 20 кадров в секунду), иначе поток уведомлений из ConPTY просто парализовал очередь сообщений UI.
Честной и показательной метрикой плавности является время кадра. Я разделил процесс замера на три изолированные фазы:
compose– композитинг буферов окон, расчет перекрытий, тени и оверлеи (0.7–1.8 мс);render– отрисовка плашек и глифов через Skia в текстуру (2.2–4.1 мс);paint– вывод сформированного кадра в окно Windows (0.4–0.9 мс).
Суммарно кадр на GPU со Skia собирается в среднем за 3.4 мс (с пиками до 6.8 мс при тяжелом пересчете). Стандарт 60 Гц (16.6 мс) перекрывается с запасом, и даже на мониторах 144 Гц (6.9 мс) интерфейс работает без задержек.
Расход оперативной памяти тоже находится в приемлемых границах:
Чистый портативный запуск со Skia и текстурными атласами шрифтов – около 20.9 МБ выделенной физической памяти процесса.
Активная рабочая сессия с десятью вкладками, историей и буфером терминала – около 41 МБ. Для векторного графического приложения с собственной прорисовкой шрифтов, думаю, приемлемо.
Интересный случай произошел при запуске среды выполнения WebAssembly (Wasmtime). В первой тестовой сборке с поддержкой плагинов MTN2 на чистом старте внезапно отъел почти 29 МБ памяти и породил в диспетчере задач 45 потоков в состоянии покоя. Запуск с ключами --no-skia и --no-wasm сразу выявил причину: JIT-компилятор Cranelift внутри Wasmtime по умолчанию создавал пул параллельной компиляции по числу логических ядер процессора. На тестовой 32-поточной машине он выделил 32 спящих потока со служебными структурами.
Решилось это буквально одной строкой:
wasmtime_config_parallel_compilation_set(FConfig, False);Заодно и саму загрузку библиотеки Wasmtime я перевел в ленивый режим. Пока пользователь не запустит модуль, требующий WASM, библиотека вообще не подгружается в память. Библиотеки внешних плагинов не загружаются все вместе на старте, приложение считывает манифесты plugin.json, а сама DLL поднимается в память только при первом обращении к соответствующему формату архива или схеме VFS.
В итоге сделать прототип с двумя синими панелями и переходом по папкам несложно – это приятная задача на пару свободных вечеров. Но между простым прототипом и надежным инструментом, в котором можно спокойно провести рабочий день, лежат сотни незаметных деталей. Я поставил себе простой критерий: «Я сам должен иметь возможность комфортно провести рабочий день в MTN2, не переключаясь в Проводник Windows или Far для повседневных задач».
Хотя на GitHub уже выложены скомпилированные релизы, проект пока находится в статусе альфа-версии. Это проверка на себе: я сам использую программу как основной инструмент, и именно в процессе живой ежедневной работы постоянно вылезают погрешности, находятся баги и тут же исправляются.
Тем не менее к версии 0.3.5 в MTN2 уже работает весь основной функционал файлового менеджера. Навскидку:
Ради чего создавалось – двухпанельная навигация с вкладками и историей. Независимые списки каталогов на левой и правой панелях, быстрый выбор дисков, избранные пути, закрытие и переключение вкладок, а также история последних переходов.
Всякие там – копирование, перемещение и удаление выполняются в фоновых потоках без блокировки интерфейса, с подробной индикацией прогресса и возможностью безопасной отмены.
Встроенный просмотрщик (
F3) и редактор (F4) – открытие файлов любого размера, автоматическое определение кодировок (UTF-8, UTF-16, ANSI/OEM), структурированный рендеринг форматированной документации на Markdown с таблицами и режим шестнадцатеричного дампа.Панель быстрого просмотра (
Ctrl+Q) – отображение содержимого выделенного файла или папки на соседней панели прямо во время перемещения по списку.Работа с архивами и системными хранилищами: навигация по архивам ZIP и 7z как по обычным каталогам, просмотр и восстановление файлов из Корзины Windows (
recycle://), быстрый переход к системным папкам (sys://folders) и виртуальные проектные рабочие пространства (ws:///).Поиск по маскам и тексту (
Alt+F7), а также двустороннее сравнение содержимого папок по датам и размерам (Ctrl+Shift+C) с подсветкой расхождений на обеих панелях.Контрольные суммы (
Ctrl+Alt+H): потоковый расчет и автоматическая сверка файлов по MD5, SHA-1, SHA-256 и SHA-512.Редактирование атрибутов (R/H/S/A), прав доступа и временных меток (
Ctrl+Shift+A), а также открытие стандартного окна свойств Windows (Alt+Enter).Пользовательское меню (
F2) – запуск настраиваемых сценариев автоматизации с классическими макроподстановками имен, путей и списков файлов, с поддержкой как глобального файла конфигурации, так и локальных меню проектов.mtn2menu.json.
Ну и просто пробегусь по возможностям (и особенностям реализации), которые, как мне кажется, интересны.
Встроенная консоль работает через Windows Pseudo Console API (CreatePseudoConsole) без обходных путей на анонимных каналах ввода-вывода, из-за которых в терминалах зависали vim, ssh или интерактивное автодополнение. Фоновая командная оболочка запускается заранее, открывая терминал по Ctrl+O без задержки.

Вместо окна справки (со списком клавиш) встроен контекстный просмотрщик документации на Markdown (uHelpViewer.pas) с оглавлением, поиском и переходом по ссылкам. Нажатие F1 – контекстное, в диалоге поиска открывает раздел о поиске, а в меню – раздел о меню.

Фоновые операции не блокируют ввод: всплывающие уведомления в углу экрана подтверждают выполнение «тихих» команд вроде копирования полного пути (Ctrl+Alt+Ins) или только имени файла (Alt+Shift+Ins), не отнимая фокус у клавиатуры.
Реализован режим единственного экземпляра приложения – запуск mtn2.exe <путь> из Проводника или консоли не создает новое окно, а через именованный мьютекс и системные сообщения WM_COPYDATA передает путь в уже работающий процесс, открывая его новой вкладкой.
Сама виртуальная файловая система умеет открывать архивы как обычные папки (zip:// и 7z://) с поддержкой вложенности через разделитель !/ (рекурсивный разбор цепочки архивов прямо в памяти без распаковки промежуточных контейнеров на диск), а специализированная схема recycle:// напрямую взаимодействует с Windows Shell через интерфейсы IShellFolder2 и IFileOperation. Здесь, возможно, переделаю: разделитель !/ – не есть хорошо.
По Alt+Enter открывается родное окно свойств файла Windows через SEE_MASK_INVOKEIDLIST, по Alt+F11 – история просмотренных и измененных файлов, в полях ввода по Ctrl+Down выпадает история ранее набранных значений, а служебный ключ запуска --fps выводит время фаз кадра прямо в заголовок окна.
Интерфейс поддерживает русский и английский языки с возможностью переключения на лету (uStrings.pas). Локализация охватывает всё приложение: от главного и контекстных меню, меток функциональных клавиш и системных уведомлений до всех встроенных диалогов. При этом базовый английский язык зашит прямо в исходный код как основа по умолчанию, а русский загружается из скомпилированного ресурса STRINGS_RU (ru.json) с возможностью подключения сторонних языковых файлов из папки strings/.
Параллельно дорабатываю внешний вид диалогов и элементов управления. В текстовом интерфейсе важна «красота» каждого знакоместа (смотри NDN). Выверяю отображение кнопок, флажков, радиокнопок и полей ввода, выравнивание по сетке, одинарные и двойные рамки псевдографики, контрастные тени диалоговых окон с учетом полупрозрачности подложки и цветовые акценты фокуса в зависимости от выбранной темы оформления (NDN или FAR).
А чтобы не верстать 42 диалоговых окна «вслепую» в обычном текстовом редакторе, высчитывая координаты ячеек X, Y, W, H, была создана утилита DialogDesigner (src/tools/DialogDesigner) – визуальный редактор JSON-диалогов.

Отдельная задача – организация автоматизированного конвейера CI/CD в GitHub Actions. Для проектов на Rust, Go или веб-стеке всё просто – стандартный облачный образ Ubuntu и автозапуск тестов. RAD Studio – коммерческая среда.
Решил эту проблему через гибридный конвейер сборки:
Облачные раннеры GitHub (Ubuntu) закрывают общие задачи – проверку безопасности через
gitleaks, валидацию целостности JSON-ресурсов диалогов и кросс-компиляцию Rust-плагинаmtn.wsв WebAssembly (wasm32-unknown-unknown).Собственный локальный агент сборки (
actions-runner) – моя машина под управлением Windows с развернутой RAD Studio иdcc64.exe. Раннер зарегистрирован с меткойdelphiи запускается интерактивно (run.cmd), а не службой Windows. Это необходимо, так как тесты ConPTY-консоли, буфера обмена и оконного композитора требуют живой пользовательской сессии (Session 1), а под изолированной системной службой Session 0 такие проверки падают.Запуск сборочного задания защищен репозиторной переменной
DELPHI_RUNNER == 'true'и ограничен только внутренними ветками (конвейер игнорирует внешние запросы на слияние (PR) и исключает исполнение недоверенного чужого кода на локальной машине). Был такой неприятный случай (не в этом проекте).При пуше в
mainили создании релизного тегаv*локальный раннер отрабатывает скриптbuild.ps1, прогоняет 700 автотестов DUnitX в 7 изолированных раннерах черезrun-tests.ps1, пакует артефакты и черезpackage-release.ps1автоматически формирует и публикует готовый релиз на GitHub.
Чего в проекте пока нет, но планируется, размышляется:
Очень хочется подсветку синтаксиса в редакторе. Просмотрщик уже форматирует Markdown, таблицы, обычный текст и шестнадцатеричные дампы. Но раскраска исходного кода на C++, Rust, Pascal или Python – пока думаю: или интеграция внешнего лексера (Tree-sitter или TextMate), или собственный расширяемый, но простой парсер. Это отдельная большая задача.
Из Total – пакетное переименование файлов. Пока мне не понадобились групповые операции по маскам, счетчикам и регулярным выражениям, но они запланированы на следующий релизный цикл.
Мосты к плагинам FAR Manager и Total Commander. Архитектура ядра готова к взаимодействию через декларативный UI и C-совместимый бинарный ABI, но сами адаптеры под сторонние библиотеки пока находятся на стадии проектирования. Да и пока думаю, зачем это надо. Большинство этих плагинов не смогут чисто архитектурно работать в MTN2.
Уже упоминал, но в общем списке – кроссплатформенный запуск на Linux и macOS. Ядро платформонезависимо, но терминальный слой завязан на Windows ConPTY. Замена его на
forkptyиtermiosстанет следующим крупным этапом.Связанная с пунктом 4 – полноэкранная матрица знакомест (VT-сетка) для терминала. Встроенный ConPTY терминал уже реализует сценарии командных оболочек (PowerShell, CMD, Bash в WSL) и потокового вывода утилит. Однако для работы интерактивных консольных программ (вроде
vim,htop,nanoилиless) требуется реализация альтернативного экранного буфера – 2D-матрицы знакомест по стандарту DECSET 1049 с абсолютным позиционированием курсора в координатной сетке. Эта подсистема сейчас находится в разработке.Ну и по мелочи – интерактивное дерево каталогов по
Alt+F10и поддержка сетевого протокола FTP.
Есть и проблемки. Рост кодовой базы оставил технический долг, который сейчас приходится планомерно разгребать:
В папке
src/Coreскопилось более 220 файлов.pasбез понятного разделения по подсистемам. Наследие этапа прототипирования. Сейчас я постепенно раскладываю эту общую массу по изолированным пакетам (VFS, терминал, редактор, оконный менеджер, элементы ввода).Отдельные модули – слишком много разнородных обязанностей. Главный кандидат на рефакторинг – модуль двухпанельного окна
uDualPanelWindow.pas, разросшийся почти до 9 тысяч строк кода. Он координирует вкладки, перехватывает горячие клавиши, выводит всплывающие оверлеи и держит часть логики отрисовки. Его разделение на специализированные контроллеры – одна из моих текущих задач, никак не решусь.Если подсистемы VFS, графический конвейер и ConPTY уже выстроены на интерфейсах (
IVirtualFileSystem,IThemeRenderer,IConPtySessionLife), то в некоторых диалогах и вспомогательных модулях все еще жесткие прямые связки между классами и временные глобальные экземпляры сущностей.Продолжается планомерное приведение именования к единым стандартам Object Pascal, устранение циклических зависимостей в блоках импорта (
uses) и расширение тестового покрытия. Недавно проект я полностью перевел на DUnitX. Этот переход я долго откладывал, в процессе разработки устал и запутался во множестве временных проверочных программок, раскиданных по разным углам репозитория. В итоге здесь на помощь пришел ИИ, взяв на себя расчистку завалов и миграцию проверок в фикстуры. Сейчас тестовая база разделена на 7 изолированных консольных раннеров по подсистемам (Core,VFS,Panels,Editor,Console,Dialogs,Plugins), насчитывает уже около семисот автотестов и формирует отчеты в формате NUnit XML для конвейера непрерывной интеграции (CI), хотя комплексные сценарии UI пока проверяются вручную.
Про что еще можно рассказать... Можно рассказать про устройство подсистем MTN2 с примерами кода, архитектурными схемами. Подводные камни тоже интересны, размер грабель показателен. Ну, например, навскидку:
Графический конвейер: как выжать стабильные миллисекунды на кадр на GPU, поддержать лигатуры и эмодзи, и как оптимизация замеров шрифтов разогнала верстку Markdown-таблиц с 8 секунд до 30 миллисекунд.
MDI в терминале: отсечение невидимых областей, порядок слоев Z-order, диспетчеризация мыши, цветовая раскраска файлов с живой палитрой и межпроцессное открытие вкладок.
Асинхронный VFS и PPL-задачи: вложенные архивы
!/, интеграция с Shell API для Корзины и защита UI от зависаний.Живая консоль: Windows ConPTY API, парсинг ANSI/VT100, xterm TrueColor, постоянные сеансы терминала и два режима маршрутизации клавиатуры.
Потоковый просмотрщик и редактор больших файлов: автоопределение кодировок, вызов внешних редакторов и системные свойства Windows.
Декларативный UI в JSON: рантайм-верстка при смене языка, запуск плагинов на WebAssembly через Wasmtime в строгой изоляции без WASI и архитектура будущих мостов к FAR и Total Commander.
Баг компилятора
dcc64с кодировкой UTF-8 без BOM, сломавший горячие клавиши: портативный режим сportable.dat, механизм безопасного самообновления через--wait-pid, переход на фреймворк DUnitX с нарезкой тестов по подсистемам, честные замеры памяти и организация CI/CD в GitHub Actions.
Для меня эта разработка подтвердила простое правило: хочешь сделать что-то хорошее для себя – делай сам (практически всегда, за исключением одной пикантной области). Когда вокруг всё стараются унифицировать под единый средний шаблон, именно индивидуальный, штучный инструмент, созданный под собственные привычки, дает чувство контроля и удовольствие от работы. Связка современного Object Pascal, графического фреймворка FireMonkey, библиотеки Skia и Windows ConPTY на практике оказалась быстрой и гибкой. Возможность за 2 секунды получить компактный бинарник без виртуальных машин, который запускается мгновенно и отрисовывает кадр за 3.4 миллисекунды прямо на GPU – это именно то, ради чего стоит заниматься системным программированием.
Проект MTN2 развивается, живет и уже закрывает мои повседневные задачи. Да, текущие релизы на GitHub – это альфа-версия, ошибки в которой отлавливаются и оперативно правятся по результатам ежедневной практической работы, но этим можно и удобно пользоваться. Этот проект создавался как дань уважения классике – из NDN с любовью... но на современном GPU-конвейере и с прицелом на текущие реалии 2026 года.
Исходный код проекта, документация и скомпилированные релизы открыты и доступны на GitHub: https://github.com/Laex/MTN2.
KioskNews shows a cleaned-up reading view extracted from the publisher’s page — the original always lives on their site, not ours.