Привет, Хабр! Обычно в своих дайджестах разработки far2l я рассказываю сразу о пачке новостей, накопившихся за год. Но сегодня случай особый. Мы реализовали фичПривет, Хабр! Обычно в своих дайджестах разработки far2l я рассказываю сразу о пачке новостей, накопившихся за год. Но сегодня случай особый. Мы реализовали фич

Как я делал перенос по словам в редакторе far2l

6м. чтение

Привет, Хабр! Обычно в своих дайджестах разработки far2l я рассказываю сразу о пачке новостей, накопившихся за год. Но сегодня случай особый. Мы реализовали фичу, тикет на которую висел в багтрекере с 10 ноября 2016 года. Фичу, которой мне самому остро не хватало ещё со времён использования Far Manager в Windows. Фичу, к которой многие боялись подступиться из-за сложности реализации в архитектуре, заточенной под «одна строка кода = одна строка на экране». Встречайте: перенос по словам (Word Wrap) во встроенном редакторе far2l! Под катом — рассказ о том, почему это заняло 9 лет, как Junior/Middle навыков C/C++ хватило для задачи уровня Senior благодаря Gemini 2.5 и 3 Pro, и как помог процесс формат патчей .ap.

8ac6a8dffdc87e7b03ef9511497c4380.png

9 лет ожидания

Тикет #201 с запросом сделать перенос по словам я открыл ещё в 2016ом, буквально через пару месяцев после первоначальной публикации исходного кода far2l. Проблема понятна каждому, кто хоть раз открывал minified json, длинный лог или просто писал тексты в Markdown/LaTeX: горизонтальный скролл — это боль. В «Блокноте» Windows эта функция была всегда. В современных GUI-редакторах — тоже. А в Far — нет.

Почему так долго никто не делал перенос? Потому что редактор Far Manager (и far2l как его наследника) — сложный механизм, где концепция «одна логическая строка (т.е. как в файле) = одна строка на экране» прошита очень глубоко. Курсор, выделение, скроллинг, отрисовка — всё завязано на это. Переписать это — значит перетряхнуть половину редактора.

Эпоха нейросетей: как Junior C++ смог в Senior задачу

Я никогда не считал себя сильным C++ разработчиком.Мой уровень в «плюсах» — где-то между Junior и Middle. Я понятия не имел, как правильно архитектурно реализовать свёртку строк (Soft Wrap) в текстовом редакторе. Наверняка профи сделали бы это быстрее и лучше меня, но с 2016 года никто из профи за это так и не взялся: видимо, задача и правда выглядела пугающе объемной. Однако на дворе 2025 год, и у нас есть мощные LLM!

Разработка заняла около двух недель увлеченного кодинга. Моим главным инструментом стали нейросети Gemini Pro с контекстным окном на мегатокен. Это критически важно, когда нужно «скармливать» модели десяток связанных файлов исходников (edit.cpp, editor.cpp, fileedit.cpp и заголовки), чтобы она понимала контекст целиком, а не галлюцинировала из-за незнания каких-то функций.

Начинал я этот марафон с Gemini 2.5 Pro, но буквально в процессе работы вышла Gemini 3 Pro. Я сразу переключился на неё, и впечатления сугубо положительные: она ещё лучше держит сложный контекст старого C++ кода и реже ошибается в логике неочевидных взаимосвязей классов Far'а.

Методология: формат .ap в бою

В этой работе я активно использовал свой формат AI-friendly Patch (.ap), о котором уже писал на Хабре ранее, это позволило автоматизировать рутину. Вместо того чтобы руками править код по советам чат-бота, я получал готовые к применению микро-патчи. Подобные форматы используют внутри для применения изменений и AI-агенты, но мне нравится вручную контроллировать процесс. Кроме того, мне важно, чтобы модель видела все наши шаги, а не только текущую подзадачу (агенты же используют для каждой подзадачи новый контекст). А ещё совсем глупенькие ответы (которые начинаются, когда перегружаешь контекстное окно сложной инфой) сразу заметно, потому что получаются кривые, не применяющиеся патчи. В этот момент надо просить модель написать саммари диалога, и идти с ним в новый чат, не забыв снова экспонировать модели все нужные файлы.

  • Масштаб работы: всего было применено порядка 80 тривиальных патчей (не считая десятков экспериментальных, которые ушли в корзину).

  • Процесс: около 10 длинных веток диалогов с нейросетью.

  • Эволюция инструмента: и спецификация формата .ap и сам скрипт-патчер дошлифовывались прямо в процессе. Реальный сложный кейс показывал, где в спецификации слабые места, и они оперативно устранялись.

Архитектура решения

Как мы с моделями это сделали, не сломав совместимость со всем остальным кодом, включая Plug-in API? В основе редактора лежит класс Edit, который отвечает за одну логическую строку текста. Раньше он просто рисовал себя от начала до конца. Мы внедрили концепцию визуальных строк.

  1. Определение точек разрыва: в класс Edit добавлен метод RecalculateWordWrap, рассчитывающий точки разрыва внутри этой логической строки. Он вызывается при изменении ширины окна или контента. Это «мягкий» перенос — строки, с которыми идёт фактическая работа, не разрезаются, меняется только их представление.

  2. Отрисовка: мы используем несколько отдельных Edit, каждый длиной в ширину экрана, кладём в каждый подстроку логической строки согласно уже известным точкам переноса, и просим эти Edit отрисовать себя. В перспективе можно сделать так, чтобы сам Edit умел отрисовывать себя многострочно, но на практике оказалось, что и текущее решение работает вполне быстро, так что пока оставили его: лучшее враг хорошего.

  3. Навигация: это было самое сложное. Нажатие Down больше не может просто перекидывать фокус на следующий объект Edit в списке. Если мы в середине длинной строки, Down должен сместить курсор на следующую визуальную строку внутри текущей логической. Переход к следующему Edit происходит только тогда, когда мы на последней визуальной строке.

Бонус: выделение мышью

Пока я учил редактор свёртке, пришлось перелопатить обработку мыши (ProcessMouse). А раз уж мы всё равно переписываем логику маппинга координат экрана в позицию в тексте, почему бы не сделать нормальное мышыное выделение? Теперь можно начать выделение на одной строке, потянуть мышь вниз, и выделение корректно «потечёт» по визуальным строкам, как в браузере или Word. И, разумеется, уже существовавшее в far2l выделение двойным и тройным мышиными кликами также адаптировано под новую реальность.

Баги и регрессии

Конечно, без багов не обошлось. То курсор прыгал не туда, то End отправлял в бесконечность. Но исправлять их с помощью тех же моделей получалось довольно быстро. Если случалась регрессия, я не просто описывал модели ошибку, а показывал diff изменений, связанных с реализацию вызвавшей регрессию фичи, вместе с полным кодом релеватных файлов. Имея перед «глазами» разницу, Gemini Pro во всех случаях (иногда с лёгким наставничеством с моей стороны) находила причину поломки и генерировала фикс (в том же ap формате).

Итог

Фича уже готова и в мастере, уже использую её в повседневной работе. Что мы имеем в сухом остатке:

  1. Закрыл один из старейших запросов сообщества (и собственный pain)

  2. Убедился, что с современными LLM (особенно уровня Gemini 3 Pro) порог входа в сложные C/C++ проекты и legacy-код становится для меня примемлемым

  3. Провёл инструментарию .ap патчей боевое крещение

Друзья, потестируйте (свежую версию можно взять, например, в ppa)! Это большое изменение в ядре редактора, и коллективный разум всегда находит то, что мы упустили. Баги несите, как обычно, на GitHub. И, конечно, заходите пообщаться в чате!

Источник

Возможности рынка
Логотип 2016 coin
2016 coin Курс (2016)
$0.0000814
$0.0000814$0.0000814
+1.11%
USD
График цены 2016 coin (2016) в реальном времени
Отказ от ответственности: Статьи, размещенные на этом веб-сайте, взяты из общедоступных источников и предоставляются исключительно в информационных целях. Они не обязательно отражают точку зрения MEXC. Все права принадлежат первоисточникам. Если вы считаете, что какой-либо контент нарушает права третьих лиц, пожалуйста, обратитесь по адресу service@support.mexc.com для его удаления. MEXC не дает никаких гарантий в отношении точности, полноты или своевременности контента и не несет ответственности за любые действия, предпринятые на основе предоставленной информации. Контент не является финансовой, юридической или иной профессиональной консультацией и не должен рассматриваться как рекомендация или одобрение со стороны MEXC.