Public/ProfileHook.ps1
|
# --------------------------------------------------------------------------- # Profile hook installer # --------------------------------------------------------------------------- function Install-TTProfileHook { <# .SYNOPSIS Add the TerminalTracker prompt hook to your PowerShell profile. .DESCRIPTION Adds a snippet to $PROFILE.CurrentUserAllHosts that wraps the prompt function to call Update-TTSession on every prompt render. Also starts the background monitor if not already running. .PARAMETER Force Reinstall the hook even if one is already present. .EXAMPLE Install-TTProfileHook Installs the prompt hook in the PowerShell profile. .EXAMPLE Install-TTProfileHook -Force Reinstalls the prompt hook, replacing any existing one. #> [CmdletBinding()] param( [switch]$Force ) $profilePath = $PROFILE.CurrentUserAllHosts if (-not (Test-Path (Split-Path $profilePath -Parent))) { New-Item -Path (Split-Path $profilePath -Parent) -ItemType Directory -Force | Out-Null } $startMarker = '# >>> TerminalTracker Hook >>>' $endMarker = '# <<< TerminalTracker Hook <<<' $modulePath = Join-Path (Split-Path $PSScriptRoot -Parent) 'TerminalTracker.psd1' $hookBlock = @" $startMarker # Auto-generated by TerminalTracker. Do not edit this block manually. Import-Module '$modulePath' -Force -DisableNameChecking `$Global:__TTOriginalPrompt = if (`$Function:prompt) { `$Function:prompt } else { { "PS> " } } function Global:prompt { # Call original prompt `$result = & `$Global:__TTOriginalPrompt # Update tracker (non-blocking, errors suppressed) try { Update-TTSession } catch { } return `$result } # Start monitor if not already running if (-not (Get-Job -Name 'TerminalTracker-Monitor' -ErrorAction SilentlyContinue)) { Start-TTMonitor -AsJob | Out-Null } $endMarker "@ if (Test-Path $profilePath) { $content = [System.IO.File]::ReadAllText($profilePath) $startIdx = $content.IndexOf($startMarker) if ($startIdx -ge 0) { if (-not $Force) { Write-Verbose "Profile hook already installed. Use -Force to reinstall." return } # Backup before modifying $backupPath = "$profilePath.bak" [System.IO.File]::Copy($profilePath, $backupPath, $true) # Remove existing hook by exact index $endIdx = $content.IndexOf($endMarker) if ($endIdx -gt $startIdx) { $before = $content.Substring(0, $startIdx).TrimEnd() $after = $content.Substring($endIdx + $endMarker.Length).TrimStart("`r", "`n") $content = if ($after) { "$before`r`n$after" } else { $before } } } $content = $content.TrimEnd() + "`n" + $hookBlock [System.IO.File]::WriteAllText($profilePath, $content, [System.Text.Encoding]::UTF8) } else { [System.IO.File]::WriteAllText($profilePath, $hookBlock, [System.Text.Encoding]::UTF8) } # Update config $cfg = Get-TTConfig $cfg.ProfileHookInstalled = $true Write-JsonFile $script:ConfigFile $cfg Write-Verbose "Profile hook installed at: $profilePath" Write-Verbose "Restart your PowerShell sessions for it to take effect." } function Remove-TTProfileHook { <# .SYNOPSIS Remove the TerminalTracker prompt hook from your PowerShell profile. .DESCRIPTION Removes the TerminalTracker hook block from $PROFILE.CurrentUserAllHosts. Creates a backup of the profile before modification. .EXAMPLE Remove-TTProfileHook Removes the prompt hook from the PowerShell profile. #> [CmdletBinding(SupportsShouldProcess)] param() if (-not $PSCmdlet.ShouldProcess("PowerShell profile hook", "Remove")) { return } $profilePath = $PROFILE.CurrentUserAllHosts if (-not (Test-Path $profilePath)) { Write-Verbose "No profile found."; return } $startMarker = '# >>> TerminalTracker Hook >>>' $endMarker = '# <<< TerminalTracker Hook <<<' $content = [System.IO.File]::ReadAllText($profilePath) $startIdx = $content.IndexOf($startMarker) $endIdx = $content.IndexOf($endMarker) if ($startIdx -ge 0 -and $endIdx -gt $startIdx) { # Backup before modifying $backupPath = "$profilePath.bak" [System.IO.File]::Copy($profilePath, $backupPath, $true) # Remove hook block by exact index $before = $content.Substring(0, $startIdx).TrimEnd() $after = $content.Substring($endIdx + $endMarker.Length).TrimStart("`r", "`n") $newContent = if ($after) { "$before`r`n$after" } else { $before } [System.IO.File]::WriteAllText($profilePath, $newContent, [System.Text.Encoding]::UTF8) Write-Verbose "Profile hook removed." $cfg = Get-TTConfig $cfg.ProfileHookInstalled = $false Write-JsonFile $script:ConfigFile $cfg } else { Write-Verbose "No hook found in profile." } } function Repair-TTProfileHook { <# .SYNOPSIS Detect and repair a broken TerminalTracker profile hook path. .DESCRIPTION Checks $PROFILE.CurrentUserAllHosts for a hook block that references a bad path containing 'Public\TerminalTracker'. If found, removes the old block and reinstalls using Install-TTProfileHook to write the correct path. .EXAMPLE Repair-TTProfileHook Detects and repairs a bad profile hook if one exists. #> [CmdletBinding()] param() $profilePath = $PROFILE.CurrentUserAllHosts if (-not (Test-Path $profilePath)) { Write-Host "No profile file found at: $profilePath" -ForegroundColor Yellow return } $content = [System.IO.File]::ReadAllText($profilePath) $startMarker = '# >>> TerminalTracker Hook >>>' $endMarker = '# <<< TerminalTracker Hook <<<' $startIdx = $content.IndexOf($startMarker) if ($startIdx -lt 0) { Write-Host "No TerminalTracker hook found in profile." -ForegroundColor Gray return } $endIdx = $content.IndexOf($endMarker) if ($endIdx -le $startIdx) { Write-Host "Hook markers malformed in profile." -ForegroundColor Red return } $hookBlock = $content.Substring($startIdx, $endIdx - $startIdx + $endMarker.Length) # Check for bad path pattern: any path ending with Public\TerminalTracker (with any extension) if ($hookBlock -notmatch 'Public[/\\]TerminalTracker') { Write-Host "Profile hook path looks correct -- no repair needed." -ForegroundColor Green return } Write-Host "Bad hook path detected (Public\TerminalTracker.*). Repairing..." -ForegroundColor Yellow # Backup profile $backupPath = "$profilePath.bak" try { [System.IO.File]::Copy($profilePath, $backupPath, $true) Write-Host "Profile backed up to: $backupPath" -ForegroundColor Gray } catch { Write-Host "Could not create backup: $_" -ForegroundColor Red return } # Remove old hook block $before = $content.Substring(0, $startIdx).TrimEnd() $after = $content.Substring($endIdx + $endMarker.Length).TrimStart("`r", "`n") $stripped = if ($after) { "$before`r`n$after" } else { $before } [System.IO.File]::WriteAllText($profilePath, $stripped, [System.Text.Encoding]::UTF8) # Reinstall with correct path try { Install-TTProfileHook -Force Write-Host "Profile hook repaired successfully. Restart your terminals to apply." -ForegroundColor Green } catch { Write-Host "Hook removal succeeded but reinstall failed: $_" -ForegroundColor Red } } |