This is a guide that helps you install oh-my-posh and its necessary boilerplate without deep dive to their documentation
In this guide, it is assumed that you have installed:
- VS Code (User setup, not system one);
- PowerShell 6+, whatever way (Microsoft Store, WinGet, Portable);
- Windows Terminal from Microsoft Store.
If not, you need to modify all following scripts below to make it work with different environment.
Install oh-my-posh
, posh-git
and then close tab.
winget install XP8K0HKJFRXGCK --source msstore --accept-source-agreements --accept-package-agreements
Install-Module posh-git -Scope CurrentUser
exit
Then close Windows Terminal window or reopen a tab, because we need environment variables to refresh.
Open Windows Terminal/pswh from admin:
Win+R, type wt
, Ctrl + Shift + Enter, click "Yes"
then execute these commands:
Add-MpPreference -ExclusionProcess "oh-my-posh.exe"
You now can close tab from admin, it will not be needed again.
PowerShell can do some things before launch. We need posh-git
and oh-my-posh
to launch on every PowerShell instance.
Open wt
/pwsh
and then execute this code:
if (Test-Path -Path $Profile -PathType Leaf) {
Write-Host "Profile already exists"
} else {
New-Item -Path $PROFILE -Type File
Write-Host "Profile Created"
}
function AddLineToFile {
param (
[Parameter(Mandatory=$True)]
[string]$PathToFile,
[Parameter(Mandatory=$True)]
[string]$Pattern,
[Parameter(Mandatory=$True)]
[string]$LineToAdd
)
# get the file contents
$fileContents = Get-Content -Path $PathToFile
$found = $False
Foreach ($item in $fileContents)
{
If ($item -like $Pattern)
{
Write-Host "`"$Pattern`" string already exists"
Write-Host "Nothing to do"
$found = $True
break
}
}
if ($found -ne $True) {
Add-Content -Path $PROFILE -Value $LineToAdd
Write-Host "`"$LineToAdd`" line was added"
}
}
AddLineToFile $PROFILE "Import-Module posh-git*" "Import-Module posh-git";
AddLineToFile $PROFILE "oh-my-posh init pwsh*" "oh-my-posh init pwsh | Invoke-Expression";
You can add some tweaks in your $PROFILE
later, above is just necessary stuff to get oh-my-posh
work.
This code does what the paragraph says:
- It downloads the latest
CaskaydiaCove
font zip-file; - Unzips it;
- Installs all the kinds of the font;
- Removes downloaded font files;
- Patches Windows Terminal settings with backup;
- Patches VS Code settings with backup.
You can execute this code with the same pwsh instance from previous paragraph:
# Initial setup
$developerName = "ryanoasis";
$repoName = "nerd-fonts";
$wtFileToDownload = "CascadiaCode.zip";
$fontNameToSet = "CaskaydiaCove NFM";
# Get latest NerdFont release version
$url = "https://github.com/$developerName/$repoName/releases/latest";
$request = [System.Net.WebRequest]::Create($url);
$response = $request.GetResponse();
$realTagUrl = $response.ResponseUri.OriginalString;
$version = $realTagUrl.split("/")[-1].Trim("v");
$wtFileName = $wtFileToDownload; # $wtFileName should be because maybe there is $version in its name
$realDownloadUrl = $realTagUrl.Replace("tag", "download") + "/" + $wtFileName;
Write-Host $realDownloadUrl;
# Download Nerdfont file
$fontsFileLocation = "$env:TEMP/$wtFileName";
$fontsDirectoryLocation = "$env:TEMP/"+(Split-Path $fontsFileLocation -LeafBase);
Invoke-WebRequest -Uri $realDownloadUrl -OutFile $fontsFileLocation;
# Extract Nerdfont file
Write-Host "Expanding $fontsFileLocation";
Expand-Archive $fontsFileLocation -DestinationPath $fontsDirectoryLocation;
Get-ChildItem -Path $fontsDirectoryLocation -Include "*.ttf","*.ttc","*.otf" -Recurse | ForEach-Object {(New-Object -ComObject Shell.Application).Namespace(0x14).CopyHere($_.FullName, 0x10)};
Write-Host "Removing file at path $fontsFileLocation";
Remove-Item $fontsFileLocation -ErrorAction Continue;
Write-Host "Succesfully removed file at path $fontsFileLocation";
Remove-Item $fontsDirectoryLocation -ErrorAction Continue -Recurse;
Write-Host "Succesfully removed directory at path $fontsDirectoryLocation";
Write-Host "";
# Set font in Windows Terminal
$wtSettingsFileLocation = "$env:LOCALAPPDATA\Packages\Microsoft.WindowsTerminal_8wekyb3d8bbwe\LocalState\settings.json";
if (Test-Path -Path $wtSettingsFileLocation) {
Write-Host "File at path $wtSettingsFileLocation exists. Performing changes";
# get backup copy file with .bak extension
$configPath = $wtSettingsFileLocation;
$configPathBak = $configPath + ".bak";
Copy-Item $configPath $configPathBak -ErrorAction Continue;
# change font-face
$wtFile = Get-Content $wtSettingsFileLocation -raw | ConvertFrom-Json -Depth 100;
$success = $False;
try {
if (-not $wtFile.profiles.defaults.font) {
Write-Host "No font property found in $wtSettingsFileLocation. Creating it";
$jsonContent = [PSCustomObject]@{}
$wtFile.profiles.defaults | Add-Member -NotePropertyName "font" -NotePropertyValue ([PSCustomObject]@{"face" = $fontNameToSet})
} else {
if (-not $wtFile.profiles.defaults.font.face) {
Write-Host "No font.face property found in $wtSettingsFileLocation. Creating it";
Add-Member -InputObject $wtFile.profiles.defaults.font -MemberType NoteProperty -Name "face" -Value $fontNameToSet
} else {
$wtFile.profiles.defaults.font.face = $fontNameToSet;
}
}
$success = $True;
Write-Host "File $wtSettingsFileLocation successfully modified";
}
catch {
$wtFileName = Split-Path $wtSettingsFileLocation -Leaf;
Write-Host "Error modifying $wtFileName file contents: $_";
}
# save successfully modified file
if ($success -eq $True) {
Set-Content -Value ($wtFile | ConvertTo-Json -Depth 100) -Path $wtSettingsFileLocation;
}
} else {
Write-Host "File at path $wtSettingsFileLocation does not exist. No changes will be made";
}
# Set font in VS Code
$vscodeSettingsPath = "$env:APPDATA\Code\User\settings.json";
# get backup copy file with .bak extension
if (Test-Path -Path $vscodeSettingsPath) {
Write-Host "File at path $vscodeSettingsPath exists. Performing changes";
$configPath = $vscodeSettingsPath;
$configPathBak = $configPath + ".bak";
Copy-Item $configPath $configPathBak -ErrorAction Continue;
$fontSetting = "terminal.integrated.fontFamily";
$vscodeFile = Get-Content -Raw -Path $vscodeSettingsPath -ErrorAction silentlycontinue | ConvertFrom-Json -Depth 100
$success = $False;
try {
if (-not $vscodeFile.$fontSetting) {
Add-Member -InputObject $vscodeFile -MemberType NoteProperty -Name $fontSetting -Value $fontNameToSet
} else {
$vscodeFile.$fontSetting = $fontNameToSet;
}
$success = $True;
Write-Host "File $vscodeSettingsPath successfully modified";
}
catch {
$vscodeFileName = Split-Path $vscodeSettingsPath -Leaf;
Write-Host "Error modifying $vscodeFileName file contents: $_";
}
# save successfully modified file
if ($success -eq $True) {
Set-Content -Value ($vscodeFile | ConvertTo-Json -Depth 100) -Path $vscodeSettingsPath;
}
}
We are using Caskaydia Cove font, but you can change $wtFileToDownload
and $fontNameToSet
to set a different one. List is here.
Script also creates backup files of configs for a case if somethings is getting corrupted. Follow these paths to restore or modify configs:
- Windows Terminal config path:
%LOCALAPPDATA%\Packages\Microsoft.WindowsTerminal_8wekyb3d8bbwe\LocalState
- VS Code config path:
%APPDATA%\Code\User
You can use either this command, getting the latest of theme, not tied up with oh-my-posh
setup:
oh-my-posh init pwsh --config "https://raw.githubusercontent.com/JanDeDobbeleer/oh-my-posh/main/themes/M365Princess.omp.json" | Invoke-Expression
Or use the same theme but out-of-the-box:
oh-my-posh init pwsh --config "$env:POSH_THEMES_PATH/M365Princess.omp.json" | Invoke-Expression
I prefer the second one, because who knows what breaking changes would happen by theme?
You can set a different theme from here.
That's all, folks! You just need 3 wt
instances and 5 scripts to install oh-my-posh
. Hope this is the simplest guide you ever met!
Thanks for your job! Can you please integrate the auto-skipping for the fonts installation? I have a Win11, and for the command:
Get-ChildItem -Path $fontsDirectoryLocation -Include "*.ttf","*.ttc","*.otf" -Recurse | ForEach-Object {(New-Object -ComObject Shell.Application).Namespace(0x14).CopyHere($_.FullName, 0x10)};
I should manually skip or confirm the installation for all font they already installed in my system.
Best regards