synedit是一个优秀的代码显示控件,自带高亮等普通IDE相关功能,具体自己百度。
一、发现问题:
最近想做一个python显示小工具,synedit+SynPythonSyn在使用高亮时,部分关键字总是不行,而有些又可以,好奇怪啊。(这里注意,我安装的synedit,是玩Unigui控件里带的,反正应该也一样)
二、分析问题
于是就打开uSynHighlighterPython.pas,分析,发现关键字都在里面,并且都创建时都添加到关键字里面了。
// List of keywords
KEYWORDCOUNT = 29;
KEYWORDS: array [1..KEYWORDCOUNT] of UnicodeString =
(
'and',
'assert',
'break',
'class',
'continue',
'def',
'del',
'elif',
'else',
'except',
'exec',
'finally',
'for',
'from',
'global',
'if',
'import',
'in',
'is',
'lambda',
'not',
'or',
'pass',
'print',
'raise',
'return',
'try',
'while',
'yield'
);
for f := 1 to KEYWORDCOUNT do
GlobalKeywords.AddObject(KEYWORDS[f], Pointer(Ord(tkKey)));
并在控件创建时已经加载,也没少
于是,检查匹配代码
SetString(s, fToIdent, fStringLen);
if FKeywords.Find(s, i) then
//下断点,追进去,可能是控件内,C++Builder在显示控件内变量时不是很准确,不过代码还是能看到。
function TStringList.Find(const S: string; var Index: Integer): Boolean;
var
L, H, I, C: Integer;
begin
Result := False;
L := 0;
H := FCount - 1;
while L <= H do
begin
I := (L + H) shr 1;
C := CompareStrings(FList[I].FString, S);
if C < 0 then L := I + 1 else
begin
H := I - 1;
if C = 0 then
begin
Result := True;
if Duplicates <> dupAccept then L := I;
end;
end;
end;
Index := L;
end;
分析这个函数,这个函数不是一条条查询,而是二分查找法,但这种查找法需要一个前提条件,就是被查找列表必须是一个有序列表,前面都没有排序啊
看来时漏了一个排序函数Sort()
三、验证问题
怎么验证呢?想办法把列表内容显示出,看看有无相关接口。
打开 uSynEditHighlighter.hpp,
protected:
__property System::Classes::TStringList* Keywords = {read=FKeywords};
看看,能否在C++Builder里
TStringLIst *slt=USynPythonSyn1->Keywords;
提示,protected模式不行,于是就剪切到public下,结果编译通过了,运行显示所有关键字都在,不过顺序时输入顺序(没排序)
四、解决问题
如果不怕麻烦,在源文件里增加一个排序函数
GlobalKeywords.Sort();
可能本人比较懒,不想重新编译安装,既然关键字列表可以引出来,那是否可以在程序初始化时,给他排下顺序,于是说干就干,结果通过了。
USynPythonSyn1->Keywords->Sort();
五、解决小结
uSynEditHighlighter.hpp里将Keywords属性放在public里
__property System::Classes::TStringList* Keywords = {read=FKeywords};
然后在自己程序的初始化里增加一个排序语句
USynPythonSyn1->Keywords->Sort();