LINUX.ORG.RU

реализация отображения текста и подсветки синтаксиса


0

2

Может кто знает, где можно почитать о сабже?

Наверняка вся эта тема - адский баян, начиная с середины прошлого века :) Но толковых трудов по теме не нагуглил. Может кто заранее знает?


===

Детали

Нужно реализовать простую отображалку кода с подсветкой синтаксиса.
Парсер уже есть, о коде можно узнать всё что угодно, проблема именно в грамотном отображении. (Использовать готовые решения типа эклипсы нельзя, арсенал ограничен минимальным набором типа «картинка»+«шрифт», всё остальное должно быть велосипедом)

Больше всего интересуют проблемы перфоманса перекрашивания текста. Если на каждый новый символ производить полный переразбор текста, а потом перекрашивать заново, то всё будет нещадно тормозить и/или мигать (как и происходит в кое-каких редакторах). Т.е. с точки зрения графики нужно как минимум определять регион и устраивать блиттинг, а сточки зрения парсанья нужно парсить дерево (ну или что там, если дерево неприменимо) необычным макаром исходя из региона. Ну и в общем, из этого можно сочинить целую философию, и если уже есть готовая, то проще проехать на готовеньком ;)

Есть еще вопросы. Например, сейчас многие текстовые редакторы начинают тормозить, когда строки очень длинные. Или когда начинаешь редактировать середину длинной строки. Как борются с этими проблемами? Транзакционная модель и ерархические undo-redo - тоже вопрос, но приоритет у него поменьше.

★★★★☆

Последнее исправление: stevejobs (всего исправлений: 1)

Если совсем велосипедно, то я бы делал так:
- парсер на flex парсит текст и делает дерево (или еще что-нить) токенов
- есть map с соответствием токен - стиль
- знаешь начальную, конечную строку отображения. Берешь токен, его стиль - пишешь текст.

а, вообще:
man Command Flyweight

Rubbiroid
()

Если нужно только подсвечивать ключевые слова, то все очень просто, я такое писал. А если требуется учитывать структуру, то первое, что в голову приходит — парсить с задержкой (как в эклипсе).

note173 ★★★★★
()
Ответ на: комментарий от Rubbiroid

> - есть map с соответствием токен - стиль

- знаешь начальную, конечную строку отображения. Берешь токен, его стиль - пишешь текст.


и вот тут, тащем-то, начинаются проблемы.

допустим, у нас «stat.» - это statement, а «stat» (без точки) - синтаксическая ошибка.

[code]
foo(X,Y) ->
(bar(X,Y) -> statement1.),...
[/code]

допустим, человек пропускает точку:

[code]
foo(X,Y) ->
(bar(X,Y) -> statement1),...
[/code]

тогда в отдельности элементы выражения смысл имеют, а вот «bar(X,Y) -> statement1» с пропущенной точкой - это синтаксическая ошибка.

мне это видится как-то так:

1) попросить парсер, возможно ли восстановиться из такой ситуации без потери смысла. Если да, подчеркиваем statement1 красной волнистой, пищем «пропущена точка после statement».

2) если воостановление невозможно, нужно определить масштаб ошибки. Если есть однозначное дерево (тогда почему нельзя воосстановиться? ;), то мы подчеркиваем неверную ветвь («bar(X,Y) -> statement1»). Если у нас какие-то макроподстановки («#define true false»), особенно игнорирующие порядок выполнения команд, масштаб трагедии может быть разнообразный.

3) в зависимости от масштаба ошибки - кромсаем текст на регионы. Тут надо провести ряд мероприятий с графикой: перерисовку невидимых частей лучше не делать, перерисовку видимых частей лучше сгруппировать в одну операцию перерисовки, если это возможно, перерисовку уже перерисованного (если при макроподстановках перерисовочные регионы перекрываются) не делать, итп.

4) все сделанные изменения нужно как-то упихать в транзакции - во-первых, чтобы не рушилось, во-вторых чтбоы был быстрый undo

Тащем-то это все это можно сделать разными способами. Хотелось бы порассуждать на эту тему...

stevejobs ★★★★☆
() автор топика

Итак,

1) обычно для раскрашивания текста дерево разбора не нужно, а нужен лишь поток токенов (т.е., нужен лексинг, а не парсинг)

2) (я сам так не делал, но думаю, что так можно) Если рассмотреть, например, разбор на лексемы с помощью регулярных выражений, то разбор осуществляется проходом конечного автомата по строке. Идея в том, что промежуточные состояния конечного автомата (или иного средства разбора текста) можно хранить вместе с текстом, и тогда можно делать инкрементальный разбор текста: разбор текста после измненения начинать с измененного символа и до момента, как состояние автомата ресинхронизируется со старым, запомненным, состоянием.

3) Вообще, все зависит от того, что тормозит. Если текст хранится в виде массива строк, то может тормозить вставка в середину строки, для этого есть gap buffer. Тормозить может разбиение строки на линейки текста, подсчет высоты линеек текста (если шрифт неоднороден или если текст может содержать различные вставки), разбивка на страницы, и еще много чего.

dmitry_vk ★★★
()
Ответ на: комментарий от note173

эклипса же тормозит? и на длинных строчках тормозит, и на рефакторингах тормозит, а если запустить текстовый поиск по большим файлам (например, приложить в проект дампы sql) - вылетает с null pointer exception. (поэтому жавовские рефакторинги приходится делать в идее). Когда печатаешь текст, визуально видно, что она его расцвечивает с задержкой.

а как сделано в емаксе?

stevejobs ★★★★☆
() автор топика
Ответ на: комментарий от dmitry_vk

> Идея в том, что промежуточные состояния конечного автомата (или иного средства разбора текста) можно хранить вместе с текстом,

вот это круто, да, спасибо

Вообще, все зависит от того, что тормозит.


пока что еще ничего не тормозит, потому что ничего нет ;) Хочу на берегу узнать, как делать _правильно_

stevejobs ★★★★☆
() автор топика
Ответ на: комментарий от stevejobs

Это уже будет не «раскрашивание текста», а полномерная проверка синтаксиса. Тут я пас, бо построение компиляторов только через семестр :)
Если знаешь немецкий - могу скинуть линк на скринкаст лекций про построение компиляторов.

Rubbiroid
()
Ответ на: комментарий от dmitry_vk

> разбивка на страницы

Проецировать в оперативку только те участки, которые видны (отображаются на текущей странице). Либо которые нужны для парсинга (хранить в метаданных ссылки на зависимости от участков файла?) Потом кусочки дефрагментировать, часто используемые рядомстоящие, если оперативка будет кончаться - дропать их.

Хорошая идея?

stevejobs ★★★★☆
() автор топика
Ответ на: комментарий от Rubbiroid

немецкий не знаю. Но это отдельная тема, т.е. не написание парсеров вообще, а анализ scope of change и парсинг кусочков - наверное, не такая частая задача, чтобы ее стоило демонстрировать в скринкастах)

stevejobs ★★★★☆
() автор топика
Ответ на: комментарий от shty

Там же KatePart юзается. А вообще поддерживаю — посмотреть код самых мощных движков для подсветки, вроде scintilla или katepart

fat_angel ★★★★★
()
Ответ на: комментарий от fat_angel

KatePart - это только движок, нужно еще и реализацию.

Pavval ★★★★★
()
Ответ на: комментарий от stevejobs

Можешь поболтать с разрабами kdevelop на тему реализации этого. Вроде даже были какие-то доки по реализации, но сейчас найти не могу.

Pavval ★★★★★
()

Нужно реализовать простую отображалку кода с подсветкой синтаксиса. Парсер уже есть, о коде можно узнать всё что угодно

именно отображалка нужна ? то есть редактировать код в ней не надо ??

можно xml+xslt. На досуге, когда время есть, балуюсь - делаю интерпретатор. Чтобы отлаживать парсер(и частично лексер), заставил его выдавать xml и через xslt смотрел результат - очень удобно. Заодно получился своеобразный unit-test и валидатор кода.

MKuznetsov ★★★★★
()
Ответ на: комментарий от stevejobs

надо редактор кода

тогда как уже сказали

2) (я сам так не делал, но думаю, что так можно) Если рассмотреть, например, разбор на лексемы с помощью регулярных выражений, то разбор осуществляется проходом конечного автомата по строке. Идея в том, что промежуточные состояния конечного автомата (или иного средства разбора текста) можно хранить вместе с текстом, и тогда можно делать инкрементальный разбор текста: разбор текста после измненения начинать с измененного символа и до момента, как состояние автомата ресинхронизируется со старым, запомненным, состоянием.

или всё-таки взять Scintilla :)

MKuznetsov ★★★★★
()

Решение

Похоже, никто не знает классических трудов на эту тему.

Единственное полное решение - смотреть исходники готовых редакторов кода.

stevejobs ★★★★☆
() автор топика
Ответ на: комментарий от Rubbiroid

> Если знаешь немецкий - могу скинуть линк на скринкаст лекций про построение компиляторов.

Какие ещё лекции на немецком?) Есть книга Вирта и Книга Дракона, классика как бэ, всё уже на русский переведено.

Norgat ★★★★★
()
Ответ на: комментарий от Norgat

>Какие ещё лекции на немецком?
самые обычные с универа. http://seblog.cs.uni-kassel.de/category/pastterms/cc/

Есть книга Вирта и Книга Дракона, классика как бэ, всё уже на русский переведено.

Книга - это хорошо, но не всем подходит. Я, например, лучше воспринимаю информацию, когда мне это рассказывают, чем когда я читаю.

Rubbiroid
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.