Для цього потрібно підключити в uses модуль RegularExpressions.
Шаблон (в даному випадку для PL/SQL) прописаний в константі C_LEXEM_PATTERN, змінити або доповнити його буде не складно. Для коментарів реалізовано шаблон C_COMMENTS_PATTERN. Класовою процедурою TRegEx.Replace виконується додавання до знайденого тексту тегу <b>.
Коментарі в PL\SQL починаються з двох мінусів "--" або обмежуються операторами /* та */. Для коментарів застосовується фарбування шрифту в зелений колір: <font color="#008080">$1</font>
function SqlSyntaxLight(const aSqlText: string): string;
const
C_LEXEM_PATTERN = '(?i)(' +
'\bAGGREGATE\b|\bALL\b|\bALTER\b|\bAND\b|\bANY\b|\bAS\b|\bASC\b|\bAVG\b|\bBEFORE\b|\bBEGIN\b|' +
'\bBETWEEN\b|\bBULK\b|\bBY\b|\bCASE\b|\bCAST\b|\bCHAR\b|\bCHECK\b|\bCOLLECT\b|\bCOMMENT\b|' +
'\bCOMMIT\b|\bCOUNT\b|\bCURRENT\b|\bCURRENT_USER\b|\bCURSOR\b|\bDATE\b|\bDAY\b|\bDEC\b|\bDECIMAL\b|' +
'\bDECLARE\b|\bDEFAULT\b|\bDELETE\b|\bDESC\b|\bDISTINCT\b|\bEACH\b|\bELSE\b|\bELSIF\b|\bEND\b|' +
'\bEXCEPTION\b|\bEXECUTE\b|\bEXISTS\b|\bFALSE\b|\bFETCH\b|\bFIRST\b|\bFOR\b|\bFORALL\b|\bFOUND\b|' +
'\bFROM\b|\bFULL\b|\bFUNCTION\b|\bGROUPING\b|\bHAVING\b|\bIF\b|\bIN\b|\bINNER\b|\bINSERT\b|\bINTEGER\b|' +
'\bINTERSECT\b|\bINTERVAL\b|\bINTO\b|\bIS\b|\bJOIN\b|\bLAST\b|\bLEFT\b|\bLEVEL\b|\bLIKE\b|\bLOOP\b|' +
'\bMAX\b|\bMIN\b|\bMONTH\b|\bNEXT\b|\bNEXTVAL\b|\bNOT\b|\bNOTFOUND\b|\bNOWAIT\b|\bNULL\b|\bNULLS\b|' +
'\bNUMBER\b|\bNUMERIC\b|\bOF\b|\bOLD\b|\bON\b|\bOR\b|\bORDER\b|\bOUT\b|\bOUTER\b|\bPLS_INTEGER\b|' +
'\bPOSITIVE\b|\bPRIOR\b|\bPROCEDURE\b|\bRAISE\b|\bRANGE\b|\bRAW\b|\bREPLACE\b|\bRESULT\b|\bRETURN\b|' +
'\bRIGHT\b|\bROLLBACK\b|\bROW\b|\bROWCOUNT\b|\bROWID\b|\bROWTYPE\b|\bSELECT\b|\bSELF\b|\bSET\b|\bSETS\b|' +
'\bSTRING\b|\bSUBTYPE\b|\bSUM\b|\bSYSDATE\b|\bTABLE\b|\bTHEN\b|\bTIME\b|\bTIMESTAMP\b|\bTO\b|' +
'\bTRANSACTION\b|\bTRIGGER\b|\bTRIM\b|\bTRUE\b|\bTYPE\b|\bUNDER\b|\bUNION\b|\bUNIQUE\b|\bUPDATE\b|' +
'\bUROWID\b|\bUSE\b|\bUSER\b|\bUSING\b|\bVALUE\b|\bVALUES\b|\bVARCHAR\b|\bVARCHAR2\b|\bVARIABLE\b|' +
'\bWHEN\b|\bWHERE\b|\bWHILE\b|\bWITH\b|\bXOR\b|\bYEAR\b'+
')';
C_COMMENTS_PATTERN = '(?is)((/\*.*?\*/)|(--.*?\n))';
begin
Result := TRegEx.Replace(aSqlText, C_LEXEM_PATTERN, '<b>$1</b>');
Result := TRegEx.Replace(Result, C_COMMENTS_PATTERN, '<font color="#008080">$1</font>');
end;
Результат роботи даної функції можна бачити нижче:
select name
from employee e join (select department_id, max(salary) as max_salary /* Comment 1 */ from employee e2 group by department_id) d on d.department_id=e.department_id --Comment 2 where e.salary = d.max_salary
Для виділення xml-тегів та атрибутів потрібно написати трішки складніший регулярний вираз:
const C_XML_PATTERN = '(?is)(<[\?\/]?)(\w+)(\s+\w+?=".*?")?([\?\/]?>)'; C_ATTR_PATTERN = '(?is)\s+((\w+)="(.*?)")';
Але вся незручність підсвічування xml-текстів полягає в тому, що переглядач сприймає xml-теги як частину html-документу, і тому, в кращому разі, просто некоректно відображує документ.
Тому для усунення такої ситуації використовується таблиця перетворень символів між xml та html.
function EncodeXMLStr(const aValue: string): string;
const
HSym : array[0..3] of string = ('&','<','>','"');
TSym : array[0..3] of string = ('&' ,'<' ,'>' ,'"' );
var
i : integer;
sTmp : string;
begin
for i := 1 to Length(aValue) do
if (Ord(aValue[i]) in [32, 40..58]) or (Ord(aValue[i]) >= 65)then
sTmp := Concat(sTmp, aValue[i])
else
begin
case aValue[i] of
'<' : sTmp := Concat(sTmp, '<');
'>' : sTmp := Concat(sTmp, '>');
'&' : sTmp := Concat(sTmp, '&');
'"' : sTmp := Concat(sTmp, '"');
'''' : sTmp := Concat(sTmp, ''');
else
sTmp := Concat(sTmp, '&#', IntToStr(Ord(aValue[i])), ';');
end;
end;
Result := sTmp;
end;
Функція підсвічування xml-текстів з врахуванням перекодування буде виглядати так:
function XmlSyntaxLight(const aXmlText: string): string; const C_XML_PATTERN = '(?is)((<|<)[\?\/]?)(\w+)(\s+\w+?=".*?")?([\?\/]?(>|>))'; C_ATTR_PATTERN = '(?is)\s+((\w+)="(.*?)")'; begin Result := EncodeXMLStr(aXmlText); Result := TRegEx.Replace(Result, C_XML_PATTERN, '<font color="blue">$1</font>' + '<font color="brown">$3</font>' + ' $4' + '<font color="blue">$5</font>'); Result := TRegEx.Replace(Result, C_ATTR_PATTERN, ' <font color="green">$2</font>' + '<font color="navy">="</font>' + '<font color="black">$3</font>' + '<font color="navy">"</font>'); end;
Результат роботи функції:
<?xml version="1.0"?>
<Root >
<COMMON_PARAMS >
<Param18996 Date="41334" DateValue="01.03.2013" TabOrder="0"/>
<Param18997 Date="41435" DateValue="10.06.2013" TabOrder="1"/>
<Param18999 KeyList="1" KeyValue="1" TabOrder="2" Text="Some text"/>
<Param18998 KeyValue="2572" TabOrder="3" Text="Some text"/>
<Param19729 KeyValue="1766" TabOrder="4" Text="Some text"/>
<Param19730 KeyValue="1770" TabOrder="5" Text="Some text"/>
<Param19731 KeyValue="1847" TabOrder="6" Text="Some text"/>
<Param19000 KeyList="630" KeyValue="630" TabOrder="7" Text="630"/>
<Param19727 KeyList="" TabOrder="8" Text="Some text"/>
</COMMON_PARAMS >
</Root >
SyntaxHighlighter, наприклад, це робить так:
<?xml version="1.0"?>
<Root>
<COMMON_PARAMS>
<Param18996 Date="41334" DateValue="01.03.2013" TabOrder="0"/>
<Param18997 Date="41435" DateValue="10.06.2013" TabOrder="1"/>
<Param18999 KeyList="1" KeyValue="1" TabOrder="2" Text="Some text"/>
<Param18998 KeyList="" KeyValue="2572" TabOrder="3" Text="Some text"/>
<Param19729 KeyList="" KeyValue="1766" TabOrder="4" Text="Some text"/>
<Param19730 KeyList="" KeyValue="1770" TabOrder="5" Text="Some text"/>
<Param19731 KeyList="" KeyValue="1847" TabOrder="6" Text="Some text"/>
<Param19000 KeyList="630" KeyValue="630" TabOrder="7" Text="630"/>
<Param19727 KeyList="" TabOrder="8" Text="Some text"/>
</COMMON_PARAMS>
</Root>
Кольорова гама підсвічування - справа смаку (і внутрішніх стандартів) кожного.
Детальніше про роботу з регулярними виразами в Delphi можна прочитати тут.
Немає коментарів :
Дописати коментар