mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-05-01 19:23:44 +02:00
537 lines
14 KiB
ObjectPascal
537 lines
14 KiB
ObjectPascal
{(*}
|
|
(*------------------------------------------------------------------------------
|
|
Delphi Code formatter source code
|
|
|
|
The Original Code is Settings.pas, released April 2000.
|
|
The Initial Developer of the Original Code is Anthony Steele.
|
|
Portions created by Anthony Steele are Copyright (C) 1999-2008 Anthony Steele.
|
|
All Rights Reserved.
|
|
Contributor(s): Anthony Steele.
|
|
|
|
The contents of this file are subject to the Mozilla Public License Version 1.1
|
|
(the "License"). you may not use this file except in compliance with the License.
|
|
You may obtain a copy of the License at http://www.mozilla.org/NPL/
|
|
|
|
Software distributed under the License is distributed on an "AS IS" basis,
|
|
WITHOUT WARRANTY OF ANY KIND, either express or implied.
|
|
See the License for the specific language governing rights and limitations
|
|
under the License.
|
|
|
|
Alternatively, the contents of this file may be used under the terms of
|
|
the GNU General Public License Version 2 or later (the "GPL")
|
|
See http://www.gnu.org/licenses/gpl.html
|
|
------------------------------------------------------------------------------*)
|
|
{*)}
|
|
|
|
unit JcfSettings;
|
|
|
|
{ this is the settings on how to parse. As of 2.0 this is always from a file
|
|
The file name is stored in registry
|
|
This allows centralised settings on a shared dir }
|
|
|
|
{$I JcfGlobal.inc}
|
|
|
|
interface
|
|
|
|
uses
|
|
{ local }
|
|
SetObfuscate, SetClarify,
|
|
SetIndent, SetSpaces, SetReturns,
|
|
SetComments, SetCaps, SetWordList,
|
|
SetAlign, SetReplace, SetUses, SetPreProcessor,
|
|
SettingsStream, SetTransform, SetAsm,
|
|
JcfVersionConsts; //, IDEOptionsIntf;
|
|
|
|
type
|
|
|
|
{ TFormatSettings }
|
|
|
|
//TFormatSettings = class(TAbstractIDEEnvironmentOptions)
|
|
TFormatSettings = class(TObject)
|
|
private
|
|
fcObfuscate: TSetObfuscate;
|
|
fcClarify: TSetClarify;
|
|
fcSpaces: TSetSpaces;
|
|
fcIndent: TSetIndent;
|
|
fcReturns: TSetReturns;
|
|
fcComments: TSetComments;
|
|
|
|
fcCaps: TSetCaps;
|
|
fcSpecificWordCaps: TSetWordList;
|
|
fcIdentifierCaps: TSetWordList;
|
|
fcNotIdentifierCaps: TSetWordList;
|
|
fcUnitNameCaps: TSetWordList;
|
|
|
|
fcSetAsm: TSetAsm;
|
|
|
|
fcPreProcessor: TSetPreProcessor;
|
|
fcAlign: TSetAlign;
|
|
fcUses: TSetUses;
|
|
|
|
fcReplace: TSetReplace;
|
|
|
|
fcTransform: TSetTransform;
|
|
|
|
fbWriteOnExit: boolean;
|
|
fbHasRead: boolean;
|
|
fbDirty: boolean;
|
|
|
|
fsDescription: string;
|
|
fdtWriteDateTime: TDateTime;
|
|
fsWriteVersion: string;
|
|
|
|
procedure FromStream(const pcStream: TSettingsInput);
|
|
public
|
|
constructor Create(const pbReadRegFile: boolean);
|
|
destructor Destroy; override;
|
|
//class function GetGroupCaption: String; override;
|
|
//class function GetInstance: TAbstractIDEOptions; override;
|
|
//procedure DoAfterWrite({%H-}Restore: boolean); override;
|
|
|
|
procedure Read;
|
|
procedure ReadFromFile(const psFileName: string; const pbMustExist: boolean);
|
|
procedure ReadDefaults;
|
|
procedure Write;
|
|
|
|
procedure MakeConsistent;
|
|
|
|
procedure ToStream(const pcStream: TSettingsOutput);
|
|
|
|
property Description: string Read fsDescription Write fsDescription;
|
|
property WriteDateTime: TDateTime Read fdtWriteDateTime Write fdtWriteDateTime;
|
|
property WriteVersion: string Read fsWriteVersion Write fsWriteVersion;
|
|
|
|
property Obfuscate: TSetObfuscate Read fcObfuscate;
|
|
property Clarify: TSetClarify Read fcClarify;
|
|
property Indent: TSetIndent Read fcIndent;
|
|
property Spaces: TSetSpaces Read fcSpaces;
|
|
property Returns: TSetReturns Read fcReturns;
|
|
property Comments: TSetComments Read fcComments;
|
|
|
|
property Caps: TSetCaps Read fcCaps;
|
|
property SpecificWordCaps: TSetWordList Read fcSpecificWordCaps;
|
|
property IdentifierCaps: TSetWordList Read fcIdentifierCaps;
|
|
property NotIdentifierCaps: TSetWordList Read fcNotIdentifierCaps;
|
|
property UnitNameCaps: TSetWordList Read fcUnitNameCaps;
|
|
property SetAsm: TSetAsm Read fcSetAsm;
|
|
|
|
property PreProcessor: TSetPreProcessor Read fcPreProcessor;
|
|
|
|
|
|
property Align: TSetAlign Read fcAlign;
|
|
property Replace: TSetReplace Read fcReplace;
|
|
property UsesClause: TSetUses Read fcUses;
|
|
|
|
property Transform: TSetTransform read fcTransform;
|
|
|
|
property WriteOnExit: boolean Read fbWriteOnExit Write fbWriteOnExit;
|
|
property Dirty: boolean Read fbDirty Write fbDirty;
|
|
property HasRead: boolean read fbHasRead write fbHasRead;
|
|
end;
|
|
|
|
function FormattingSettings: TFormatSettings;
|
|
|
|
// create from a settings file
|
|
function FormatSettingsFromFile(const psFileName: string): TFormatSettings;
|
|
|
|
var
|
|
JCFOptionsGroup: Integer;
|
|
const
|
|
JCFOptionFormatFile = 1;
|
|
JCFOptionObfuscate = 2;
|
|
JCFOptionClarify = 3;
|
|
JCFOptionSpaces = 4;
|
|
JCFOptionIndentation = 5;
|
|
JCFOptionBlankLines = 6;
|
|
JCFOptionAlign = 7;
|
|
JCFOptionLongLines = 8;
|
|
JCFOptionReturns = 9;
|
|
JCFOptionCaseBlocks = 10;
|
|
JCFOptionBlocks = 11;
|
|
JCFOptionCompilerDirectives = 12;
|
|
JCFOptionComments = 13;
|
|
JCFOptionWarnings = 14;
|
|
JCFOptionObjectPascal = 15;
|
|
JCFOptionAnyWord = 16;
|
|
JCFOptionIdentifiers = 17;
|
|
JCFOptionNotIdentifiers = 18;
|
|
JCFOptionUnitName = 19;
|
|
JCFOptionFindAndReplace = 20;
|
|
JCFOptionUses = 21;
|
|
JCFOptionBasic = 22;
|
|
JCFOptionTransform = 23;
|
|
JCFOptionAsm = 24;
|
|
JCFOptionPreProcessor = 25;
|
|
|
|
const
|
|
GUI_PAD = 3;
|
|
|
|
implementation
|
|
|
|
uses
|
|
{ delphi }
|
|
{$IFNDEF FPC}Windows,{$ELSE}LazFileUtils, LazUTF8,{$ENDIF} SysUtils, Dialogs,
|
|
{ local }
|
|
JcfStringUtils,
|
|
JcfSetBase,
|
|
JcfRegistrySettings,
|
|
jcfuiconsts in '../IdePlugin/lazarus/jcfuiconsts.pas';
|
|
|
|
|
|
constructor TFormatSettings.Create(const pbReadRegFile: boolean);
|
|
begin
|
|
inherited Create();
|
|
|
|
fcObfuscate := TSetObfuscate.Create;
|
|
fcClarify := TSetClarify.Create;
|
|
fcIndent := TSetIndent.Create;
|
|
fcSpaces := TSetSpaces.Create;
|
|
fcReturns := TSetReturns.Create;
|
|
|
|
fcComments := TSetComments.Create;
|
|
|
|
fcCaps := TSetCaps.Create;
|
|
fcSpecificWordCaps := TSetWordList.Create('SpecificWordCaps');
|
|
fcIdentifierCaps := TSetWordList.Create('Identifiers');
|
|
fcNotIdentifierCaps := TSetWordList.Create('NotIdent');
|
|
fcUnitNameCaps := TSetWordList.Create('UnitNameCaps');
|
|
|
|
fcSetAsm := TSetAsm.Create();
|
|
|
|
fcPreProcessor := TSetPreProcessor.Create;
|
|
|
|
fcAlign := TSetAlign.Create;
|
|
fcReplace := TSetReplace.Create;
|
|
fcUses := TSetUses.Create;
|
|
fcTransform := TSetTransform.Create;
|
|
|
|
if pbReadRegFile then
|
|
begin
|
|
Read;
|
|
end;
|
|
|
|
fbWriteOnExit := True;
|
|
fbDirty := False;
|
|
end;
|
|
|
|
destructor TFormatSettings.Destroy;
|
|
begin
|
|
if WriteOnExit then
|
|
Write;
|
|
|
|
FreeAndNil(fcObfuscate);
|
|
FreeAndNil(fcClarify);
|
|
FreeAndNil(fcIndent);
|
|
FreeAndNil(fcSpaces);
|
|
FreeAndNil(fcReturns);
|
|
FreeAndNil(fcComments);
|
|
|
|
FreeAndNil(fcCaps);
|
|
FreeAndNil(fcSpecificWordCaps);
|
|
FreeAndNil(fcIdentifierCaps);
|
|
FreeAndNil(fcNotIdentifierCaps);
|
|
FreeAndNil(fcUnitNameCaps);
|
|
FreeAndNil(fcSetAsm);
|
|
|
|
FreeAndNil(fcPreProcessor);
|
|
|
|
FreeAndNil(fcReplace);
|
|
FreeAndNil(fcAlign);
|
|
FreeAndNil(fcUses);
|
|
FreeAndNil(fcTransform);
|
|
|
|
inherited;
|
|
end;
|
|
|
|
//class function TFormatSettings.GetGroupCaption: String;
|
|
//begin
|
|
// Result := lisJCFFormatSettings;
|
|
//end;
|
|
//
|
|
//class function TFormatSettings.GetInstance: TAbstractIDEOptions;
|
|
//begin
|
|
// Result := FormatSettings;
|
|
//end;
|
|
//
|
|
//procedure TFormatSettings.DoAfterWrite(Restore: boolean);
|
|
//begin
|
|
// { settings are now in need of saving }
|
|
// Dirty := True;
|
|
// { check consistency of settings }
|
|
// MakeConsistent;
|
|
// { save to file }
|
|
// Write;
|
|
//end;
|
|
|
|
const
|
|
CODEFORMAT_SETTINGS_SECTION = 'JediCodeFormatSettings';
|
|
|
|
REG_VERSION = 'WriteVersion';
|
|
REG_WRITE_DATETIME = 'WriteDateTime';
|
|
REG_DESCRIPTION = 'Description';
|
|
|
|
procedure TFormatSettings.Read;
|
|
var
|
|
lcReg: TJCFRegistrySettings;
|
|
begin
|
|
// use the Settings File if it exists
|
|
lcReg := GetRegSettings;
|
|
ReadFromFile(lcReg.FormatConfigFileName, lcReg.FormatConfigNameSpecified);
|
|
end;
|
|
|
|
procedure TFormatSettings.ReadFromFile(const psFileName: string; const pbMustExist: boolean);
|
|
var
|
|
lsText: string;
|
|
lcFile: TSettingsInputString;
|
|
begin
|
|
if {$ifdef FPC}FileExistsUTF8(psFileName){$else}FileExists(psFileName){$endif} then
|
|
begin
|
|
// debug ShowMessage('Reading settings from file ' + lsSettingsFileName);
|
|
|
|
// now we know the file exists - try get settings from it
|
|
{$ifdef FPC}
|
|
lsText := string(FileToString(UTF8ToSys(psFileName)));
|
|
{$else}
|
|
lsText := string(FileToString(psFileName));
|
|
{$endif}
|
|
lcFile := TSettingsInputString.Create(lsText);
|
|
try
|
|
FromStream(lcFile);
|
|
finally
|
|
lcFile.Free;
|
|
end;
|
|
end
|
|
else
|
|
begin
|
|
if pbMustExist then
|
|
begin
|
|
//MessageDlg(Format(lisTheSettingsFileDoesNotExist, [psFileName, NativeLineBreak]), mtError, [mbOK], 0);
|
|
writeln(Format(lisTheSettingsFileDoesNotExist, [psFileName, NativeLineBreak]));
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
|
|
procedure TFormatSettings.ReadDefaults;
|
|
var
|
|
lcSetDummy: TSettingsInputDummy;
|
|
begin
|
|
lcSetDummy := TSettingsInputDummy.Create;
|
|
try
|
|
FromStream(lcSetDummy);
|
|
finally
|
|
lcSetDummy.Free;
|
|
end;
|
|
end;
|
|
|
|
procedure TFormatSettings.Write;
|
|
var
|
|
lcReg: TJCFRegistrySettings;
|
|
lcFile: TSettingsStreamOutput;
|
|
begin
|
|
if not Dirty then
|
|
exit;
|
|
|
|
{ user may have specified no-write }
|
|
lcReg := GetRegSettings;
|
|
if lcReg.FormatFileWriteOption = eNeverWrite then
|
|
exit;
|
|
|
|
if lcReg.FormatConfigFileName = '' then
|
|
exit;
|
|
|
|
{$ifdef FPC}
|
|
if FileExistsUTF8(lcReg.FormatConfigFileName) and FileIsReadOnlyUTF8(lcReg.FormatConfigFileName) then
|
|
{$else}
|
|
if FileExists(lcReg.FormatConfigFileName) and FileIsReadOnly(lcReg.FormatConfigFileName) then
|
|
{$endif}
|
|
begin
|
|
{ fail quietly? }
|
|
if lcReg.FormatFileWriteOption = eAlwaysWrite then
|
|
//MessageDlg(Format(lisErrorWritingSettingsFileReadOnly, [lcReg.FormatConfigFileName]), mtError, [mbOK], 0);
|
|
writeln(Format(lisErrorWritingSettingsFileReadOnly, [lcReg.FormatConfigFileName]));
|
|
exit;
|
|
end;
|
|
|
|
try
|
|
// use the Settings file name
|
|
{$ifdef FPC}
|
|
lcFile := TSettingsStreamOutput.Create(UTF8ToSys(GetRegSettings.FormatConfigFileName));
|
|
{$else}
|
|
lcFile := TSettingsStreamOutput.Create(GetRegSettings.FormatConfigFileName);
|
|
{$endif}
|
|
try
|
|
ToStream(lcFile);
|
|
|
|
// not dirty any more
|
|
fbDirty := False;
|
|
finally
|
|
lcFile.Free;
|
|
end;
|
|
except
|
|
on e: Exception do
|
|
begin
|
|
if lcReg.FormatFileWriteOption = eAlwaysWrite then
|
|
begin
|
|
//MessageDlg(Format(lisErrorWritingSettingsException, [GetRegSettings.FormatConfigFileName, NativeLineBreak, E.Message]), mtError, [mbOK], 0);
|
|
writeln(Format(lisErrorWritingSettingsException, [GetRegSettings.FormatConfigFileName, NativeLineBreak, E.Message]));
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
|
|
procedure TFormatSettings.ToStream(const pcStream: TSettingsOutput);
|
|
|
|
procedure WriteToStream(const pcSet: TSetBase);
|
|
begin
|
|
Assert(pcSet <> nil);
|
|
pcStream.OpenSection(pcSet.Section);
|
|
pcSet.WriteToStream(pcStream);
|
|
pcStream.CloseSection(pcSet.Section);
|
|
end;
|
|
|
|
begin
|
|
Assert(pcStream <> nil);
|
|
pcStream.WriteXMLHeader;
|
|
|
|
pcStream.OpenSection(CODEFORMAT_SETTINGS_SECTION);
|
|
|
|
pcStream.Write(REG_VERSION, PROGRAM_VERSION);
|
|
pcStream.Write(REG_WRITE_DATETIME, Now);
|
|
pcStream.Write(REG_DESCRIPTION, Description);
|
|
|
|
WriteToStream(fcObfuscate);
|
|
WriteToStream(fcClarify);
|
|
WriteToStream(fcIndent);
|
|
WriteToStream(fcSpaces);
|
|
WriteToStream(fcReturns);
|
|
WriteToStream(fcComments);
|
|
|
|
WriteToStream(fcCaps);
|
|
WriteToStream(fcSpecificWordCaps);
|
|
WriteToStream(fcIdentifierCaps);
|
|
WriteToStream(fcNotIdentifierCaps);
|
|
WriteToStream(fcUnitNameCaps);
|
|
WriteToStream(fcSetAsm);
|
|
|
|
WriteToStream(fcPreProcessor);
|
|
WriteToStream(fcAlign);
|
|
WriteToStream(fcReplace);
|
|
WriteToStream(fcUses);
|
|
WriteToStream(fcTransform);
|
|
|
|
pcStream.CloseSection(CODEFORMAT_SETTINGS_SECTION);
|
|
end;
|
|
|
|
procedure TFormatSettings.FromStream(const pcStream: TSettingsInput);
|
|
var
|
|
lcAllSettings: TSettingsInput;
|
|
|
|
procedure ReadFromStream(const pcSet: TSetBase);
|
|
var
|
|
lcSection: TSettingsInput;
|
|
begin
|
|
Assert(pcSet <> nil);
|
|
|
|
lcSection := lcAllSettings.ExtractSection(pcSet.Section);
|
|
if lcSection <> nil then
|
|
begin
|
|
pcSet.ReadFromStream(lcSection);
|
|
lcSection.Free;
|
|
end
|
|
else
|
|
begin
|
|
lcSection := TSettingsInputDummy.Create;
|
|
try
|
|
pcSet.ReadFromStream(lcSection);
|
|
finally
|
|
lcSection.Free;
|
|
end;
|
|
//ShowMessage('Skipping section ' + pcSet.Section + ' as it was not found');
|
|
end;
|
|
end;
|
|
|
|
begin
|
|
|
|
{ basic test - we are only interested in the
|
|
<JediCodeFormaTFormatSettings> ... </JediCodeFormaTFormatSettings> part of the file
|
|
If this start & end is not present, then is is the wrong file }
|
|
lcAllSettings := pcStream.ExtractSection(CODEFORMAT_SETTINGS_SECTION);
|
|
if lcAllSettings = nil then
|
|
begin
|
|
//ShowMessage(lisNoSettingsFound);
|
|
writeln(lisNoSettingsFound);
|
|
exit;
|
|
end;
|
|
|
|
try
|
|
fsWriteVersion := pcStream.Read(REG_VERSION, '');
|
|
fsDescription := pcStream.Read(REG_DESCRIPTION, '');
|
|
fdtWriteDateTime := pcStream.Read(REG_WRITE_DATETIME, 0.0);
|
|
|
|
ReadFromStream(fcObfuscate);
|
|
ReadFromStream(fcClarify);
|
|
ReadFromStream(fcIndent);
|
|
ReadFromStream(fcSpaces);
|
|
ReadFromStream(fcReturns);
|
|
ReadFromStream(fcComments);
|
|
ReadFromStream(fcCaps);
|
|
ReadFromStream(fcSpecificWordCaps);
|
|
ReadFromStream(fcIdentifierCaps);
|
|
ReadFromStream(fcNotIdentifierCaps);
|
|
ReadFromStream(fcUnitNameCaps);
|
|
ReadFromStream(fcSetAsm);
|
|
|
|
ReadFromStream(fcPreProcessor);
|
|
|
|
ReadFromStream(fcAlign);
|
|
ReadFromStream(fcReplace);
|
|
ReadFromStream(fcUses);
|
|
ReadFromStream(fcTransform);
|
|
|
|
fbHasRead := True;
|
|
finally
|
|
lcAllSettings.Free;
|
|
end;
|
|
end;
|
|
|
|
|
|
var
|
|
// a module var
|
|
mcFormatSettings: TFormatSettings = nil;
|
|
|
|
function FormattingSettings: TFormatSettings;
|
|
begin
|
|
if mcFormatSettings = nil then
|
|
mcFormatSettings := TFormatSettings.Create(true);
|
|
|
|
Result := mcFormatSettings;
|
|
end;
|
|
|
|
function FormatSettingsFromFile(const psFileName: string): TFormatSettings;
|
|
begin
|
|
if mcFormatSettings = nil then
|
|
mcFormatSettings := TFormatSettings.Create(false);
|
|
|
|
mcFormatSettings.ReadFromFile(psFileName, true);
|
|
Result := mcFormatSettings;
|
|
end;
|
|
|
|
|
|
procedure TFormatSettings.MakeConsistent;
|
|
begin
|
|
{ one consistency check so far
|
|
- if linebreaking is off, then "remove returns in expressions" must also be off }
|
|
|
|
if Returns.RebreakLines = rbOff then
|
|
Returns.RemoveExpressionReturns := False;
|
|
end;
|
|
|
|
initialization
|
|
//JCFOptionsGroup := GetFreeIDEOptionsGroupIndex(GroupEditor);
|
|
//RegisterIDEOptionsGroup(JCFOptionsGroup, TFormatSettings);
|
|
finalization
|
|
FreeAndNil(mcFormatSettings);
|
|
end.
|