Для цього потрібно підключити в 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 можна прочитати тут.
Немає коментарів :
Дописати коментар