From 5a1919ec07565c58cd862bbddaf6c3112d4fc852 Mon Sep 17 00:00:00 2001 From: Michael Schimmel Date: Wed, 24 Sep 2025 08:38:26 +0200 Subject: [PATCH] Added Wildcards and -fc to PasIntfExtract --- IntfExtract/ExtractPascalInterfaces.dpr | 98 ++++++++++++++++++++++--- 1 file changed, 87 insertions(+), 11 deletions(-) diff --git a/IntfExtract/ExtractPascalInterfaces.dpr b/IntfExtract/ExtractPascalInterfaces.dpr index d9a6796..e0ea8aa 100644 --- a/IntfExtract/ExtractPascalInterfaces.dpr +++ b/IntfExtract/ExtractPascalInterfaces.dpr @@ -41,6 +41,10 @@ type InDegree: Integer; Processed: Boolean; + // Fields for the -fc (focus complete) feature + IsFcStartFile: Boolean; + FullSource: TStringList; + constructor Create(const AFilePath: string); destructor Destroy; override; function ParseUnit: Boolean; @@ -100,6 +104,8 @@ begin AdjacencyList := TUnitInfoList.Create; InDegree := 0; Processed := False; + IsFcStartFile := False; + FullSource := TStringList.Create; end; destructor TUnitInfo.Destroy; @@ -108,6 +114,7 @@ begin InterfaceUses.Free; FOriginalLines.Free; AdjacencyList.Free; + FullSource.Free; inherited Destroy; end; @@ -425,7 +432,6 @@ begin end else if inUsesBlock then begin - // FIXED: Use AppendLine to preserve newlines for comment stripping logic usesBuilder.AppendLine(Trim(LineValue)); lineIsForUses := True; end; @@ -534,6 +540,7 @@ var writeToClipboard: Boolean; currentParamIndex: Integer; focusMode: Boolean; + fcMode: Boolean; focusFilesParameter: string; initialFocusFiles: TStringList; filesToExcludeFromOutput: TStringList; @@ -552,10 +559,11 @@ begin filesToExcludeFromOutput := nil; exitcode := 0; focusMode := False; + fcMode := False; focusFilesParameter := ''; try - var usageStr := 'Usage: ExtractPascalInterfaces.exe [-r] [-dirs ] [-f | -fx ] [-o | -c] ...'; + var usageStr := 'Usage: ExtractPascalInterfaces.exe [-r] [-dirs ] [-f|-fx|-fc ] [-o | -c] ...'; WriteLn('Delphi Interface Extractor'); sourceDirectories := TList.Create; @@ -623,11 +631,11 @@ begin exit; end; end - else if SameText(currentParam, '-f') or SameText(currentParam, '-fx') then + else if SameText(currentParam, '-f') or SameText(currentParam, '-fx') or SameText(currentParam, '-fc') then begin if focusMode then begin - WriteLn('Error: -f and -fx options cannot be used together.'); + WriteLn('Error: Focus options (-f, -fx, -fc) cannot be used together.'); WriteLn(usageStr); exitcode := 1; exit; @@ -636,10 +644,42 @@ begin if currentParamIndex + 1 <= ParamCount then begin focusMode := True; + fcMode := SameText(currentParam, '-fc'); focusFilesParameter := ParamStr(currentParamIndex + 1); - initialFocusFiles.Text := StringReplace(focusFilesParameter, ';', sLineBreak, [rfReplaceAll]); - if SameText(currentParam, '-fx') then - filesToExcludeFromOutput.Text := initialFocusFiles.Text; + var patternsList := TStringList.Create; + var expandedFocusFiles := TStringList.Create; + try + patternsList.Text := StringReplace(focusFilesParameter, ';', sLineBreak, [rfReplaceAll]); + for var pattern in patternsList do + begin + if (pattern.Contains('*')) or (pattern.Contains('?')) then + begin + var searchPath := ExtractFilePath(pattern); + var searchMask := ExtractFileName(pattern); + if searchPath = '' then + searchPath := TDirectory.GetCurrentDirectory; + try + expandedFocusFiles.AddStrings(TDirectory.GetFiles(searchPath, searchMask)); + except + on E: EDirectoryNotFoundException do + WriteLn('Warning: Directory for pattern not found, skipping: ' + pattern); + end; + end + else + begin + expandedFocusFiles.Add(pattern); + end; + end; + + initialFocusFiles.Clear; + initialFocusFiles.AddStrings(expandedFocusFiles); + + if SameText(currentParam, '-fx') then + filesToExcludeFromOutput.Text := initialFocusFiles.Text; + finally + patternsList.Free; + expandedFocusFiles.Free; + end; Inc(currentParamIndex, 2); end else @@ -822,6 +862,19 @@ begin end; end; + if fcMode then + begin + // After filtering, identify the start files and store their full source + for var unitInfo in allUnits.Values do + begin + if initialFocusFiles.IndexOf(unitInfo.FilePath) > -1 then + begin + unitInfo.IsFcStartFile := True; + unitInfo.FullSource.AddStrings(unitInfo.FOriginalLines); + end; + end; + end; + WriteLn('Building dependency graph...'); for var currentUnit in allUnits.Values do for var usedUnitName in currentUnit.InterfaceUses do @@ -921,7 +974,13 @@ begin outputContent.Add('// - ' + dirPath + IfThen(recursiveSearch, ' (recursive)', '')); if focusMode then begin - var modeStr := IfThen(filesToExcludeFromOutput.Count > 0, '-fx', '-f'); + var modeStr: string; + if fcMode then + modeStr := '-fc' + else if filesToExcludeFromOutput.Count > 0 then + modeStr := '-fx' + else + modeStr := '-f'; outputContent.Add('// Focus mode (' + modeStr + ') active for files: ' + focusFilesParameter); end; outputContent.Add('// Generated on: ' + DateTimeToStr(Now)); @@ -963,15 +1022,32 @@ begin if filesToExcludeFromOutput.IndexOf(item.FilePath) > -1 then Continue; - if item.InterfaceSection.Count > 0 then + if item.IsFcStartFile then begin + // For -fc start files, add the complete source code outputContent .Add('//=================================================================================================='); - outputContent.Add('//== UNIT START: ' + item.Name + ' (from ' + ExtractFileName(item.FilePath) + ')'); + outputContent.Add('//== FULL UNIT START: ' + item.Name + ' (from ' + ExtractFileName(item.FilePath) + ')'); + outputContent + .Add('//=================================================================================================='); + outputContent.AddStrings(item.FullSource); + outputContent + .Add('//=================================================================================================='); + outputContent.Add('//== FULL UNIT END: ' + item.Name); + outputContent + .Add('//=================================================================================================='); + outputContent.Add(''); + end + else if item.InterfaceSection.Count > 0 then + begin + // For all other units, add the interface section only + outputContent + .Add('//=================================================================================================='); + outputContent.Add('//== INTERFACE START: ' + item.Name + ' (from ' + ExtractFileName(item.FilePath) + ')'); outputContent .Add('//=================================================================================================='); outputContent.AddStrings(item.InterfaceSection); - outputContent.Add('//== UNIT END: ' + item.Name); + outputContent.Add('//== INTERFACE END: ' + item.Name); outputContent .Add('//=================================================================================================='); outputContent.Add('');