Browse Source

Comment/Uncomment selection.

Margers 1 month ago
parent
commit
35fb1a1f63
5 changed files with 185 additions and 7 deletions
  1. 8 0
      packages/ide/fpconst.pas
  2. 4 0
      packages/ide/fphelp.pas
  3. 6 1
      packages/ide/fpide.pas
  4. 163 4
      packages/ide/weditor.pas
  5. 4 2
      packages/ide/wviews.pas

+ 8 - 0
packages/ide/fpconst.pas

@@ -221,6 +221,12 @@ const
      }
 
      cmPrint             = 248;
+     { in wviews.pas defined
+     cmCommentSel        = 249;
+     cmUnCommentSel      = 250;
+     }
+
+
 
      cmNotImplemented    = 1000;
      cmNewFromTemplate   = 1001;
@@ -394,6 +400,8 @@ const
      hcPasteWin          = hcShift+cmPasteWin;
      hcSelectAll         = hcShift+cmSelectAll;
      hcUnselect          = hcShift+cmUnselect;
+     hcCommentSel        = hcShift+cmCommentSel;
+     hcUnCommentSel      = hcShift+cmUnCommentSel;
 
      hcFindProcedure     = hcShift+cmFindProcedure;
      hcObjects           = hcShift+cmObjects;

+ 4 - 0
packages/ide/fphelp.pas

@@ -138,6 +138,8 @@ const
       hint_editselectall     = 'Select the whole text';
       hint_editunselect      = 'Unselect everything';
       hint_showclipboard     = 'Open then clipboard window';
+      hint_commentsel        = 'Insert line comment in front of each selected line';
+      hint_uncommentsel      = 'Remove line comment (if any) from beginning of every selected line';
       hint_searchmenu        = 'Text and symbols search commands';
       hint_searchfind        = 'Search for text';
       hint_searchreplace     = 'Search for text and replace it with new text';
@@ -301,6 +303,8 @@ begin
     hcPasteWin      : S:=hint_editpastewin;
     hcClear         : S:=hint_editclear;
     hcShowClipboard : S:=hint_showclipboard;
+    hcCommentSel    : S:=hint_commentsel;
+    hcUnCommentSel  : S:=hint_uncommentsel;
 
     hcSearchMenu    : S:=hint_searchmenu;
     hcFind          : S:=hint_searchfind;

+ 6 - 1
packages/ide/fpide.pas

@@ -260,6 +260,8 @@ resourcestring  menu_local_gotosource = '~G~oto source';
                 menu_edit_showclipboard= '~S~how clipboard';
                 menu_edit_selectall    = 'Select ~A~ll';
                 menu_edit_unselect     = 'U~n~select';
+                menu_edit_comment      = 'Com~m~ent selection';
+                menu_edit_uncomment    = 'Unc~o~mment selection';
 
                 menu_search            = '~S~earch';
                 menu_search_find       = '~F~ind...';
@@ -941,8 +943,11 @@ begin
       NewItem(menu_edit_selectall,menu_key_edit_all, all_Key, cmSelectAll, hcSelectAll,
       NewItem(menu_edit_unselect,'', kbNoKey, cmUnselect, hcUnselect,
       NewLine(
+      NewItem(menu_edit_comment,'', kbNoKey, cmCommentSel, hcCommentSel,
+      NewItem(menu_edit_uncomment,'', kbNoKey, cmUnCommentSel, hcUnCommentSel,
+      NewLine(
       NewItem(menu_edit_showclipboard,'', kbNoKey, cmShowClipboard, hcShowClipboard,
-      WinPMI))))))))
+      WinPMI)))))))))))
 {$ifdef DebugUndo}))){$endif DebugUndo}
       )))),
     NewSubMenu(menu_search,hcSearchMenu, NewMenu(

+ 163 - 4
packages/ide/weditor.pas

@@ -198,15 +198,18 @@ const
       eaUpperCase         = 19;
       eaLowerCase         = 20;
       eaToggleCase        = 21;
-      eaDummy             = 22;
+      eaCommentSel        = 22;
+      eaUnCommentSel      = 23;
+      eaDummy             = 24;
       LastAction          = eaDummy;
 
-      ActionString : array [0..LastAction-1] of string[13] =
+      ActionString : array [0..LastAction-1] of string[14] =
         ('','Move','InsLine','InsText','DelLine','DelText',
          'SelChange','Cut','Paste','PasteWin','DelChar','Clear',
          'CopyBlock','MoveBlock','DelBlock',
          'ReadBlock','IndentBlock','UnindentBlock','Overwrite',
-         'UpperCase','LowerCase','ToggleCase');
+         'UpperCase','LowerCase','ToggleCase',
+         'CommentBlock','UnCommentBlock');
 
       CIndicator    = #2#3#1;
       CEditor       = #33#34#35#36#37#38#39#40#41#42#43#44#45#46#47#48#49#50;
@@ -678,6 +681,8 @@ type
     public
       { Editor primitives }
       procedure   SelectAll(Enable: boolean); virtual;
+      procedure   CommentSel; virtual;
+      procedure   UnCommentSel; virtual;
     public
       { Editor commands }
       SearchRunCount: integer;
@@ -799,7 +804,7 @@ const
      ToClipCmds         : TCommandSet = ([cmCut,cmCopy,cmCopyWin,
        { cmUnselect should because like cut, copy, copywin:
          if there is a selection, it is active, else it isn't }
-       cmUnselect]);
+       cmUnselect,cmCommentSel,cmUnCommentSel]);
      FromClipCmds       : TCommandSet = ([cmPaste]);
      NulClipCmds        : TCommandSet = ([cmClear]);
      UndoCmd            : TCommandSet = ([cmUndo]);
@@ -3936,6 +3941,8 @@ begin
 
           cmSelectAll   : SelectAll(true);
           cmUnselect    : SelectAll(false);
+          cmCommentSel  : CommentSel;
+          cmUnCommentSel: UnCommentSel;
 {$ifdef WinClipSupported}
           cmCopyWin     : ClipCopyWin;
           cmPasteWin    : ClipPasteWin;
@@ -7285,6 +7292,158 @@ begin
   DrawView;
 end;
 
+procedure TCustomCodeEditor.CommentSel;
+var
+  ey,i : Sw_Integer;
+  S,Ind : Sw_AString;
+  Pos : Tpoint;
+  WasPersistentBlocks : boolean;
+  WhiteLen, k : Sw_Integer;
+  LLen : Sw_Integer; { length of longest line }
+begin
+  if IsReadOnly then Exit;
+  if (SelStart.X=SelEnd.X) and (SelStart.Y=SelEnd.Y) then Exit;
+  Lock;
+  ey:=SelEnd.Y;
+  if SelEnd.X=0 then
+   dec(ey);
+  S:='';
+  { Find shortest white space of beginning of line from all lines
+    for simplisity reason Tab is not recognized as white space in this regard }
+  LLen:=0;
+  WhiteLen:=-1;
+  WhiteLen:= WhiteLen shr 1; { logical SHR to get max sw_integer }
+  for i:=SelStart.Y to ey do
+    begin
+      S:=GetDisplayText(i);
+      LLen:=Max(LLen,Length(S));
+      S:=GetLineText(i);
+      LLen:=Max(LLen,Length(S)); {whatever is longer displayed text or actual line text }
+      WhiteLen:=Min(WhiteLen,Length(S));
+      if WhiteLen = 0 then
+        break; {string length is zero, no lower where to go }
+      k:=1;
+      while (k<=WhiteLen) and (S[k]=' ') do { Tab do not count in }
+        inc(k);
+      WhiteLen:=k-1;
+      if WhiteLen = 0 then
+        break; { we have done enough, no white spaces at all }
+    end;
+  if WhiteLen=(sw_integer(-1) shr 1) then
+    WhiteLen:=0; { eee, never can happen, but if ever then we will be safe }
+{$if sizeof(sw_astring)>8}
+  if LLen > 252 then { if lines are shortstrings and there is no room to add 2 chars }
+  begin
+    UnLock;
+    MessageBox('Lines too long!', nil, mfOKButton);
+    exit;
+  end;
+{$endif}
+  AddGroupedAction(eaCommentSel);
+  WasPersistentBlocks:=IsFlagSet(efPersistentBlocks);
+  if not WasPersistentBlocks then
+    SetFlags(GetFlags or efPersistentBlocks);
+  {selection Start and End move along}
+  if SelStart.X>WhiteLen then inc(SelStart.X,2);
+  if SelEnd.X>WhiteLen then inc(SelEnd.X,2);
+  { put line comment in front of every selected line }
+  Ind:='//';
+  for i:=SelStart.Y to ey do
+   begin
+     S:=GetLineText(i);
+     S:=copy(S,1,WhiteLen)+Ind+copy(S,WhiteLen+1,Length(S));
+     SetLineText(i,S);
+     Pos.X:=WhiteLen;Pos.Y:=i;
+     AddAction(eaInsertText,Pos,Pos,Ind,GetFlags);
+   end;
+  Pos:=CurPos;
+  { this removes selection if Shift is pressed as well }
+  if (CurPos.X > WhiteLen) and (SelStart.Y<=CurPos.Y) and (CurPos.Y<=ey) then
+    SetCurPtr(CurPos.X+2,CurPos.Y);
+  {after SetCurPtr return PersistentBlocks as it was before}
+  if not WasPersistentBlocks then
+    SetFlags(GetFlags and (not longword(efPersistentBlocks)));
+  { must be added manually here PM }
+  AddAction(eaMoveCursor,Pos,CurPos,'',GetFlags);
+  UpdateAttrsRange(SelStart.Y,SelEnd.Y,attrAll);
+  DrawLines(CurPos.Y);
+  SetModified(true);
+  CloseGroupedAction(eaCommentSel);
+  UnLock;
+end;
+
+procedure TCustomCodeEditor.UnCommentSel;
+var
+  ey,i : Sw_Integer;
+  S,Ind : Sw_AString;
+  Pos : Tpoint;
+  WasPersistentBlocks : boolean;
+  WhiteLen, k : Sw_Integer;
+  WasGroupAction : boolean;
+  NeedToMoveCursor:boolean;
+begin
+  if IsReadOnly then Exit;
+  if (SelStart.X=SelEnd.X) and (SelStart.Y=SelEnd.Y) then Exit;
+  Lock;
+  ey:=SelEnd.Y;
+  if SelEnd.X=0 then
+   dec(ey);
+  WasGroupAction:=false;
+  NeedToMoveCursor:=false;
+  { remove line comment from beginning of every selected line ( if there is any) }
+  Ind:='//';
+  for i:=SelStart.Y to ey do
+   begin
+     S:=GetLineText(i);
+     fog('S "'+S+'"');
+     if Length(S)<2 then continue;
+     WhiteLen:=0;
+     for k:=1 to Length(S)-1 do
+       if not (S[k] in [' ',#9]) then
+         break; { white space is over }
+     if (S[k]<>'/') or (S[k+1]<>'/') then continue;  { continue if comment not found }
+     WhiteLen:=k-1;
+     if not WasGroupAction then
+     begin
+       {add group action only if there is at least one action
+        because empty group action throw segment fault when do Undo }
+       WasGroupAction:=true;
+       AddGroupedAction(eaUnCommentSel);
+     end;
+     S:=copy(S,1,WhiteLen)+copy(S,WhiteLen+1+2,Length(S)); { delete line comment string '//' }
+     SetLineText(i,S);
+     Pos.X:=WhiteLen;Pos.Y:=i;
+     AddAction(eaDeleteText,Pos,Pos,Ind,GetFlags);
+     {selection Start and End move along}
+     if i=SelStart.Y then
+       if (SelStart.X>1) and (SelStart.X>WhiteLen+1) then dec(SelStart.X,2);
+     if i=SelEnd.Y then
+       if (SelEnd.X>1) and (SelEnd.X>WhiteLen+1) then dec(SelEnd.X,2);
+     if i=CurPos.Y then
+       if (CurPos.X>1) and (CurPos.X>WhiteLen+1) then NeedToMoveCursor:=true;
+   end;
+  if WasGroupAction then
+  begin
+    WasPersistentBlocks:=IsFlagSet(efPersistentBlocks);
+    if not WasPersistentBlocks then
+      SetFlags(GetFlags or efPersistentBlocks);
+    Pos:=CurPos;
+    { this removes selection if Shift is pressed as well }
+    if NeedToMoveCursor then
+      SetCurPtr(CurPos.X-2,CurPos.Y);
+    {after SetCurPtr return PersistentBlocks as it was before}
+    if not WasPersistentBlocks then
+      SetFlags(GetFlags and (not longword(efPersistentBlocks)));
+    { must be added manually here PM }
+    AddAction(eaMoveCursor,Pos,CurPos,'',GetFlags);
+    UpdateAttrsRange(SelStart.Y,SelEnd.Y,attrAll);
+    DrawLines(CurPos.Y);
+    SetModified(true);
+    CloseGroupedAction(eaUnCommentSel);
+  end;
+  UnLock;
+end;
+
 procedure TCustomCodeEditor.SelectionChanged;
 var Enable,CanPaste: boolean;
 begin

+ 4 - 2
packages/ide/wviews.pas

@@ -21,10 +21,12 @@ uses Objects,Drivers,Views,Menus,Dialogs,Outline;
 const
       evIdle                 = $8000;
 
-      cmCopyWin = 240;
-      cmPasteWin = 241;
+      cmCopyWin           = 240;
+      cmPasteWin          = 241;
       cmSelectAll         = 246;
       cmUnselect          = 247;
+      cmCommentSel        = 249;
+      cmUnCommentSel      = 250;
 
       cmLocalMenu            = 54100;
       cmUpdate               = 54101;