Private/PathOptimizer.ps1
|
function Get-PathPriority { <# .SYNOPSIS Determines the priority category of a PATH entry. .DESCRIPTION Returns a numeric priority (lower = higher priority) based on path type. #> [CmdletBinding()] param( [Parameter(Mandatory)] [string]$Path ) $normalizedPath = $Path.ToLowerInvariant().TrimEnd('\') # Priority 1: Windows System Critical if ($normalizedPath -match '^c:\\windows\\system32$' -or $normalizedPath -match '^c:\\windows\\system32\\wbem$' -or $normalizedPath -match '^c:\\windows\\system32\\openssh$' -or $normalizedPath -match '^c:\\windows\\system32\\windowspowershell') { return @{ Priority = 10; Category = 'System Critical' } } # Priority 2: Windows Core if ($normalizedPath -match '^c:\\windows$') { return @{ Priority = 20; Category = 'Windows Core' } } # Priority 3: PowerShell 7+ if ($normalizedPath -match 'powershell\\7') { return @{ Priority = 30; Category = 'PowerShell 7' } } # Priority 4: Development Tools (Git, VS Code, etc.) if ($normalizedPath -match '\\git\\' -or $normalizedPath -match 'vs code' -or $normalizedPath -match 'visual studio' -or $normalizedPath -match '\\dotnet\\?' -or $normalizedPath -match 'github cli') { return @{ Priority = 40; Category = 'Development Tools' } } # Priority 5: Language Runtimes (user-preferred versions first) if ($normalizedPath -match 'python' -or $normalizedPath -match 'node' -or $normalizedPath -match '\\go\\' -or $normalizedPath -match 'java' -or $normalizedPath -match 'rust' -or $normalizedPath -match 'ruby' -or $normalizedPath -match '\\nvm' -or $normalizedPath -match 'cargo') { # User-local installations get higher priority than system-wide if ($normalizedPath -match 'appdata|users\\[^\\]+\\') { return @{ Priority = 50; Category = 'Language Runtime (User)' } } return @{ Priority = 55; Category = 'Language Runtime (System)' } } # Priority 6: Package Managers if ($normalizedPath -match 'chocolatey' -or $normalizedPath -match 'scoop' -or $normalizedPath -match 'winget' -or $normalizedPath -match 'npm' -or $normalizedPath -match 'yarn') { return @{ Priority = 60; Category = 'Package Manager' } } # Priority 7: SDK and Database Tools if ($normalizedPath -match 'sql server' -or $normalizedPath -match 'docker' -or $normalizedPath -match 'kubernetes' -or $normalizedPath -match 'azure' -or $normalizedPath -match 'aws') { return @{ Priority = 70; Category = 'SDK/Cloud Tools' } } # Priority 8: Security Tools if ($normalizedPath -match 'gpg' -or $normalizedPath -match 'gnupg' -or $normalizedPath -match 'openssh' -or $normalizedPath -match 'putty' -or $normalizedPath -match 'ssh') { return @{ Priority = 80; Category = 'Security Tools' } } # Priority 9: Application-specific (Program Files) if ($normalizedPath -match '^c:\\program files') { return @{ Priority = 90; Category = 'Application (System)' } } # Priority 10: User AppData applications if ($normalizedPath -match 'appdata') { return @{ Priority = 100; Category = 'Application (User)' } } # Priority 11: Other system paths if ($normalizedPath -match '^c:\\programdata') { return @{ Priority = 110; Category = 'ProgramData' } } # Priority 12: Everything else return @{ Priority = 999; Category = 'Other' } } function Get-OptimizedPathOrder { <# .SYNOPSIS Analyzes PATH entries and suggests an optimized order. .DESCRIPTION Returns PATH entries sorted by priority category, keeping relative order within categories to minimize disruption. #> [CmdletBinding()] param( [Parameter(Mandatory)] [string[]]$Paths, [switch]$ShowCategories ) $categorizedPaths = @() $position = 0 foreach ($path in $Paths) { $priority = Get-PathPriority -Path $path $categorizedPaths += [PSCustomObject]@{ OriginalPosition = $position Path = $path Priority = $priority.Priority Category = $priority.Category } $position++ } # Sort by priority, then by original position within same priority $sorted = $categorizedPaths | Sort-Object Priority, OriginalPosition if ($ShowCategories) { return $sorted } return $sorted | Select-Object -ExpandProperty Path } function Compare-PathOrder { <# .SYNOPSIS Compares current PATH order with optimized order. #> [CmdletBinding()] param( [Parameter(Mandatory)] [string[]]$CurrentPaths, [Parameter(Mandatory)] [string[]]$OptimizedPaths ) $changes = @() for ($i = 0; $i -lt $OptimizedPaths.Count; $i++) { $currentIndex = [array]::IndexOf($CurrentPaths, $OptimizedPaths[$i]) if ($currentIndex -ne $i) { $changes += [PSCustomObject]@{ Path = $OptimizedPaths[$i] CurrentPosition = $currentIndex + 1 NewPosition = $i + 1 Movement = if ($currentIndex -gt $i) { '↑ Up' } else { '↓ Down' } } } } return $changes } |