Tools/choco.ps1
|
# Companion for choco — fuzzy pickers built on Invoke-DFPicker + fzf. # Select-ChocoPackage (cins) search → install # Remove-ChocoPackage (crm) installed → uninstall # Invoke-ChocoUpdate (cup) outdated → upgrade (multi-select) # # Dot-sourced by Register-DFTool when choco is registered. Every user-facing # function/alias is declared `global:` so it survives Register-DFTool's scope. # # Chocolatey has no first-class object module, but its CLI has a machine-readable # mode (`-r` / `--limit-output`) that emits pipe-delimited rows — so we split on # '|' instead of scraping aligned columns. install/uninstall/upgrade need # elevation; they run through the configured sudo alias when it is available # (see Invoke-DFChocoElevated). # # Previews are prefixed with `ping -n 2 127.0.0.1 >nul &` — a ~1s cmd sleep that # debounces the preview: fzf kills the running preview command when the cursor # moves, so scrolling fast never spawns `choco info` for skipped items. # Guard: choco must be on PATH. function global:Assert-DFChoco { <# .SYNOPSIS Returns $true when choco is on PATH; otherwise warns and returns $false. .DESCRIPTION Guard used by the choco pickers (cins, crm, cup). Defined by DotForge's choco companion. .EXAMPLE if (Assert-DFChoco) { choco list } Runs choco only when it is installed. .OUTPUTS System.Boolean. .LINK https://github.com/simsrw73/DotForge/blob/main/docs/guide/tools.md #> if (Get-Command choco -ErrorAction Ignore) { return $true } Write-Warning 'DotForge: choco is not installed. See https://chocolatey.org/install' return $false } # Run a choco command elevated via DotForge's sudo alias when present; otherwise run directly # (choco will fail/prompt for elevation itself if the shell is not admin). function global:Invoke-DFChocoElevated { <# .SYNOPSIS Runs choco with the given arguments, elevated through gsudo when available. .DESCRIPTION When DotForge's sudo alias points at gsudo, runs sudo choco <args>, which shows a UAC prompt; otherwise runs choco <args> directly, and choco fails without admin rights for commands that need them. Defined by DotForge's choco companion. .PARAMETER ChocoArgs Arguments passed to choco unchanged. .EXAMPLE Invoke-DFChocoElevated upgrade ripgrep -y Upgrades ripgrep from an unelevated shell. .OUTPUTS Whatever choco writes. .LINK https://github.com/simsrw73/DotForge/blob/main/docs/guide/tools.md #> param([Parameter(ValueFromRemainingArguments)][string[]]$ChocoArgs) if ((Get-Alias sudo -ErrorAction Ignore)?.Definition -eq 'gsudo') { sudo choco @ChocoArgs } else { choco @ChocoArgs } } # What differs about Chocolatey; the shared flow is Invoke-DFPackageManagerAction. # choco's machine-readable -r output is 'name|version|...', no object module exists. $script:DFPackageManagerSpecs['choco'] = @{ Name = 'choco' Require = { Assert-DFChoco } SearchPrompt = 'Search choco packages' Preview = 'choco info {2}' Search = { param($Query) choco search $Query -r 2>$null | Where-Object { $_ -match '\|' } | ForEach-Object { $parts = $_ -split '\|' ('{0,-38} {1}' -f $parts[0], $parts[1]) + "`t" + $parts[0] } } Installed = { param($Source) choco list -r 2>$null | Where-Object { $_ -match '\|' } | ForEach-Object { $parts = $_ -split '\|' ('{0,-38} {1}' -f $parts[0], $parts[1]) + "`t" + $parts[0] } } # `choco outdated -r` → name|current|available|pinned Outdated = { choco outdated -r 2>$null | Where-Object { $_ -match '\|' } | ForEach-Object { $parts = $_ -split '\|' ('{0,-34} {1} -> {2}' -f $parts[0], $parts[1], $parts[2]) + "`t" + $parts[0] } } InstallCommand = Format-DFInstallCommand -Manager $DFCurrentTool # from this record's installs block UninstallCommand = 'choco uninstall {0} -y' # fzf's execute() keys run in a cmd subshell: elevate through gsudo when it's set up. InPlace = { param($command) if ((Get-Alias sudo -ErrorAction Ignore)?.Definition -eq 'gsudo') { "sudo $command" } else { $command } } Install = { param($Id) Invoke-DFChocoElevated install $Id -y } Uninstall = { param($Id) Invoke-DFChocoElevated uninstall $Id -y } Update = { param($Id) Invoke-DFChocoElevated upgrade $Id -y } UpdateAll = { Invoke-DFChocoElevated upgrade all -y } UpdateWord = 'upgrade' UpdatingWord = 'Upgrading' AllMessage = 'Upgrading all packages…' } function global:Select-ChocoPackage { <# .SYNOPSIS Searches the Chocolatey community feed, fuzzy-picks a package, and returns or runs its install command. .DESCRIPTION Runs choco search for -Query and lists the results in fzf with a choco info preview, shown after the cursor rests on an item for about a second. Keys: Enter return the command 'choco install <id> -y' (nothing is installed; run it in an elevated shell) Alt-R close the picker and install the selection now Alt-I install the highlighted package without closing the picker Bound to Ctrl+G, C when PSReadLine is loaded: type a search term, press the chord, pick a package, and the install command replaces the line. Defined by DotForge's choco companion; requires fzf (or $Env:Picker). Installing, uninstalling and upgrading need an elevated shell: they run through gsudo when DotForge's sudo alias points at it, which shows a UAC prompt; otherwise choco itself fails without admin rights. .PARAMETER Query Search terms passed to choco search. When omitted, you are prompted. .EXAMPLE cins ripgrep Pick ripgrep and press Enter to get: choco install ripgrep -y .OUTPUTS System.String (the install command) on Enter; otherwise none. .LINK https://github.com/simsrw73/DotForge/blob/main/docs/guide/tools.md #> [CmdletBinding()] param([string]$Query = '') Invoke-DFPackageManagerAction -Manager choco -Action Install -Query $Query } Set-Alias -Name cins -Value Select-ChocoPackage -Scope Global -Force function global:Remove-ChocoPackage { <# .SYNOPSIS Fuzzy-picks an installed Chocolatey package and uninstalls it. .DESCRIPTION Lists installed packages (choco list) in fzf with a choco info preview. Keys: Enter uninstall the selection Alt-X uninstall the highlighted package without closing the picker Alt-C return the command 'choco uninstall <id> -y' instead Defined by DotForge's choco companion; requires fzf (or $Env:Picker). Installing, uninstalling and upgrading need an elevated shell: they run through gsudo when DotForge's sudo alias points at it, which shows a UAC prompt; otherwise choco itself fails without admin rights. .EXAMPLE crm Pick an installed package and press Enter to uninstall it. .OUTPUTS System.String (the uninstall command) on Alt-C; otherwise none. .LINK https://github.com/simsrw73/DotForge/blob/main/docs/guide/tools.md #> [CmdletBinding()] param() Invoke-DFPackageManagerAction -Manager choco -Action Uninstall } Set-Alias -Name crm -Value Remove-ChocoPackage -Scope Global -Force function global:Invoke-ChocoUpdate { <# .SYNOPSIS Fuzzy-picks outdated Chocolatey packages and upgrades them. .DESCRIPTION Lists packages with a newer version (choco outdated: installed -> available) in fzf with a choco info preview. Keys: Tab mark a package (repeat for several) Enter upgrade the marked packages, or the highlighted one Alt-A run choco upgrade all -y Defined by DotForge's choco companion; requires fzf (or $Env:Picker). Installing, uninstalling and upgrading need an elevated shell: they run through gsudo when DotForge's sudo alias points at it, which shows a UAC prompt; otherwise choco itself fails without admin rights. .EXAMPLE cup Mark packages with Tab, then press Enter to upgrade them. .OUTPUTS None. choco writes its own progress. .LINK https://github.com/simsrw73/DotForge/blob/main/docs/guide/tools.md #> [CmdletBinding()] param() Invoke-DFPackageManagerAction -Manager choco -Action Update } Set-Alias -Name cup -Value Invoke-ChocoUpdate -Scope Global -Force # ── PSReadLine binding: Ctrl+G, C ─────────────────────────────────────────── # Type a search term, press Ctrl+G then C: pick in fzf, and the install command # lands on the command line (editable — press Enter to run). Uses the current # line as the query. Guarded so it is a no-op when PSReadLine is unavailable. Register-DFPrefillChord -Chord 'Ctrl+g,c' -Picker 'Select-ChocoPackage' ` -Description 'DotForge: choco search → install command onto the line' |