-
-
Save saropa/c63be2d1770b9721483e06029421323c to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #Requires -Version 7 | |
| <# | |
| .SYNOPSIS | |
| Counts lines, characters (bytes), and calculates total size (KB) of code/files in the parent directory. | |
| Groups by file extension (incl. '[No Extension]') and top directories. Provides sorted/colored summaries. | |
| .DESCRIPTION | |
| Scans files, counts lines & gets size in bytes (using FileInfo.Length for accuracy across all types). | |
| Groups results by extension (files without extensions are grouped as '[No Extension]') AND by directory level. | |
| Outputs summaries using Format-Table with fixed-width columns and ANSI color: | |
| 1. Unfiltered Results by Extension (Sorted by Extension, includes Size KB). | |
| 2. Included Files Summary by Extension (> Min lines, Sorted by Lines Desc, Colored, includes Size KB). | |
| 3. Excluded File Details by Extension (Shows ALL excluded types found, Sorted by Lines Desc, Colored, includes Size KB). Clarifies that Min lines doesn't apply here. | |
| 4. Directory Summary (Top 1-2 levels > Min lines, Sorted by Lines Desc, Colored, includes Size KB). Based on Included files only. | |
| 5. Top 10 Included Files (by lines). | |
| 6. Top 10 Excluded Files (by raw lines). | |
| Displays a colorful ASCII art logo. | |
| .PARAMETER ExcludePatterns | |
| Array of patterns to exclude files/directories. Supports wildcards (*). | |
| .PARAMETER ExcludeExtensions | |
| Array of file extensions (lowercase, leading dot) to exclude. | |
| .PARAMETER MinReportLineCount | |
| Minimum total lines for a group to appear in INCLUDED and DIRECTORY summary tables. | |
| .PARAMETER ColorThresholdHigh, ColorThresholdMedium, ColorThresholdLow, ColorThresholdCharsHigh, ColorThresholdCharsMedium, ColorThresholdCharsLow, ColorThresholdKBHigh, ColorThresholdKBMedium, ColorThresholdKBLow | |
| Thresholds for coloring Lines, Chars (Bytes), and Size (KB) columns in summary tables. | |
| .NOTES | |
| Version: 1.25 <-- Updated Version | |
| Author: Saropa (Adapted for Line Counting by AI) | |
| Copyright: © 2024 Saropa | |
| Usage: Run from PowerShell. Use -Verbose for detailed logs. Ensure terminal supports ANSI colors. | |
| #> | |
| # --- Configuration --- | |
| # $VerbosePreference = 'Continue' # <--- Enable for detailed debugging | |
| param( | |
| # --- ExcludePatterns --- | |
| [string[]]$ExcludePatterns = @( | |
| "*.g.dart", "*.freezed.dart", "lib/generated_plugin_registrant.dart", | |
| "build/*", ".dart_tool/*", "bin/cache/*", "test/.test_coverage.dart", | |
| "android/*", "ios/*", "dependency_overrides/*", "assets/*", | |
| ".idea/*", ".vscode/*" | |
| ), | |
| # --- ExcludeExtensions --- | |
| [string[]]$ExcludeExtensions = @( | |
| '.png', '.jpg', '.jpeg', '.gif', '.bmp', '.svg', '.webp', '.ico', '.xcf', | |
| '.zip', '.tar', '.gz', '.rar', '.7z', '.ttf', '.otf', '.woff', '.woff2', | |
| '.lnk', '.mp3', '.wav', '.ogg', '.aac', '.mp4', '.mov', '.avi', '.webm', | |
| '.pdf', '.exe', '.dll', '.so', '.dylib', '.bat', '.cmd', '.ps1', '.sh', | |
| '.apk', '.aab', '.ipa', '.obj', '.o', '.a', '.lib', '.bin', '.dat', '.data', | |
| '.dill', '.aar', '.jar', '.dex', '.class', '.pyc', '.pdb', | |
| '.stamp', '.d', '.dep', '.cache', '.idx', '.vsidx', '.jks', '.keystore', | |
| '.log', '.sqlite', '.db', '.lock', '.metadata', '.bak' # Restored .keystore | |
| ), | |
| [int]$MinReportLineCount = 10, | |
| # Color Thresholds - Lines | |
| [long]$ColorThresholdHigh = 10000, [long]$ColorThresholdMedium = 1000, [long]$ColorThresholdLow = 100, | |
| # Color Thresholds - Chars (Bytes) | |
| [long]$ColorThresholdCharsHigh = 500000, [long]$ColorThresholdCharsMedium = 50000, [long]$ColorThresholdCharsLow = 5000, | |
| # --- ADDED Color Thresholds - Size (KB) --- | |
| [long]$ColorThresholdKBHigh = 5000, [long]$ColorThresholdKBMedium = 500, [long]$ColorThresholdKBLow = 50 # Default KB thresholds | |
| ) | |
| #region Functions | |
| # Function to display the Saropa "S" logo in ASCII art | |
| function Show-SaropaLogo { | |
| # ... (logo code omitted for brevity) ... | |
| Write-Host " | |
| `r`n`r`n`r`n | |
| $([char]0x1b)[38;5;208m ....$([char]0x1b)[0m | |
| $([char]0x1b)[38;5;208m `-+shdmNMMMMNmdhs+-$([char]0x1b)[0m | |
| $([char]0x1b)[38;5;209m -odMMMNyo/-..````.++:+o+/-$([char]0x1b)[0m | |
| $([char]0x1b)[38;5;215m `/dMMMMMM/` ``````````$([char]0x1b)[0m | |
| $([char]0x1b)[38;5;220m `dMMMMMMMMNdhhhdddmmmNmmddhs+-$([char]0x1b)[0m | |
| $([char]0x1b)[38;5;226m /MMMMMMMMMMMMMMMMMMMMMMMMMMMMMNh/$([char]0x1b)[0m | |
| $([char]0x1b)[38;5;190m . :sdmNNNNMMMMMNNNMMMMMMMMMMMMMMMMm+$([char]0x1b)[0m | |
| $([char]0x1b)[38;5;154m o `..~~~::~+==+~:/+sdNMMMMMMMMMMMo$([char]0x1b)[0m | |
| $([char]0x1b)[38;5;118m m .+NMMMMMMMMMN$([char]0x1b)[0m | |
| $([char]0x1b)[38;5;123m m+ :MMMMMMMMMm$([char]0x1b)[0m | |
| $([char]0x1b)[38;5;87m /N: :MMMMMMMMM/$([char]0x1b)[0m | |
| $([char]0x1b)[38;5;51m oNs. `+NMMMMMMMMo$([char]0x1b)[0m | |
| $([char]0x1b)[38;5;45m :dNy/. ./smMMMMMMMMm:$([char]0x1b)[0m | |
| $([char]0x1b)[38;5;39m `/dMNmhyso+++oosydNNMMMMMMMMMd/$([char]0x1b)[0m | |
| $([char]0x1b)[38;5;33m .odMMMMMMMMMMMMMMMMMMMMdo-$([char]0x1b)[0m | |
| $([char]0x1b)[38;5;57m `-+shdNNMMMMNNdhs+-$([char]0x1b)[0m | |
| $([char]0x1b)[38;5;57m ````$([char]0x1b)[0m | |
| " -ForegroundColor Green | |
| $coloredCopyright = @" | |
| $([char]0x1b)[38;5;195m© 2024 Saropa. All rights reserved. | |
| $([char]0x1b)[38;5;117mhttps://saropa.com | |
| "@ | |
| Write-Host $coloredCopyright | |
| $email = "dev.tools@saropa.com" | |
| $esc = [char]27 | |
| Write-Host " $esc]8;;mailto:$email$esc\Email $email$esc]8;;$esc\`n" | |
| } | |
| # Function to convert path to Unix-style separators | |
| function Convert-PathToUnixStyle { param([string]$Path) ; if ([string]::IsNullOrEmpty($Path)) { return "" } ; return $Path -replace '\\', '/' } | |
| # Function to normalize a directory path | |
| function Normalize-DirectoryPath { param([string]$Path) ; if ([string]::IsNullOrEmpty($Path)) { return $null } ; try { $absPath = Resolve-Path -Path $Path -ErrorAction Stop ; $unixPath = Convert-PathToUnixStyle -Path $absPath.ProviderPath ; if (-not $unixPath.EndsWith('/')) { $unixPath += '/' } ; return $unixPath } catch { Write-Warning "Could not normalize directory path: $Path. Error: $($_.Exception.Message)" ; return $null } } | |
| # Function to get the effective extension (lowercase), returns "[No Extension]" if none | |
| function Get-EffectiveExtension { | |
| param( | |
| [System.IO.FileInfo]$FileInfo, | |
| [string]$NoExtensionPlaceholder = '[No Extension]' # Define placeholder here | |
| ) | |
| $fileName = $FileInfo.Name | |
| $baseExtension = $FileInfo.Extension | |
| $effectiveExtension = $baseExtension | |
| # Handle multi-part extensions explicitly | |
| if ($fileName.EndsWith('.g.dart', [System.StringComparison]::OrdinalIgnoreCase)) { $effectiveExtension = '.g.dart' } | |
| elseif ($fileName.EndsWith('.freezed.dart', [System.StringComparison]::OrdinalIgnoreCase)) { $effectiveExtension = '.freezed.dart' } | |
| elseif ($fileName.EndsWith('.config.yaml', [System.StringComparison]::OrdinalIgnoreCase)) { $effectiveExtension = '.config.yaml' } | |
| # Handle dotfiles like '.gitignore' where Extension property might be empty or just '.' | |
| elseif (-not [string]::IsNullOrEmpty($baseExtension) -and $baseExtension -eq $fileName -and $fileName.StartsWith('.')) { $effectiveExtension = $fileName } | |
| # Final check and normalization | |
| if (-not [string]::IsNullOrEmpty($effectiveExtension)) { | |
| if (-not $effectiveExtension.StartsWith('.')) { | |
| $effectiveExtension = '.' + $effectiveExtension | |
| } | |
| return $effectiveExtension.ToLowerInvariant() | |
| } else { | |
| # Return placeholder if no extension was found | |
| return $NoExtensionPlaceholder | |
| } | |
| } | |
| # Function to check if a file should be excluded | |
| function Test-IsExcluded { param([Parameter(Mandatory=$true)][System.IO.FileInfo]$FileInfo, [Parameter(Mandatory=$true)][string[]]$Patterns, [Parameter(Mandatory=$true)][string]$NormalizedBaseDirectory, [Parameter(Mandatory=$true)][string[]]$ExcludedExtensions) ; Write-Verbose "--- Testing Exclusions for: $($FileInfo.FullName) ---" ; $fileExtension = Get-EffectiveExtension -FileInfo $FileInfo -NoExtensionPlaceholder $null ; if (-not [string]::IsNullOrEmpty($fileExtension)) { if ($ExcludedExtensions -contains $fileExtension) { Write-Verbose "[RESULT] Excluded: Extension type '$fileExtension' is in the extension exclusion list." ; return $true } else { Write-Verbose "[Check 1 OK] Extension '$fileExtension' not in extension exclusion list." } } else { Write-Verbose "[Check 1 SKIPPED] File has no detectable extension." } ; $unixFullPath = Convert-PathToUnixStyle -Path $FileInfo.FullName ; $relativePathString = $null ; if ($NormalizedBaseDirectory -ne $null -and $unixFullPath.StartsWith($NormalizedBaseDirectory, [System.StringComparison]::OrdinalIgnoreCase)) { $relativePathString = $unixFullPath.Substring($NormalizedBaseDirectory.Length) ; Write-Verbose "[Check 2 Path] Relative Path: '$relativePathString'" } else { Write-Verbose "[Check 2 Path] Cannot determine relative path or file '$unixFullPath' outside base '$NormalizedBaseDirectory'." ; Write-Verbose "[RESULT] Included: Cannot apply path patterns." ; return $false } ; foreach ($pattern in $Patterns) { $patternCheckResult = $false ; $matchType = "Unknown" ; $normalizedPattern = $pattern ; if ($normalizedPattern.StartsWith("*.")) { $matchType = "Suffix" ; if ($FileInfo.Name -like $normalizedPattern) { $patternCheckResult = $true } } elseif ($normalizedPattern.EndsWith("/*")) { $matchType = "Directory" ; $dirPattern = $normalizedPattern.Substring(0, $normalizedPattern.Length - 1) ; if ($relativePathString -like "$dirPattern*") { $patternCheckResult = $true } } else { $matchType = "Exact" ; if ($relativePathString -eq $normalizedPattern) { $patternCheckResult = $true } } ; if ($patternCheckResult) { Write-Verbose "[RESULT] Excluded: Relative path '$relativePathString' matches ($matchType) pattern '$pattern'." ; return $true } else { Write-Verbose "[Check 2 Pattern OK] Relative path '$relativePathString' does NOT match ($matchType) pattern '$pattern'." } } ; Write-Verbose "[RESULT] Included: No exclusion rules matched." ; return $false } | |
| # Function to get top directory levels (1 or 2), handles root/unknown | |
| function Get-DirectoryLevels { | |
| param( | |
| [string]$RelativePath, | |
| [string]$RootPlaceholder = '[Root Directory]', | |
| [string]$RootFilePlaceholder = '[Project Root File]' | |
| ) | |
| if ([string]::IsNullOrEmpty($RelativePath)) { return $RootPlaceholder } # Or maybe '[Unknown Path]'? | |
| $parts = $RelativePath.Split('/') | |
| if ($parts.Count -le 1) { | |
| # It's a file directly in the base directory | |
| return $RootFilePlaceholder | |
| } elseif ($parts.Count -eq 2) { | |
| # e.g., "lib/file.txt" -> return "lib" | |
| return $parts[0] | |
| } else { | |
| # e.g., "lib/src/file.txt" -> return "lib/src" | |
| return "$($parts[0])/$($parts[1])" | |
| } | |
| } | |
| # Function to format number with ANSI colors based on thresholds (4 Colors) | |
| function Format-NumberWithColor { | |
| param( | |
| [long]$Number, | |
| [long]$ThresholdHigh, | |
| [long]$ThresholdMedium, | |
| [long]$ThresholdLow | |
| ) | |
| $esc = [char]0x1b | |
| $reset = "$esc[0m" | |
| $red = "$esc[38;5;196m" # Bright Red | |
| $yellow = "$esc[38;5;220m" # Bright Yellow | |
| $blue = "$esc[38;5;39m" # Bright Blue | |
| $formattedNumber = "{0:N0}" -f $Number | |
| if ($Number -ge $ThresholdHigh) { return "$red$formattedNumber$reset" } | |
| elseif ($Number -ge $ThresholdMedium) { return "$yellow$formattedNumber$reset" } | |
| elseif ($Number -ge $ThresholdLow) { return "$blue$formattedNumber$reset" } | |
| else { return $formattedNumber } | |
| } | |
| #endregion Functions | |
| # --- Main Script --- | |
| Show-SaropaLogo | |
| $parentDirRaw = $null; $normalizedParentDir = $null | |
| try { | |
| $parentDirRaw = Split-Path -Path $PSScriptRoot -Parent -ErrorAction Stop | |
| $normalizedParentDir = Normalize-DirectoryPath -Path $parentDirRaw | |
| if ($normalizedParentDir -eq $null) { throw "Failed." } | |
| } | |
| catch { Write-Error "Could not determine/normalize parent directory ($PSScriptRoot). Error: $($_.Exception.Message)"; Exit 1 } | |
| $normalizedExcludeExtensions = $ExcludeExtensions | ForEach-Object { $_.ToLowerInvariant() } | |
| Write-Host "-----------------------------------------------------" | |
| Write-Host " Counting Lines & Chars (Bytes) of Code (v1.25)" # <-- Updated Version | |
| Write-Host " Target Directory: $normalizedParentDir" | |
| Write-Host " Minimum Lines for Included/Directory Tables: $MinReportLineCount" | |
| Write-Host " Color Thresholds (Lines): High >= $ColorThresholdHigh (Red), Medium >= $ColorThresholdMedium (Yellow), Low >= $ColorThresholdLow (Blue)" | |
| Write-Host " Color Thresholds (Chars): High >= $ColorThresholdCharsHigh (Red), Medium >= $ColorThresholdCharsMedium (Yellow), Low >= $ColorThresholdCharsLow (Blue)" | |
| Write-Host " Color Thresholds (SizeKB): High >= $ColorThresholdKBHigh (Red), Medium >= $ColorThresholdKBMedium (Yellow), Low >= $ColorThresholdKBLow (Blue)" # ADDED KB thresholds info | |
| Write-Host "" | |
| Write-Host "Exclusion Patterns Applied:" ; $ExcludePatterns | ForEach-Object { Write-Host " - $_" } | |
| Write-Host "" ; Write-Host "Excluded Extension Types:" | |
| $maxWidth = [Math]::Max(60, $Host.UI.RawUI.WindowSize.Width - 5) ; $currentLine = " - " ; $firstExt = $true | |
| foreach ($ext in $normalizedExcludeExtensions) { $extWithComma = if ($firstExt) { $ext } else { ", $ext" } ; if (($currentLine.Length + $extWithComma.Length) -gt $maxWidth) { Write-Host $currentLine; $currentLine = " $ext" } else { $currentLine += $extWithComma } ; $firstExt = $false } ; Write-Host $currentLine | |
| Write-Host "-----------------------------------------------------`n" | |
| $totalFilesFound = 0 ; [long]$totalLinesFound = 0 ; [long]$totalCharsFound = 0 | |
| $processedFilesData = [System.Collections.Generic.List[PSCustomObject]]::new() | |
| $noExtensionPlaceholder = '[No Extension]' # Consistent placeholder | |
| $rootFilePlaceholder = '[Project Root File]' | |
| $rootPlaceholder = '[Root Directory]' | |
| $unknownPathPlaceholder = '[Unknown Path]' # For files outside base dir | |
| # --- Scan, Count, and Process Files --- | |
| Write-Host "Scanning files recursively..." | |
| $files = Get-ChildItem -Path $normalizedParentDir -Recurse -File -ErrorAction SilentlyContinue | |
| $totalFileCount = $files.Count | |
| Write-Host "Found $totalFileCount files to process..." | |
| Write-Host "Processing files, counting lines & characters (bytes), and determining exclusions..." | |
| $progressCount = 0 ; $updateInterval = [Math]::Max(1, [Math]::Floor($totalFileCount / 50)) | |
| foreach ($file in $files) { | |
| $progressCount++ ; if ($totalFileCount -gt 0) { if ($progressCount % $updateInterval -eq 0 -or $progressCount -eq $totalFileCount) { $percentComplete = [Math]::Floor(($progressCount / $totalFileCount) * 100) ; Write-Progress -Activity "Processing Files" -Status "File $progressCount of $totalFileCount ($percentComplete%)" -PercentComplete $percentComplete -CurrentOperation $file.Name } } | |
| [long]$lineCount = 0 ; [long]$rawLineCount = 0 | |
| [long]$charCount = 0 ; [long]$rawCharCount = 0 | |
| # --- FIX 3: Get Character/Byte Count using FileInfo.Length for accuracy --- | |
| $rawCharCount = $file.Length | |
| # Get Line Count (only if needed or for raw count) | |
| try { | |
| $reader = [System.IO.StreamReader]::new($file.FullName) | |
| while ($reader.ReadLine() -ne $null) { $rawLineCount++ } | |
| $reader.Close() ; $reader.Dispose() | |
| } catch { Write-Verbose "[WARNING] Could not read file for line count: $($file.FullName) - Error: $($_.Exception.Message)" } | |
| # Determine effective extension (gets placeholder if none) | |
| $effectiveExtension = Get-EffectiveExtension -FileInfo $file -NoExtensionPlaceholder $noExtensionPlaceholder | |
| # Check exclusions | |
| $isExcluded = Test-IsExcluded -FileInfo $file -Patterns $ExcludePatterns -NormalizedBaseDirectory $normalizedParentDir -ExcludedExtensions $normalizedExcludeExtensions | |
| # Set included counts (0 if excluded) | |
| if (-not $isExcluded) { $lineCount = $rawLineCount ; $charCount = $rawCharCount } | |
| else { $lineCount = 0 ; $charCount = 0 } # Effective counts are 0 for excluded | |
| # Determine Directory Level | |
| $unixFullPath = Convert-PathToUnixStyle -Path $file.FullName | |
| $relativePathString = $null | |
| $dirLevel = $unknownPathPlaceholder # Default if path normalization fails | |
| if ($normalizedParentDir -ne $null -and $unixFullPath.StartsWith($normalizedParentDir, [System.StringComparison]::OrdinalIgnoreCase)) { | |
| $relativePathString = $unixFullPath.Substring($normalizedParentDir.Length) | |
| $dirLevel = Get-DirectoryLevels -RelativePath $relativePathString -RootFilePlaceholder $rootFilePlaceholder -RootPlaceholder $rootPlaceholder | |
| } | |
| $processedFilesData.Add([PSCustomObject]@{ | |
| FullName = $file.FullName | |
| Extension = $effectiveExtension # Now includes placeholder | |
| RawLines = $rawLineCount | |
| RawChars = $rawCharCount # Accurate byte count | |
| Lines = $lineCount | |
| Chars = $charCount # Accurate byte count if included | |
| IsExcluded = $isExcluded | |
| DirectoryLevel = $dirLevel # Now includes placeholders | |
| }) | |
| $totalFilesFound++ | |
| $totalLinesFound += $rawLineCount | |
| $totalCharsFound += $rawCharCount # Sum of all file lengths (bytes) | |
| } | |
| if ($totalFileCount -gt 0) { Write-Progress -Activity "Processing Files" -Completed } | |
| # --- Process Results --- | |
| Write-Host "`nCalculating summaries..." | |
| $filteredFilesData = $processedFilesData | Where-Object { -not $_.IsExcluded } | |
| $excludedFilesData = $processedFilesData | Where-Object { $_.IsExcluded } | |
| # --- MODIFIED Get-SummaryData to handle placeholders --- | |
| function Get-SummaryData { | |
| param( | |
| $Data, | |
| [string]$GroupByProperty, # 'Extension' or 'DirectoryLevel' | |
| [string]$MinCountProperty = 'Lines', | |
| [int]$MinCountValue = 0, | |
| [bool]$UseRawCounts = $false | |
| ) | |
| # Placeholders are now part of the data, no separate 'WithoutValue' needed | |
| $result = @{ Summary = @() } | |
| if ($null -eq $Data -or $Data.Count -eq 0) { return $result } | |
| $linesProp = if ($UseRawCounts) { 'RawLines' } else { 'Lines' } | |
| $charsProp = if ($UseRawCounts) { 'RawChars' } else { 'Chars' } | |
| try { | |
| # Group by the property (which includes placeholders like '[No Extension]') | |
| $groupedData = $Data | Group-Object $GroupByProperty -ErrorAction Stop | |
| # Aggregate data | |
| $summary = $groupedData | Select-Object @{Name=$GroupByProperty; Expression={$_.Name}}, # Name is now the extension or dir level (or placeholder) | |
| @{Name='Files'; Expression={$_.Count}}, | |
| @{Name='Lines'; Expression={ ($_.Group.$linesProp | Measure-Object -Sum -ErrorAction SilentlyContinue).Sum -as [long] }}, | |
| @{Name='Chars'; Expression={ ($_.Group.$charsProp | Measure-Object -Sum -ErrorAction SilentlyContinue).Sum -as [long] }}, # Chars now accurately reflects bytes | |
| @{Name='SizeKB'; Expression={ [Math]::Round( (($_.Group.$charsProp | Measure-Object -Sum -ErrorAction SilentlyContinue).Sum -as [long]) / 1024 ) }} | |
| # Apply minimum filter based on the specified property and value | |
| $summary = $summary | Where-Object { $_.$MinCountProperty -ge $MinCountValue } -ErrorAction Stop | |
| $result.Summary = $summary | |
| Write-Verbose "Get-SummaryData: Grouped by '$GroupByProperty'. Found $($summary.Count) groups where '$MinCountProperty' >= $MinCountValue (using $(if($UseRawCounts){'Raw'}else{'Effective'}) counts)." | |
| } catch { | |
| Write-Warning "Get-SummaryData: Error during processing for '$GroupByProperty'. Error: $($_.Exception.Message)" | |
| # Reset on error | |
| $result.Summary = @() | |
| } | |
| return $result | |
| } | |
| # --- Calculate Summaries --- | |
| # 1. Unfiltered (Raw counts, Min Files = 0 - show all found extensions/placeholders) | |
| $unfilteredResult = Get-SummaryData -Data $processedFilesData -GroupByProperty 'Extension' -MinCountProperty 'Files' -MinCountValue 0 -UseRawCounts $true | |
| $unfilteredSummaryTable = $unfilteredResult.Summary | Sort-Object Extension | |
| # 2. Included (Effective counts, Min Lines = $MinReportLineCount) | |
| $includedExtResult = Get-SummaryData -Data $filteredFilesData -GroupByProperty 'Extension' -MinCountProperty 'Lines' -MinCountValue $MinReportLineCount | |
| $includedSummaryTableExt = $includedExtResult.Summary | Sort-Object Lines -Descending | |
| # 3. Excluded (Raw counts, Min Files = 1 - show all *found* excluded types/placeholders) | |
| $excludedExtResult = Get-SummaryData -Data $excludedFilesData -GroupByProperty 'Extension' -MinCountProperty 'Files' -MinCountValue 1 -UseRawCounts $true | |
| $excludedSummaryTableExt = $excludedExtResult.Summary | Sort-Object Lines -Descending # Sort by Raw Lines desc | |
| # 4. Directory (Effective counts from Included Files, Min Lines = $MinReportLineCount) | |
| $directoryResult = Get-SummaryData -Data $filteredFilesData -GroupByProperty 'DirectoryLevel' -MinCountProperty 'Lines' -MinCountValue $MinReportLineCount | |
| $directorySummaryTable = $directoryResult.Summary | Sort-Object Lines -Descending | |
| # 5. Top Included Files | |
| $topIncludedFiles = $filteredFilesData | Sort-Object Lines -Descending | Select-Object -First 10 FullName, Lines, Chars | |
| # 6. Top Excluded Files | |
| $topExcludedFiles = $excludedFilesData | Sort-Object RawLines -Descending | Select-Object -First 10 FullName, @{Name="Lines (Raw)"; Expression={$_.RawLines}}, @{Name="Chars (Raw)"; Expression={$_.RawChars}} | |
| # Calculate Totals | |
| $totalFilesFiltered = ($filteredFilesData | Measure-Object).Count | |
| [long]$totalLinesFiltered = ($filteredFilesData.Lines | Measure-Object -Sum -ErrorAction SilentlyContinue).Sum | |
| [long]$totalCharsFiltered = ($filteredFilesData.Chars | Measure-Object -Sum -ErrorAction SilentlyContinue).Sum # Uses accurate Chars | |
| [long]$totalSizeKBFiltered = [Math]::Round($totalCharsFiltered / 1024) | |
| $totalFilesExcluded = ($excludedFilesData | Measure-Object).Count | |
| [long]$totalLinesExcluded = ($excludedFilesData.RawLines | Measure-Object -Sum -ErrorAction SilentlyContinue).Sum | |
| [long]$totalCharsExcluded = ($excludedFilesData.RawChars | Measure-Object -Sum -ErrorAction SilentlyContinue).Sum # Uses accurate RawChars | |
| [long]$totalSizeKBExcluded = [Math]::Round($totalCharsExcluded / 1024) | |
| [long]$totalSizeKBFound = [Math]::Round($totalCharsFound / 1024) | |
| # --- Display Results --- | |
| # --- MODIFIED: Added SizeKB COLORING to Format Definitions --- | |
| $commonFormatProperties = @( | |
| @{Name='Files'; Expression={"{0:N0}" -f $_.Files}; Alignment='Right'; Width=16}, | |
| @{Name='Lines'; Expression={ Format-NumberWithColor -Number $_.Lines -ThresholdHigh $ColorThresholdHigh -ThresholdMedium $ColorThresholdMedium -ThresholdLow $ColorThresholdLow }; Alignment='Right'; Width=16}, | |
| @{Name='Chars'; Expression={ Format-NumberWithColor -Number $_.Chars -ThresholdHigh $ColorThresholdCharsHigh -ThresholdMedium $ColorThresholdCharsMedium -ThresholdLow $ColorThresholdCharsLow }; Alignment='Right'; Width=18}, | |
| # --- ADDED KB Coloring --- | |
| @{Name='Size (KB)'; Expression={ Format-NumberWithColor -Number $_.SizeKB -ThresholdHigh $ColorThresholdKBHigh -ThresholdMedium $ColorThresholdKBMedium -ThresholdLow $ColorThresholdKBLow }; Alignment='Right'; Width=16} | |
| ) | |
| $unfilteredFormat = @( @{Name='Extension'; Expression={$_.Extension}; Width=30} ) + $commonFormatProperties | |
| $includedFormat = @( @{Name='Extension'; Expression={$_.Extension}; Width=30} ) + $commonFormatProperties | |
| $excludedFormat = @( @{Name='Extension'; Expression={$_.Extension}; Width=30} ) + $commonFormatProperties # Using colored props now | |
| $directoryFormat = @( @{Name='Directory'; Expression={$_.DirectoryLevel}; Width=50} ) + $commonFormatProperties | |
| # Top File formats remain unchanged | |
| $topIncludedFormat = @( | |
| @{Name='FullName'; Expression={$_.FullName}; Width=120}, | |
| @{Name='Lines'; Expression={"{0:N0}" -f $_.Lines}; Alignment='Right'; Width=16}, | |
| @{Name='Chars'; Expression={"{0:N0}" -f $_.Chars}; Alignment='Right'; Width=18} # Chars is accurate byte count now | |
| ) | |
| $topExcludedFormat = @( | |
| @{Name='FullName'; Expression={$_.FullName}; Width=120}, | |
| @{Name='Lines (Raw)'; Expression={"{0:N0}" -f $_.'Lines (Raw)'}; Alignment='Right'; Width=16}, | |
| @{Name='Chars (Raw)'; Expression={"{0:N0}" -f $_.'Chars (Raw)'}; Alignment='Right'; Width=18} # Chars is accurate byte count now | |
| ) | |
| # 1. Unfiltered Results by Extension | |
| Write-Host "`n--- UNFILTERED RESULTS (All Files By Extension) ---" | |
| Write-Host "Shows all file types (incl. $noExtensionPlaceholder) found (using raw counts). Sorted by Extension." | |
| if ($unfilteredSummaryTable.Count -gt 0) { | |
| $unfilteredSummaryTable | Format-Table -Property $unfilteredFormat | |
| } else { Write-Host "No files found." } | |
| # --- REMOVED "WithoutValue" reporting - it's now in the table --- | |
| Write-Host ("`nTotal Files (Unfiltered Scan): {0:N0}" -f $totalFilesFound) | |
| Write-Host ("Total Lines (Unfiltered Scan): {0:N0}" -f $totalLinesFound) | |
| Write-Host ("Total Chars (Bytes) (Unfiltered Scan): {0:N0}" -f $totalCharsFound) # Clarified Chars = Bytes | |
| Write-Host ("Total Size KB (Unfiltered Scan): {0:N0}" -f $totalSizeKBFound) | |
| # 2. Included Files Summary by Extension | |
| Write-Host "`n--- INCLUDED FILES SUMMARY (Included Files > $MinReportLineCount Lines per Group) ---" | |
| Write-Host "Sorted by Line Count Descending (Colored). Types below threshold omitted. Includes '$noExtensionPlaceholder'." | |
| Write-Host "" | |
| if ($includedSummaryTableExt.Count -gt 0) { | |
| $includedSummaryTableExt | Format-Table -Property $includedFormat | |
| } else { Write-Host "No included groups met the minimum line count threshold of $MinReportLineCount." } | |
| # --- REMOVED "WithoutValue" reporting --- | |
| Write-Host ("`nTotal Included Files (Actual): {0:N0}" -f $totalFilesFiltered) | |
| Write-Host ("Total Included Lines (Actual): {0:N0}" -f $totalLinesFiltered) | |
| Write-Host ("Total Included Chars (Bytes) (Actual): {0:N0}" -f $totalCharsFiltered) # Clarified Chars = Bytes | |
| Write-Host ("Total Included Size KB (Actual): {0:N0}" -f $totalSizeKBFiltered) | |
| # 3. Excluded File Details by Extension | |
| Write-Host "`n--- EXCLUDED FILE DETAILS (Shows All Excluded Types Found) ---" | |
| Write-Host "Sorted by Line Count Descending (Colored). Shows RAW counts. Includes '$noExtensionPlaceholder'." | |
| Write-Host "NOTE: This table lists ALL excluded types/groups found (min 1 file), ignoring the '$MinReportLineCount' parameter." | |
| Write-Host "" | |
| if ($excludedSummaryTableExt.Count -gt 0) { | |
| $excludedSummaryTableExt | Format-Table -Property $excludedFormat | |
| } else { Write-Host "No excluded files were found." } | |
| # --- REMOVED "WithoutValue" reporting and listing --- | |
| Write-Host ("`nTotal Excluded Files (Actual): {0:N0}" -f $totalFilesExcluded) | |
| Write-Host ("Total Excluded Lines (Raw): {0:N0}" -f $totalLinesExcluded) | |
| Write-Host ("Total Excluded Chars (Bytes) (Raw): {0:N0}" -f $totalCharsExcluded) # Clarified Chars = Bytes | |
| Write-Host ("Total Excluded Size KB (Raw): {0:N0}" -f $totalSizeKBExcluded) | |
| # 4. Directory Summary | |
| Write-Host "`n--- DIRECTORY SUMMARY (Top 1-2 Levels > $MinReportLineCount Lines per Directory Group) ---" | |
| Write-Host "Counts lines/chars/size from INCLUDED files only. Sorted by Line Count Descending (Colored). Includes '$rootFilePlaceholder' etc." | |
| Write-Host "" | |
| if ($directorySummaryTable.Count -gt 0) { | |
| $directorySummaryTable | Format-Table -Property $directoryFormat | |
| } else { Write-Host "No directories met the minimum line count threshold of $MinReportLineCount based on included files." } | |
| # --- REMOVED "WithoutValue" reporting --- | |
| # 5. Top 10 Included Files | |
| Write-Host "`n--- TOP 10 INCLUDED FILES (By Line Count) ---" | |
| if ($topIncludedFiles.Count -gt 0) { | |
| $topIncludedFiles | Format-Table -Property $topIncludedFormat | |
| } else { Write-Host "No included files found." } | |
| # 6. Top 10 Excluded Files | |
| Write-Host "`n--- TOP 10 EXCLUDED FILES (By Raw Line Count) ---" | |
| if ($topExcludedFiles.Count -gt 0) { | |
| $topExcludedFiles | Format-Table -Property $topExcludedFormat | |
| } else { Write-Host "No excluded files found."} | |
| Write-Host "`n-----------------------------------------------------" | |
| Write-Host " Line Count Complete." | |
| Write-Host "-----------------------------------------------------`n" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment