Poshify.psm1
<#
.SYNOPSIS Poshify - A PowerShell module for managing oh-my-posh themes .DESCRIPTION This module provides functions to manage oh-my-posh themes including listing, installing, and switching between themes. .NOTES Author: Poshify Module Version: 1.0.0 #> # Module variables $script:PoshifyThemesPath = Join-Path $env:USERPROFILE ".poshthemes" $script:OhMyPoshGitHubThemesUrl = "https://api.github.com/repos/JanDeDobbeleer/oh-my-posh/contents/themes" $script:ProfileBackupPath = Join-Path $env:USERPROFILE ".poshthemes\.profile_backup" <# .SYNOPSIS Gets available local oh-my-posh themes .DESCRIPTION Lists all oh-my-posh theme files available in the local themes directory .EXAMPLE Get-PoshifyTheme Lists all available local themes .EXAMPLE Get-PoshifyTheme -Name "agnoster" Gets information about a specific theme .OUTPUTS System.IO.FileInfo[] #> function Get-PoshifyTheme { [CmdletBinding()] param( [Parameter(Position = 0)] [string]$Name ) try { # Ensure themes directory exists if (-not (Test-Path $script:PoshifyThemesPath)) { Write-Warning "Themes directory not found at: $script:PoshifyThemesPath" Write-Host "Creating themes directory..." -ForegroundColor Yellow New-Item -ItemType Directory -Path $script:PoshifyThemesPath -Force | Out-Null } # Get theme files $themeFiles = Get-ChildItem -Path $script:PoshifyThemesPath -Filter "*.omp.json" -ErrorAction SilentlyContinue if ($Name) { $theme = $themeFiles | Where-Object { $_.BaseName -like "*$Name*" } if (-not $theme) { Write-Error "Theme '$Name' not found in local themes directory" return } return $theme } if ($themeFiles.Count -eq 0) { Write-Host "No themes found in: $script:PoshifyThemesPath" -ForegroundColor Yellow Write-Host "Use Find-PoshifyTheme to discover and Install-PoshifyTheme to download themes" -ForegroundColor Cyan return } Write-Host "Available local themes:" -ForegroundColor Green return $themeFiles } catch { Write-Error "Failed to get themes: $($_.Exception.Message)" } } <# .SYNOPSIS Finds oh-my-posh themes available online .DESCRIPTION Lists all oh-my-posh themes available in the official GitHub repository .EXAMPLE Find-PoshifyTheme Lists all available online themes .EXAMPLE Find-PoshifyTheme -Name "agnoster" Searches for themes containing "agnoster" in their name .OUTPUTS PSCustomObject[] #> function Find-PoshifyTheme { [CmdletBinding()] param( [Parameter(Position = 0)] [string]$Name ) try { Write-Host "Fetching available themes from oh-my-posh GitHub repository..." -ForegroundColor Cyan # Fetch themes from GitHub API $response = Invoke-RestMethod -Uri $script:OhMyPoshGitHubThemesUrl -Method Get -ErrorAction Stop # Filter for JSON theme files $themes = $response | Where-Object { $_.name -like "*.omp.json" } | ForEach-Object { [PSCustomObject]@{ Name = $_.name -replace '\.omp\.json$', '' FileName = $_.name DownloadUrl = $_.download_url Size = [math]::Round($_.size / 1KB, 2) LastModified = $_.git_url } } if ($Name) { $themes = $themes | Where-Object { $_.Name -like "*$Name*" } if ($themes.Count -eq 0) { Write-Warning "No themes found matching '$Name'" return } } Write-Host "Found $($themes.Count) themes available online:" -ForegroundColor Green return $themes } catch { Write-Error "Failed to fetch themes from GitHub: $($_.Exception.Message)" Write-Host "Make sure you have internet connectivity and GitHub is accessible" -ForegroundColor Yellow } } <# .SYNOPSIS Installs an oh-my-posh theme .DESCRIPTION Downloads and saves a theme from the official oh-my-posh repository .PARAMETER Name The name of the theme to install .EXAMPLE Install-PoshifyTheme -Name "agnoster" Downloads and installs the agnoster theme .EXAMPLE Install-PoshifyTheme -Name "powerlevel10k_rainbow" Downloads and installs the powerlevel10k_rainbow theme .OUTPUTS System.IO.FileInfo #> function Install-PoshifyTheme { [CmdletBinding()] param( [Parameter(Mandatory = $true, Position = 0)] [string]$Name ) try { # Ensure themes directory exists if (-not (Test-Path $script:PoshifyThemesPath)) { New-Item -ItemType Directory -Path $script:PoshifyThemesPath -Force | Out-Null } # Check if theme already exists locally $existingTheme = Get-ChildItem -Path $script:PoshifyThemesPath -Filter "*$Name*.omp.json" -ErrorAction SilentlyContinue if ($existingTheme) { Write-Warning "Theme '$Name' already exists locally" Write-Host "Use Get-PoshifyTheme to see all local themes" -ForegroundColor Yellow return $existingTheme } Write-Host "Searching for theme '$Name' online..." -ForegroundColor Cyan # Find the theme online $onlineThemes = Find-PoshifyTheme -Name $Name if (-not $onlineThemes) { Write-Error "Theme '$Name' not found online" return } # If multiple matches, let user choose $selectedTheme = if ($onlineThemes.Count -gt 1) { Write-Host "Multiple themes found matching '$Name':" -ForegroundColor Yellow for ($i = 0; $i -lt $onlineThemes.Count; $i++) { Write-Host " [$i] $($onlineThemes[$i].Name)" -ForegroundColor Cyan } $choice = Read-Host "Select theme number (0-$($onlineThemes.Count-1))" $onlineThemes[$choice] } else { $onlineThemes[0] } # Download the theme Write-Host "Downloading theme '$($selectedTheme.Name)'..." -ForegroundColor Green $themePath = Join-Path $script:PoshifyThemesPath $selectedTheme.FileName Invoke-WebRequest -Uri $selectedTheme.DownloadUrl -OutFile $themePath -ErrorAction Stop if (Test-Path $themePath) { Write-Host "Theme '$($selectedTheme.Name)' installed successfully!" -ForegroundColor Green Write-Host "Theme location: $themePath" -ForegroundColor Cyan return Get-Item $themePath } else { Write-Error "Theme download failed - file not found after download" } } catch { Write-Error "Failed to install theme '$Name': $($_.Exception.Message)" Write-Host "Make sure you have internet connectivity and the theme name is correct" -ForegroundColor Yellow } } <# .SYNOPSIS Sets the current oh-my-posh theme .DESCRIPTION Applies a theme by updating the user's PowerShell profile and calling oh-my-posh init .PARAMETER Name The name of the theme to apply .PARAMETER ThemePath Optional direct path to a theme file .EXAMPLE Set-PoshifyTheme -Name "agnoster" Sets the agnoster theme as the current prompt .EXAMPLE Set-PoshifyTheme -ThemePath "C:\path\to\custom.omp.json" Sets a custom theme file as the current prompt .OUTPUTS None #> function Set-PoshifyTheme { [CmdletBinding()] param( [Parameter(ParameterSetName = "ByName", Position = 0)] [string]$Name, [Parameter(ParameterSetName = "ByPath")] [string]$ThemePath ) try { # Determine theme file path $themeFile = if ($PSCmdlet.ParameterSetName -eq "ByPath") { if (-not (Test-Path $ThemePath)) { Write-Error "Theme file not found: $ThemePath" return } Get-Item $ThemePath } else { # Find theme by name $localThemes = Get-PoshifyTheme -Name $Name if (-not $localThemes) { Write-Error "Theme '$Name' not found locally" Write-Host "Use Find-PoshifyTheme to discover themes and Install-PoshifyTheme to download them" -ForegroundColor Yellow return } $localThemes[0] } # Check if oh-my-posh is installed $ohMyPosh = Get-Command oh-my-posh -ErrorAction SilentlyContinue if (-not $ohMyPosh) { Write-Error "oh-my-posh is not installed or not in PATH" Write-Host "Install oh-my-posh from: https://ohmyposh.dev/docs/installation" -ForegroundColor Yellow return } # Backup current profile if it exists $profilePath = $PROFILE.CurrentUserAllHosts if (Test-Path $profilePath) { Write-Host "Backing up current profile..." -ForegroundColor Cyan Copy-Item -Path $profilePath -Destination $script:ProfileBackupPath -Force } # Create or update profile Write-Host "Setting theme to '$($themeFile.BaseName)'..." -ForegroundColor Green $profileContent = @" # Poshify Theme - Generated by Poshify Module # Theme: $($themeFile.BaseName) # Generated on: $(Get-Date -Format "yyyy-MM-dd HH:mm:ss") oh-my-posh init pwsh --config "$($themeFile.FullName)" | Invoke-Expression "@ # Add to profile if (Test-Path $profilePath) { # Remove existing Poshify entries $existingContent = Get-Content $profilePath -Raw $existingContent = $existingContent -replace '# Poshify Theme - Generated by Poshify Module[\s\S]*?(?=\n#|\noh-my-posh init|\n\$|\nfunction|\nSet-|\nWrite-|\nif|\nImport-Module|\n$)', '' $existingContent = $existingContent.TrimEnd() if ($existingContent) { $profileContent = "$existingContent`n`n$profileContent" } } Set-Content -Path $profilePath -Value $profileContent -Force Write-Host "Theme set successfully!" -ForegroundColor Green Write-Host "Theme file: $($themeFile.FullName)" -ForegroundColor Cyan Write-Host "Profile updated: $profilePath" -ForegroundColor Cyan Write-Host "" -ForegroundColor Yellow Write-Host "To apply the theme immediately, restart PowerShell or run:" -ForegroundColor Yellow Write-Host " oh-my-posh init pwsh --config `"$($themeFile.FullName)`" | Invoke-Expression" -ForegroundColor Cyan } catch { Write-Error "Failed to set theme: $($_.Exception.Message)" Write-Host "Make sure you have write permissions to your PowerShell profile" -ForegroundColor Yellow } } <# .SYNOPSIS Resets the PowerShell prompt to default .DESCRIPTION Removes oh-my-posh configuration from the user's PowerShell profile and restores the default PowerShell prompt .EXAMPLE Reset-PoshifyTheme Resets the prompt to default PowerShell appearance .OUTPUTS None #> function Reset-PoshifyTheme { [CmdletBinding()] param() try { $profilePath = $PROFILE.CurrentUserAllHosts if (-not (Test-Path $profilePath)) { Write-Host "No PowerShell profile found - prompt is already default" -ForegroundColor Yellow return } # Read current profile $profileContent = Get-Content $profilePath -Raw # Check if Poshify theme is configured if ($profileContent -notmatch '# Poshify Theme - Generated by Poshify Module') { Write-Host "No Poshify theme configuration found in profile" -ForegroundColor Yellow # Check for any oh-my-posh configuration if ($profileContent -match 'oh-my-posh init') { Write-Warning "Found oh-my-posh configuration in profile, but it's not managed by Poshify" $confirm = Read-Host "Do you want to remove all oh-my-posh configuration? (y/N)" if ($confirm -ne 'y') { return } # Remove all oh-my-posh lines $profileContent = $profileContent -replace 'oh-my-posh init[\s\S]*?\n', "`n" $profileContent = $profileContent -replace '\n{3,}', "`n`n" $profileContent = $profileContent.Trim() Set-Content -Path $profilePath -Value $profileContent -Force Write-Host "All oh-my-posh configuration removed from profile" -ForegroundColor Green } else { Write-Host "Prompt is already using default PowerShell configuration" -ForegroundColor Green } return } # Restore backup if available if (Test-Path $script:ProfileBackupPath) { Write-Host "Restoring profile from backup..." -ForegroundColor Cyan Copy-Item -Path $script:ProfileBackupPath -Destination $profilePath -Force Remove-Item -Path $script:ProfileBackupPath -Force -ErrorAction SilentlyContinue Write-Host "Profile restored from backup" -ForegroundColor Green } else { # Remove Poshify configuration Write-Host "Removing Poshify theme configuration..." -ForegroundColor Cyan $profileContent = $profileContent -replace '# Poshify Theme - Generated by Poshify Module[\s\S]*?(?=\n#|\n\$|\nfunction|\nSet-|\nWrite-|\nif|\nImport-Module|\n$)', '' $profileContent = $profileContent.TrimEnd() Set-Content -Path $profilePath -Value $profileContent -Force Write-Host "Poshify theme configuration removed" -ForegroundColor Green } Write-Host "PowerShell prompt reset to default" -ForegroundColor Green Write-Host "Restart PowerShell to see the changes" -ForegroundColor Yellow } catch { Write-Error "Failed to reset theme: $($_.Exception.Message)" Write-Host "Make sure you have write permissions to your PowerShell profile" -ForegroundColor Yellow } } # Create CLI-friendly aliases for common operations New-Alias -Name 'poshify-theme-get' -Value 'Get-PoshifyTheme' -ErrorAction SilentlyContinue New-Alias -Name 'poshify-theme-find' -Value 'Find-PoshifyTheme' -ErrorAction SilentlyContinue New-Alias -Name 'poshify-theme-install' -Value 'Install-PoshifyTheme' -ErrorAction SilentlyContinue New-Alias -Name 'poshify-theme-set' -Value 'Set-PoshifyTheme' -ErrorAction SilentlyContinue New-Alias -Name 'poshify-theme-reset' -Value 'Reset-PoshifyTheme' -ErrorAction SilentlyContinue # Create a main Poshify command that acts as a CLI utility function Poshify { <# .SYNOPSIS Main Poshify CLI utility command .DESCRIPTION Provides a command-line interface for managing oh-my-posh themes .EXAMPLE Poshify theme install agnoster Downloads and installs the agnoster theme .EXAMPLE Poshify theme list Lists all available local themes .EXAMPLE Poshify theme find Finds available themes online .EXAMPLE Poshify theme set agnoster Sets the agnoster theme as current .EXAMPLE Poshify theme reset Resets theme to default PowerShell prompt #> [CmdletBinding()] param( [Parameter(Position = 0, Mandatory = $true)] [ValidateSet('theme')] [string]$Command, [Parameter(Position = 1, Mandatory = $true)] [ValidateSet('list', 'find', 'install', 'set', 'reset')] [string]$Action, [Parameter(Position = 2)] [string]$ThemeName ) switch ($Action) { 'list' { Get-PoshifyTheme } 'find' { if ($ThemeName) { Find-PoshifyTheme -Name $ThemeName } else { Find-PoshifyTheme } } 'install' { if (-not $ThemeName) { Write-Error "Theme name is required for install action" Write-Host "Usage: Poshify theme install <theme-name>" -ForegroundColor Yellow return } Install-PoshifyTheme -Name $ThemeName } 'set' { if (-not $ThemeName) { Write-Error "Theme name is required for set action" Write-Host "Usage: Poshify theme set <theme-name>" -ForegroundColor Yellow return } Set-PoshifyTheme -Name $ThemeName } 'reset' { Reset-PoshifyTheme } default { Write-Error "Unknown action: $Action" Write-Host "Available actions: list, find, install, set, reset" -ForegroundColor Yellow } } } # Export module functions and aliases Export-ModuleMember -Function @( 'Get-PoshifyTheme', 'Find-PoshifyTheme', 'Install-PoshifyTheme', 'Set-PoshifyTheme', 'Reset-PoshifyTheme', 'Poshify' ) -Alias @( 'poshify-theme-get', 'poshify-theme-find', 'poshify-theme-install', 'poshify-theme-set', 'poshify-theme-reset' ) |