-
Здравствуйте! Имеется следующая строка, которую нужно раскрасить:
DisplayValue("param1","param2")
а именно - выделить название функции перед первой скобкой. Казалось бы, ничего сложного, но у меня за 2 часа "метода тыка" ничего не выходит :((( Итоговой код следующий:
...
{
className: 'function',
begin: '^[a-zA-Z1-9]+', end: '\\(',
excludeEnd: true
}
...
Что я делаю не так? -
Ещё несколько слов после дальнейших попыток.
Код теперь такой:
{
className: 'function',
begin: '^\\w', end: '\\(',
excludeEnd: true
}
Строку
DisplayValue("param1","param2")
он прекрасно раскрашивает. А вот если ниже неё написать
DisplayValue("param1","param2")
Next
Всё, весь текст становится чёрным... Если перед Next поставить пробел - всё приходит в норму.
Что же я забыл? :( -
Совершенно невозможно что-то понять без полного описания языка. Проблема может быть не только в том правиле, которое вы привели.
Плюс фраза "весь текст становится чёрным" имеет смысл, только если знать, что у вас обозначается чёрным. При отладке лучше смотреть не на цвета, а на DOM-дерево, которое получается.
-
Да, интересно то, что если смотреть DOM - раскраски вообще нет, то есть span'ы отсутствуют. Привожу полный код своего языка:
Кстати, если дать такую строку на раскраску:hljs.LANGUAGES.mmb =
{
case_insensitive: false,
defaultMode:
{
lexems: [hljs.IDENT_RE],
contains: ['string', 'number', 'comment', 'function'],
keywords: {
'keyword': {'TRUE': 1, 'FALSE': 1, 'If': 1, 'Then': 1, 'End': 1, 'For': 1, 'To': 1, 'Next': 1, 'Infinity': 1, 'SrcDir': 1, 'SrcDrive': 1, 'Embedded': 1, 'Windows': 1, 'System': 1, 'Temp': 1, 'File': 1, 'List': 1, 'This': 1}
}
},
modes: [
hljs.C_NUMBER_MODE,
hljs.C_BLOCK_COMMENT_MODE,
{
className: 'comment',
begin: '\\*\\*', end: '$'
},
{
className: 'string',
begin: '\'', end: '\''
},
{
className: 'function',
begin: '^\\w', end: '\\(',
excludeEnd: true
}
]
};
DisplayValue("param1","param2")
Next
DisplayValue("param1","param2")
скрипт всё сделает правильно, будет 2 спана. Но! Во второй он захватывает
Next
DisplayValue
словно они в одной строке!
Иван Сагалаев, и спасибо вам за highlight! :) -
Всё, у меня мысли закончились. Надеюсь только на вашу помощь. Истратил часов 5 точно на это дело :((
Задача - раскрасить название функции, оно стоит перед скобками. Всё, до чего я дошёл и как делал - выше предоставил.
Заранее спасибо! -
Так, я нашёл время вникнуть :-).
Вот эта штука:
{ className: 'function', begin: '^\\w', end: '\\(', excludeEnd: true }Означает буквально, что функция начинается с любой буквы в начале строки, а заканчивается открывающей скобкой. Между ними может попасть абсолютно всё что угодно :
DisplayValue - тут что- нибудь - 'dfsdf!!!' (И это всё будет одной функцией. Очевидно, это не то, что вам нужно :-). Лучше всего функцию описать как конструкцию "имя со скобками", внутри которой будут уже отдельно её имя и параметры:
{ className: 'function', contains: ['title', 'params'], begin: '\\w+\\(', end: '^', returnBegin: true }, { className: 'title', begin: '\\w+', end: '^' }, { className: 'params', begin: '\\(', end: '\\)', }Интересный момент в том, что описание function заканчивается как
end: '^', что означает "заканчивается сразу". Однако любые вложенные режимы (title и params) имеют шанс начаться до того, как закончится родительский режим function. Поэтому после начала function тут же находится режим title, который съедает всё название, а после него сразу же params, который съедает открывающую и закрывающую скобки. И только после этого, когда больше ничего из них не нашлось, тут же закрывается function. -
"Между ними может попасть абсолютно всё что угодно"
Да-да, я так и понял, но никак не мог придумать выход.
"Лучше всего функцию описать как конструкцию "имя со скобками""
Вот это классное решение! Я бы до него не дошёл. Вам, как разработчику, несколько легче понять это дело, зная свою библиотеку и принцип её работы :)
Спасибо большое за помощь! Всё работает просто замечательно!!! -
Вам, как разработчику, несколько легче понять это дело
Это да. Но я, сказать по правде, тоже далеко не сразу придумываю, как это всё описывать. Например применение returnBegin для меня самого несколько таинственным выглядит :-).
-
Ещё одна заковырка возникла.
Немного модифицировал класс function:
То есть, мне нужно, чтобы функция начиналась обязательно с начала строки и впереди неё может быть пробел (код выстраивается "ступеньками").begin: '^[ ]*\\w+\\('
С такми кодом браузер начинает зависать. Видимо, highlight зацикливается или что-то в этом роде и раскраски никакой не происходит.
Если убрать из кода returnBegin: true, то становится ясным, что моя регулярка составлена правильно (всё раскрашивается верно), но раскраска, само собой, захватывает скобку
DisplayValue(
Как думаете, что здесь не так? -
гм... Дело вот в этой штуковине:
Думаю дальше.end: '^' -
о! Нашёл решение, но мне оно не кажется изящным... Хотя, рабочее.
То есть, конец правила я решил представить тоже открывающейся скобкой.begin: '^[ ]*\\w+\\(', end: '\\('
Буду рад услышать ваше мнение и мысли :) -
Там вот что происходит. Вот в такой ситуации:
begin: '...', end: '^'... из-за того, что end закрывается сразу же, нужно, чтобы всё, что находится между begin и end было покрыто внутренними правилами из contains. Вы добавили в определение begin пробелы, а ни title, ни params не изменились. В итоге получается так:
- Парсер находит паттерн, подходящий под начало function.
- Весь этот паттерн (пробелы, название, скобка) возвращается обратно в исходную строку из-за returnBegin
- Начинается проверка на внутренние режимы, но первым символом стоит пробел, который не начинает ни title, ни params.
- function тут же закрывается.
Именно из-за этого происходит и зацикливание: всё начало функции вернулось по returnBegin в исходную строку, дальше мы не продвинулись, и соответственно находим его снова.
То есть при использовании комбинации из returnBegin и
end: '^'обязательно надо внутренними режимами "выедать" всё содержимое родительского режима. Соответственно, починить ситуацию можно просто добавлением ещё одного режима, который будет съедать whitespace:{ className: 'function', contains: ['title', 'params', 'whitespace'], begin: '^ *\\w+\\(', end: '^', returnBegin: true }, { className: 'title', begin: '\\w+', end: '^' }, { className: 'params', begin: '\\(', end: '\\)', }, { className: 'whitespace', begin: ' +', end: '^', noMarkup: true // это чтобы оно бессмысленных span'ов не плодило } -
Ага, вот оно как. Понял, спасибо :) Такое решение по крайней мере выглядит более логичным, чем я поставил скобку. Лучше его и применю :)
Скорее всего, последняя задача, которая стоит передо мной - это второй вид функций, которые могут встречаться во всей строке, а не только всю её и занимать:
Вот здесь есть функции CHAR, NOL, StrCopy, которые тоже нужно раскрасить... Не могу придумать регулярку для такой ситуации. Получается, перед началом функции обязательно хоть что-то будет стоять! Причём, не текстовый символ. Чаще всего это: =, +, ( или пробел.kb$=CHAR(kb)
...
For i=1 To NOL(ini$)
...
kb$=StrCopy(kb$,1,count)
Пытался написать, что в начале регулярки не будет границы слов (\B) - это не помогло. Но оно и ясно почему...
Даже не знаю, что ещё придумать... Пробовал по принципу, приведённому вами выше (выедание) - получилось несколько коряво. Больше пока идей нет :( -
Увы, ничего не выходит... Решил обойтись без универсального метода и написал такое условие:
Первая часть регулярки - это для функций в верхем регистре (CHAR, VAL, ..). Вторая - варианты начала других функций языка (например, Str - для StrCopy, StrGet, ...).begin: '(?:[A-Z]{3,}|(?:Str|Extract|Pub|Screen|Object)\\w+)\\(', end: '^'
Но мне, как программисту, такое решение не очень нравится, хочется универсальности :) Не поможете? Может у вас будут какие мысли. -
Если эти функции тоже имеют открывающую скобку после имени, то чем они отличаются от предыдущих? Если не отличаются, то почему бы не оставить одно правило на всех, убрав у него условие на начало строки и пробелы?
-
Если эти функции тоже имеют открывающую скобку после имени, то чем они отличаются от предыдущих?Раскраска разная у тех функций и этих.
Если сделать так, то получается вот такая картина. Первый вид функций: функция, которая стоит за счёт лесенки через несколько пробелов впереди:убрав у него условие на начало строки и пробелы
раскрашивается верно. А вот ту, которая начинается с самого начала строки - захватывает раскраска второго вида функции. Почему-то:[color=#000080] LoadText[/color]("valSel","a$")
А в остальном всё работает правильно. Но вот такие нюансы меня и ставят в ступор.[color=blue]LoadText[/color]("valSel","b$")
Получается, нужно ешё как-то задать регулярку, чтобы не раскрашивалась функция, которая начинается с новой строки. Но вот как... И в ту ли сторону я мыслю... -
Нет, вот регулярка, что-то отменяющая — это почти всегда плохая идея. Я думаю, что тут можно просто описать два режима начала функций, причём первым поставить тот, который с новой строки ищет (порядок режимов имеет значение). Тогда он будет пробоваться раньше и находить функции первого вида. А на функции второго вида будет срабатывать второй режим.
{ className: 'function1', contains: ['title', 'params', 'whitespace'], begin: '^ *\\w+\\(', end: '^', returnBegin: true }, { className: 'function2', contains: ['title', 'params'], # без whitespace, он тут не нужен begin: '\\w+\\(', end: '^', returnBegin: true },Режимы title и params будут использоваться и там, и там, их достаточно описать один раз:
{ className: 'title', begin: '\\w+', end: '^' }, { className: 'params', begin: '\\(', end: '\\)', }, { className: 'whitespace', begin: ' +', end: '^', noMarkup: true // это чтобы оно бессмысленных span'ов не плодило } -
их достаточно описать один разНо ведь я не могу так сделать, раскраска разная у обоих видов функций. Классы css разные.
В итоге у меня выходит такой код:
На основе такого кода оба вида функций раскрашиваются в класс c_name (!!!), то есть в стиль первого вида функции. Фантастика какая-то... :){
className: 'command',
contains: ['c_name', 'whitespace'],
begin: '^ *\\w+\\(', end: '^',
returnBegin: true
},
{
className: 'c_name',
begin: '\\w+', end: '^'
},
{
className: 'whitespace',
begin: ' +', end: '^',
noMarkup: true
},
{
className: 'function',
contains: ['f_name'],
begin: '\\w+\\(', end: '^',
returnBegin: true
},
{
className: 'f_name',
begin: '\\w+', end: '^'
} -
Но ведь я не могу так сделать, раскраска разная у обоих видов функций. Классы css разные.
Ну это-то не проблема. Я описал два разных вида функций: function1 и function2. Чтобы дать разные цвета title'ам внутри них, в CSS нужно иметь такое:
.function1 .title { color: red; } .function2 .title { color: blue; }{ className: 'command', contains: ['c_name', 'whitespace'], begin: '^ *\\w+\\(', end: '^', returnBegin: true },Решили без params? Тогда определение command закончится сразу до первой скобки... Хотя наверное это не проблема.
На основе такого кода оба вида функций раскрашиваются в класс c_name
А можете выложить где-нибудь тестовую страницу с этим? А то так трудно придумать, почему оно может не работать.
-
Ну это-то не проблема. Я описал два разных вида функций: function1 и function2. Чтобы дать разные цвета title'ам внутри них, в CSS нужно иметь такое:Точно, я и забыл, что вложенность спанов получается. Но проблему это не решает, к сожалению. Просто код кратче стал.
Да, мне параметры раскрашивать не нужно. Да и на общую раскраску они вроде не влияют, если убрать...Решили без params?
Да, конечно:А можете выложить где-нибудь тестовую страницу с этим?
http://devate.ru/highlight/
Смотрите, уже в первой строке видно второй вид функций. Раскраска прошла почему-то классом первого вида... А должен быть просто синим цветом.
Первый вид функций вы можете наблюдать в команде DisplayValue и далее. Вот они в своей раскраске. Да плюс ещё и раскрасили второй вид функций почему-то...
В общем, по коду вы сами всё поймёте.
Спасибо, что уделяете мне время! :) -
Немного покопавшись в собственных исходниках, я понял, в чём проблема :-). Маркер начала строки (
^) в начале регулярке на самом деле не работает, как задумано: он срабатывает везде, где начинает искаться следующий режим без учёта собственно строк исходного кода. Если нужен символ начала строки в коде, то можно использовать\n. Хотя это и не одно и то же, но в данном случае не будет важно. Вот так, в итоге, будет работать:{ className: 'command', contains: ['name', 'whitespace', 'newline'], begin: '\\n *\\w+\\(', end: '^', returnBegin: true }, { className: 'function', contains: ['name'], begin: '\\w+\\(', end: '^', returnBegin: true }, { className: 'name', begin: '\\w+', end: '^' }, { className: 'whitespace', begin: ' +', end: '^', noMarkup: true }, { className: 'newline', begin: '\\n', end: '^', noMarkup: true } -
Просто класс! Всё работает, как нужно!!! Вроде, на этом и заканчивается описание нужного мне языка ;)
Иван, спасибо большое за оперативную помощь! Вы очень помогли мне!
Удачи вам и в дальнейшем над разработкой highlight.js! -
Поздравляю :-)
-
Здравствуйте ещё раз!
Занялся портированием подсветки кода на сайт и возникла одна маленькая проблема...
Код у меня начинается так:
из-за этого сверху получается пустая строка... Ведь в pre как нарисуешь - так всё и получишь. Но она мне не нужна, дизайн портит. Хорошо, начинаю писать сразу после тега code и тут выходит одна неувязочка...<pre><code>
код
Помните это? В общем, если у меня в начале этой строки идёт функция, скажем DisplayValueЕсли нужен символ начала строки в коде, то можно использовать \n.
то ваша хитрость не срабатывает, выходит \n там нет - и код раскрашивается неверно :(<pre><code>DisplayValue
Вот собственно такая проблема. Как думаете, что здесь можно придумать? -
Пока не знаю... Попробую подумать на досуге.
-
Иван, есть успехи? :) Может быть, для меня как-то индивидуально поправить саму js-библиотеку, её код?
-
Пока не придумал. Вопрос, собственно, не в том пока, править библиотеку или язык, а в том, как это различие (начало файла или начало строки) вообще установить.
-
Здравствуйте! А сейчас успехов не предвидится? :)
Внимание! Это довольно старый топик, посты в него не попадут в новые, и их никто не увидит. Пишите пост, если хотите просто дополнить топик, а чтобы задать новый вопрос — начните новый.

