Skip to content

Commit 51ef268

Browse files
committed
Fix eza listings, wizard font menu, -CiMode prompts, and font detection.
1 parent c3b3c27 commit 51ef268

7 files changed

Lines changed: 147 additions & 69 deletions

File tree

.github/workflows/ci.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -335,11 +335,11 @@ jobs:
335335
}
336336
Write-Host "OK: $($schemes.Count) curated schemes validated" -ForegroundColor Green
337337
338-
# Fonts: expect 6 entries, each with Asset, DisplayName, Desc
338+
# Fonts: expect 6 entries, each with Name (wizard menu label), Asset, DisplayName, Desc
339339
$fonts = $found['CuratedFonts']
340340
if (-not $fonts) { Write-Host "FAIL: CuratedFonts not found" -ForegroundColor Red; exit 1 }
341341
if ($fonts.Count -ne 6) { Write-Host "FAIL: expected 6 curated fonts, got $($fonts.Count)" -ForegroundColor Red; $errors++ }
342-
$fontReq = @('Asset','DisplayName','Desc')
342+
$fontReq = @('Name','Asset','DisplayName','Desc')
343343
foreach ($f in $fonts) {
344344
foreach ($k in $fontReq) {
345345
if (-not $f.ContainsKey($k) -or [string]::IsNullOrWhiteSpace([string]$f[$k])) {

Microsoft.PowerShell_profile.ps1

Lines changed: 83 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1974,7 +1974,7 @@ function df {
19741974
# Find and replace text in a file
19751975
function sed($file, $find, $replace) {
19761976
if (-not $file -or -not (Test-Path -LiteralPath $file)) {
1977-
Write-Warning "File not found: $file"
1977+
Write-Error "File not found: $file"
19781978
return
19791979
}
19801980
if ($null -eq $find -or $find -eq '') { Write-Error "Usage: sed <file> <find> <replace>"; return }
@@ -2206,11 +2206,12 @@ if (Get-Command eza -ErrorAction SilentlyContinue) {
22062206
else {
22072207
Remove-Item Alias:\ls -Force -ErrorAction SilentlyContinue
22082208
}
2209-
# ls/la/ll/lt: directory listing via eza (icons, git status, tree)
2210-
function ls { eza --icons @args }
2211-
function la { eza -a --icons @args }
2212-
function ll { eza -la --icons --git @args }
2213-
function lt { eza --tree --icons --level=2 @args }
2209+
# ls/la/ll/lt: directory listing via eza (icons, git status, tree). Pass the icon setting as
2210+
# --icons=WHEN: eza takes an optional value there, so a bare --icons swallows a following path.
2211+
function ls { eza --icons=auto @args }
2212+
function la { eza -a --icons=auto @args }
2213+
function ll { eza -la --icons=auto --git @args }
2214+
function lt { eza --tree --icons=auto --level=2 @args }
22142215
}
22152216
else {
22162217
if ($isInteractive) { Write-Warning "eza not found. Install it with: winget install -e --id eza-community.eza" }
@@ -2765,7 +2766,7 @@ if (Get-Command wsl.exe -ErrorAction SilentlyContinue) {
27652766
$unc = Resolve-WslUncPath -Distro $Distro -Path $Path
27662767
if (-not $unc) { return }
27672768
if (Get-Command eza -ErrorAction SilentlyContinue) {
2768-
$ezaArgs = @('--tree', "--level=$Depth", '--icons', '--git-ignore')
2769+
$ezaArgs = @('--tree', "--level=$Depth", '--icons=auto', '--git-ignore')
27692770
if ($All) { $ezaArgs += '-a' }
27702771
& eza @ezaArgs $unc
27712772
}
@@ -2835,7 +2836,10 @@ function reload { . $PROFILE }
28352836
# Diagnose tools, caches, fonts, PATH, modules, and plugins with OK, WARN, or FAIL results.
28362837
function Test-ProfileHealth {
28372838
[CmdletBinding()]
2838-
param()
2839+
param(
2840+
# Emit the result objects for scripting; the rendered report prints either way.
2841+
[switch]$PassThru
2842+
)
28392843

28402844
$results = @()
28412845

@@ -2891,38 +2895,65 @@ function Test-ProfileHealth {
28912895
$results += [pscustomobject]@{ Category = 'Config'; Check = 'user-settings.json'; Status = 'WARN'; Detail = 'missing (no overrides applied)' }
28922896
}
28932897

2894-
# Font from terminal-config.json.fontInstall.displayName
2895-
$tcPath = Join-Path $cacheDir 'terminal-config.json'
2896-
if (Test-Path $tcPath) {
2897-
try {
2898-
$tc = Get-Content $tcPath -Raw -ErrorAction Stop | ConvertFrom-Json -ErrorAction Stop
2899-
$fontName = if ($tc.fontInstall) { $tc.fontInstall.displayName } else { $null }
2900-
if ($fontName) {
2901-
# Report unavailable System.Drawing as WARN on non-Windows platforms.
2902-
if (-not ('System.Drawing.Text.InstalledFontCollection' -as [type])) {
2903-
Add-Type -AssemblyName System.Drawing -ErrorAction SilentlyContinue
2904-
}
2905-
if (-not ('System.Drawing.Text.InstalledFontCollection' -as [type])) {
2906-
$results += [pscustomobject]@{ Category = 'Fonts'; Check = $fontName; Status = 'WARN'; Detail = 'System.Drawing unavailable on this host; cannot verify' }
2907-
}
2908-
else {
2909-
$installed = $false
2898+
# Check the font this install actually uses: a wizard choice in user-settings.json
2899+
# overrides the shipped terminal-config.json default.
2900+
$fontName = $null
2901+
try {
2902+
if (Test-Path $us) {
2903+
$userCfg = Get-Content $us -Raw -ErrorAction Stop | ConvertFrom-Json -ErrorAction Stop
2904+
if ($userCfg.defaults -and $userCfg.defaults.font -and $userCfg.defaults.font.face) {
2905+
$fontName = [string]$userCfg.defaults.font.face
2906+
}
2907+
}
2908+
}
2909+
catch { $null = $_ }
2910+
if (-not $fontName) {
2911+
$tcPath = Join-Path $cacheDir 'terminal-config.json'
2912+
if (Test-Path $tcPath) {
2913+
try {
2914+
$tc = Get-Content $tcPath -Raw -ErrorAction Stop | ConvertFrom-Json -ErrorAction Stop
2915+
if ($tc.fontInstall) { $fontName = [string]$tc.fontInstall.displayName }
2916+
}
2917+
catch { $null = $_ }
2918+
}
2919+
}
2920+
if ($fontName) {
2921+
# Report unavailable System.Drawing as WARN on non-Windows platforms.
2922+
if (-not ('System.Drawing.Text.InstalledFontCollection' -as [type])) {
2923+
Add-Type -AssemblyName System.Drawing -ErrorAction SilentlyContinue
2924+
}
2925+
if (-not ('System.Drawing.Text.InstalledFontCollection' -as [type])) {
2926+
$results += [pscustomobject]@{ Category = 'Fonts'; Check = $fontName; Status = 'WARN'; Detail = 'System.Drawing unavailable on this host; cannot verify' }
2927+
}
2928+
else {
2929+
$installed = $false
2930+
try {
2931+
$fc = New-Object System.Drawing.Text.InstalledFontCollection
2932+
$installed = $fc.Families.Name -contains $fontName
2933+
$fc.Dispose()
2934+
}
2935+
catch { $null = $_ }
2936+
# GDI+ caches the family list per process, so a font installed after this session
2937+
# started reads as missing; the font registry is the authoritative fallback.
2938+
if (-not $installed) {
2939+
foreach ($hive in @('HKCU:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Fonts', 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Fonts')) {
29102940
try {
2911-
$fc = New-Object System.Drawing.Text.InstalledFontCollection
2912-
$installed = $fc.Families.Name -contains $fontName
2913-
$fc.Dispose()
2941+
$fontKey = Get-ItemProperty -Path $hive -ErrorAction Stop
2942+
if (@($fontKey.PSObject.Properties.Name | Where-Object { $_ -like "$fontName*" }).Count -gt 0) {
2943+
$installed = $true
2944+
break
2945+
}
29142946
}
29152947
catch { $null = $_ }
2916-
if ($installed) {
2917-
$results += [pscustomobject]@{ Category = 'Fonts'; Check = $fontName; Status = 'OK'; Detail = 'installed' }
2918-
}
2919-
else {
2920-
$results += [pscustomobject]@{ Category = 'Fonts'; Check = $fontName; Status = 'FAIL'; Detail = 'not installed (run setup.ps1 -Wizard or Update-Profile)' }
2921-
}
29222948
}
29232949
}
2950+
if ($installed) {
2951+
$results += [pscustomobject]@{ Category = 'Fonts'; Check = $fontName; Status = 'OK'; Detail = 'installed' }
2952+
}
2953+
else {
2954+
$results += [pscustomobject]@{ Category = 'Fonts'; Check = $fontName; Status = 'FAIL'; Detail = 'not installed (run setup.ps1 -Wizard or Update-Profile)' }
2955+
}
29242956
}
2925-
catch { $null = $_ }
29262957
}
29272958

29282959
# PATH - WindowsApps (winget shims location)
@@ -2979,8 +3010,9 @@ function Test-ProfileHealth {
29793010
$summaryColor = if ($failCount -gt 0) { 'Red' } elseif ($warnCount -gt 0) { 'Yellow' } else { 'Green' }
29803011
Write-Host ("Summary: {0} OK, {1} WARN, {2} FAIL" -f $okCount, $warnCount, $failCount) -ForegroundColor $summaryColor
29813012

2982-
# Return the objects too so scripts can query: Test-ProfileHealth | Where Status -eq 'FAIL'
2983-
$results
3013+
# Emit objects only on request: a bare call would otherwise render the table a second
3014+
# time through the default formatter. Scripts use -PassThru to query the rows.
3015+
if ($PassThru) { $results }
29843016
}
29853017
Set-Alias -Name psp-doctor -Value Test-ProfileHealth -Scope Script
29863018

@@ -3354,7 +3386,8 @@ function Uninstall-Profile {
33543386
# Phase 5: Nerd Fonts (opt-in). Shell font installs land per-user on Windows 10/11 unless
33553387
# elevated, so both scopes are swept; only the machine-wide one needs admin.
33563388
if ($RemoveFonts) {
3357-
# Derive the uninstall font filter from terminal-config.json with the install default as fallback.
3389+
# Derive the uninstall font filter from what setup actually installed: a wizard font choice
3390+
# in user-settings.json wins over terminal-config.json, which wins over the install default.
33583391
$fontDisplayName = 'CaskaydiaCove NF'
33593392
try {
33603393
$tcPath = Join-Path $env:LOCALAPPDATA 'PowerShellProfile\terminal-config.json'
@@ -3364,6 +3397,16 @@ function Uninstall-Profile {
33643397
}
33653398
}
33663399
catch { $null = $_ }
3400+
try {
3401+
$usPath = Join-Path $env:LOCALAPPDATA 'PowerShellProfile\user-settings.json'
3402+
if (Test-Path $usPath) {
3403+
$usCfg = Get-Content $usPath -Raw | ConvertFrom-Json
3404+
if ($usCfg.defaults -and $usCfg.defaults.font -and $usCfg.defaults.font.face) {
3405+
$fontDisplayName = [string]$usCfg.defaults.font.face
3406+
}
3407+
}
3408+
}
3409+
catch { $null = $_ }
33673410
$tokens = @($fontDisplayName -split '\s+' | Where-Object { $_ })
33683411
# Registry entries keep the display form ("CaskaydiaCove NF Bold (TrueType)")...
33693412
$regNamePattern = ($tokens | ForEach-Object { [regex]::Escape($_) }) -join '.*'
@@ -5856,7 +5899,8 @@ function Start-ProfileTour {
58565899
$null = Read-Host 'Ready'
58575900
foreach ($cat in $categories) {
58585901
Write-Host ''
5859-
Write-Host ("-- {0} ({1} commands) --" -f $cat.Name, $cat.Count) -ForegroundColor Cyan
5902+
$countLabel = if ($cat.Count -eq 1) { 'command' } else { 'commands' }
5903+
Write-Host ("-- {0} ({1} {2}) --" -f $cat.Name, $cat.Count, $countLabel) -ForegroundColor Cyan
58605904
foreach ($entry in ($cat.Group | Sort-Object Name | Select-Object -First 8)) {
58615905
$synopsis = if ($entry.Synopsis) { $entry.Synopsis } else { '' }
58625906
Write-Host (" {0,-22} {1}" -f $entry.Name, $synopsis) -ForegroundColor Gray
@@ -6142,7 +6186,7 @@ ${g}reload${r} - Reload the PowerShell profile.
61426186
${g}Clear-ProfileCache${r} - Reset profile caches plus OMP internal caches.
61436187
${g}Clear-Cache${r} [-IncludeSystemCaches] - Clear user/system temp caches.
61446188
${g}duration${r} - Elapsed time of the last command.
6145-
${g}Test-ProfileHealth${r} / ${g}psp-doctor${r} - Diagnose install: tools, caches, fonts, PATH.
6189+
${g}Test-ProfileHealth${r} [-PassThru] / ${g}psp-doctor${r} - Diagnose install: tools, caches, fonts, PATH. -PassThru also returns the rows for scripting.
61466190
${g}Uninstall-Profile${r} - Remove profile, caches, and WT changes. Use -All for everything, -HardResetWindowsTerminal to reset WT to defaults, -Force to uninstall PSFzf/tools even under CI/agent env vars.
61476191
61486192
${c}Git${r}

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -286,7 +286,7 @@ Run `Show-Help` in your terminal for a colored version of this list.
286286
| `Clear-Cache` [-IncludeSystemCaches] | Clear user temp/browser caches (optionally system dirs) |
287287
| `Clear-ProfileCache` | Reset profile caches plus OMP internal caches |
288288
| `duration` | Show elapsed time of the last executed command |
289-
| `Test-ProfileHealth` / `psp-doctor` | Diagnose install (tools, caches, fonts, PATH, modules) |
289+
| `Test-ProfileHealth [-PassThru]` / `psp-doctor` | Diagnose install (tools, caches, fonts, PATH, modules); `-PassThru` also emits the result rows for scripting |
290290
| `winutil [-ExpectedSha256 <hash>]` / `winutil -Force` | Fetch [Chris Titus WinUtil](https://github.com/ChrisTitusTech/winutil). Safe-by-default: prints source URL and SHA256, then stops. Re-run with `-ExpectedSha256 '<hash>'` (hash-pinned) or `-Force` (trust without verification) to stage execution, and PowerShell still asks for a high-impact confirmation before launch. |
291291
| `harden` | Open [Harden Windows Security](https://github.com/HotCakeX/Harden-Windows-Security) with an explicit confirmation prompt before launch. |
292292

0 commit comments

Comments
 (0)