# This is an example profile for PSReadLine.## This is roughly what I use so there is some emphasis on emacs bindings,# but most of these bindings make sense in Windows mode as well.

Import-ModulePSReadLine

Set-PSReadLineOption-EditModeEmacs

# Searching for commands with up/down arrow is really handy. The# option "moves to end" is useful if you want the cursor at the end# of the line while cycling through history like it does w/o searching,# without that option, the cursor will remain at the position it was# when you used up arrow, which can be useful if you forget the exact# string you started the search on.Set-PSReadLineOption-HistorySearchCursorMovesToEndSet-PSReadLineKeyHandler-KeyUpArrow-FunctionHistorySearchBackwardSet-PSReadLineKeyHandler-KeyDownArrow-FunctionHistorySearchForward

# 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-KeyF7`-BriefDescriptionHistory`-LongDescription'Show command history'`-ScriptBlock{$pattern=$null[Microsoft.PowerShell.PSConsoleReadLine]::GetBufferState([ref]$pattern,[ref]$null)if($pattern){$pattern=[regex]::Escape($pattern)}

# This is an example of a macro that you might use to execute a command.# This will add the command to history.Set-PSReadLineKeyHandler-KeyCtrl+B`-BriefDescriptionBuildCurrentDirectory`-LongDescription"Build the current directory"`-ScriptBlock{[Microsoft.PowerShell.PSConsoleReadLine]::RevertLine()[Microsoft.PowerShell.PSConsoleReadLine]::Insert("msbuild")[Microsoft.PowerShell.PSConsoleReadLine]::AcceptLine()}

# In Emacs mode - Tab acts like in bash, but the Windows style completion# is still useful sometimes, so bind some keys so we can do bothSet-PSReadLineKeyHandler-KeyCtrl+Q-FunctionTabCompleteNextSet-PSReadLineKeyHandler-KeyCtrl+Shift+Q-FunctionTabCompletePrevious

# Clipboard interaction is bound by default in Windows mode, but not Emacs mode.Set-PSReadLineKeyHandler-KeyShift+Ctrl+C-FunctionCopySet-PSReadLineKeyHandler-KeyCtrl+V-FunctionPaste

# CaptureScreen is good for blog posts or email showing a transaction# of what you did when asking for help or demonstrating a technique.Set-PSReadLineKeyHandler-Chord'Ctrl+D,Ctrl+C'-FunctionCaptureScreen

# The built-in word movement uses character delimiters, but token based word# movement is also very useful - these are the bindings you'd use if you# prefer the token based movements bound to the normal emacs word movement# key bindings.Set-PSReadLineKeyHandler-KeyAlt+D-FunctionShellKillWordSet-PSReadLineKeyHandler-KeyAlt+Backspace-FunctionShellBackwardKillWordSet-PSReadLineKeyHandler-KeyAlt+B-FunctionShellBackwardWordSet-PSReadLineKeyHandler-KeyAlt+F-FunctionShellForwardWordSet-PSReadLineKeyHandler-KeyShift+Alt+B-FunctionSelectShellBackwardWordSet-PSReadLineKeyHandler-KeyShift+Alt+F-FunctionSelectShellForwardWord

#region Smart Insert/Delete

# 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'"',"'"`-BriefDescriptionSmartInsertQuote`-LongDescription"Insert paired quotes if not already on a quote"`-ScriptBlock{param($key,$arg)

# If text is selected, just quote it without any smartsif($selectionStart-ne-1){[Microsoft.PowerShell.PSConsoleReadLine]::Replace($selectionStart,$selectionLength,$quote+$line.SubString($selectionStart,$selectionLength)+$quote)[Microsoft.PowerShell.PSConsoleReadLine]::SetCursorPosition($selectionStart+$selectionLength+2)return}

# If we're on or inside a **quoted** string token (so not generic), we need to be smarterif($token-is[StringToken]-and$token.Kind-ne[TokenKind]::Generic){# If we're at the start of the string, assume we're inserting a new stringif($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){if($line[0..$cursor].Where{$_-eq$quote}.Count%2-eq1){# 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}

# Sometimes you enter a command but realize you forgot to do something else first.# This binding will let you save that command in the history so you can recall it,# but it doesn't actually execute. It also clears the line with RevertLine so the# undo stack is reset - though redo will still reconstruct the command line.Set-PSReadLineKeyHandler-KeyAlt+w`-BriefDescriptionSaveInHistory`-LongDescription"Save current line in history but do not execute"`-ScriptBlock{param($key,$arg)

# Insert text from the clipboard as a here stringSet-PSReadLineKeyHandler-KeyCtrl+Shift+v`-BriefDescriptionPasteAsHereString`-LongDescription"Paste the clipboard text as a here string"`-ScriptBlock{param($key,$arg)

# Sometimes you want to get a property of invoke a member on what you've entered so far# but you need parens to do that. This binding will help by putting parens around the current selection,# or if nothing is selected, the whole line.Set-PSReadLineKeyHandler-Key'Alt+('`-BriefDescriptionParenthesizeSelection`-LongDescription"Put parenthesis around the selection or entire line and move the cursor to after the closing parenthesis"`-ScriptBlock{param($key,$arg)

# Each time you press Alt+', this key handler will change the token# under or before the cursor. It will cycle through single quotes, double quotes, or# no quotes each time it is invoked.Set-PSReadLineKeyHandler-Key"Alt+'"`-BriefDescriptionToggleQuoteArgument`-LongDescription"Toggle quotes on the argument under the cursor"`-ScriptBlock{param($key,$arg)

# If the cursor is at the end (it's really 1 past the end) of the previous token,# we only want to change the previous token if there is no token under the cursorif($extent.EndOffset-eq$cursor-and$foreach.MoveNext()){$nextToken=$foreach.Currentif($nextToken.Extent.StartOffset-eq$cursor){$tokenToChange=$nextToken}}break}}

if($tokenToChange-ne$null){$extent=$tokenToChange.Extent$tokenText=$extent.Textif($tokenText[0]-eq'"'-and$tokenText[-1]-eq'"'){# Switch to no quotes$replacement=$tokenText.Substring(1,$tokenText.Length-2)}elseif($tokenText[0]-eq"'"-and$tokenText[-1]-eq"'"){# Switch to double quotes$replacement='"'+$tokenText.Substring(1,$tokenText.Length-2)+'"'}else{# Add single quotes$replacement="'"+$tokenText+"'"}

# This example will replace any aliases on the command line with the resolved commands.Set-PSReadLineKeyHandler-Key"Alt+%"`-BriefDescriptionExpandAliases`-LongDescription"Replace all aliases with the full command"`-ScriptBlock{param($key,$arg)