mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-05-01 20:43:42 +02:00
312 lines
8.4 KiB
ObjectPascal
312 lines
8.4 KiB
ObjectPascal
{
|
|
***************************************************************************
|
|
* *
|
|
* This source is free software; you can redistribute it and/or modify *
|
|
* it under the terms of the GNU General Public License as published by *
|
|
* the Free Software Foundation; either version 2 of the License, or *
|
|
* (at your option) any later version. *
|
|
* *
|
|
* This code is distributed in the hope that it will be useful, but *
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
|
* General Public License for more details. *
|
|
* *
|
|
* A copy of the GNU General Public License is available on the World *
|
|
* Wide Web at <http://www.gnu.org/copyleft/gpl.html>. You can also *
|
|
* obtain it by writing to the Free Software Foundation, *
|
|
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
|
* *
|
|
***************************************************************************
|
|
|
|
Author: Mattias Gaertner
|
|
|
|
Abstract:
|
|
TCodeTemplatesTool enhances TStandardCodeTool with the ability to insert
|
|
code templates.
|
|
}
|
|
unit CodeTemplatesTool;
|
|
|
|
{$mode objfpc}{$H+}
|
|
|
|
interface
|
|
|
|
{$I codetools.inc}
|
|
|
|
uses
|
|
{$IFDEF MEM_CHECK}
|
|
MemCheck,
|
|
{$ENDIF}
|
|
Classes, SysUtils, FileProcs, CodeTree, CodeAtom, KeywordFuncLists,
|
|
LinkScanner, AVL_Tree, SourceChanger,
|
|
CustomCodeTool, PascalParserTool, CodeToolsStructs, StdCodeTools;
|
|
|
|
type
|
|
TCodeTemplateSyntax = (
|
|
ctsxDefault
|
|
);
|
|
{ ctsxDefault:
|
|
|
|
The backslash '\' makes special chars to normal chars.
|
|
| for cursor
|
|
$(MacroName) for macro variables
|
|
$MacroName(Param) for macro functions
|
|
|
|
|
|
If the variable contains several lines, the lines are indented like the
|
|
first line.
|
|
Example:
|
|
Inserting the text
|
|
|
|
"begin"
|
|
" i:=1;"
|
|
"end;"
|
|
Into the text
|
|
|
|
"begin"
|
|
" |"
|
|
"end;"
|
|
|
|
at the | results in
|
|
|
|
"begin"
|
|
" begin"
|
|
" i:=1;"
|
|
" end;"
|
|
"end;"
|
|
|
|
|
|
Defined variables:
|
|
|
|
$(Selection) - replaced by the current selection
|
|
|
|
$(Indent) - replaced by nothing. Set Indent for multiline macros
|
|
Example:
|
|
Text: " Text: $(Indent)$(Selection)"
|
|
Selection: "First"
|
|
"Second"
|
|
Result: " Text: First"
|
|
" Second"
|
|
}
|
|
|
|
TCodeToolTemplate = class
|
|
private
|
|
FIndent: integer;
|
|
FNewLineAtEnd: boolean;
|
|
FNewLineAtStart: boolean;
|
|
FSyntax: TCodeTemplateSyntax;
|
|
FTemplate: string;
|
|
procedure SetIndent(const AValue: integer);
|
|
procedure SetNewLineAtEnd(const AValue: boolean);
|
|
procedure SetNewLineAtStart(const AValue: boolean);
|
|
procedure SetSyntax(const AValue: TCodeTemplateSyntax);
|
|
procedure SetTemplate(const AValue: string);
|
|
public
|
|
property Template: string read FTemplate write SetTemplate;
|
|
property NewLineAtStart: boolean read FNewLineAtStart write SetNewLineAtStart;
|
|
property NewLineAtEnd: boolean read FNewLineAtEnd write SetNewLineAtEnd;
|
|
property Syntax: TCodeTemplateSyntax read FSyntax write SetSyntax;
|
|
property Indent: integer read FIndent write SetIndent;
|
|
end;
|
|
|
|
{ TCodeTemplatesTool }
|
|
|
|
TCodeTemplatesTool = class(TStandardCodeTool)
|
|
public
|
|
function InsertCodeTemplate(CursorPos,EndPos: TCodeXYPosition;
|
|
TopLine: integer; CodeTemplate: TCodeToolTemplate;
|
|
out NewPos: TCodeXYPosition; out NewTopLine: integer;
|
|
SourceChangeCache: TSourceChangeCache): boolean;
|
|
function ExtractProcedureHeader(CursorPos: TCodeXYPosition;
|
|
Attributes: TProcHeadAttributes; var ProcHead: string): boolean;
|
|
|
|
procedure CalcMemSize(Stats: TCTMemStats); override;
|
|
end;
|
|
|
|
implementation
|
|
|
|
{ TCodeTemplatesTool }
|
|
|
|
function TCodeTemplatesTool.InsertCodeTemplate(CursorPos,
|
|
EndPos: TCodeXYPosition; TopLine: integer; CodeTemplate: TCodeToolTemplate;
|
|
out NewPos: TCodeXYPosition; out NewTopLine: integer;
|
|
SourceChangeCache: TSourceChangeCache): boolean;
|
|
var
|
|
NewText: TMemoryStream;
|
|
TemplatePos: Integer;
|
|
LastWrittenTemplatePos: Integer;
|
|
TemplateStr: String;
|
|
TemplateStrLen: Integer;
|
|
|
|
procedure FlushTemplate;
|
|
var
|
|
FromPos: Integer;
|
|
ToPos: Integer;
|
|
begin
|
|
FromPos:=LastWrittenTemplatePos+1;
|
|
ToPos:=TemplatePos-1;
|
|
if ToPos>TemplateStrLen then
|
|
ToPos:=TemplateStrLen;
|
|
if FromPos<=ToPos then
|
|
NewText.Write(TemplateStr[FromPos],ToPos-FromPos+1);
|
|
LastWrittenTemplatePos:=ToPos;
|
|
end;
|
|
|
|
procedure CalculateNewCursorPos;
|
|
begin
|
|
|
|
end;
|
|
|
|
procedure ParseMacro;
|
|
var
|
|
MacroStart: Integer;
|
|
MacroFuncNameStart: Integer;
|
|
MacroFuncNameEnd: Integer;
|
|
BracketLvl: Integer;
|
|
MacroParamStart: Integer;
|
|
MacroParamEnd: Integer;
|
|
begin
|
|
MacroStart:=TemplatePos;
|
|
inc(MacroStart);
|
|
MacroFuncNameStart:=TemplatePos;
|
|
while (TemplatePos<=TemplateStrLen)
|
|
and IsIdentChar[TemplateStr[TemplatePos]] do
|
|
inc(TemplatePos);
|
|
MacroFuncNameEnd:=TemplatePos;
|
|
if (TemplatePos<=TemplateStrLen) and (TemplateStr[TemplatePos]='(') then
|
|
begin
|
|
inc(TemplatePos);
|
|
MacroParamStart:=TemplatePos;
|
|
MacroParamEnd:=MacroParamStart;
|
|
BracketLvl:=1;
|
|
while (TemplatePos<=TemplateStrLen) do begin
|
|
case TemplateStr[TemplatePos] of
|
|
'\':
|
|
begin
|
|
inc(TemplatePos);
|
|
if (TemplatePos>TemplateStrLen) then break;
|
|
end;
|
|
'(': inc(BracketLvl);
|
|
')':
|
|
begin
|
|
dec(BracketLvl);
|
|
if BracketLvl=0 then begin
|
|
MacroParamEnd:=TemplatePos;
|
|
break;
|
|
end;
|
|
end;
|
|
end;
|
|
inc(TemplatePos);
|
|
end;
|
|
if MacroFuncNameStart<MacroFuncNameEnd then begin
|
|
// a macro function
|
|
// ToDo
|
|
end else if MacroParamStart<MacroParamEnd then begin
|
|
// a macro variable
|
|
// ToDo
|
|
end;
|
|
end;
|
|
LastWrittenTemplatePos:=TemplatePos;
|
|
end;
|
|
|
|
begin
|
|
Result:=false;
|
|
NewPos:=CursorPos;
|
|
NewText:=TMemoryStream.Create;
|
|
try
|
|
// parse the template
|
|
TemplatePos:=1;
|
|
LastWrittenTemplatePos:=TemplatePos-1;
|
|
TemplateStr:=CodeTemplate.Template;
|
|
TemplateStrLen:=length(TemplateStr);
|
|
while TemplatePos<=TemplateStrLen do begin
|
|
case TemplateStr[TemplatePos] of
|
|
'\':
|
|
begin
|
|
FlushTemplate;
|
|
LastWrittenTemplatePos:=TemplatePos;
|
|
inc(TemplatePos,2);
|
|
end;
|
|
|
|
'|':
|
|
begin
|
|
FlushTemplate;
|
|
CalculateNewCursorPos;
|
|
LastWrittenTemplatePos:=TemplatePos;
|
|
inc(TemplatePos);
|
|
end;
|
|
|
|
'$':
|
|
begin
|
|
FlushTemplate;
|
|
ParseMacro;
|
|
end;
|
|
|
|
else
|
|
inc(TemplatePos);
|
|
end;
|
|
end;
|
|
FlushTemplate;
|
|
|
|
|
|
finally
|
|
NewText.Free;
|
|
end;
|
|
end;
|
|
|
|
function TCodeTemplatesTool.ExtractProcedureHeader(CursorPos: TCodeXYPosition;
|
|
Attributes: TProcHeadAttributes; var ProcHead: string): boolean;
|
|
var
|
|
CleanCursorPos: integer;
|
|
ANode: TCodeTreeNode;
|
|
begin
|
|
Result:=false;
|
|
ProcHead:='';
|
|
BuildTreeAndGetCleanPos(trTillCursor,CursorPos,CleanCursorPos,[]);
|
|
ANode:=FindDeepestNodeAtPos(CleanCursorPos,True);
|
|
while (ANode<>nil) and (ANode.Desc<>ctnProcedure) do
|
|
ANode:=ANode.Parent;
|
|
if ANode=nil then exit;
|
|
ProcHead:=ExtractProcHead(ANode,Attributes);
|
|
Result:=true;
|
|
end;
|
|
|
|
procedure TCodeTemplatesTool.CalcMemSize(Stats: TCTMemStats);
|
|
begin
|
|
inherited CalcMemSize(Stats);
|
|
end;
|
|
|
|
{ TCodeToolTemplate }
|
|
|
|
procedure TCodeToolTemplate.SetIndent(const AValue: integer);
|
|
begin
|
|
if FIndent=AValue then exit;
|
|
FIndent:=AValue;
|
|
end;
|
|
|
|
procedure TCodeToolTemplate.SetNewLineAtEnd(const AValue: boolean);
|
|
begin
|
|
if FNewLineAtEnd=AValue then exit;
|
|
FNewLineAtEnd:=AValue;
|
|
end;
|
|
|
|
procedure TCodeToolTemplate.SetNewLineAtStart(const AValue: boolean);
|
|
begin
|
|
if FNewLineAtStart=AValue then exit;
|
|
FNewLineAtStart:=AValue;
|
|
end;
|
|
|
|
procedure TCodeToolTemplate.SetSyntax(const AValue: TCodeTemplateSyntax);
|
|
begin
|
|
if FSyntax=AValue then exit;
|
|
FSyntax:=AValue;
|
|
end;
|
|
|
|
procedure TCodeToolTemplate.SetTemplate(const AValue: string);
|
|
begin
|
|
if FTemplate=AValue then exit;
|
|
FTemplate:=AValue;
|
|
end;
|
|
|
|
end.
|
|
|