Ver Fonte

+ Enhance code complete by inserting unit symbols

pierre há 23 anos atrás
pai
commit
5953173600
3 ficheiros alterados com 290 adições e 34 exclusões
  1. 16 2
      ide/fp.pas
  2. 234 9
      ide/fpcodcmp.pas
  3. 40 23
      ide/fpcompil.pas

+ 16 - 2
ide/fp.pas

@@ -302,8 +302,19 @@ BEGIN
   ReadINIFile;
   InitDesktopFile;
   LoadDesktop;
+
+  { Handle Standard Units }
+  if UseAllUnitsInCodeComplete then
+    AddAvailableUnitsToCodeComplete(false);
+
+  if UseStandardUnitsInCodeComplete and not assigned(UnitsCodeCompleteWords) then
+    AddStandardUnitsToCodeComplete;
+
+  { why are the screen contents parsed at startup? Gabor
+    to be able to find location of error in last compilation
+    from command line PM }
   ParseUserScreen;
-  { why are the screen contents parsed at startup? Gabor }
+
   EnableCatchSignals;
   { Update IDE }
   IDEApp.Update;
@@ -426,7 +437,10 @@ BEGIN
 END.
 {
   $Log$
-  Revision 1.9  2002-05-29 22:29:42  pierre
+  Revision 1.10  2002-09-04 14:07:12  pierre
+   + Enhance code complete by inserting unit symbols
+
+  Revision 1.9  2002/05/29 22:29:42  pierre
    Asciitab now in fvision
 
   Revision 1.8  2002/04/12 11:28:55  pierre

+ 234 - 9
ide/fpcodcmp.pas

@@ -18,6 +18,8 @@ type
     private
       CodeCompleteLB : PAdvancedListBox;
       RB : PRadioButtons;
+      CB : PCheckBoxes;
+      MinInputL,InputL : PInputLine;
       procedure Add;
       procedure Edit;
       procedure Delete;
@@ -27,6 +29,8 @@ function FPCompleteCodeWord(const WordS: string; var Text: string): boolean;
 
 procedure InitCodeComplete;
 function  LoadCodeComplete(var S: TStream): boolean;
+procedure AddStandardUnitsToCodeComplete;
+procedure AddAvailableUnitsToCodeComplete(OnlyStandard : boolean);
 function  StoreCodeComplete(var S: TStream): boolean;
 procedure DoneCodeComplete;
 
@@ -35,19 +39,20 @@ type
       TCodeCompleteCase = (ccc_unchanged, ccc_lower, ccc_upper, ccc_mixed);
 const
      CodeCompleteCase : TCodeCompleteCase = ccc_unchanged;
+     UnitsCodeCompleteWords : PCodeCompleteWordList = nil;
 
 procedure RegisterCodeComplete;
 
 implementation
 
-uses Views,MsgBox,
+uses Views,MsgBox,Validate,
 {$ifdef FVISION}
      FVConsts,
 {$else}
      Commands,
 {$endif}
-     WEditor,
-     FPConst,FPString,FPViews;
+     WEditor, FPCompil, FPVars, FPSymbol, BrowCol,
+     App,FPConst,FPString,FPViews;
 
 {$ifndef NOOBJREG}
 const
@@ -61,14 +66,83 @@ const
 
 function FPCompleteCodeWord(const WordS: string; var Text: string): boolean;
 var OK: boolean;
-    Index: sw_integer;
+    CIndex, Index, i : sw_integer;
+    St, UpWordS : string;
 begin
+  if ShowOnlyUnique then
+    UpWordS:=UpCaseStr(WordS);
   OK:=Assigned(CodeCompleteWords);
   if OK then
   begin
-    Text:=CodeCompleteWords^.Lookup(WordS,Index);
+    Text:=CodeCompleteWords^.Lookup(WordS,CIndex);
+    OK:=(CIndex<>-1) and (length(Text)<>length(WordS));
+    if OK and ShowOnlyUnique and (CIndex<CodeCompleteWords^.Count-1) then
+      begin
+        St:=PString(CodeCompleteWords^.At(CIndex+1))^;
+        if (UpCaseStr(Copy(St,1,length(WordS)))=UpWordS) then
+          begin
+            if UpCase(st[Length(UpWordS)+1])<>Upcase(Text[Length(UpWordS)+1]) then
+              begin
+                Text:='';
+                FPCompleteCodeWord:=false;
+                exit;
+              end
+            else
+              { only give the common part }
+              begin
+                i:=Length(UpWordS)+1;
+                while (i<=length(st)) and (i<=length(text)) and (UpCase(st[i])=Upcase(Text[i])) do
+                  inc(i);
+                SetLength(Text,i-1);
+              end;
+          end;
+      end;
+  end;
+  if (ShowOnlyUnique or not OK) and Assigned(UnitsCodeCompleteWords) then
+  begin
+    Text:=UnitsCodeCompleteWords^.Lookup(WordS,Index);
     OK:=(Index<>-1) and (length(Text)<>length(WordS));
+    if ShowOnlyUnique and (Index<UnitsCodeCompleteWords^.Count-1) then
+      begin
+        St:=PString(UnitsCodeCompleteWords^.At(Index+1))^;
+        if UpCaseStr(Copy(St,1,length(WordS)))=UpWordS then
+          begin
+            if UpCase(st[Length(UpWordS)+1])<>Upcase(Text[Length(UpWordS)+1]) then
+              begin
+                Text:='';
+                FPCompleteCodeWord:=false;
+                exit;
+              end
+            else
+              { only give the common part }
+              begin
+                i:=Length(UpWordS)+1;
+                while (i<=length(st)) and (i<=length(text)) and (UpCase(st[i])=Upcase(Text[i])) do
+                  inc(i);
+                SetLength(Text,i-1);
+              end;
+          end;
+      end;
   end;
+
+  if ShowOnlyUnique and (Index<>-1) and (CIndex<>-1) then
+    begin
+      St:=PString(CodeCompleteWords^.At(CIndex+1))^;
+      if UpCase(st[Length(UpWordS)+1])<>Upcase(Text[Length(UpWordS)+1]) then
+        begin
+          Text:='';
+          FPCompleteCodeWord:=false;
+          exit;
+        end
+      else
+        { only give the common part }
+        begin
+          i:=Length(UpWordS)+1;
+          while (i<=length(st)) and (i<=length(text)) and (UpCase(st[i])=Upcase(Text[i])) do
+            inc(i);
+          SetLength(Text,i-1);
+        end;
+    end;
   if OK=false then Text:=''
   else case CodeCompleteCase of
     ccc_upper : Text:=UpcaseStr(Text);
@@ -97,9 +171,89 @@ begin
   }
 end;
 
+
+procedure AddAvailableUnitsToCodeComplete(OnlyStandard : boolean);
+
+var
+  I : sw_integer;
+  Overflow: boolean;
+  Level : longint;
+  UpStandardUnits : string;
+
+  procedure InsertInS(P: PSymbol); {$ifndef FPC}far;{$endif}
+
+    procedure InsertItemsInS(P: PSymbolCollection);
+    var I: Sw_integer;
+    begin
+      for I:=0 to P^.Count-1 do
+        InsertInS(P^.At(I));
+    end;
+
+  begin
+    Inc(level);
+    if UnitsCodeCompleteWords^.Count=MaxCollectionSize then
+       begin Overflow:=true; Exit; end;
+    UnitsCodeCompleteWords^.Insert(NewStr(P^.GetName));
+    { this is wrong because it inserted args or locals of proc
+      in the globals list !! PM}
+    if (P^.Items<>nil) and (level=1) and
+        (not OnlyStandard or (Pos(P^.GetName+',',UpStandardUnits)>0)) then
+      InsertItemsInS(P^.Items);
+    Dec(level);
+  end;
+
+begin
+  if OnlyStandard then
+    UpStandardunits:=UpCaseStr(StandardUnits)+',';
+  if IsSymbolInfoAvailable then
+    begin
+      if Assigned(UnitsCodeCompleteWords) then
+        begin
+          Dispose(UnitsCodeCompleteWords,done);
+          UnitsCodeCompleteWords:=nil;
+        end;
+
+      New(UnitsCodeCompleteWords, Init(10,10));
+      level:=0;
+      Overflow:=false;
+      BrowCol.Modules^.ForEach(@InsertInS);
+      { if Overflow then
+        WarningBox(msg_toomanysymbolscantdisplayall,nil); }
+    end;
+end;
+
+procedure AddStandardUnitsToCodeComplete;
+var
+  HiddenSource : PSourceWindow;
+  R : TRect;
+begin
+  Desktop^.GetExtent(R);
+  New(HiddenSource,init(R,''));
+  CompilingHiddenFile:=HiddenSource;
+  { compile a dummy file to get symbol info }
+  with HiddenSource^.Editor^ do
+    begin
+      FileName:='__fp__.pp';
+      if StandardUnits<>'' then
+        begin
+          AddLine('uses');
+          Addline(StandardUnits+';');
+        end;
+      Addline('begin');
+      Addline('end.');
+      SaveFile;
+    end;
+  DoCompile(cCompile);
+  AddAvailableUnitsToCodeComplete(true);
+  { Now add the interface declarations to the Code Complete list }
+  CompilingHiddenFile:=nil;
+  Dispose(HiddenSource,Done);
+end;
+
 function LoadCodeComplete(var S: TStream): boolean;
 var C: PCodeCompleteWordList;
     OK: boolean;
+    StPtr : PString;
 begin
   New(C, Load(S));
   OK:=Assigned(C) and (S.Status=stOk);
@@ -108,6 +262,14 @@ begin
       if Assigned(CodeCompleteWords) then Dispose(CodeCompleteWords, Done);
       CodeCompleteWords:=C;
       S.Read(CodeCompleteCase,Sizeof(TCodeCompleteCase));
+      S.Read(UseStandardUnitsInCodeComplete,Sizeof(UseStandardUnitsInCodeComplete));
+      S.Read(UseAllUnitsInCodeComplete,Sizeof(UseAllUnitsInCodeComplete));
+      S.Read(ShowOnlyUnique,Sizeof(ShowOnlyUnique));
+      S.Read(CodeCompleteMinLen,Sizeof(CodeCompleteMinLen));
+      StPtr:=S.ReadStr;
+      StandardUnits:=GetStr(StPtr);
+      if assigned(StPtr) then
+        FreeMem(StPtr,Length(StandardUnits)+1);
     end
   else
     if Assigned(C) then
@@ -123,6 +285,11 @@ begin
   begin
     CodeCompleteWords^.Store(S);
     S.Write(CodeCompleteCase,Sizeof(TCodeCompleteCase));
+    S.Write(UseStandardUnitsInCodeComplete,Sizeof(UseStandardUnitsInCodeComplete));
+    S.Write(UseAllUnitsInCodeComplete,Sizeof(UseAllUnitsInCodeComplete));
+    S.Write(ShowOnlyUnique,Sizeof(ShowOnlyUnique));
+    S.Write(CodeCompleteMinLen,Sizeof(CodeCompleteMinLen));
+    S.WriteStr(@StandardUnits);
     OK:=OK and (S.Status=stOK);
   end;
   StoreCodeComplete:=OK;
@@ -132,6 +299,11 @@ procedure DoneCodeComplete;
 begin
   if Assigned(CodeCompleteWords) then Dispose(CodeCompleteWords, Done);
   CodeCompleteWords:=nil;
+  if Assigned(UnitsCodeCompleteWords) then
+    begin
+      Dispose(UnitsCodeCompleteWords,done);
+      UnitsCodeCompleteWords:=nil;
+    end;
 end;
 
 constructor TCodeCompleteDialog.Init;
@@ -139,11 +311,13 @@ var R,R2,R3: TRect;
     Items: PSItem;
     SB: PScrollBar;
 begin
-  R.Assign(0,0,46,20);
+  R.Assign(0,0,50,22);
   inherited Init(R,dialog_codecomplete);
   HelpCtx:=hcCodeCompleteOptions;
+
+  { name list dialog }
   GetExtent(R); R.Grow(-3,-2); Inc(R.A.Y); R3.Copy(R); Dec(R.B.X,12);
-  Dec(R.B.Y,5);
+  Dec(R.B.Y,7);
   R2.Copy(R); R2.Move(1,0); R2.A.X:=R2.B.X-1;
   New(SB, Init(R2)); Insert(SB);
   New(CodeCompleteLB, Init(R,1,SB));
@@ -151,7 +325,8 @@ begin
   R2.Copy(R); R2.Move(0,-1); R2.B.Y:=R2.A.Y+1; Dec(R2.A.X);
   Insert(New(PLabel, Init(R2, label_codecomplete_keywords, CodeCompleteLB)));
 
-  R.Copy(R3); R.A.Y:=R.B.Y-4; Dec(R.B.X,14); Inc(R.A.X);
+  { Case choice }
+  R.Copy(R3); Dec(R.B.Y,2); R.A.Y:=R.B.Y-4; Inc(R.A.X); R.B.X:=R.A.X+15;
   Items:=NewSItem('Unc~h~anged',
            NewSItem('~L~ower',
            NewSItem('~U~pper',
@@ -162,6 +337,38 @@ begin
   Insert(New(PLabel, Init(R2, 'Case handling', RB)));
   Insert(RB);
 
+  { Mininum length inputline }
+  R.Copy(R3); R.A.Y:=R.B.Y-7;R.B.Y:=R.A.Y+1; Dec(R.B.X); R.A.X:=R.B.X -5;
+  New(MinInputL, Init(R,5));
+  MinInputL^.SetValidator(New(PRangeValidator, Init(1,255)));
+  Insert(MinInputL);
+  R2.Copy(R); R2.A.X:=20;Dec(R2.B.X,5);
+  Insert(New(PLabel, Init(R2, 'Min. length', MinInputL)));
+
+  { Standard/all units booleans }
+  Items:=nil;
+  Items:=NewSItem('Add standard units', Items);
+  Items:=NewSItem('Add available units', Items);
+  Items:=NewSItem('Show only unique', Items);
+  R.Copy(R3); R.A.Y:=R.B.Y-5;R.B.Y:=R.A.Y+3; Inc(R.A.X,18); Dec(R.B.X);
+  New(CB, Init(R, Items));
+  Insert(CB);
+  R2.Copy(R); R2.Move(0,-1); R2.B.Y:=R2.A.Y+1; Dec(R2.A.X);
+  Insert(New(PLabel, Init(R2, 'Unit handling', CB)));
+  R2.Copy(R); R2.Move(0,-1); R2.B.Y:=R2.A.Y+1;
+  If UseStandardUnitsInCodeComplete then
+    CB^.Press(0);
+  If UseAllUnitsInCodeComplete then
+    CB^.Press(1);
+
+  { Standard unit name boolean }
+  R.Copy(R3); R.A.Y:=R.B.Y-1; Inc(R.A.X); Dec(R.B.X);
+  New(InputL,Init(R,255));
+  Insert(InputL);
+  InputL^.SetValidator(New(PFilterValidator,Init(NumberChars+AlphaChars+[','])));
+  R2.Copy(R); R2.Move(0,-1); R2.B.Y:=R2.A.Y+1; Dec(R2.A.X);R2.B.X:=R2.A.X+25;
+  Insert(New(PLabel, Init(R2, '~S~tandard unit list', InputL)));
+
   R.Copy(R3); R.A.X:=R.B.X-10; R.B.Y:=R.A.Y+2;
   Insert(New(PButton, Init(R, button_OK, cmOK, bfNormal)));
   R.Move(0,2);
@@ -215,19 +422,37 @@ end;
 function TCodeCompleteDialog.Execute: Word;
 var R: word;
     C: PCodeCompleteWordList;
-    I: integer;
+    NewVal, I: integer;
+    NewValStr : string;
 begin
   New(C, Init(10,20));
   if Assigned(CodeCompleteWords) then
   for I:=0 to CodeCompleteWords^.Count-1 do
     C^.Insert(NewStr(GetStr(CodeCompleteWords^.At(I))));
   CodeCompleteLB^.NewList(C);
+  InputL^.SetData(StandardUnits);
+  NewValStr:=IntToStr(CodeCompleteMinLen);
+  MinInputL^.SetData(NewValStr);
   R:=inherited Execute;
   if R=cmOK then
     begin
       if Assigned(CodeCompleteWords) then Dispose(CodeCompleteWords, Done);
       CodeCompleteWords:=C;
       CodeCompleteCase:=TCodeCompleteCase(RB^.Value);
+      UseStandardUnitsInCodeComplete:=CB^.Mark(0);
+      UseAllUnitsInCodeComplete:=CB^.Mark(1);
+      if UseStandardUnitsInCodeComplete and (not UseAllUnitsInCodeComplete or not assigned(UnitsCodeCompleteWords)) and
+         ((StandardUnits<>GetStr(InputL^.Data)) or not assigned(UnitsCodeCompleteWords)) then
+        begin
+          InputL^.GetData(StandardUnits);
+          AddStandardUnitsToCodeComplete;
+        end
+      else
+        InputL^.GetData(StandardUnits);
+      MinInputL^.GetData(NewValStr);
+      NewVal:=StrToInt(NewValStr);
+      if NewVal>0 then
+        CodeCompleteMinLen:=NewVal;
     end
   else
     Dispose(C, Done);

+ 40 - 23
ide/fpcompil.pas

@@ -125,7 +125,8 @@ procedure ParseUserScreen;
 
 procedure RegisterFPCompile;
 
-
+const
+  CompilingHiddenFile : PSourceWindow = nil;
 
 implementation
 
@@ -158,7 +159,8 @@ uses
   FPString,FPRedir,FPDesk,
   FPUsrScr,FPHelp,
 {$ifndef NODEBUG}FPDebug,{$endif}
-  FPConst,FPVars,FPUtils,FPIntf,FPSwitch;
+  FPConst,FPVars,FPUtils,
+  FPCodCmp,FPIntf,FPSwitch;
 
 {$ifndef NOOBJREG}
 const
@@ -778,7 +780,10 @@ function GetMainFile(Mode: TCompileMode): string;
 var FileName: string;
     P : PSourceWindow;
 begin
-  P:=Message(Desktop,evBroadcast,cmSearchWindow,nil);
+  if assigned(CompilingHiddenFile) then
+    P:=CompilingHiddenFile
+  else
+    P:=Message(Desktop,evBroadcast,cmSearchWindow,nil);
   if (PrimaryFileMain='') and (P=nil) then
     FileName:='' { nothing to compile }
   else
@@ -874,12 +879,15 @@ begin
   CtrlBreakHit:=false;
 { Create Compiler Status Dialog }
   CompilationPhase:=cpCompiling;
-  New(CompilerStatusDialog, Init);
-  CompilerStatusDialog^.SetState(sfModal,true);
-  { disable window closing }
-  CompilerStatusDialog^.Flags:=CompilerStatusDialog^.Flags and not wfclose;
-  Application^.Insert(CompilerStatusDialog);
-  CompilerStatusDialog^.Update;
+  if not assigned(CompilingHiddenFile) then
+    begin
+      New(CompilerStatusDialog, Init);
+      CompilerStatusDialog^.SetState(sfModal,true);
+      { disable window closing }
+      CompilerStatusDialog^.Flags:=CompilerStatusDialog^.Flags and not wfclose;
+      Application^.Insert(CompilerStatusDialog);
+      CompilerStatusDialog^.Update;
+    end;
 { hook compiler output }
 {$ifdef TP}
   do_status:=CompilerStatus;
@@ -975,7 +983,8 @@ begin
      (status.errorCount=0) then
     begin
        CompilationPhase:=cpLinking;
-       CompilerStatusDialog^.Update;
+       if assigned(CompilerStatusDialog) then
+         CompilerStatusDialog^.Update;
        SetStatus('Assembling and/or linking...');
 {$ifndef redircompiler}
        { At least here we want to catch output
@@ -1045,20 +1054,23 @@ begin
       CompilationPhase:=cpFailed;
 { Show end status }
   { reenable window closing }
-  CompilerStatusDialog^.Flags:=CompilerStatusDialog^.Flags or wfclose;
-  CompilerStatusDialog^.Update;
-  CompilerStatusDialog^.ReDraw;
-  CompilerStatusDialog^.SetState(sfModal,false);
-  if ((CompilationPhase in[cpAborted,cpDone,cpFailed]) or (ShowStatusOnError)) and (Mode<>cRun) then
-   repeat
-     CompilerStatusDialog^.GetEvent(E);
-     if IsExitEvent(E)=false then
-      CompilerStatusDialog^.HandleEvent(E);
-   until IsExitEvent(E) or not assigned(CompilerStatusDialog);
   if assigned(CompilerStatusDialog) then
     begin
-      Application^.Delete(CompilerStatusDialog);
-      Dispose(CompilerStatusDialog, Done);
+      CompilerStatusDialog^.Flags:=CompilerStatusDialog^.Flags or wfclose;
+      CompilerStatusDialog^.Update;
+      CompilerStatusDialog^.ReDraw;
+      CompilerStatusDialog^.SetState(sfModal,false);
+      if ((CompilationPhase in[cpAborted,cpDone,cpFailed]) or (ShowStatusOnError)) and (Mode<>cRun) then
+       repeat
+         CompilerStatusDialog^.GetEvent(E);
+         if IsExitEvent(E)=false then
+          CompilerStatusDialog^.HandleEvent(E);
+       until IsExitEvent(E) or not assigned(CompilerStatusDialog);
+      if assigned(CompilerStatusDialog) then
+        begin
+          Application^.Delete(CompilerStatusDialog);
+          Dispose(CompilerStatusDialog, Done);
+        end;
     end;
   CompilerStatusDialog:=nil;
 { end compilation returns true if the messagewindow should be removed }
@@ -1109,6 +1121,8 @@ begin
   if Not Assigned(Modules) and (CompilationPhase<>cpDone) and
      ((DesktopFileFlags and dfSymbolInformation)<>0) then
     ReadSymbolsFile(BrowserName);
+  if UseAllUnitsInCodeComplete and not assigned(CompilingHiddenFile) then
+    AddAvailableUnitsToCodeComplete(false);
 end;
 
 function NeedRecompile(Mode :TCompileMode; verbose : boolean): boolean;
@@ -1265,7 +1279,10 @@ end;
 end.
 {
   $Log$
-  Revision 1.9  2002-08-26 13:03:14  pierre
+  Revision 1.10  2002-09-04 14:07:12  pierre
+   + Enhance code complete by inserting unit symbols
+
+  Revision 1.9  2002/08/26 13:03:14  pierre
    + add a lock to speed up parsing of userscreen
 
   Revision 1.8  2002/04/10 22:37:37  pierre