Skip to content

Instantly share code, notes, and snippets.

@gerane
Forked from rkeithhill/PSReadLine_config.ps1
Created March 1, 2017 16:54
Show Gist options
  • Save gerane/bb3692e87a6b53fd1da2e9a825c2939a to your computer and use it in GitHub Desktop.
Save gerane/bb3692e87a6b53fd1da2e9a825c2939a to your computer and use it in GitHub Desktop.
PSReadline configuration updated for PSReadline v1.1
# Need to explicitly import PSReadLine in a number of cases: Windows versions < 10 and
# x86 consoles that aren't loading PSReadLine.
# Source: https://gist.github.com/rkeithhill/3103994447fd307b68be#file-psreadline_config-ps1
# Other hosts (ISE, ConEmu) don't always work as well with PSReadline.
if ($host.Name -ne 'ConsoleHost') { return }
# PSReadline hasn't been auto-imported, try to manually import it
if (!(Get-Module PSReadline -ErrorAction SilentlyContinue)) {
if (!$IsLinux -and !$IsOSX -and ([IntPtr]::Size -eq 4) -and !(Get-Module -ListAvailable PSReadline)) {
$origPSModulePath = $env:PSModulePath
$env:PSModulePath += ';C:\Program Files\WindowsPowerShell\Modules'
Import-Module PSReadline
$env:PSModulePath = $origPSModulePath
}
else {
Import-Module PSReadline
}
}
Set-PSReadlineOption -MaximumHistoryCount 10000 -HistorySearchCursorMovesToEnd -HistoryNoDuplicates -HistorySavePath $PSScriptRoot\PSReadLine_history.txt
Set-PSReadlineOption -ExtraPromptLineCount 1
Set-PSReadlineOption -AddToHistoryHandler {
param([string]$line)
return $line.Length -gt 3
}
Set-PSReadlineKeyHandler -Chord UpArrow -Function HistorySearchBackward
Set-PSReadlineKeyHandler -Chord DownArrow -Function HistorySearchForward
if (!$IsLinux -and !$IsOSX) {
Set-PSReadlineKeyHandler -Chord 'Ctrl+D,Ctrl+C' -Function CaptureScreen
# Insert paired quotes if not already on a quote
Set-PSReadlineKeyHandler -Chord "Ctrl+'","Ctrl+Shift+'" `
-BriefDescription SmartInsertQuote `
-Description "Insert paired quotes if not already on a quote" `
-ScriptBlock {
param($key, $arg)
$line = $null
$cursor = $null
[Microsoft.PowerShell.PSConsoleReadLine]::GetBufferState([ref]$line, [ref]$cursor)
$keyChar = $key.KeyChar
if ($key.Key -eq 'Oem7') {
if ($key.Modifiers -eq 'Control') {
$keyChar = "`'"
}
elseif ($key.Modifiers -eq 'Shift','Control') {
$keyChar = '"'
}
}
if ($line[$cursor] -eq $key.KeyChar) {
# Just move the cursor
[Microsoft.PowerShell.PSConsoleReadLine]::SetCursorPosition($cursor + 1)
}
else {
# Insert matching quotes, move cursor to be in between the quotes
[Microsoft.PowerShell.PSConsoleReadLine]::Insert("$keyChar" * 2)
[Microsoft.PowerShell.PSConsoleReadLine]::GetBufferState([ref]$line, [ref]$cursor)
[Microsoft.PowerShell.PSConsoleReadLine]::SetCursorPosition($cursor - 1)
}
}
# Copy the current path to the clipboard
Set-PSReadlineKeyHandler -Key Alt+c `
-BriefDescription CopyCurrentPathToClipboard `
-LongDescription "Copy the current path to the clipboard" `
-ScriptBlock {
param($key, $arg)
Add-Type -Assembly System.Windows.Forms
[System.Windows.Forms.Clipboard]::SetText($pwd.Path, 'Text')
}
# Paste the clipboard text as a here string
Set-PSReadlineKeyHandler -Key Ctrl+Shift+v `
-BriefDescription PasteAsHereString `
-LongDescription "Paste the clipboard text as a here string" `
-ScriptBlock {
param($key, $arg)
Add-Type -Assembly System.Windows.Forms
if ([System.Windows.Forms.Clipboard]::ContainsText())
{
# Get clipboard text - remove trailing spaces, convert \r\n to \n, and remove the final \n.
$text = ([System.Windows.Forms.Clipboard]::GetText() -replace "\p{Zs}*`r?`n","`n").TrimEnd()
[Microsoft.PowerShell.PSConsoleReadLine]::Insert("@'`n$text`n'@")
}
else
{
[Microsoft.PowerShell.PSConsoleReadLine]::Ding()
}
}
# Put parentheses around the selection or entire line and move the cursor to after the closing paren
Set-PSReadlineKeyHandler -Key 'Ctrl+(' `
-BriefDescription ParenthesizeSelection `
-LongDescription "Put parentheses around the selection or entire line and move the cursor to after the closing parenthesis" `
-ScriptBlock {
param($key, $arg)
$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)
{
$replacement = '(' + $line.SubString($selectionStart, $selectionLength) + ')'
[Microsoft.PowerShell.PSConsoleReadLine]::Replace($selectionStart, $selectionLength, $replacement)
[Microsoft.PowerShell.PSConsoleReadLine]::SetCursorPosition($selectionStart + $selectionLength + 2)
}
else
{
[Microsoft.PowerShell.PSConsoleReadLine]::Replace(0, $line.Length, '(' + $line + ')')
[Microsoft.PowerShell.PSConsoleReadLine]::EndOfLine()
}
}
# 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"))
}
}
}
# Insert matching braces
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 }
}
$line = $null
$cursor = $null
[Microsoft.PowerShell.PSConsoleReadLine]::GetBufferState([ref]$line, [ref]$cursor)
if ($cursor -eq $line.Length -or $line[$cursor] -match '\)|}|\]|\s')
{
[Microsoft.PowerShell.PSConsoleReadLine]::Insert("$($key.KeyChar)$closeChar")
[Microsoft.PowerShell.PSConsoleReadLine]::GetBufferState([ref]$line, [ref]$cursor)
[Microsoft.PowerShell.PSConsoleReadLine]::SetCursorPosition($cursor - 1)
}
else
{
[Microsoft.PowerShell.PSConsoleReadLine]::Insert($key.KeyChar)
}
}
# Insert closing brace or skip
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)")
}
}
# Replace all aliases with the full command
Set-PSReadlineKeyHandler -Key Alt+r `
-BriefDescription ResolveAliases `
-LongDescription "Replace all aliases with the full 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)
$startAdjustment = 0
foreach ($token in $tokens)
{
if ($token.TokenFlags -band [System.Management.Automation.Language.TokenFlags]::CommandName)
{
$alias = $ExecutionContext.InvokeCommand.GetCommand($token.Extent.Text, 'Alias')
if ($alias -ne $null)
{
$resolvedCommand = if ($alias.ResolvedCommandName) { $alias.ResolvedCommandName } else { $alias.Definition }
if ($resolvedCommand -ne $null)
{
$extent = $token.Extent
$length = $extent.EndOffset - $extent.StartOffset
[Microsoft.PowerShell.PSConsoleReadLine]::Replace(
$extent.StartOffset + $startAdjustment,
$length,
$resolvedCommand)
# Our copy of the tokens won't have been updated, so we need to
# adjust by the difference in length
$startAdjustment += ($resolvedCommand.Length - $length)
}
}
}
}
}
# Save current line in history but do not execute
Set-PSReadlineKeyHandler -Key Alt+w `
-BriefDescription SaveInHistory `
-LongDescription "Save current line in history but do not execute" `
-ScriptBlock {
param($key, $arg)
$line = $null
$cursor = $null
[Microsoft.PowerShell.PSConsoleReadLine]::GetBufferState([ref]$line, [ref]$cursor)
[Microsoft.PowerShell.PSConsoleReadLine]::AddToHistory($line)
[Microsoft.PowerShell.PSConsoleReadLine]::RevertLine()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment