ps/Modules/Cole.PowerShell.Developer/Scratch/Compare-File.bak.ps1
2023-05-30 22:51:22 -07:00

133 lines
4.9 KiB
PowerShell

function Compare-File {
<#
.SYNOPSIS
Compares two files, displaying differences in a manner similar to traditional console-based diff utilities.
#>
param(
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
$CompareFrom,
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
$CompareTo,
[switch]$Porcelain
)
$CompareFrom = (Resolve-Path $CompareFrom).Path
$CompareTo = (Resolve-Path $CompareTo).Path
$totalFormatWidth = 11 # 5 for numbers, 6 for 2x ' : ' as separators
$screenWidth = Get-ConsoleDisplayWidth
$fixedWidth = ($screenWidth - ($screenWidth % 2) - $totalFormatWidth) / 2
$fileHeaderPrint = " "
$fileHeaderFrom = Select-RightSubstringWithPadLeft -String $CompareFrom -Length $fixedWidth
$fileHeaderTo = Select-RightSubstringWithPadLeft -String $CompareTo -Length $fixedWidth
## Get the content from each file
$contentFrom = Get-Content -Path $CompareFrom
$contentTo = Get-Content -Path $CompareTo
## Compare the two files. Get-Content annotates output objects with
## a 'ReadCount' property that represents the line number in the file
## that the text came from.
$comparedLines = Compare-Object -ReferenceObject $contentFrom -DifferenceObject $contentTo -IncludeEqual | Sort-Object { $line.InputObject.ReadCount }
if ($comparedLines.Count -eq 0) {
if (!$Porcelain) {
"$fileHeaderPrint : $fileHeaderFrom : $fileHeaderTo"
Write-Host "Contents were the same"
}
return
}
$shortestFileLength = [Math]::Min($contentFrom.Length, $contentTo.Length)
$lineNumberColor = $PSStyle.ForegroundColor.LightCyan
$reset = $PSStyle.Reset
$diffLeftColor = $PSStyle.ForegroundColor.LightRed
$diffRightColor = $PSStyle.ForegroundColor.Green
$lineNumber = 0
$fromResults = @{}
$toResults = @{}
$lineNumbers = @()
foreach ($line in $comparedLines) {
$lineNumber = $line.InputObject.ReadCount
if($line.SideIndicator -eq "=>")
{
$lineNumbers += $lineNumber
$lineOperation = "added"
$fromResults[$lineNumber] = $line.InputObject
}
elseif($line.SideIndicator -eq "<=")
{
$lineNumbers += $lineNumber
$lineOperation = "deleted"
$toResults[$lineNumber] = $line.InputObject
}
}
if ($lineNumbers.Count -gt 0) {
$lineNumbers = $lineNumbers | Sort-Object | Get-Unique
$groups = Group-Numbers -Values $lineNumbers
$printedLineNumbers = @()
$print = @("$fileHeaderPrint : $fileHeaderFrom : $fileHeaderTo")
foreach ($group in $groups) {
$first = $group[0] - 2
if ($first -lt 0) {
$first = 0
}
$last = $group[-1] + 2
if ($last -gt $shortestFileLength) {
$last = $shortestFileLength
}
for ($i = $first; $i -lt $last; $i++) {
# We already wrote the line somewhere else (think overlaps)
if ($printedLineNumbers -contains $i) {
continue
}
if ($lineNumbers -contains $i) {
# We need to print this as a difference
$diffLeftColor = $PSStyle.ForegroundColor.LightRed
$diffRightColor = $PSStyle.ForegroundColor.Green
$to = $toResults[$lineNumber]
$from = $fromResults[$lineNumber]
} else {
# This is not a difference line, print it "normally"
$to = $contentTo[$i]
$from = $contentFrom[$i]
$diffLeftColor = $PSStyle.Reset
$diffRightColor = $PSStyle.Reset
}
$lineNumberLead = "$lineNumber".PadLeft(5, ' ')
$from = "$from".PadRight($fixedWidth," ").Substring(0,$fixedWidth)
$to = "$to".PadRight($fixedWidth," ").Substring(0,$fixedWidth)
$print += "$lineNumberColor$("$i".PadLeft(5))$reset : $diffLeftColor$from$reset : $diffRightColor$to$reset"
$printedLineNumbers += $i
}
}
if ($print.Count -gt 0) {
$print
} else {
}
}
$print = @()
foreach ($lineNumber in $lineNumbers) {
$lineNumberLead = "$lineNumber".PadLeft(5, ' ')
$from = $fromResults[$lineNumber]
$from = "$from".PadRight($fixedWidth," ").Substring(0,$fixedWidth)
$to = $toResults[$lineNumber]
$to = "$to".PadRight($fixedWidth," ").Substring(0,$fixedWidth)
$print += "$($PSStyle.ForegroundColor.LightCyan)$lineNumberLead$($PSStyle.Reset) : $($PSStyle.ForegroundColor.LightRed)$from$($PSStyle.Reset) : $($PSStyle.ForegroundColor.Green)$to$($PSStyle.Reset)"
}
if ($print.Count -gt 0) {
"$fileHeaderPrint : $fileHeaderFrom : $fileHeaderTo"
$print
} else {
}
}