📄 synmacrorecorder.pas
字号:
end;
end;
end
else begin
{not AfterProcessing}
case State of
msStopped:
if Command = RecordCommandID then
begin
RecordMacro( TCustomSynEdit( Sender ) );
Handled := True;
end
else if Command = PlaybackCommandID then
begin
PlaybackMacro( TCustomSynEdit( Sender ) );
Handled := True;
end;
msPlaying:
;
msPaused:
if Command = PlaybackCommandID then
begin
Resume;
Handled := True;
end;
msRecording:
if Command = PlaybackCommandID then
begin
Pause;
Handled := True;
end
else if Command = RecordCommandID then
begin
Stop;
Handled := True;
end;
end;
end;
end;
procedure TCustomSynMacroRecorder.Pause;
begin
if State <> msRecording then
Error( sCannotPause );
fState := msPaused;
StateChanged;
end;
procedure TCustomSynMacroRecorder.PlaybackMacro(aEditor: TCustomSynEdit);
var
cEvent: integer;
begin
if State <> msStopped then
Error( sCannotPlay );
fState := msPlaying;
try
StateChanged;
for cEvent := 0 to EventCount -1 do
begin
Events[ cEvent ].Playback( aEditor );
if State <> msPlaying then
break;
end;
finally
if State = msPlaying then
begin
fState := msStopped;
StateChanged;
end;
end;
end;
procedure TCustomSynMacroRecorder.RecordMacro(aEditor: TCustomSynEdit);
begin
if fState <> msStopped then
Error( sCannotRecord );
Clear;
fEvents := TList.Create;
fEvents.Capacity := 512;
fState := msRecording;
fCurrentEditor := aEditor;
StateChanged;
end;
procedure TCustomSynMacroRecorder.RemoveEditor(aEditor: TCustomSynEdit);
begin
inherited RemoveEditor( aEditor );
end;
procedure TCustomSynMacroRecorder.Resume;
begin
if fState <> msPaused then
Error( sCannotResume );
fState := msRecording;
StateChanged;
end;
procedure TCustomSynMacroRecorder.SaveToStream(aDest: TStream);
var
cEvent, eCnt : integer;
begin
eCnt := EventCount;
aDest.Write(eCnt, sizeof(eCnt));
for cEvent := 0 to eCnt -1 do
Events[ cEvent ].SaveToStream( aDest );
end;
procedure TCustomSynMacroRecorder.SetShortCut(const Index: Integer;
const Value: TShortCut);
var
cEditor: integer;
begin
if fShortCuts[TSynMacroCommand(Index)] <> Value then
begin
if Assigned(fEditors) then
if Value <> 0 then
begin
for cEditor := 0 to fEditors.Count -1 do
HookEditor( Editors[cEditor], fCommandIDs[TSynMacroCommand(Index)],
fShortCuts[TSynMacroCommand(Index)], Value );
end else
begin
for cEditor := 0 to fEditors.Count -1 do
UnHookEditor( Editors[cEditor], fCommandIDs[TSynMacroCommand(Index)],
fShortCuts[TSynMacroCommand(Index)] );
end;
fShortCuts[TSynMacroCommand(Index)] := Value;
end;
end;
procedure TCustomSynMacroRecorder.StateChanged;
begin
if Assigned( OnStateChange ) then
OnStateChange( Self );
end;
procedure TCustomSynMacroRecorder.Stop;
begin
if fState = msStopped then
Exit;
fState := msStopped;
fCurrentEditor := nil;
if fEvents.Count = 0 then
FreeAndNil( fEvents );
StateChanged;
end;
function TCustomSynMacroRecorder.GetAsString: string;
var
i : integer;
eStr : string;
begin
Result := 'macro ' + MacroName + #13#10 + 'begin' + #13#10;
if Assigned(fEvents) then
begin
for i := 0 to fEvents.Count -1 do
begin
eStr := Events[i].AsString;
if eStr <> '' then
Result := Result + ' ' + eStr + #13#10;
end;
end;
Result := Result + 'end';
end;
procedure TCustomSynMacroRecorder.SetAsString(const Value: string);
var
i, p, Cmd : Integer;
S : TStrings;
cmdStr : string;
iEvent: TSynMacroEvent;
begin
Stop;
Clear;
fEvents := TList.Create;
// process file line by line and create events
S := TStringList.Create;
try
S.Text := Value;
for i := 0 to S.Count - 1 do
begin
cmdStr := Trim(S[i]);
p := Pos(' ', cmdStr);
if p = 0 then p := Length(cmdStr)+1;
Cmd := ecNone;
if IdentToEditorCommand(Copy(cmdStr, 1, p-1), Longint(Cmd)) then // D2 needs type-cast
begin
Delete(cmdStr, 1, p);
iEvent := CreateMacroEvent(Cmd);
try
fEvents.Add(iEvent);
iEvent.InitEventParameters(cmdStr);
except
iEvent.Free;
end;
end;
end;
finally
S.Free;
end;
end;
procedure TCustomSynMacroRecorder.LoadFromFile(aFilename: string);
var
F : TFileStream;
begin
F := TFileStream.Create(aFilename, fmOpenRead);
try
LoadFromStream(F);
MacroName := ChangeFileExt(ExtractFileName(aFilename), '');
finally
F.Free;
end;
end;
procedure TCustomSynMacroRecorder.SaveToFile(aFilename: string);
var
F : TFileStream;
begin
F := TFileStream.Create(aFilename, fmCreate);
try
SaveToStream(F);
finally
F.Free;
end;
end;
{ TSynBasicEvent }
function TSynBasicEvent.GetAsString: string;
begin
Result := '';
EditorCommandToIdent(Command, Result);
if RepeatCount > 1 then
Result := Result + ' ' + IntToStr(RepeatCount);
end;
procedure TSynBasicEvent.InitEventParameters(aStr: string);
begin
// basic events have no parameters but can contain an optional repeat count
RepeatCount := StrToIntDef(Trim(aStr), 1);
end;
procedure TSynBasicEvent.Initialize(aCmd: TSynEditorCommand; aChar: Char;
aData: Pointer);
begin
Command := aCmd;
{$IFDEF SYN_DEVELOPMENT_CHECKS}
if (aChar <> #0) or (aData <> nil) then
raise Exception.Create('TSynBasicEvent cannot handle Char <> #0 or Data <> nil');
{$ENDIF}
end;
procedure TSynBasicEvent.LoadFromStream(aStream: TStream);
begin
aStream.Read( fRepeatCount, SizeOf(fRepeatCount) );
end;
procedure TSynBasicEvent.Playback(aEditor: TCustomSynEdit);
var
i : Integer;
begin
for i := 1 to RepeatCount do
aEditor.CommandProcessor( Command, #0, nil );
end;
procedure TSynBasicEvent.SaveToStream(aStream: TStream);
begin
aStream.Write( Command, SizeOf(TSynEditorCommand) );
aStream.Write( RepeatCount, SizeOf(RepeatCount) );
end;
{ TSynCharEvent }
function TSynCharEvent.GetAsString: string;
begin
Result := '';
EditorCommandToIdent(ecChar, Result);
Result := Result + ' ' + Key;
if RepeatCount > 1 then
Result := Result + ' ' + IntToStr(RepeatCount);
end;
procedure TSynCharEvent.InitEventParameters(aStr: string);
begin
// aStr should be a Key value one character in length
// with an optional repeat count whitespace separated
if Length(aStr) >= 1 then
Key := aStr[1]
else
Key := ' ';
Delete(aStr, 1, 1); // if possible delete the first character
RepeatCount := StrToIntDef(Trim(aStr), 1);
end;
procedure TSynCharEvent.Initialize(aCmd: TSynEditorCommand; aChar: Char;
aData: Pointer);
begin
Key := aChar;
Assert( aData = nil );
end;
procedure TSynCharEvent.LoadFromStream(aStream: TStream);
begin
aStream.Read( fKey, SizeOf(Key) );
aStream.Read( fRepeatCount, SizeOf(fRepeatCount) );
end;
procedure TSynCharEvent.Playback(aEditor: TCustomSynEdit);
var
i : Integer;
begin
for i := 1 to RepeatCount do
aEditor.CommandProcessor( ecChar, Key, nil );
end;
procedure TSynCharEvent.SaveToStream(aStream: TStream);
const
iCharCommand: TSynEditorCommand = ecChar;
begin
aStream.Write( iCharCommand, SizeOf(TSynEditorCommand) );
aStream.Write( Key, SizeOf(Key) );
aStream.Write( RepeatCount, SizeOf(RepeatCount) );
end;
{ TSynPositionEvent }
function TSynPositionEvent.GetAsString: string;
begin
Result := inherited GetAsString;
// add position data here
Result := Result + Format(' (%d, %d)', [Position.Char, Position.Line]);
if RepeatCount > 1 then
Result := Result + ' ' + IntToStr(RepeatCount);
end;
procedure TSynPositionEvent.InitEventParameters(aStr: string);
var
i, o, c, x, y : Integer;
valStr : string;
begin
inherited;
// aStr should be (x, y) with optional repeat count whitespace separated
aStr := Trim(aStr);
i := Pos(',', aStr);
o := Pos('(', aStr);
c := Pos(')', aStr);
if (not ((i = 0) or (o = 0) or (c = 0))) and
((i > o) and (i < c)) then
begin
valStr := Copy(aStr, o+1, i-o-1);
x := StrToIntDef(valStr, 1);
Delete(aStr, 1, i);
aStr := Trim(aStr);
c := Pos(')', aStr);
valStr := Copy(aStr, 1, c-1);
y := StrToIntDef(valStr, 1);
Position := TBufferCoord( Point(x,y) );
Delete(aStr, 1, c);
aStr := Trim(aStr);
RepeatCount := StrToIntDef(aStr, 1);
end;
end;
procedure TSynPositionEvent.Initialize(aCmd: TSynEditorCommand;
aChar: Char; aData: Pointer);
begin
inherited;
if aData <> nil then
Position := TBufferCoord( aData^ )
else
Position := TBufferCoord( Point(0,0) );
end;
procedure TSynPositionEvent.LoadFromStream(aStream: TStream);
begin
aStream.Read( fPosition, SizeOf(Position) );
end;
procedure TSynPositionEvent.Playback(aEditor: TCustomSynEdit);
begin
if (Position.Char <> 0) or (Position.Line <> 0) then
aEditor.CommandProcessor( Command, #0, @Position )
else
aEditor.CommandProcessor( Command, #0, nil );
end;
procedure TSynPositionEvent.SaveToStream(aStream: TStream);
begin
inherited;
aStream.Write( Position, SizeOf(Position) );
end;
{ TSynStringEvent }
{$IFNDEF SYN_COMPILER_3_UP}
function QuotedStr(const S: string; QuoteChar: Char): string;
var
i: Integer;
begin
Result := S;
for i := Length(Result) downto 1 do
if Result[i] = QuoteChar then
Insert(QuoteChar, Result, i);
Result := QuoteChar + Result + QuoteChar;
end;
{$ENDIF}
function TSynStringEvent.GetAsString: string;
begin
Result := '';
EditorCommandToIdent(ecString, Result);
{$IFDEF SYN_COMPILER_3_UP}
Result := Result + ' ' + AnsiQuotedStr(Value, #39);
{$ELSE}
Result := Result + ' ' + QuotedStr(Value, #39);
{$ENDIF}
if RepeatCount > 1 then
Result := Result + ' ' + IntToStr(RepeatCount);
end;
procedure TSynStringEvent.InitEventParameters(aStr: string);
var
o, c : Integer;
valStr : string;
begin
// aStr = 'test' with optional whitespace separated repeat count
o := Pos('''', aStr);
c := LastDelimiter('''', aStr);
valStr := Copy(aStr, o+1, c-o-1);
Value := StringReplace(valStr, '''''', '''', [rfReplaceAll]);
Delete(aStr, 1, c);
RepeatCount := StrToIntDef(Trim(aStr), 1);
end;
procedure TSynStringEvent.Initialize(aCmd: TSynEditorCommand; aChar: Char;
aData: Pointer);
begin
Value := String(aData);
end;
procedure TSynStringEvent.LoadFromStream(aStream: TStream);
var
l : Integer;
Buff : PChar;
begin
aStream.Read(l, SizeOf(l));
GetMem(Buff, l);
try
{$IFNDEF SYN_CLX} //js 07-04-2002 changed from IFDEF WINDOWS
FillMemory(Buff, l, 0);
{$ENDIF}
aStream.Read(Buff^, l);
fString := Buff;
finally
FreeMem(Buff);
end;
aStream.Read( fRepeatCount, SizeOf(fRepeatCount) );
end;
procedure TSynStringEvent.Playback(aEditor: TCustomSynEdit);
var
i, j : Integer;
begin
for j := 1 to RepeatCount do
begin
// aEditor.CommandProcessor( ecString, #0, Pointer(Value) );
// SynEdit doesn't actually support the ecString command so we convert
// it into ecChar commands
for i := 1 to Length(Value) do
aEditor.CommandProcessor(ecChar, Value[i], nil);
end;
end;
procedure TSynStringEvent.SaveToStream(aStream: TStream);
const
StrCommand: TSynEditorCommand = ecString;
var
l : Integer;
Buff : PChar;
begin
aStream.Write(StrCommand, SizeOf(StrCommand));
l := Length(Value) + 1;
aStream.Write(l, sizeof(l));
GetMem(Buff, l);
try
{$IFNDEF SYN_CLX} //js 07-04-2002 changed from IFDEF WINDOWS
FillMemory(Buff, l, 0);
{$ENDIF}
StrPCopy(Buff, Value);
aStream.Write(Buff^, l);
finally
FreeMem(Buff);
end;
aStream.Write( RepeatCount, SizeOf(RepeatCount) );
end;
{ TSynMacroEvent }
constructor TSynMacroEvent.Create;
begin
inherited Create;
fRepeatCount := 1;
end;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -