Tools/vivid.ps1
|
# Companion for vivid — resolve the configured theme, generate (or reuse a # cached) LS_COLORS value, and apply it to the session. Caching mirrors # Private/Get-DFHelpTopicList.ps1's file-plus-fingerprint pattern: the # fingerprint is just the resolved theme name, so a theme change invalidates # the cache and a stable theme reuses it without spawning vivid again # (~42ms measured locally — worth avoiding on every shell startup). # # Calls `vivid` via a raw `&`, not Private/Invoke-DFCommandCapture.ps1's # mockable seam: Invoke-DFApplyLSColorsTheme is registered as a detached # function:global: (so it's callable after Register-DFTool returns, and # from the fls picker), and PowerShell's module-privacy boundary makes # Private functions unreachable from a function:global: scriptblock's # .GetNewClosure() body regardless of dot-sourcing — confirmed empirically # (this is a hard scoping constraint, not a missed refactor). See # docs/superpowers/specs/2026-09-03-vivid-ls-colors-design.md Section 4. Set-Item -Path 'function:global:Invoke-DFApplyLSColorsTheme' -Value ({ <# .SYNOPSIS Resolves and applies an LS_COLORS value for the named vivid theme. .PARAMETER Force Bypass the cache and regenerate even when the theme name matches what's cached — use after a vivid upgrade that may have shifted a theme's palette. #> [CmdletBinding()] param( [Parameter(Mandatory)][string]$Name, [switch]$Force ) if (-not $Env:XDG_CACHE_HOME) { Write-Warning 'DotForge: $Env:XDG_CACHE_HOME is not set. Call Initialize-DFEnvironment first.' return } $cacheDir = Join-Path $Env:XDG_CACHE_HOME 'dotforge' $cacheFile = Join-Path $cacheDir 'ls-colors.txt' $keyFile = Join-Path $cacheDir 'ls-colors.key' $cacheValid = -not $Force -and (Test-Path $cacheFile) -and (Test-Path $keyFile) -and ((Get-Content $keyFile -Raw).Trim() -eq $Name) if ($cacheValid) { $value = (Get-Content $cacheFile -Raw).Trim() } else { $raw = & vivid generate $Name 2>&1 | Out-String if ($LASTEXITCODE -ne 0) { Write-Warning "DotForge: vivid theme '$Name' failed — $($raw.Trim())" return } $value = $raw.Trim() New-DFDirectory $cacheDir Set-Content -Path $keyFile -Value $Name -Encoding UTF8 Set-Content -Path $cacheFile -Value $value -Encoding UTF8 } [System.Environment]::SetEnvironmentVariable('LS_COLORS', $value, 'Process') }.GetNewClosure()) # Resolve: per-tool VividTheme -> shared Theme -> tool JSON default. $_settings = $DFCurrentTool.PSObject.Properties['settings']?.Value $_default = $_settings.PSObject.Properties['theme']?.Value ?? 'catppuccin-mocha' $_theme = Get-DFConfiguredTheme -ToolKey 'VividTheme' -Default $_default $_theme = Resolve-DFThemeName -Name $_theme -ThemeMap ($DFCurrentTool.PSObject.Properties['themeMap']?.Value) Invoke-DFApplyLSColorsTheme -Name $_theme # Live picker: list vivid's own themes, preview each via `vivid preview`, # apply the chosen one immediately (same cache/apply path as registration). Set-Item -Path 'function:global:Select-LSColorsTheme' -Value ({ [CmdletBinding()] param() Invoke-DFPicker ` -List { vivid themes } ` -Header 'Select LS_COLORS theme [Enter to apply for this session]' ` -Preview 'vivid preview {}' ` -Action { param($n) Invoke-DFApplyLSColorsTheme -Name $n Write-Host "Theme applied: $n (to persist: set `$Global:DFConfig['VividTheme'] = '$n')" -ForegroundColor Green } }.GetNewClosure()) Set-Alias -Name fls -Value Select-LSColorsTheme -Scope Global -Force |