mirror of
https://github.com/doublecmd/doublecmd.git
synced 2026-06-21 09:58:13 +00:00
944 lines
26 KiB
ObjectPascal
944 lines
26 KiB
ObjectPascal
unit dmHigh;
|
|
|
|
{$mode objfpc}{$H+}
|
|
|
|
interface
|
|
|
|
uses
|
|
Classes, SysUtils, Forms, Controls, SynEdit, DCStringHashListUtf8, LCLVersion,
|
|
SynEditHighlighter, SynHighlighterJava, SynHighlighterXML, SynHighlighterLFM,
|
|
SynHighlighterPHP, SynHighlighterSQL, SynHighlighterCss, SynHighlighterPython,
|
|
SynHighlighterVB, SynHighlighterLua, SynUniHighlighter,
|
|
uHighlighters, uColors, fpJson;
|
|
|
|
const
|
|
HighlighterConfig = 'highlighters.xml';
|
|
|
|
type
|
|
|
|
{ TdmHighl }
|
|
|
|
TdmHighl = class(TComponent)
|
|
private
|
|
FTemp: Boolean;
|
|
procedure LoadColors(AConfig: TJSONObject);
|
|
procedure SaveColors(AConfig: TJSONObject);
|
|
procedure LoadUniColors(AConfig: TJSONObject);
|
|
procedure SaveUniColors(AConfig: TJSONObject);
|
|
private
|
|
procedure CreateHighlighters;
|
|
procedure LoadUniHighlighters;
|
|
function GetSyn(Index: Integer): TSynCustomHighlighter;
|
|
function GetSyn(AClass: TSynCustomHighlighterClass): TSynCustomHighlighter;
|
|
procedure CopyHighlighter(SourceHighlighter, TargetHighlighter: TSynCustomHighlighter);
|
|
public
|
|
SynHighlighterList: TStringList;
|
|
SynHighlighterHashList: TStringHashListUtf8;
|
|
public
|
|
constructor Create(AOwner: TComponent; ATemp: Boolean); overload;
|
|
destructor Destroy; override;
|
|
procedure Assign(Source: TPersistent); override;
|
|
function Clone: TdmHighl;
|
|
function GetHighlighter(SynEdit: TCustomSynEdit; const sExtension: string): TSynCustomHighlighter;
|
|
procedure SetHighlighter(SynEdit: TCustomSynEdit; Highlighter: TSynCustomHighlighter);
|
|
property Highlighters[Index: Integer]: TSynCustomHighlighter read GetSyn;
|
|
property SynPlainTextHighlighter: TSynCustomHighlighter index 0 read GetSyn;
|
|
end;
|
|
|
|
{ THighlighters }
|
|
|
|
THighlighters = class
|
|
private
|
|
FStyle: Integer;
|
|
FStyles: array[0..Pred(THEME_COUNT)] of TJSONObject;
|
|
private
|
|
procedure LoadColors; overload;
|
|
procedure SaveColors; overload;
|
|
procedure LoadDefaults(const AKey: String; AConfig: TJSONObject); overload;
|
|
public
|
|
constructor Create;
|
|
destructor Destroy; override;
|
|
procedure UpdateStyle;
|
|
procedure LoadDefaults; overload;
|
|
procedure Load(const FileName: String); overload;
|
|
procedure Save(const FileName: String); overload;
|
|
procedure LoadColors(AConfig: TJSONObject); overload;
|
|
procedure SaveColors(AConfig: TJSONObject); overload;
|
|
end;
|
|
|
|
var
|
|
dmHighl: TdmHighl;
|
|
gHighlighters: THighlighters;
|
|
|
|
implementation
|
|
|
|
uses
|
|
Graphics, SynEditTypes, SynUniClasses, FileUtil, uHighlighterProcs, DCXmlConfig,
|
|
LCLType, DCJsonConfig, uGlobsPaths, DCClassesUtf8, DCOSUtils, DCStrUtils, uLng,
|
|
uGlobs, uSysFolders, SynUniRules;
|
|
|
|
const
|
|
ConfigVersion = 2;
|
|
|
|
const
|
|
DEFAULT_HIGHLIGHTERS: array[0..19] of TSynCustomHighlighterClass =
|
|
(
|
|
TSynPlainTextHighlighter,
|
|
TSynXMLSyn, TSynPerlSynEx, TSynPythonSyn, TSynUNIXShellScriptSynEx,
|
|
TSynBatSynEx, TSynCppSynEx, TSynCssSyn, TSynDiffSynEx,
|
|
TSynHTMLSynEx, TSynIniSynEx, TSynJavaSyn, TSynLFMSyn,
|
|
TSynPasSynEx, TSynPHPSyn, TSynPoSynEx, TSynSQLSyn,
|
|
TSynTeXSynEx, TSynVBSyn, TSynLuaSyn
|
|
);
|
|
|
|
function SynHighlighterSortCompare(List: TStringList; Index1, Index2: Integer): Integer;
|
|
begin
|
|
if CompareStr(List[Index1], rsSynLangPlainText) = 0 then
|
|
Result:= -1
|
|
else if CompareStr(List[Index2], rsSynLangPlainText) = 0 then
|
|
Result:= 1
|
|
else
|
|
Result:= CompareStr(List[Index1], List[Index2]);
|
|
end;
|
|
|
|
{ TdmHighl }
|
|
|
|
procedure TdmHighl.LoadColors(AConfig: TJSONObject);
|
|
var
|
|
I, J, K: Integer;
|
|
AName, AValue: String;
|
|
AValues: TStringArray;
|
|
AList, Attributes: TJSONArray;
|
|
AItem, AttributeNode: TJSONObject;
|
|
Highlighter: TSynCustomHighlighter;
|
|
Attribute: TSynHighlighterAttributes;
|
|
begin
|
|
if AConfig.Find('Highlighters', AList) then
|
|
begin
|
|
for I:= 0 to AList.Count - 1 do
|
|
begin
|
|
AItem:= AList.Objects[I];
|
|
AName:= AItem.Get('Name', EmptyStr);
|
|
Highlighter:= TSynCustomHighlighter(SynHighlighterHashList.Data[AName]);
|
|
if Assigned(Highlighter) and (not (Highlighter is TSynUniSyn)) then
|
|
begin
|
|
Attributes:= AItem.Get('Attributes', TJSONArray(nil));
|
|
if Assigned(Attributes) and (Attributes.Count > 0) then
|
|
begin
|
|
for J:= 0 to Attributes.Count - 1 do
|
|
begin
|
|
AttributeNode:= Attributes.Objects[J];
|
|
AName:= AttributeNode.Get('Name', EmptyStr);
|
|
AValue:= AttributeNode.Get('Value', EmptyStr);
|
|
AValues:= AValue.Split(['|'], TStringSplitOptions.ExcludeEmpty);
|
|
|
|
if (Length(AName) = 0) or (Length(AValues) <> 7) then
|
|
Continue;
|
|
|
|
for K:= 0 to Highlighter.AttrCount - 1 do
|
|
begin
|
|
Attribute:= Highlighter.Attribute[K];
|
|
if SameText(Attribute.StoredName, AName) then
|
|
begin
|
|
Attribute.Background := TColor(StrToIntDef(AValues[0], Integer(Attribute.Background)));
|
|
Attribute.Foreground := TColor(StrToIntDef(AValues[1], Integer(Attribute.Foreground)));
|
|
Attribute.FrameColor := TColor(StrToIntDef(AValues[2], Integer(Attribute.FrameColor)));
|
|
Attribute.FrameStyle := TSynLineStyle(StrToIntDef(AValues[3], Integer(Attribute.FrameStyle)));
|
|
Attribute.FrameEdges := TSynFrameEdges(StrToIntDef(AValues[4], Integer(Attribute.FrameEdges)));
|
|
Attribute.IntegerStyle := StrToIntDef(AValues[5], Attribute.IntegerStyle);
|
|
Attribute.IntegerStyleMask := StrToIntDef(AValues[6], Attribute.IntegerStyleMask);
|
|
Break;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TdmHighl.SaveColors(AConfig: TJSONObject);
|
|
var
|
|
I, J: Integer;
|
|
AValue: String;
|
|
AttributeNode: TJSONObject;
|
|
HighlighterNode: TJSONObject;
|
|
AList, Attributes: TJSONArray;
|
|
Highlighter: TSynCustomHighlighter;
|
|
Attribute: TSynHighlighterAttributes;
|
|
begin
|
|
if AConfig.Find('Highlighters', AList) then
|
|
AList.Clear
|
|
else begin
|
|
AList:= TJSONArray.Create;
|
|
AConfig.Add('Highlighters', AList);
|
|
end;
|
|
|
|
for I := 0 to SynHighlighterList.Count - 1 do
|
|
begin
|
|
if SynHighlighterList.Objects[I] is TSynUniSyn then Continue;
|
|
Highlighter:= TSynCustomHighlighter(SynHighlighterList.Objects[I]);
|
|
|
|
HighlighterNode:= TJSONObject.Create;
|
|
HighlighterNode.Add('Name', Highlighter.LanguageName);
|
|
|
|
Attributes:= TJSONArray.Create;
|
|
|
|
for J:= 0 to Highlighter.AttrCount - 1 do
|
|
begin
|
|
Attribute:= Highlighter.Attribute[J];
|
|
AttributeNode:= TJSONObject.Create;
|
|
AttributeNode.Add('Name', Attribute.StoredName);
|
|
|
|
AValue:= '$' + HexStr(Attribute.Background, 8) + '|' +
|
|
'$' + HexStr(Attribute.Foreground, 8) + '|' +
|
|
'$' + HexStr(Attribute.FrameColor, 8) + '|' +
|
|
IntToStr(Integer(Attribute.FrameStyle)) + '|' +
|
|
IntToStr(Integer(Attribute.FrameEdges)) + '|' +
|
|
IntToStr(Attribute.IntegerStyle) + '|' +
|
|
IntToStr(Attribute.IntegerStyleMask);
|
|
|
|
AttributeNode.Add('Value', AValue);
|
|
|
|
Attributes.Add(AttributeNode);
|
|
end;
|
|
HighlighterNode.Add('Attributes', Attributes);
|
|
AList.Add(HighlighterNode);
|
|
end;
|
|
end;
|
|
|
|
procedure TdmHighl.LoadUniColors(AConfig: TJSONObject);
|
|
var
|
|
I: Integer;
|
|
AName: String;
|
|
AList: TJSONArray;
|
|
AItem: TJSONObject;
|
|
ARanges: TJSONArray;
|
|
Highlighter: TSynCustomHighlighter;
|
|
|
|
function LoadRule(AList: TJSONArray; SymbRule: TSynRule): TJSONObject;
|
|
var
|
|
J: Integer;
|
|
AValue: String;
|
|
begin
|
|
for J:= 0 to AList.Count - 1 do
|
|
begin
|
|
Result:= AList.Objects[J];
|
|
AName:= Result.Get('Name', EmptyStr);
|
|
|
|
if SameStr(AName, SymbRule.Name) then
|
|
begin
|
|
AValue:= Result.Get('Attributes', EmptyStr);
|
|
if Length(AValue) > 0 then
|
|
begin
|
|
SymbRule.Attribs.LoadFromString(AValue);
|
|
end;
|
|
Exit;
|
|
end;
|
|
end;
|
|
Result:= nil;
|
|
end;
|
|
|
|
procedure LoadRange(ARanges: TJSONArray; ARange: TSynRange);
|
|
var
|
|
Index: Integer;
|
|
AList: TJSONArray;
|
|
ARule: TJSONObject;
|
|
begin
|
|
ARule:= LoadRule(ARanges, ARange);
|
|
|
|
if (ARule = nil) then Exit;
|
|
|
|
if (ARange.SetCount > 0) then
|
|
begin
|
|
AList:= ARule.Get('Sets', TJSONArray(nil));
|
|
if Assigned(AList) and (AList.Count > 0) then
|
|
begin
|
|
for Index:= 0 to ARange.SetCount - 1 do
|
|
begin
|
|
LoadRule(AList, ARange.Sets[Index]);
|
|
end;
|
|
end;
|
|
end;
|
|
if (ARange.KeyListCount > 0) then
|
|
begin
|
|
AList:= ARule.Get('KeyLists', TJSONArray(nil));
|
|
if Assigned(AList) and (AList.Count > 0) then
|
|
begin
|
|
for Index:= 0 to ARange.KeyListCount - 1 do
|
|
begin
|
|
LoadRule(AList, ARange.KeyLists[Index]);
|
|
end;
|
|
end;
|
|
end;
|
|
if (ARange.RangeCount > 0) then
|
|
begin
|
|
AList:= ARule.Get('Ranges', TJSONArray(nil));
|
|
if Assigned(AList) and (AList.Count > 0) then
|
|
begin
|
|
for Index:= 0 to ARange.RangeCount - 1 do
|
|
begin
|
|
LoadRange(AList, ARange.Ranges[Index]);
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
begin
|
|
if AConfig.Find('UniHighlighters', AList) then
|
|
begin
|
|
for I:= 0 to AList.Count - 1 do
|
|
begin
|
|
AItem:= AList.Objects[I];
|
|
AName:= AItem.Get('Name', EmptyStr);
|
|
Highlighter:= TSynCustomHighlighter(SynHighlighterHashList.Data[AName]);
|
|
if Assigned(Highlighter) and (Highlighter is TSynUniSyn) then
|
|
begin
|
|
with TSynUniSyn(Highlighter) do
|
|
begin
|
|
ARanges:= AItem.Get('Ranges', TJSONArray(nil));
|
|
if Assigned(ARanges) and (ARanges.Count > 0) then
|
|
begin
|
|
LoadRange(ARanges, MainRules);
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TdmHighl.SaveUniColors(AConfig: TJSONObject);
|
|
var
|
|
I: Integer;
|
|
SynUniSyn: TSynUniSyn;
|
|
|
|
procedure SaveRule(ARules: TJSONArray; SymbRule: TSynRule);
|
|
var
|
|
ARule: TJSONObject;
|
|
begin
|
|
ARule:= TJSONObject.Create;
|
|
ARule.Add('Name', SymbRule.Name);
|
|
ARule.Add('Attributes', SymbRule.Attribs.ToString);
|
|
ARules.Add(ARule);
|
|
end;
|
|
|
|
procedure SaveRange(ARules: TJSONArray; ARange: TSynRange);
|
|
var
|
|
Index: Integer;
|
|
ARule: TJSONObject;
|
|
Sets, KeyLists, Ranges: TJSONArray;
|
|
begin
|
|
ARule:= TJSONObject.Create;
|
|
|
|
ARule.Add('Name', ARange.Name);
|
|
ARule.Add('Attributes', ARange.Attribs.ToString);
|
|
|
|
if (ARange.SetCount > 0) then
|
|
begin
|
|
Sets:= TJSONArray.Create;
|
|
for Index:= 0 to ARange.SetCount - 1 do
|
|
begin
|
|
SaveRule(Sets, ARange.Sets[Index]);
|
|
end;
|
|
ARule.Add('Sets', Sets);
|
|
end;
|
|
|
|
if (ARange.KeyListCount > 0) then
|
|
begin
|
|
KeyLists:= TJSONArray.Create;
|
|
for Index:= 0 to ARange.KeyListCount - 1 do
|
|
begin
|
|
SaveRule(KeyLists, ARange.KeyLists[Index]);
|
|
end;
|
|
ARule.Add('KeyLists', KeyLists);
|
|
end;
|
|
|
|
if (ARange.RangeCount > 0) then
|
|
begin
|
|
Ranges:= TJSONArray.Create;
|
|
for Index:= 0 to ARange.RangeCount - 1 do
|
|
begin
|
|
SaveRange(Ranges, ARange.Ranges[Index]);
|
|
end;
|
|
ARule.Add('Ranges', Ranges);
|
|
end;
|
|
|
|
ARules.Add(ARule);
|
|
end;
|
|
|
|
procedure SaveHighlighter(AList: TJSONArray);
|
|
var
|
|
AItem: TJSONObject;
|
|
ARules: TJSONArray;
|
|
begin
|
|
AItem:= TJSONObject.Create;
|
|
AItem.Add('Name', SynUniSyn.Info.General.Name);
|
|
|
|
ARules:= TJSONArray.Create;
|
|
SaveRange(ARules, SynUniSyn.MainRules);
|
|
AItem.Add('Ranges', ARules);
|
|
|
|
AList.Add(AItem);
|
|
end;
|
|
|
|
var
|
|
AList: TJSONArray;
|
|
begin
|
|
if AConfig.Find('UniHighlighters', AList) then
|
|
AList.Clear
|
|
else begin
|
|
AList:= TJSONArray.Create;
|
|
AConfig.Add('UniHighlighters', AList);
|
|
end;
|
|
|
|
for I := 0 to SynHighlighterList.Count - 1 do
|
|
begin
|
|
if SynHighlighterList.Objects[I] is TSynUniSyn then
|
|
begin
|
|
SynUniSyn:= TSynUniSyn(SynHighlighterList.Objects[I]);
|
|
//if SynUniSyn.Tag < 0 then
|
|
begin
|
|
SaveHighlighter(AList);
|
|
SynUniSyn.Tag:= 0;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TdmHighl.LoadUniHighlighters;
|
|
var
|
|
AName: String;
|
|
I, Index: Integer;
|
|
AList: TStringList;
|
|
AFileName: String = '';
|
|
ACache: TStringListEx;
|
|
HighLighter: TSynCustomHighlighter;
|
|
begin
|
|
ACache:= TStringListEx.Create;
|
|
ACache.CaseSensitive:= FileNameCaseSensitive;
|
|
if not gUseConfigInProgramDir then begin
|
|
AFileName:= IncludeTrailingBackslash(GetAppDataDir) + 'highlighters' + ';';
|
|
end;
|
|
AList:= FindAllFiles(AFileName + gpHighPath, '*.hgl');
|
|
for I:= 0 to AList.Count - 1 do
|
|
begin
|
|
AFileName:= ExtractFileName(AList[I]);
|
|
if ACache.IndexOf(AFileName) < 0 then
|
|
begin
|
|
HighLighter:= TSynUniSyn.Create(Self);
|
|
try
|
|
TSynUniSyn(HighLighter).LoadFromFile(AList[I]);
|
|
AName:= TSynUniSyn(HighLighter).Info.General.Name;
|
|
Index:= SynHighlighterList.IndexOf(AName);
|
|
if (Index < 0) then
|
|
SynHighlighterList.AddObject(AName, Highlighter)
|
|
else begin
|
|
// Add duplicate external highlighter
|
|
if SynHighlighterList.Objects[Index] is TSynUniSyn then
|
|
begin
|
|
AName:= AName + ' #' + IntToStr(I);
|
|
SynHighlighterList.AddObject(AName, Highlighter);
|
|
end
|
|
// Replace built-in highlighter
|
|
else begin
|
|
SynHighlighterList.Objects[Index].Free;
|
|
SynHighlighterList.Objects[Index]:= Highlighter;
|
|
end;
|
|
end;
|
|
ACache.Add(AFileName);
|
|
except
|
|
FreeAndNil(HighLighter);
|
|
end;
|
|
end;
|
|
end;
|
|
AList.Free;
|
|
ACache.Free;
|
|
end;
|
|
|
|
function TdmHighl.GetSyn(Index: Integer): TSynCustomHighlighter;
|
|
begin
|
|
Result:= TSynCustomHighlighter(SynHighlighterList.Objects[Index]);
|
|
end;
|
|
|
|
function TdmHighl.GetSyn(AClass: TSynCustomHighlighterClass): TSynCustomHighlighter;
|
|
var
|
|
Index: Integer;
|
|
begin
|
|
for Index:= 0 to SynHighlighterList.Count - 1 do
|
|
begin
|
|
if SynHighlighterList.Objects[Index] is AClass then
|
|
Exit(TSynCustomHighlighter(SynHighlighterList.Objects[Index]));
|
|
end;
|
|
Result:= nil;
|
|
end;
|
|
|
|
procedure TdmHighl.CreateHighlighters;
|
|
var
|
|
I: Integer;
|
|
Highlighter: TSynCustomHighlighter;
|
|
begin
|
|
for I:= 0 to High(DEFAULT_HIGHLIGHTERS) do
|
|
begin
|
|
{$PUSH}{$HINTS OFF}{$WARNINGS OFF}
|
|
Highlighter:= DEFAULT_HIGHLIGHTERS[I].Create(Self);
|
|
{$POP}
|
|
Highlighter.Tag:= PtrInt(I <> 0);
|
|
SynHighlighterList.AddObject(HighLighter.LanguageName, HighLighter);
|
|
end;
|
|
|
|
LoadUniHighlighters;
|
|
|
|
for I:= 0 to SynHighlighterList.Count - 1 do
|
|
begin
|
|
HighLighter:= TSynCustomHighlighter(SynHighlighterList.Objects[I]);
|
|
SynHighlighterHashList.Add(HighLighter.LanguageName, HighLighter);
|
|
if not (Highlighter is TSynUniSyn) then
|
|
begin
|
|
with HighLighter.AddSpecialAttribute(rsSynDefaultText, SYNS_XML_DefaultText) do
|
|
begin
|
|
Background:= clWindow;
|
|
Foreground:= clWindowText;
|
|
end;
|
|
end;
|
|
end;
|
|
SynHighlighterList.CustomSort(@SynHighlighterSortCompare);
|
|
end;
|
|
|
|
constructor TdmHighl.Create(AOwner: TComponent; ATemp: Boolean);
|
|
begin
|
|
FTemp:= ATemp;
|
|
SynHighlighterList:= TStringList.Create;
|
|
SynHighlighterHashList:= TStringHashListUtf8.Create(True);
|
|
if not FTemp then CreateHighlighters;
|
|
inherited Create(AOwner);
|
|
end;
|
|
|
|
destructor TdmHighl.Destroy;
|
|
begin
|
|
inherited Destroy;
|
|
SynHighlighterList.Free;
|
|
SynHighlighterHashList.Free;
|
|
end;
|
|
|
|
procedure TdmHighl.CopyHighlighter(SourceHighlighter, TargetHighlighter: TSynCustomHighlighter);
|
|
var
|
|
J: Integer;
|
|
begin
|
|
if SourceHighlighter is TSynUniSyn then
|
|
TSynUniSyn(TargetHighlighter).Assign(TSynUniSyn(SourceHighlighter))
|
|
else begin
|
|
TargetHighlighter.Tag:= SourceHighlighter.Tag;
|
|
TargetHighlighter.DefaultFilter:= SourceHighlighter.DefaultFilter;
|
|
for J:= 0 to SourceHighlighter.AttrCount - 1 do
|
|
begin
|
|
TargetHighlighter.Attribute[J].Assign(SourceHighlighter.Attribute[J]);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TdmHighl.Assign(Source: TPersistent);
|
|
var
|
|
I: Integer;
|
|
Highl: TdmHighl absolute Source;
|
|
begin
|
|
for I:= 0 to SynHighlighterList.Count - 1 do
|
|
begin
|
|
CopyHighlighter(TSynCustomHighlighter(Highl.SynHighlighterList.Objects[I]),
|
|
TSynCustomHighlighter(SynHighlighterList.Objects[I])
|
|
);
|
|
end;
|
|
end;
|
|
|
|
function TdmHighl.Clone: TdmHighl;
|
|
var
|
|
I: Integer;
|
|
AClass: TSynCustomHighlighterClass;
|
|
Highlighter: TSynCustomHighlighter;
|
|
SourceHighlighter: TSynCustomHighlighter;
|
|
begin
|
|
Result:= TdmHighl.Create(Application, True);
|
|
|
|
for I:= 0 to SynHighlighterList.Count - 1 do
|
|
begin
|
|
SourceHighlighter:= TSynCustomHighlighter(SynHighlighterList.Objects[I]);
|
|
AClass:= TSynCustomHighlighterClass(SourceHighlighter.ClassType);
|
|
{$PUSH}{$HINTS OFF}{$WARNINGS OFF}
|
|
Highlighter:= AClass.Create(Result);
|
|
{$POP}
|
|
if not (Highlighter is TSynUniSyn) then
|
|
begin
|
|
with HighLighter.AddSpecialAttribute(rsSynDefaultText, SYNS_XML_DefaultText) do
|
|
begin
|
|
Background:= clWindow;
|
|
Foreground:= clWindowText;
|
|
end;
|
|
end;
|
|
CopyHighlighter(SourceHighlighter, Highlighter);
|
|
Result.SynHighlighterHashList.Add(Highlighter.LanguageName, HighLighter);
|
|
Result.SynHighlighterList.AddObject(Highlighter.LanguageName, Highlighter);
|
|
end;
|
|
end;
|
|
|
|
function TdmHighl.GetHighlighter(SynEdit: TCustomSynEdit;
|
|
const sExtension: string): TSynCustomHighlighter;
|
|
var
|
|
Extension: String;
|
|
begin
|
|
Result:= GetHighlighterFromFileExt(SynHighlighterList, sExtension);
|
|
// Determine file type by content
|
|
if (Result = nil) and (SynEdit.Lines.Count > 0) then
|
|
begin
|
|
Extension:= SynEdit.Lines[0];
|
|
if StrBegins(Extension, '<?xml') then
|
|
Result:= GetSyn(TSynXMLSyn)
|
|
else if StrBegins(Extension, '#!') then
|
|
begin
|
|
// Unix shell script
|
|
if (Pos('sh', Extension) > 0) then
|
|
Result:= GetSyn(TSynUNIXShellScriptSynEx)
|
|
// Python script
|
|
else if (Pos('python', Extension) > 0) then
|
|
Result:= GetSyn(TSynPythonSyn)
|
|
// Perl script
|
|
else if (Pos('perl', Extension) > 0) then
|
|
Result:= GetSyn(TSynPerlSynEx);
|
|
end;
|
|
end;
|
|
// Default syntax highlighter
|
|
if (Result = nil) then Result:= SynPlainTextHighlighter;
|
|
end;
|
|
|
|
procedure TdmHighl.SetHighlighter(SynEdit: TCustomSynEdit; Highlighter: TSynCustomHighlighter);
|
|
var
|
|
I: LongInt;
|
|
Attribute: TSynHighlighterAttributes;
|
|
begin
|
|
if (Highlighter is TSynPlainTextHighlighter) then
|
|
SynEdit.Highlighter:= nil
|
|
else begin
|
|
SynEdit.Highlighter:= Highlighter;
|
|
end;
|
|
|
|
if Highlighter is TSynUniSyn then
|
|
Attribute:= TSynUniSyn(Highlighter).MainRules.Attribs
|
|
else begin
|
|
I:= Highlighter.AttrCount - 1;
|
|
repeat
|
|
Attribute:= Highlighter.Attribute[I];
|
|
Dec(I);
|
|
until (I < 0) or SameText(Attribute.StoredName, SYNS_XML_DefaultText);
|
|
end;
|
|
|
|
SynEdit.Color:= Attribute.Background;
|
|
SynEdit.Font.Color:= Attribute.Foreground;
|
|
end;
|
|
|
|
{ THighlighters }
|
|
|
|
procedure THighlighters.LoadColors;
|
|
var
|
|
AStyle: TJSONObject;
|
|
begin
|
|
AStyle:= FStyles[FStyle];
|
|
dmHighl.LoadColors(AStyle);
|
|
dmHighl.LoadUniColors(AStyle);
|
|
end;
|
|
|
|
procedure THighlighters.SaveColors;
|
|
var
|
|
AStyle: TJSONObject;
|
|
begin
|
|
AStyle:= FStyles[FStyle];
|
|
dmHighl.SaveColors(AStyle);
|
|
dmHighl.SaveUniColors(AStyle);
|
|
end;
|
|
|
|
procedure THighlighters.LoadDefaults(const AKey: String; AConfig: TJSONObject);
|
|
var
|
|
AName: String;
|
|
I, J: Integer;
|
|
Theme: TJSONObject;
|
|
Themes: TJSONArray;
|
|
|
|
procedure LoadItem(Index: Integer);
|
|
var
|
|
Idx: Integer;
|
|
begin
|
|
Idx:= Theme.IndexOfName(AKey);
|
|
if (Idx >= 0) then begin
|
|
FStyles[Index].Arrays[AKey]:= Theme.Extract(Idx) as TJSONArray;
|
|
end;
|
|
end;
|
|
|
|
begin
|
|
if AConfig.Find('Styles', Themes) then
|
|
begin
|
|
for I:= 0 to Themes.Count - 1 do
|
|
begin
|
|
Theme:= Themes.Objects[I];
|
|
AName:= Theme.Get('Name', EmptyStr);
|
|
for J:= 0 to High(THEME_NAME) do
|
|
begin
|
|
if (AName = THEME_NAME[J]) then
|
|
begin
|
|
LoadItem(J);
|
|
Break;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
constructor THighlighters.Create;
|
|
begin
|
|
FStyle:= TColorThemes.StyleIndex;
|
|
dmHighl:= TdmHighl.Create(Application, False);
|
|
LoadDefaults;
|
|
end;
|
|
|
|
destructor THighlighters.Destroy;
|
|
var
|
|
Index: Integer;
|
|
begin
|
|
inherited Destroy;
|
|
|
|
for Index:= 0 to High(FStyles) do
|
|
begin
|
|
FStyles[Index].Free;
|
|
end;
|
|
end;
|
|
|
|
procedure THighlighters.UpdateStyle;
|
|
var
|
|
ANewStyle: Integer;
|
|
begin
|
|
ANewStyle := TColorThemes.StyleIndex;
|
|
|
|
if FStyle <> ANewStyle then
|
|
begin
|
|
SaveColors;
|
|
FStyle:= ANewStyle;
|
|
LoadColors;
|
|
end;
|
|
end;
|
|
|
|
procedure THighlighters.LoadDefaults;
|
|
var
|
|
Index: Integer;
|
|
ARoot: TJSONObject;
|
|
AStream: TResourceStream;
|
|
begin
|
|
for Index:= 0 to High(FStyles) do
|
|
begin
|
|
FStyles[Index]:= TJSONObject.Create;
|
|
FStyles[Index].Add('UniHighlighters', TJSONArray.Create);
|
|
end;
|
|
AStream:= TResourceStream.Create(HInstance, 'HIGHLIGHTERS', RT_RCDATA);
|
|
try
|
|
ARoot:= GetJSON(AStream, True) as TJSONObject;
|
|
try
|
|
LoadDefaults('Highlighters', ARoot);
|
|
finally
|
|
ARoot.Free;
|
|
end;
|
|
finally
|
|
AStream.Free;
|
|
end;
|
|
if mbFileExists(gpHighPath + 'highlighters.json') then
|
|
try
|
|
with TJsonConfig.Create do
|
|
try
|
|
LoadFromFile(gpHighPath + 'highlighters.json');
|
|
LoadDefaults('UniHighlighters', Root);
|
|
finally
|
|
Free;
|
|
end;
|
|
except
|
|
// Ignore
|
|
end;
|
|
LoadColors;
|
|
end;
|
|
|
|
procedure THighlighters.LoadColors(AConfig: TJSONObject);
|
|
var
|
|
AName: String;
|
|
I, J: Integer;
|
|
Theme: TJSONObject;
|
|
Themes: TJSONArray;
|
|
|
|
procedure LoadItem(const AKey: String; Index: Integer);
|
|
var
|
|
AItem: TJSONArray;
|
|
begin
|
|
if Theme.Find(AKey, AItem) then
|
|
begin
|
|
FStyles[Index].Arrays[AKey]:= AItem.Clone as TJSONArray;
|
|
end;
|
|
end;
|
|
|
|
begin
|
|
if AConfig.Find('Styles', Themes) then
|
|
begin
|
|
for I:= 0 to Themes.Count - 1 do
|
|
begin
|
|
Theme:= Themes.Objects[I];
|
|
AName:= Theme.Get('Name', EmptyStr);
|
|
for J:= 0 to High(THEME_NAME) do
|
|
begin
|
|
if (AName = THEME_NAME[J]) then
|
|
begin
|
|
LoadItem('Highlighters', J);
|
|
LoadItem('UniHighlighters', J);
|
|
Break;
|
|
end;
|
|
end;
|
|
end;
|
|
LoadColors;
|
|
end;
|
|
end;
|
|
|
|
procedure THighlighters.SaveColors(AConfig: TJSONObject);
|
|
var
|
|
AName: String;
|
|
I, J: Integer;
|
|
Theme: TJSONObject;
|
|
Themes: TJSONArray;
|
|
|
|
procedure SaveItem(const AKey: String; Index: Integer);
|
|
var
|
|
AItem: TJSONArray;
|
|
begin
|
|
if FStyles[Index].Find(AKey, AItem) then
|
|
begin
|
|
Theme.Arrays[AKey]:= AItem.Clone as TJSONArray;
|
|
end;
|
|
end;
|
|
|
|
begin
|
|
SaveColors;
|
|
|
|
if AConfig.Find('Styles', Themes) then
|
|
begin
|
|
for I:= 0 to Themes.Count - 1 do
|
|
begin
|
|
Theme:= Themes.Objects[I];
|
|
AName:= Theme.Get('Name', EmptyStr);
|
|
for J:= 0 to High(THEME_NAME) do
|
|
begin
|
|
if (AName = THEME_NAME[J]) then
|
|
begin
|
|
SaveItem('Highlighters', J);
|
|
SaveItem('UniHighlighters', J);
|
|
Break;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure THighlighters.Load(const FileName: String);
|
|
var
|
|
J: LongInt;
|
|
Config: TXmlConfig;
|
|
AVersion: Integer = ConfigVersion;
|
|
Highlighter: TSynCustomHighlighter;
|
|
LanguageName, AttributeName: String;
|
|
Attribute: TSynHighlighterAttributes;
|
|
Root, FormNode, AttributeNode: TXmlNode;
|
|
begin
|
|
Config := TXmlConfig.Create(FileName, True);
|
|
try
|
|
Root := Config.FindNode(Config.RootNode, 'Highlighters');
|
|
if Assigned(Root) then
|
|
begin
|
|
AVersion := Config.GetAttr(Root, 'Version', ConfigVersion);
|
|
FormNode := Config.FindNode(Root, 'Highlighter');
|
|
if Assigned(FormNode) then
|
|
begin
|
|
while Assigned(FormNode) do
|
|
begin
|
|
LanguageName:= Config.GetAttr(FormNode, 'Name', EmptyStr);
|
|
Highlighter:= TSynCustomHighlighter(dmHighl.SynHighlighterHashList.Data[LanguageName]);
|
|
if Assigned(Highlighter) then
|
|
begin
|
|
Highlighter.Tag := Config.GetAttr(FormNode, 'Tag', 1);
|
|
Highlighter.DefaultFilter:= Config.GetValue(FormNode, 'DefaultFilter', Highlighter.DefaultFilter);
|
|
// Import colors from old format
|
|
if AVersion < 2 then
|
|
begin
|
|
AttributeNode := Config.FindNode(FormNode, 'Attribute');
|
|
if Assigned(AttributeNode) then
|
|
begin
|
|
while Assigned(AttributeNode) do
|
|
begin
|
|
AttributeName:= Config.GetAttr(AttributeNode, 'Name', EmptyStr);
|
|
for J:= 0 to Highlighter.AttrCount - 1 do
|
|
begin
|
|
Attribute:= Highlighter.Attribute[J];
|
|
if SameText(Attribute.StoredName, AttributeName) or SameText(Attribute.Name, AttributeName) then
|
|
begin
|
|
Attribute.Style := TFontStyles(Config.GetValue(AttributeNode, 'Style', Integer(Attribute.Style)));
|
|
Attribute.StyleMask := TFontStyles(Config.GetValue(AttributeNode, 'StyleMask', Integer(Attribute.StyleMask)));
|
|
Attribute.Foreground := TColor(Config.GetValue(AttributeNode, 'Foreground', Integer(Attribute.Foreground)));
|
|
Attribute.Background := TColor(Config.GetValue(AttributeNode, 'Background', Integer(Attribute.Background)));
|
|
Attribute.FrameColor := TColor(Config.GetValue(AttributeNode, 'FrameColor', Integer(Attribute.FrameColor)));
|
|
Attribute.FrameStyle := TSynLineStyle(Config.GetValue(AttributeNode, 'FrameStyle', Integer(Attribute.FrameStyle)));
|
|
Attribute.FrameEdges := TSynFrameEdges(Config.GetValue(AttributeNode, 'FrameEdges', Integer(Attribute.FrameEdges)));
|
|
Break;
|
|
end;
|
|
end;
|
|
AttributeNode := AttributeNode.NextSibling;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
FormNode := FormNode.NextSibling;
|
|
end;
|
|
end;
|
|
// Import colors from old format
|
|
if AVersion < 2 then SaveColors;
|
|
// Create config backup
|
|
if (AVersion < ConfigVersion) then
|
|
try
|
|
Config.WriteToFile(FileName + '.bak');
|
|
except
|
|
// Ignore
|
|
end;
|
|
end;
|
|
finally
|
|
Config.Free;
|
|
end;
|
|
end;
|
|
|
|
procedure THighlighters.Save(const FileName: String);
|
|
var
|
|
I: LongInt;
|
|
Config: TXmlConfig;
|
|
Root, FormNode: TXmlNode;
|
|
Highlighter: TSynCustomHighlighter;
|
|
begin
|
|
Config := TXmlConfig.Create;
|
|
try
|
|
Config.FileName := FileName;
|
|
Root := Config.FindNode(Config.RootNode, 'Highlighters', True);
|
|
Config.ClearNode(Root);
|
|
Config.SetAttr(Root, 'Version', ConfigVersion);
|
|
with dmHighl do
|
|
begin
|
|
for I := 0 to SynHighlighterList.Count - 1 do
|
|
begin
|
|
Highlighter := Highlighters[I];
|
|
FormNode := Config.AddNode(Root, 'Highlighter');
|
|
Config.SetAttr(FormNode, 'Tag', Highlighter.Tag);
|
|
Config.SetAttr(FormNode, 'Name', Highlighter.LanguageName);
|
|
Config.SetValue(FormNode, 'DefaultFilter', Highlighter.DefaultFilter);
|
|
end;
|
|
end;
|
|
Config.Save;
|
|
finally
|
|
Config.Free;
|
|
end;
|
|
end;
|
|
|
|
end.
|
|
|