# =========================================
# PowerShell Profile
# =========================================
using namespace System.Management.Automation
using namespace System.Management.Automation.Language
# ------------------------------
# Modules
# ------------------------------
if ($host.Name -eq 'ConsoleHost') {
Import-Module PSReadLine
}
# Terminal-Icons
if (-not (Get-Module -Name Terminal-Icons)) {
Import-Module Terminal-Icons -ErrorAction SilentlyContinue
}
# ------------------------------
# Oh-My-Posh Setup
# ------------------------------
$ThemeDir = "$HOME\Documents\PowerShell\oh-my-posh-themes"
$ThemeFile = "$ThemeDir\jandedobbeleer.omp.json"
if (-not (Test-Path $ThemeDir)) {
New-Item -ItemType Directory -Path $ThemeDir -Force | Out-Null
}
if (-not (Test-Path $ThemeFile)) {
Write-Host "Downloading Oh-My-Posh theme..." -ForegroundColor Yellow
Invoke-WebRequest -Uri "https://raw.githubusercontent.com/JanDeDobbeleer/oh-my-posh/main/themes/jandedobbeleer.omp.json" `
-OutFile $ThemeFile
}
oh-my-posh init pwsh --config $ThemeFile | Invoke-Expression
# ------------------------------
# Aliases
# ------------------------------
Set-Alias ll Get-ChildItem
Set-Alias desktop "Desktop.ps1"
# ------------------------------
# Argument Completion
# ------------------------------
Register-ArgumentCompleter -Native -CommandName winget -ScriptBlock {
param($wordToComplete, $commandAst, $cursorPosition)
[Console]::InputEncoding = [Console]::OutputEncoding = $OutputEncoding = [System.Text.Utf8Encoding]::new()
$Local:word = $wordToComplete.Replace('"','""')
$Local:ast = $commandAst.ToString().Replace('"','""')
winget complete --word="$Local:word" --commandline "$Local:ast" --position $cursorPosition |
ForEach-Object { [Microsoft.PowerShell.Automation.CompletionResult]::new($_,$_, 'ParameterValue', $_) }
}
Register-ArgumentCompleter -Native -CommandName dotnet -ScriptBlock {
param($commandName, $wordToComplete, $cursorPosition)
dotnet complete --position $cursorPosition "$wordToComplete" |
ForEach-Object { [Microsoft.PowerShell.Automation.CompletionResult]::new($_,$_, 'ParameterValue', $_) }
}
# ------------------------------
# PSReadLine Key Handlers
# ------------------------------
Set-PSReadLineKeyHandler -Key UpArrow -Function HistorySearchBackward
Set-PSReadLineKeyHandler -Key DownArrow -Function HistorySearchForward
Set-PSReadLineKeyHandler -Key F7 -BriefDescription History -LongDescription 'Show command history' -ScriptBlock {
$pattern = $null
[Microsoft.PowerShell.PSConsoleReadLine]::GetBufferState([ref]$pattern,[ref]$null)
if ($pattern) { $pattern = [regex]::Escape($pattern) }
$history = Get-Content (Get-PSReadLineOption).HistorySavePath | Where-Object { -not $pattern -or ($_ -match $pattern) }
$command = $history | Out-GridView -Title History -PassThru
if ($command) {
[Microsoft.PowerShell.PSConsoleReadLine]::RevertLine()
[Microsoft.PowerShell.PSConsoleReadLine]::Insert($command)
}
}
# Movement & deletion
Set-PSReadLineKeyHandler -Key Alt+d -Function ShellKillWord
Set-PSReadLineKeyHandler -Key Alt+Backspace -Function ShellBackwardKillWord
Set-PSReadLineKeyHandler -Key Alt+b -Function ShellBackwardWord
Set-PSReadLineKeyHandler -Key Alt+f -Function ShellForwardWord
Set-PSReadLineKeyHandler -Key Alt+B -Function SelectShellBackwardWord
Set-PSReadLineKeyHandler -Key Alt+F -Function SelectShellForwardWord
# ------------------------------
# Smart Insert/Delete Quotes & Braces
# ------------------------------
function Set-SmartQuotesAndBracesHandlers {
$paired = @{
'"' = '"'
"'" = "'"
'(' = ')'
'{' = '}'
'[' = ']'
}
foreach ($key in $paired.Keys) {
Set-PSReadLineKeyHandler -Key $key -ScriptBlock {
param($key,$arg)
$closeChar = $paired[$key.KeyChar]
$selectionStart = $null
$selectionLength = $null
[Microsoft.PowerShell.PSConsoleReadLine]::GetSelectionState([ref]$selectionStart,[ref]$selectionLength)
$line = $null
$cursor = $null
[Microsoft.PowerShell.PSConsoleReadLine]::GetBufferState([ref]$line,[ref]$cursor)
if ($selectionStart -ne -1) {
[Microsoft.PowerShell.PSConsoleReadLine]::Replace($selectionStart,$selectionLength, $key.KeyChar + $line.SubString($selectionStart,$selectionLength) + $closeChar)
[Microsoft.PowerShell.PSConsoleReadLine]::SetCursorPosition($selectionStart + $selectionLength + 2)
} else {
[Microsoft.PowerShell.PSConsoleReadLine]::Insert("$($key.KeyChar)$closeChar")
[Microsoft.PowerShell.PSConsoleReadLine]::SetCursorPosition($cursor + 1)
}
}
}
# Backspace smart deletion
Set-PSReadLineKeyHandler -Key Backspace -ScriptBlock {
param($key,$arg)
$line = $null
$cursor = $null
[Microsoft.PowerShell.PSConsoleReadLine]::GetBufferState([ref]$line,[ref]$cursor)
if ($cursor -gt 0 -and $cursor -lt $line.Length) {
$prev = $line[$cursor-1]
$next = $line[$cursor]
if (($prev,$next) -in @([char[]]('"','"'),[char[]]("'", "'"),[char[]]('(',')'),[char[]]('{','}'),[char[]]('[',']'))) {
[Microsoft.PowerShell.PSConsoleReadLine]::Delete($cursor-1,2)
return
}
}
[Microsoft.PowerShell.PSConsoleReadLine]::BackwardDeleteChar($key,$arg)
}
}
Set-SmartQuotesAndBracesHandlers
# ------------------------------
# PSReadLine Options
# ------------------------------
Set-PSReadLineOption -PredictionSource History
Set-PSReadLineOption -PredictionViewStyle ListView
Set-PSReadLineOption -EditMode Windows
# ------------------------------
# Macros
# ------------------------------
Set-PSReadLineKeyHandler -Key Ctrl+Shift+b -ScriptBlock {
[Microsoft.PowerShell.PSConsoleReadLine]::RevertLine()
[Microsoft.PowerShell.PSConsoleReadLine]::Insert("dotnet build")
[Microsoft.PowerShell.PSConsoleReadLine]::AcceptLine()
}
Set-PSReadLineKeyHandler -Key Ctrl+Shift+t -ScriptBlock {
[Microsoft.PowerShell.PSConsoleReadLine]::RevertLine()
[Microsoft.PowerShell.PSConsoleReadLine]::Insert("dotnet test")
[Microsoft.PowerShell.PSConsoleReadLine]::AcceptLine()
}
# ------------------------------
# Directory Marks
# ------------------------------
$global:PSReadLineMarks = @{}
Set-PSReadLineKeyHandler -Key Ctrl+J -ScriptBlock {
$key = [Console]::ReadKey($true)
$global:PSReadLineMarks[$key.KeyChar] = $pwd
}
Set-PSReadLineKeyHandler -Key Ctrl+j -ScriptBlock {
$key = [Console]::ReadKey()
$dir = $global:PSReadLineMarks[$key.KeyChar]
if ($dir) { cd $dir; [Microsoft.PowerShell.PSConsoleReadLine]::InvokePrompt() }
}
Set-PSReadLineKeyHandler -Key Alt+j -ScriptBlock {
$global:PSReadLineMarks.GetEnumerator() | ForEach-Object { [PSCustomObject]@{Key=$_.Key; Dir=$_.Value} } |
Format-Table -AutoSize | Out-Host
[Microsoft.PowerShell.PSConsoleReadLine]::InvokePrompt()
}