SourceEditor: Introduced Selection-Toggle-Comments issue #13824 and redone old Set/Unset Comment. Based on a patch by Flávio Etrusco

git-svn-id: trunk@20379 -
This commit is contained in:
martin 2009-06-03 18:06:25 +00:00
parent cb61eaabf5
commit 485e5c2c90
9 changed files with 211 additions and 43 deletions

View File

@ -434,8 +434,10 @@ type
{$ENDIF}
procedure AquirePrimarySelection;
function GetDefSelectionMode: TSynSelectionMode;
function GetUndoList: TSynEditUndoList;
function GetDividerDrawLevel: Integer; deprecated;
procedure SetDefSelectionMode(const AValue: TSynSelectionMode);
procedure SetDividerDrawLevel(const AValue: Integer); deprecated;
procedure SetMouseActions(const AValue: TSynEditMouseActions);
procedure SetMouseSelActions(const AValue: TSynEditMouseActions);
@ -564,7 +566,7 @@ type
procedure SetWantTabs(const Value: boolean);
procedure SetWordBlock(Value: TPoint);
{$IFDEF SYN_LAZARUS}
procedure SetLineBlock(Value: TPoint);
procedure SetLineBlock(Value: TPoint; WithLeadSpaces: Boolean = True);
procedure SetParagraphBlock(Value: TPoint);
{$ENDIF}
procedure SizeOrFontChanged(bFont: boolean);
@ -813,7 +815,7 @@ type
{$IFDEF SYN_LAZARUS}
Procedure SetHighlightSearch(const ASearch: String; AOptions: TSynSearchOptions);
procedure SelectToBrace;
procedure SelectLine;
procedure SelectLine(WithLeadSpaces: Boolean = True);
procedure SelectParagraph;
procedure SetUseIncrementalColor(const AValue : Boolean);
{$ENDIF}
@ -945,6 +947,8 @@ type
property SelectedColor: TSynSelectedColor
read FSelectedColor write FSelectedColor;
{$ENDIF}
property DefaultSelectionMode: TSynSelectionMode
read GetDefSelectionMode write SetDefSelectionMode default smNormal;
property SelectionMode: TSynSelectionMode
read GetSelectionMode write SetSelectionMode default smNormal;
// See Highlighter for new methods
@ -1342,11 +1346,21 @@ begin
end;
end;
function TCustomSynEdit.GetDefSelectionMode: TSynSelectionMode;
begin
Result := FBlockSelection.SelectionMode;
end;
function TCustomSynEdit.GetDividerDrawLevel: Integer;
begin
Result := fHighlighter.DrawDividerLevel;
end;
procedure TCustomSynEdit.SetDefSelectionMode(const AValue: TSynSelectionMode);
begin
FBlockSelection.SelectionMode := AValue; // Includes active
end;
procedure TCustomSynEdit.SurrenderPrimarySelection;
begin
if PrimarySelection.OnRequest=@PrimarySelectionRequest then
@ -2627,12 +2641,14 @@ begin
if (fStateFlags * [sfMouseSelecting, sfIsDragging] <> []) and MouseCapture
then begin
//DebugLn(' TCustomSynEdit.MouseMove CAPTURE Mouse=',dbgs(X),',',dbgs(Y),' Caret=',dbgs(CaretXY),', BlockBegin=',dbgs(BlockBegin),' BlockEnd=',dbgs(BlockEnd));
FInternalCaret.AssignFrom(FCaret);
FInternalCaret.LineCharPos := PixelsToRowColumn(Point(X,Y));
if (not(sfIsDragging in fStateFlags)) then
SetBlockEnd(FInternalCaret.LineBytePos);
if (X >= fGutterWidth) and (X < ClientWidth-ScrollBarWidth)
and (Y >= 0) and (Y < ClientHeight-ScrollBarWidth)
then
ComputeCaret(X, Y);
if (not(sfIsDragging in fStateFlags)) then
SetBlockEnd(PhysicalToLogicalPos(CaretXY));
FCaret.LineBytePos := FInternalCaret.LineBytePos;
// should we begin scrolling?
Dec(X, fGutterWidth);
// calculate chars past right
@ -3815,9 +3831,9 @@ begin
FindMatchingBracket(CaretXY,true,true,true,false);
end;
procedure TCustomSynEdit.SelectLine;
procedure TCustomSynEdit.SelectLine(WithLeadSpaces: Boolean = True);
begin
SetLineBlock(CaretXY);
SetLineBlock(CaretXY, WithLeadSpaces);
end;
procedure TCustomSynEdit.SelectParagraph;
@ -3909,6 +3925,9 @@ procedure TCustomSynEdit.SetCaretXY(Value: TPoint);
begin
fCaret.LineCharPos:= Value;
fLastCaretX:=CaretX;
if (CompareCarets(FCaret.LineBytePos, FBlockSelection.StartLineBytePos) <> 0)
and not(SelAvail or FBlockSelection.SelCanContinue(FCaret)) then
FBlockSelection.StartLineBytePos := FCaret.LineBytePos;
end;
procedure TCustomSynEdit.CaretChanged(Sender: TObject);
@ -4794,7 +4813,7 @@ end;
{$ENDIF}
{$IFDEF SYN_LAZARUS}
procedure TCustomSynEdit.SetLineBlock(Value: TPoint);
procedure TCustomSynEdit.SetLineBlock(Value: TPoint; WithLeadSpaces: Boolean = True);
var
ALine: string;
x, x2: Integer;
@ -4804,13 +4823,15 @@ begin
if (FBlockSelection.StartLinePos >= 1)
and (FBlockSelection.StartLinePos <= FTheLinesView.Count) then begin
ALine:=FTheLinesView[FBlockSelection.StartLinePos - 1];
x := FBlockSelection.StartBytePos;
while (x<length(ALine)) and (ALine[x] in [' ',#9]) do
inc(x);
FBlockSelection.StartLineBytePos := Point(x,MinMax(Value.y, 1, FTheLinesView.Count));
x2:=length(ALine)+1;
while (x2 > x) and (ALine[X2-1] in [' ',#9]) do
dec(x2);
if not WithLeadSpaces then begin
x := FBlockSelection.StartBytePos;
while (x<length(ALine)) and (ALine[x] in [' ',#9]) do
inc(x);
FBlockSelection.StartLineBytePos := Point(x,MinMax(Value.y, 1, FTheLinesView.Count));
while (x2 > x) and (ALine[X2-1] in [' ',#9]) do
dec(x2);
end;
FBlockSelection.EndLineBytePos := Point(x2, MinMax(Value.y, 1, FTheLinesView.Count));
end;
FBlockSelection.ActiveSelectionMode := smNormal;
@ -6281,7 +6302,7 @@ begin
ecColumnSelect,
ecLineSelect:
begin
SelectionMode := SEL_MODE[Command];
DefaultSelectionMode := SEL_MODE[Command];
end;
{$IFDEF SYN_MBCSSUPPORT}
ecImeStr:
@ -6618,7 +6639,7 @@ end;
procedure TCustomSynEdit.SetSelectionMode(const Value: TSynSelectionMode);
begin
fBlockSelection.SelectionMode := Value; // Set both: SelectionMode and ActiveSelectionMode
fBlockSelection.ActiveSelectionMode := Value;
end;
{begin} //sbs 2000-11-19

View File

@ -823,6 +823,7 @@ var
begin
FLines.BeginUpdate;
FCaret.Lock;
try
// BB is lower than BE
BB := FirstLineBytePos;
@ -832,10 +833,12 @@ begin
EndLineBytePos := BB; // deletes selection // calls selection changed
end;
if (Value <> nil) and (Value[0] <> #0) then begin
FCaret.LineBytePos := StartLineBytePos;
InsertText;
StartLineBytePos := FCaret.LineBytePos; // reset selection
end;
finally
FCaret.Unlock;
FLines.EndUpdate; // May reset Block Begin
end;
end;

View File

@ -267,6 +267,7 @@ begin
ecSelectionEnclose: SetResult(VK_UNKNOWN, [],VK_UNKNOWN,[]);
ecSelectionComment: SetResult(VK_UNKNOWN, [],VK_UNKNOWN,[]);
ecSelectionUncomment: SetResult(VK_UNKNOWN, [],VK_UNKNOWN,[]);
ecToggleComment: SetResult(VK_OEM_2, [ssCtrl], VK_UNKNOWN, []);
ecSelectionConditional: SetResult(VK_D, [ssShift,ssCtrl],VK_UNKNOWN,[]);
ecSelectionSort: SetResult(VK_UNKNOWN, [],VK_UNKNOWN,[]);
ecSelectionBreakLines: SetResult(VK_UNKNOWN, [],VK_UNKNOWN,[]);
@ -633,6 +634,7 @@ begin
ecSelectionEnclose: SetResult(VK_UNKNOWN, [],VK_UNKNOWN,[], VK_UNKNOWN, [], VK_UNKNOWN, []);
ecSelectionComment: SetResult(VK_UNKNOWN, [],VK_UNKNOWN,[], VK_UNKNOWN, [], VK_UNKNOWN, []);
ecSelectionUncomment: SetResult(VK_UNKNOWN, [],VK_UNKNOWN,[], VK_UNKNOWN, [], VK_UNKNOWN, []);
ecToggleComment: SetResult(VK_OEM_2, [ssCtrl],VK_UNKNOWN,[], VK_UNKNOWN, [], VK_UNKNOWN, []);
ecSelectionConditional: SetResult(VK_D, [ssShift,ssCtrl],VK_UNKNOWN,[], VK_UNKNOWN, [], VK_UNKNOWN, []);
ecSelectionSort: SetResult(VK_UNKNOWN, [],VK_UNKNOWN,[], VK_UNKNOWN, [], VK_UNKNOWN, []);
ecSelectionBreakLines: SetResult(VK_UNKNOWN, [],VK_UNKNOWN,[], VK_UNKNOWN, [], VK_UNKNOWN, []);
@ -1150,6 +1152,7 @@ begin
ecSelectionEnclose: SetResult(VK_UNKNOWN, [],VK_UNKNOWN,[]);
ecSelectionComment: SetResult(VK_UNKNOWN, [],VK_UNKNOWN,[]);
ecSelectionUncomment: SetResult(VK_UNKNOWN, [],VK_UNKNOWN,[]);
ecToggleComment: SetResult(VK_OEM_2, [ssCtrl],VK_UNKNOWN,[]);
ecSelectionConditional: SetResult(VK_D, [ssShift,ssCtrl],VK_UNKNOWN,[]);
ecSelectionSort: SetResult(VK_UNKNOWN, [],VK_UNKNOWN,[]);
ecSelectionBreakLines: SetResult(VK_UNKNOWN, [],VK_UNKNOWN,[]);
@ -1657,6 +1660,7 @@ begin
ecSelectionEnclose : Result:= lisMenuEncloseSelection;
ecSelectionComment : Result:= lismenucommentselection;
ecSelectionUncomment : Result:= lismenuuncommentselection;
ecToggleComment : Result:= lismenutogglecomment;
ecSelectionConditional : Result:= lisMenuConditionalSelection;
ecSelectionSort : Result:= lismenusortselection;
ecSelectionBreakLines : Result:= lisMenuBeakLinesInSelection;
@ -2015,6 +2019,8 @@ begin
);
AddDefault(C, 'Uncomment selection', lisMenuUncommentSelection,
ecSelectionUncomment);
AddDefault(C, 'Toggle comment', lisMenuToggleComment, ecToggleComment
);
AddDefault(C, 'Sort selection', lisSortSelSortSelection, ecSelectionSort);
AddDefault(C, 'Break Lines in selection', lisMenuBeakLinesInSelection,
ecSelectionBreakLines);

View File

@ -190,6 +190,7 @@ resourcestring
lisMenuEncloseSelection = 'Enclose selection ...';
lisMenuCommentSelection = 'Comment selection';
lisMenuUncommentSelection = 'Uncomment selection';
lisMenuToggleComment = 'Toggle comment';
lisKMInsertIFDEF = 'Insert $IFDEF';
lisMenuConditionalSelection = 'Insert $IFDEF...';
lisMenuSortSelection = 'Sort selection ...';

View File

@ -201,6 +201,7 @@ type
procedure mnuEditTabsToSpacesBlockClicked(Sender: TObject);
procedure mnuEditCommentBlockClicked(Sender: TObject);
procedure mnuEditUncommentBlockClicked(Sender: TObject);
procedure mnuEditToggleCommentClicked(Sender: TObject);
procedure mnuEditConditionalBlockClicked(Sender: TObject);
procedure mnuEditSortBlockClicked(Sender: TObject);
procedure mnuEditSelectionBreakLinesClicked(Sender: TObject);
@ -2224,6 +2225,7 @@ begin
itmEditTabsToSpacesBlock.OnClick:=@mnuEditTabsToSpacesBlockClicked;
itmEditCommentBlock.OnClick:=@mnuEditCommentBlockClicked;
itmEditUncommentBlock.OnClick:=@mnuEditUncommentBlockClicked;
itmEditToggleComment.OnClick:=@mnuEditToggleCommentClicked;
itmEditConditionalBlock.OnClick:=@mnuEditConditionalBlockClicked;
itmEditSortBlock.OnClick:=@mnuEditSortBlockClicked;
itmEditSelectionBreakLines.OnClick:=@mnuEditSelectionBreakLinesClicked;
@ -14862,6 +14864,11 @@ begin
DoSourceEditorCommand(ecSelectionUncomment);
end;
procedure TMainIDE.mnuEditToggleCommentClicked(Sender: TObject);
begin
DoSourceEditorCommand(ecToggleComment);
end;
procedure TMainIDE.mnuEditConditionalBlockClicked(Sender: TObject);
begin
DoSourceEditorCommand(ecSelectionConditional);

View File

@ -110,6 +110,7 @@ type
itmEditEncloseBlock: TIDEMenuCommand;
itmEditCommentBlock: TIDEMenuCommand;
itmEditUncommentBlock: TIDEMenuCommand;
itmEditToggleComment: TIDEMenuCommand;
itmEditConditionalBlock: TIDEMenuCommand;
itmEditSortBlock: TIDEMenuCommand;
//itmEditBlockCharConversion: TIDEMenuSection;

View File

@ -413,6 +413,7 @@ begin
CreateMenuItem(ParentMI,itmEditEncloseBlock,'itmEditEncloseBlock',lisMenuEncloseSelection);
CreateMenuItem(ParentMI,itmEditCommentBlock,'itmEditCommentBlock',lisMenuCommentSelection, 'menu_comment');
CreateMenuItem(ParentMI,itmEditUncommentBlock,'itmEditUncommentBlock',lisMenuUncommentSelection, 'menu_uncomment');
CreateMenuItem(ParentMI,itmEditToggleComment,'itmEditToggleComment',lisMenuToggleComment, 'menu_comment');
CreateMenuItem(ParentMI,itmEditConditionalBlock,'itmEditConditionalBlock',lisMenuConditionalSelection);
CreateMenuItem(ParentMI,itmEditSortBlock,'itmEditSortBlock',lisMenuSortSelection, 'menu_edit_sort');
@ -827,6 +828,7 @@ begin
itmEditTabsToSpacesBlock.Command:=GetCommand(ecSelectionTabs2Spaces);
itmEditCommentBlock.Command:=GetCommand(ecSelectionComment);
itmEditUncommentBlock.Command:=GetCommand(ecSelectionUncomment);
itmEditToggleComment.Command:=GetCommand(ecToggleComment);
itmEditConditionalBlock.Command:=GetCommand(ecSelectionConditional);
itmEditSortBlock.Command:=GetCommand(ecSelectionSort);
itmEditSelectionBreakLines.Command:=GetCommand(ecSelectionBreakLines);

View File

@ -265,6 +265,8 @@ type
procedure TabsToSpacesInSelection;
procedure CommentSelection;
procedure UncommentSelection;
procedure ToggleCommentSelection;
procedure UpdateCommentSelection(CommentOn, Toggle: Boolean);
procedure ConditionalSelection;
procedure SortSelection;
procedure BreakLinesInSelection;
@ -1672,6 +1674,9 @@ Begin
ecSelectionUnComment:
UncommentSelection;
ecToggleComment:
ToggleCommentSelection;
ecSelectionConditional:
ConditionalSelection;
@ -1867,39 +1872,160 @@ begin
end;
procedure TSourceEditor.CommentSelection;
var
OldBlockBegin, OldBlockEnd: TPoint;
begin
if ReadOnly then exit;
if not EditorComponent.SelAvail then exit;
OldBlockBegin:=FEditor.BlockBegin;
OldBlockEnd:=FEditor.BlockEnd;
FEditor.BeginUpdate;
FEditor.BeginUndoBlock;
// ToDo: replace step by step to keep bookmarks and breakpoints
FEditor.SelText:=CommentLines(EditorComponent.SelText);
FEditor.BlockBegin:=OldBlockBegin;
FEditor.BlockEnd:=OldBlockEnd;
FEditor.EndUndoBlock;
FEditor.EndUpdate;
UpdateCommentSelection(True, False);
end;
procedure TSourceEditor.UncommentSelection;
var
OldBlockBegin, OldBlockEnd: TPoint;
begin
UpdateCommentSelection(False, False);
end;
procedure TSourceEditor.ToggleCommentSelection;
begin
UpdateCommentSelection(False, True);
end;
procedure TSourceEditor.UpdateCommentSelection(CommentOn, Toggle: Boolean);
var
OldCaretPos, OldBlockStart, OldBlockEnd: TPoint;
WasSelAvail: Boolean;
WasSelMode: TSynSelectionMode;
BlockBeginLine: Integer;
BlockEndLine: Integer;
CommonIndent: Integer;
function FirstNonBlankPos(const Text: String; Start: Integer = 1): Integer;
var
i: Integer;
begin
for i := Start to Length(Text) do
if (Text[i] <> #32) and (Text[i] <> #9) then
exit(i);
Result := -1;
end;
function MinCommonIndent: Integer;
var
i, j: Integer;
begin
If CommonIndent = 0 then begin
CommonIndent := Max(FirstNonBlankPos(FEditor.Lines[BlockBeginLine - 1]), 1);
for i := BlockBeginLine + 1 to BlockEndLine do begin
j := FirstNonBlankPos(FEditor.Lines[i - 1]);
if (j < CommonIndent) and (j > 0) then
CommonIndent := j;
end;
end;
Result := CommonIndent;
end;
function InsertPos(ALine: Integer): Integer;
begin
if not WasSelAvail then
Result := MinCommonIndent
else case WasSelMode of
smColumn: // CommonIndent is not used otherwise
begin
if CommonIndent = 0 then
CommonIndent := Min(FEditor.LogicalToPhysicalPos(OldBlockStart).X,
FEditor.LogicalToPhysicalPos(OldBlockEnd).X);
Result := FEditor.PhysicalToLogicalPos(Point(CommonIndent, ALine)).X;
end;
smNormal:
begin
if OldBlockStart.Y = OldBlockEnd.Y then
Result := OldBlockStart.X
else
Result := MinCommonIndent;
end;
else
Result := 1;
end;
end;
function DeletePos(ALine: Integer): Integer;
var
line: String;
begin
line := FEditor.Lines[ALine - 1];
Result := FirstNonBlankPos(line, InsertPos(ALine));
if (WasSelMode = smColumn) and((Result < 1) or (Result > length(line) - 1))
then
Result := length(line) - 1;
Result := Max(1, Result);
if (Length(line) < Result +1) or
(line[Result] <> '/') or (line[Result+1] <> '/') then
Result := -1;
end;
var
i: Integer;
NonBlankStart, LineStart: Integer;
begin
if ReadOnly then exit;
if not EditorComponent.SelAvail then exit;
OldBlockBegin:=FEditor.BlockBegin;
OldBlockEnd:=FEditor.BlockEnd;
FEditor.BeginUpdate;
FEditor.BeginUndoBlock;
// ToDo: replace step by step to keep bookmarks and breakpoints
FEditor.SelText:=UncommentLines(EditorComponent.SelText);
FEditor.BlockBegin:=OldBlockBegin;
FEditor.BlockEnd:=OldBlockEnd;
FEditor.EndUndoBlock;
FEditor.EndUpdate;
OldCaretPos := FEditor.CaretXY;
OldBlockStart := FEditor.BlockBegin;
OldBlockEnd := FEditor.BlockEnd;
WasSelAvail := FEditor.SelAvail;
WasSelMode := FEditor.SelectionMode;
CommonIndent := 0;
BlockBeginLine := OldBlockStart.Y;
BlockEndLine := OldBlockEnd.Y;
if (OldBlockEnd.X = 1) and (BlockEndLine > BlockBeginLine) and (FEditor.SelectionMode <> smLine) then
Dec(BlockEndLine);
if Toggle then begin
CommentOn := False;
for i := BlockBeginLine to BlockEndLine do
if DeletePos(i) < 0 then begin
CommentOn := True;
break;
end;
end;
BeginUpdate;
BeginUndoBlock;
FEditor.SelectionMode := smNormal;
if CommentOn then begin
for i := BlockEndLine downto BlockBeginLine do
begin
FEditor.BlockBegin := Point(InsertPos(i), i);
FEditor.SelText := '//';
end;
if OldCaretPos.X > InsertPos(OldCaretPos.Y) then
OldCaretPos.x := OldCaretPos.X + 2;
if OldBlockStart.X > InsertPos(OldBlockStart.Y) then
OldBlockStart.X := OldBlockStart.X + 2;
if OldBlockEnd.X > InsertPos(OldBlockEnd.Y) then
OldBlockEnd.X := OldBlockEnd.X + 2;
end
else begin
for i := BlockEndLine downto BlockBeginLine do
begin
NonBlankStart := DeletePos(i);
if NonBlankStart < 1 then continue;
FEditor.BlockBegin := Point(NonBlankStart, i);
FEditor.BlockEnd := Point(NonBlankStart + 2, i);
FEditor.SelText := '';
if (OldCaretPos.Y = i) and (OldCaretPos.X > NonBlankStart) then
OldCaretPos.x := Max(OldCaretPos.X - 2, NonBlankStart);
if (OldBlockStart.Y = i) and (OldBlockStart.X > NonBlankStart) then
OldBlockStart.X := Max(OldBlockStart.X - 2, NonBlankStart);
if (OldBlockEnd.Y = i) and (OldBlockEnd.X > NonBlankStart) then
OldBlockEnd.X := Max(OldBlockEnd.X - 2, NonBlankStart);
end;
end;
EndUndoBlock;
EndUpdate;
FEditor.BlockBegin := OldBlockStart;
FEditor.BlockEnd := OldBlockEnd;
FEditor.CaretXY := OldCaretPos;
FEditor.SelectionMode := WasSelMode;
end;
procedure TSourceEditor.ConditionalSelection;

View File

@ -97,6 +97,7 @@ const
ecSelectLine = ecFirstLazarus + 61;
ecSelectParagraph = ecFirstLazarus + 62;
ecSelectionConditional = ecFirstLazarus + 63;
ecToggleComment = ecFirstLazarus + 64;
// insert text
ecInsertCharacter = ecFirstLazarus + 80;