Skip to content

Instantly share code, notes, and snippets.

@viplyzbytes
Last active February 6, 2026 11:03
Show Gist options
  • Select an option

  • Save viplyzbytes/5b8c7e835fd7bbfc4d92920c955a7bc2 to your computer and use it in GitHub Desktop.

Select an option

Save viplyzbytes/5b8c7e835fd7bbfc4d92920c955a7bc2 to your computer and use it in GitHub Desktop.
Customized Powershell Profile
# A 'using' statement must appear before any other statements in a script.
using namespace System.Management.Automation
using namespace System.Management.Automation.Language
# following lines add "ctrl+backspace" key inside vs-code powershell terminal instead of "ctel+w".
<#
if ($env:TERM_PROGRAM -eq "vscode") {
Set-PSReadLineKeyHandler -Chord 'Ctrl+w' -Function BackwardKillWord
}
#>
# fnm config for powershell
fnm env --use-on-cd --version-file-strategy=recursive | Out-String | Invoke-Expression
# Starship config file for powershell
$ENV:STARSHIP_CONFIG = "C:\Users\iam_v\.config\starship-pwsh.toml"
# invoking starship on start of powershell
Invoke-Expression (&starship init powershell)
# PSReadLine Custom Options taken from Scott Hanselman's powershell and tim sneath gists.
Import-Module PSReadLine
Set-PSReadLineKeyHandler -key Tab -Function Complete
Set-PSReadLineOption -PredictionSource HistoryAndPlugin
Set-PSReadLineOption -HistoryNoDuplicates
Set-PSReadLineOption -PredictionViewStyle Inline
Set-PSReadLineOption -EditMode Windows
# This key handler shows the entire or filtered history using Out-GridView. The typed text is used as the substring pattern for filtering.
# A selected command is inserted to the command line without invoking. Multiple command selection is supported, e.g. selected by Ctrl + Click.
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 = [System.Collections.ArrayList]@(
$last = ''
$lines = ''
foreach ($line in [System.IO.File]::ReadLines((Get-PSReadLineOption).HistorySavePath))
{
if ($line.EndsWith('`'))
{
$line = $line.Substring(0, $line.Length - 1)
$lines = if ($lines)
{
"$lines`n$line"
}
else
{
$line
}
continue
}
if ($lines)
{
$line = "$lines`n$line"
$lines = ''
}
if (($line -cne $last) -and (!$pattern -or ($line -match $pattern)))
{
$last = $line
$line
}
}
)
$history.Reverse()
$command = $history | Out-GridView -Title History -PassThru
if ($command)
{
[Microsoft.PowerShell.PSConsoleReadLine]::RevertLine()
[Microsoft.PowerShell.PSConsoleReadLine]::Insert(($command -join "`n"))
}
}
# The next four key handlers are designed to make entering matched quotes, parens, and braces a nicer experience.
# I'd like to include functions in the module that do this, but this implementation still isn't as smart as ReSharper, so I'm just providing it as a sample.
Set-PSReadLineKeyHandler -Key '"',"'" `
-BriefDescription SmartInsertQuote `
-LongDescription "Insert paired quotes if not already on a quote" `
-ScriptBlock {
param($key, $arg)
$quote = $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 text is selected, just quote it without any smarts
if ($selectionStart -ne -1)
{
[Microsoft.PowerShell.PSConsoleReadLine]::Replace($selectionStart, $selectionLength, $quote + $line.SubString($selectionStart, $selectionLength) + $quote)
[Microsoft.PowerShell.PSConsoleReadLine]::SetCursorPosition($selectionStart + $selectionLength + 2)
return
}
$ast = $null
$tokens = $null
$parseErrors = $null
[Microsoft.PowerShell.PSConsoleReadLine]::GetBufferState([ref]$ast, [ref]$tokens, [ref]$parseErrors, [ref]$null)
function FindToken
{
param($tokens, $cursor)
foreach ($token in $tokens)
{
if ($cursor -lt $token.Extent.StartOffset) { continue }
if ($cursor -lt $token.Extent.EndOffset) {
$result = $token
$token = $token -as [StringExpandableToken]
if ($token) {
$nested = FindToken $token.NestedTokens $cursor
if ($nested) { $result = $nested }
}
return $result
}
}
return $null
}
$token = FindToken $tokens $cursor
# If we're on or inside a **quoted** string token (so not generic), we need to be smarter
if ($token -is [StringToken] -and $token.Kind -ne [TokenKind]::Generic) {
# If we're at the start of the string, assume we're inserting a new string
if ($token.Extent.StartOffset -eq $cursor) {
[Microsoft.PowerShell.PSConsoleReadLine]::Insert("$quote$quote ")
[Microsoft.PowerShell.PSConsoleReadLine]::SetCursorPosition($cursor + 1)
return
}
# If we're at the end of the string, move over the closing quote if present.
if ($token.Extent.EndOffset -eq ($cursor + 1) -and $line[$cursor] -eq $quote) {
[Microsoft.PowerShell.PSConsoleReadLine]::SetCursorPosition($cursor + 1)
return
}
}
if ($null -eq $token -or
$token.Kind -eq [TokenKind]::RParen -or $token.Kind -eq [TokenKind]::RCurly -or $token.Kind -eq [TokenKind]::RBracket) {
if ($line[0..$cursor].Where{$_ -eq $quote}.Count % 2 -eq 1) {
# Odd number of quotes before the cursor, insert a single quote
[Microsoft.PowerShell.PSConsoleReadLine]::Insert($quote)
}
else {
# Insert matching quotes, move cursor to be in between the quotes
[Microsoft.PowerShell.PSConsoleReadLine]::Insert("$quote$quote")
[Microsoft.PowerShell.PSConsoleReadLine]::SetCursorPosition($cursor + 1)
}
return
}
# If cursor is at the start of a token, enclose it in quotes.
if ($token.Extent.StartOffset -eq $cursor) {
if ($token.Kind -eq [TokenKind]::Generic -or $token.Kind -eq [TokenKind]::Identifier -or
$token.Kind -eq [TokenKind]::Variable -or $token.TokenFlags.hasFlag([TokenFlags]::Keyword)) {
$end = $token.Extent.EndOffset
$len = $end - $cursor
[Microsoft.PowerShell.PSConsoleReadLine]::Replace($cursor, $len, $quote + $line.SubString($cursor, $len) + $quote)
[Microsoft.PowerShell.PSConsoleReadLine]::SetCursorPosition($end + 2)
return
}
}
# We failed to be smart, so just insert a single quote
[Microsoft.PowerShell.PSConsoleReadLine]::Insert($quote)
}
Set-PSReadLineKeyHandler -Key '(','{','[' `
-BriefDescription InsertPairedBraces `
-LongDescription "Insert matching braces" `
-ScriptBlock {
param($key, $arg)
$closeChar = switch ($key.KeyChar)
{
<#case#> '(' { [char]')'; break }
<#case#> '{' { [char]'}'; break }
<#case#> '[' { [char]']'; break }
}
$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)
{
# Text is selected, wrap it in brackets
[Microsoft.PowerShell.PSConsoleReadLine]::Replace($selectionStart, $selectionLength, $key.KeyChar + $line.SubString($selectionStart, $selectionLength) + $closeChar)
[Microsoft.PowerShell.PSConsoleReadLine]::SetCursorPosition($selectionStart + $selectionLength + 2)
} else {
# No text is selected, insert a pair
[Microsoft.PowerShell.PSConsoleReadLine]::Insert("$($key.KeyChar)$closeChar")
[Microsoft.PowerShell.PSConsoleReadLine]::SetCursorPosition($cursor + 1)
}
}
Set-PSReadLineKeyHandler -Key ')',']','}' `
-BriefDescription SmartCloseBraces `
-LongDescription "Insert closing brace or skip" `
-ScriptBlock {
param($key, $arg)
$line = $null
$cursor = $null
[Microsoft.PowerShell.PSConsoleReadLine]::GetBufferState([ref]$line, [ref]$cursor)
if ($line[$cursor] -eq $key.KeyChar)
{
[Microsoft.PowerShell.PSConsoleReadLine]::SetCursorPosition($cursor + 1)
}
else
{
[Microsoft.PowerShell.PSConsoleReadLine]::Insert("$($key.KeyChar)")
}
}
Set-PSReadLineKeyHandler -Key Backspace `
-BriefDescription SmartBackspace `
-LongDescription "Delete previous character or matching quotes/parens/braces" `
-ScriptBlock {
param($key, $arg)
$line = $null
$cursor = $null
[Microsoft.PowerShell.PSConsoleReadLine]::GetBufferState([ref]$line, [ref]$cursor)
if ($cursor -gt 0)
{
$toMatch = $null
if ($cursor -lt $line.Length)
{
switch ($line[$cursor])
{
<#case#> '"' { $toMatch = '"'; break }
<#case#> "'" { $toMatch = "'"; break }
<#case#> ')' { $toMatch = '('; break }
<#case#> ']' { $toMatch = '['; break }
<#case#> '}' { $toMatch = '{'; break }
}
}
if ($toMatch -ne $null -and $line[$cursor-1] -eq $toMatch)
{
[Microsoft.PowerShell.PSConsoleReadLine]::Delete($cursor - 1, 2)
}
else
{
[Microsoft.PowerShell.PSConsoleReadLine]::BackwardDeleteChar($key, $arg)
}
}
}
# F1 for help on the command line - naturally
Set-PSReadLineKeyHandler -Key F1 `
-BriefDescription CommandHelp `
-LongDescription "Open the help window for the current command" `
-ScriptBlock {
param($key, $arg)
$ast = $null
$tokens = $null
$errors = $null
$cursor = $null
[Microsoft.PowerShell.PSConsoleReadLine]::GetBufferState([ref]$ast, [ref]$tokens, [ref]$errors, [ref]$cursor)
$commandAst = $ast.FindAll( {
$node = $args[0]
$node -is [CommandAst] -and
$node.Extent.StartOffset -le $cursor -and
$node.Extent.EndOffset -ge $cursor
}, $true) | Select-Object -Last 1
if ($commandAst -ne $null)
{
$commandName = $commandAst.GetCommandName()
if ($commandName -ne $null)
{
$command = $ExecutionContext.InvokeCommand.GetCommand($commandName, 'All')
if ($command -is [AliasInfo])
{
$commandName = $command.ResolvedCommandName
}
if ($commandName -ne $null)
{
Get-Help $commandName -ShowWindow
}
}
}
}
# Oh-My-Posh settings
<# Install OMP:
winget install JanDeDobbeleer.OhMyPosh -s winget
#>
# Created variables for OMP theme.
# In order to change theme just change .json theme in $OMPThemePath
#$OMPThemesFolder = $($env:APPDATA)+'\..\Local\Programs\oh-my-posh\themes\'
#$OMPThemePath = $OMPThemesFolder + 'powerlevel10k_rainbow.omp.json'
#oh-my-posh init pwsh --config $OMPThemePath | Invoke-Expression
# Terminal Icons
Import-Module -Name Terminal-Icons
# this is single line comment
<# Block-Comment
To change theme, replace name of the theme with the one you want to install, i.e. the word after ..\themes\ and keep extension as ".omp.json"
After changing theme, apply the current profile by giving ".$PROFILE" command in powershell.
My Favoriate themes:
1. tokyo
2. quick-term
3. emodipt-extend
4. slim
5. space
6. plague
7. powerlevel10k_rainbow
8. montys
9. kushal
Install **file type icons** type command:
Install-Module -Name Terminal-Icons -Repository PSGallery
and then add following command to profile file of powershell:
Import-Module -Name Terminal-Icons
To install Z use coommand:
install-module -name z -force
To install PSReadLine:
install-module -name PSReadLine -AllowPrerelease -scope CurrentUser -force -SkipPublisherCheck
Options for PSReadLine:
set-PSReadLineOption -PredictionSource History
restart terminal/shell
set-PSReadLineOption -PredictionViewStyle ListView
#>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment