-
Star
(426)
You must be signed in to star a gist -
Fork
(155)
You must be signed in to fork a gist
-
-
Save shanselman/25f5550ad186189e0e68916c6d7f44c3 to your computer and use it in GitHub Desktop.
| using namespace System.Management.Automation | |
| using namespace System.Management.Automation.Language | |
| if ($host.Name -eq 'ConsoleHost') | |
| { | |
| Import-Module PSReadLine | |
| } | |
| #Import-Module PSColors | |
| #Import-Module posh-git | |
| Import-Module -Name Terminal-Icons | |
| #Import-Module oh-my-posh | |
| Import-Module z | |
| set-alias desktop "Desktop.ps1" | |
| #Set-Theme ParadoxGlucose | |
| #Set-PoshPrompt -theme "D:\Dropbox\poshv3.json" | |
| oh-my-posh --init --shell pwsh --config "c:\Users\scottha\OneDrive\poshv4.json" | Invoke-Expression | |
| 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 { | |
| [System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterValue', $_) | |
| } | |
| } | |
| # PowerShell parameter completion shim for the dotnet CLI | |
| Register-ArgumentCompleter -Native -CommandName dotnet -ScriptBlock { | |
| param($commandName, $wordToComplete, $cursorPosition) | |
| dotnet complete --position $cursorPosition "$wordToComplete" | ForEach-Object { | |
| [System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterValue', $_) | |
| } | |
| } | |
| # --- | |
| # 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. | |
| # 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-PSReadLineKeyHandler -Key UpArrow -Function HistorySearchBackward | |
| Set-PSReadLineKeyHandler -Key DownArrow -Function HistorySearchForward | |
| # 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")) | |
| } | |
| } | |
| # 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' -Function CaptureScreen | |
| # 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 -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 | |
| #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 '"',"'" ` | |
| -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) | |
| } | |
| } | |
| } | |
| #endregion Smart Insert/Delete | |
| # 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 -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() | |
| } | |
| # Insert text from the clipboard as a here string | |
| Set-PSReadLineKeyHandler -Key Ctrl+V ` | |
| -BriefDescription PasteAsHereString ` | |
| -LongDescription "Paste the clipboard text as a here string" ` | |
| -ScriptBlock { | |
| param($key, $arg) | |
| Add-Type -Assembly PresentationCore | |
| if ([System.Windows.Clipboard]::ContainsText()) | |
| { | |
| # Get clipboard text - remove trailing spaces, convert \r\n to \n, and remove the final \n. | |
| $text = ([System.Windows.Clipboard]::GetText() -replace "\p{Zs}*`r?`n","`n").TrimEnd() | |
| [Microsoft.PowerShell.PSConsoleReadLine]::Insert("@'`n$text`n'@") | |
| } | |
| else | |
| { | |
| [Microsoft.PowerShell.PSConsoleReadLine]::Ding() | |
| } | |
| } | |
| # 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+(' ` | |
| -BriefDescription ParenthesizeSelection ` | |
| -LongDescription "Put parenthesis 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) | |
| { | |
| [Microsoft.PowerShell.PSConsoleReadLine]::Replace($selectionStart, $selectionLength, '(' + $line.SubString($selectionStart, $selectionLength) + ')') | |
| [Microsoft.PowerShell.PSConsoleReadLine]::SetCursorPosition($selectionStart + $selectionLength + 2) | |
| } | |
| else | |
| { | |
| [Microsoft.PowerShell.PSConsoleReadLine]::Replace(0, $line.Length, '(' + $line + ')') | |
| [Microsoft.PowerShell.PSConsoleReadLine]::EndOfLine() | |
| } | |
| } | |
| # 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+'" ` | |
| -BriefDescription ToggleQuoteArgument ` | |
| -LongDescription "Toggle quotes on the argument under the cursor" ` | |
| -ScriptBlock { | |
| param($key, $arg) | |
| $ast = $null | |
| $tokens = $null | |
| $errors = $null | |
| $cursor = $null | |
| [Microsoft.PowerShell.PSConsoleReadLine]::GetBufferState([ref]$ast, [ref]$tokens, [ref]$errors, [ref]$cursor) | |
| $tokenToChange = $null | |
| foreach ($token in $tokens) | |
| { | |
| $extent = $token.Extent | |
| if ($extent.StartOffset -le $cursor -and $extent.EndOffset -ge $cursor) | |
| { | |
| $tokenToChange = $token | |
| # 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 cursor | |
| if ($extent.EndOffset -eq $cursor -and $foreach.MoveNext()) | |
| { | |
| $nextToken = $foreach.Current | |
| if ($nextToken.Extent.StartOffset -eq $cursor) | |
| { | |
| $tokenToChange = $nextToken | |
| } | |
| } | |
| break | |
| } | |
| } | |
| if ($tokenToChange -ne $null) | |
| { | |
| $extent = $tokenToChange.Extent | |
| $tokenText = $extent.Text | |
| if ($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 + "'" | |
| } | |
| [Microsoft.PowerShell.PSConsoleReadLine]::Replace( | |
| $extent.StartOffset, | |
| $tokenText.Length, | |
| $replacement) | |
| } | |
| } | |
| # This example will replace any aliases on the command line with the resolved commands. | |
| Set-PSReadLineKeyHandler -Key "Alt+%" ` | |
| -BriefDescription ExpandAliases ` | |
| -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 [TokenFlags]::CommandName) | |
| { | |
| $alias = $ExecutionContext.InvokeCommand.GetCommand($token.Extent.Text, 'Alias') | |
| if ($alias -ne $null) | |
| { | |
| $resolvedCommand = $alias.ResolvedCommandName | |
| 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) | |
| } | |
| } | |
| } | |
| } | |
| } | |
| # 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 | |
| } | |
| } | |
| } | |
| } | |
| # | |
| # Ctrl+Shift+j then type a key to mark the current directory. | |
| # Ctrj+j then the same key will change back to that directory without | |
| # needing to type cd and won't change the command line. | |
| # | |
| $global:PSReadLineMarks = @{} | |
| Set-PSReadLineKeyHandler -Key Ctrl+J ` | |
| -BriefDescription MarkDirectory ` | |
| -LongDescription "Mark the current directory" ` | |
| -ScriptBlock { | |
| param($key, $arg) | |
| $key = [Console]::ReadKey($true) | |
| $global:PSReadLineMarks[$key.KeyChar] = $pwd | |
| } | |
| Set-PSReadLineKeyHandler -Key Ctrl+j ` | |
| -BriefDescription JumpDirectory ` | |
| -LongDescription "Goto the marked directory" ` | |
| -ScriptBlock { | |
| param($key, $arg) | |
| $key = [Console]::ReadKey() | |
| $dir = $global:PSReadLineMarks[$key.KeyChar] | |
| if ($dir) | |
| { | |
| cd $dir | |
| [Microsoft.PowerShell.PSConsoleReadLine]::InvokePrompt() | |
| } | |
| } | |
| Set-PSReadLineKeyHandler -Key Alt+j ` | |
| -BriefDescription ShowDirectoryMarks ` | |
| -LongDescription "Show the currently marked directories" ` | |
| -ScriptBlock { | |
| param($key, $arg) | |
| $global:PSReadLineMarks.GetEnumerator() | % { | |
| [PSCustomObject]@{Key = $_.Key; Dir = $_.Value} } | | |
| Format-Table -AutoSize | Out-Host | |
| [Microsoft.PowerShell.PSConsoleReadLine]::InvokePrompt() | |
| } | |
| # Auto correct 'git cmt' to 'git commit' | |
| Set-PSReadLineOption -CommandValidationHandler { | |
| param([CommandAst]$CommandAst) | |
| switch ($CommandAst.GetCommandName()) | |
| { | |
| 'git' { | |
| $gitCmd = $CommandAst.CommandElements[1].Extent | |
| switch ($gitCmd.Text) | |
| { | |
| 'cmt' { | |
| [Microsoft.PowerShell.PSConsoleReadLine]::Replace( | |
| $gitCmd.StartOffset, $gitCmd.EndOffset - $gitCmd.StartOffset, 'commit') | |
| } | |
| } | |
| } | |
| } | |
| } | |
| # `ForwardChar` accepts the entire suggestion text when the cursor is at the end of the line. | |
| # This custom binding makes `RightArrow` behave similarly - accepting the next word instead of the entire suggestion text. | |
| Set-PSReadLineKeyHandler -Key RightArrow ` | |
| -BriefDescription ForwardCharAndAcceptNextSuggestionWord ` | |
| -LongDescription "Move cursor one character to the right in the current editing line and accept the next word in suggestion when it's at the end of current editing line" ` | |
| -ScriptBlock { | |
| param($key, $arg) | |
| $line = $null | |
| $cursor = $null | |
| [Microsoft.PowerShell.PSConsoleReadLine]::GetBufferState([ref]$line, [ref]$cursor) | |
| if ($cursor -lt $line.Length) { | |
| [Microsoft.PowerShell.PSConsoleReadLine]::ForwardChar($key, $arg) | |
| } else { | |
| [Microsoft.PowerShell.PSConsoleReadLine]::AcceptNextSuggestionWord($key, $arg) | |
| } | |
| } | |
| # Cycle through arguments on current line and select the text. This makes it easier to quickly change the argument if re-running a previously run command from the history | |
| # or if using a psreadline predictor. You can also use a digit argument to specify which argument you want to select, i.e. Alt+1, Alt+a selects the first argument | |
| # on the command line. | |
| Set-PSReadLineKeyHandler -Key Alt+a ` | |
| -BriefDescription SelectCommandArguments ` | |
| -LongDescription "Set current selection to next command argument in the command line. Use of digit argument selects argument by position" ` | |
| -ScriptBlock { | |
| param($key, $arg) | |
| $ast = $null | |
| $cursor = $null | |
| [Microsoft.PowerShell.PSConsoleReadLine]::GetBufferState([ref]$ast, [ref]$null, [ref]$null, [ref]$cursor) | |
| $asts = $ast.FindAll( { | |
| $args[0] -is [System.Management.Automation.Language.ExpressionAst] -and | |
| $args[0].Parent -is [System.Management.Automation.Language.CommandAst] -and | |
| $args[0].Extent.StartOffset -ne $args[0].Parent.Extent.StartOffset | |
| }, $true) | |
| if ($asts.Count -eq 0) { | |
| [Microsoft.PowerShell.PSConsoleReadLine]::Ding() | |
| return | |
| } | |
| $nextAst = $null | |
| if ($null -ne $arg) { | |
| $nextAst = $asts[$arg - 1] | |
| } | |
| else { | |
| foreach ($ast in $asts) { | |
| if ($ast.Extent.StartOffset -ge $cursor) { | |
| $nextAst = $ast | |
| break | |
| } | |
| } | |
| if ($null -eq $nextAst) { | |
| $nextAst = $asts[0] | |
| } | |
| } | |
| $startOffsetAdjustment = 0 | |
| $endOffsetAdjustment = 0 | |
| if ($nextAst -is [System.Management.Automation.Language.StringConstantExpressionAst] -and | |
| $nextAst.StringConstantType -ne [System.Management.Automation.Language.StringConstantType]::BareWord) { | |
| $startOffsetAdjustment = 1 | |
| $endOffsetAdjustment = 2 | |
| } | |
| [Microsoft.PowerShell.PSConsoleReadLine]::SetCursorPosition($nextAst.Extent.StartOffset + $startOffsetAdjustment) | |
| [Microsoft.PowerShell.PSConsoleReadLine]::SetMark($null, $null) | |
| [Microsoft.PowerShell.PSConsoleReadLine]::SelectForwardChar($null, ($nextAst.Extent.EndOffset - $nextAst.Extent.StartOffset) - $endOffsetAdjustment) | |
| } | |
| Set-PSReadLineOption -PredictionSource History | |
| Set-PSReadLineOption -PredictionViewStyle ListView | |
| Set-PSReadLineOption -EditMode Windows | |
| # This is an example of a macro that you might use to execute a command. | |
| # This will add the command to history. | |
| Set-PSReadLineKeyHandler -Key Ctrl+Shift+b ` | |
| -BriefDescription BuildCurrentDirectory ` | |
| -LongDescription "Build the current directory" ` | |
| -ScriptBlock { | |
| [Microsoft.PowerShell.PSConsoleReadLine]::RevertLine() | |
| [Microsoft.PowerShell.PSConsoleReadLine]::Insert("dotnet build") | |
| [Microsoft.PowerShell.PSConsoleReadLine]::AcceptLine() | |
| } | |
| Set-PSReadLineKeyHandler -Key Ctrl+Shift+t ` | |
| -BriefDescription BuildCurrentDirectory ` | |
| -LongDescription "Build the current directory" ` | |
| -ScriptBlock { | |
| [Microsoft.PowerShell.PSConsoleReadLine]::RevertLine() | |
| [Microsoft.PowerShell.PSConsoleReadLine]::Insert("dotnet test") | |
| [Microsoft.PowerShell.PSConsoleReadLine]::AcceptLine() | |
| } |
I had to move all the "Set-PsReadLineOption" to the top, otherwise only the Build key handlers were registered.
👉 To customize history run code (Get-PSReadlineOption).HistorySavePath in powershell 👈
Just remove useless/misspelled commands or clear the file to start fresh.
Works good with PowerShell Core , but Windows PowerShell has some issue with imported modules.
After updating to PowerShell 7.2.0
Copyright (c) Microsoft Corporation.
Set-PSReadLineOption -PredictionViewStyle ListView
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| Could not load type 'System.Management.Automation.Subsystem.PredictionResult' from assembly
| 'Microsoft.PowerShell.PSReadLine.Polyfiller, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'.
Exception
System.TypeLoadException: Could not load type 'System.Management.Automation.Subsystem.PredictionResult' from assembly 'Microsoft.PowerShell.PSReadLine.Polyfiller, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'.
at Microsoft.PowerShell.PSConsoleReadLine.PredictionViewBase.Reset()
at Microsoft.PowerShell.PSConsoleReadLine.PredictionInlineView.Reset()
at Microsoft.PowerShell.PSConsoleReadLine.Prediction.Reset()
at Microsoft.PowerShell.PSConsoleReadLine.Initialize(Runspace runspace, EngineIntrinsics engineIntrinsics)
at Microsoft.PowerShell.PSConsoleReadLine.ReadLine(Runspace runspace, EngineIntrinsics engineIntrinsics, CancellationToken cancellationToken)
Been messing around with powershell profiles and noticed this uses the same auto-complete that's here
Some reason I couldn't get it to work, regardless of what profile I used
where can i find this json? D:\Dropbox\poshv3.json
I've changed the following:
Set-PoshPrompt -Theme jandedobbeleer
oh-my-posh --init --shell pwsh --config ~/jandedobbeleer.omp.json | Invoke-Expression
https://gist.github.com/rodvial/8de3073a205bbb1a1d8361aa8cc2d4f

9
where can I find this JSON? D:\Dropbox\poshv3.json
This JSON is the theme he uses.
You can switch it for this:
$OMPThemesFolder = $($env:APPDATA)+'\..\Local\Programs\oh-my-posh\themes\'
$OMPThemePath = $OMPThemesFolder + 'YourThemeName.omp.json'
oh-my-posh --init --shell pwsh --config $OMPThemePath | Invoke-ExpressionThe $OMPThemesFolder will point to the default themes folder of oh-my-posh with a lot of different JSON files and choose the one you like.
Anyone know what Scott's Desktop.ps1 is?
set-alias desktop "Desktop.ps1"
Awesome Thanks Scott!
Thank you very much for posting this, its awsome
Fix for -PredictionViewStyle error:
Install-Module -Name PSReadLine -AllowPrerelease -Scope CurrentUser -Force -SkipPublisherCheck
great share Scott! 👍 thank you
Thank you for this awesome profile.
Thank you @shanselman for your work, but any location to find the file 'poshv4.json' in the command below, please?
oh-my-posh --init --shell pwsh --config "c:\Users\scottha\OneDrive*poshv4.json*" | Invoke-Expression
@nalwattar3cloudsolutions I could only find https://gist.github.com/shanselman/1f69b28bfcc4f7716e49eb5bb34d7b2c but this refers to v3. I do hope @shanselman will post the v4 as well :)
hello everyone when i add this code to powershell core all works fine but as soon as i add these
Install-Module -Name Terminal-Icons -Repository PSGallery
and add this into normal powershell
Import-Module -Name Terminal-Icons
i start to get these errors in powershell core , can someone guide me why is this happening


Right from here: https://www.hanselman.com/blog/my-ultimate-powershell-prompt-with-oh-my-posh-and-the-windows-terminal