Hotkeys.ps1
|
# HotKeys.ps1 - Define custom hotkeys for PSReadLine # This script sets up custom hotkeys in PSReadLine for enhanced command line editing and history management. # Set up command prediction to use history and display predictions in a list view style. if (($host.Name -eq 'ConsoleHost') -and ($PSVersionTable.PSVersion -ge [Version]"7.2")) { # Enable command prediction based on history Set-PSReadLineOption -PredictionSource HistoryAndPlugin } else { # For older versions, just use history for prediction Set-PSReadLineOption -PredictionSource History } Set-PSReadLineOption -PredictionSource History # Set the prediction view style to ListView for better visibility of suggestions. Set-PSReadLineOption -PredictionViewStyle ListView # Configure the Tab key to trigger menu completion, which allows cycling through possible completions in a dropdown menu. Set-PSReadLineKeyHandler -Key "Tab" -Function MenuComplete # Configure Up and Down arrow keys to move the cursor to the end of the line when searching history, which is more intuitive for most users. Set-PSReadLineOption -HistorySearchCursorMovesToEnd # Set Up and Down arrow keys to search through command history based on the current input, similar to typical shell behavior. Set-PSReadLineKeyHandler -Key UpArrow -Function HistorySearchBackward Set-PSReadLineKeyHandler -Key DownArrow -Function HistorySearchForward # This script sets up a custom hotkey (Alt+Delete) in PSReadLine to delete the current command line from history. # It works by directly manipulating the history file and then refreshing the PSReadLine cache. Set-PSReadLineKeyHandler -Chord 'Alt+Delete' ` -BriefDescription "DeleteFromHistory" ` -LongDescription "Delete the current command line from history" ` -ScriptBlock { $line = $null $cursor = $null # Get the current command line and cursor position [Microsoft.PowerShell.PSConsoleReadLine]::GetBufferState([ref]$line, [ref]$cursor) # Yes, this is a hack, but PSReadLine does not provide a direct API to check dropdown visibility $options = [Microsoft.PowerShell.PSConsoleReadLine]::GetOptions() $isPredictorOn = ($options.PredictionSource -ne 'None') # Only proceed if there is a non-empty command line if ($null -ne $line -and -not [string]::IsNullOrWhiteSpace($line)) { $target = $line.Trim() $historyPath = $options.HistorySavePath if (Test-Path $historyPath) { # remove the target command from history content $newContent = Get-Content $historyPath | Where-Object { $_ -ne $target } # move original history file to a backup location to prevent conflicts during clearing Move-Item $historyPath "$historyPath.bak" -Force -ErrorAction SilentlyContinue # Clear history using PSReadLine API [Microsoft.PowerShell.PSConsoleReadLine]::RevertLine() try { [Microsoft.PowerShell.PSConsoleReadLine]::ClearHistory() # Rebuild history file and memory cache using AddToHistory if ($null -ne $newContent) { foreach ($h in $newContent) { [Microsoft.PowerShell.PSConsoleReadLine]::AddToHistory($h) } } # Cleanup backup file Remove-Item "$historyPath.bak" -ErrorAction SilentlyContinue } catch { # In case of any error, restore the original history file to prevent data loss Move-Item "$historyPath.bak" $historyPath -Force -ErrorAction SilentlyContinue } # If predictor is on, we need to trigger it to refresh its cache after history change if ($isPredictorOn) { # Trigger a dummy input to refresh predictor cache [Microsoft.PowerShell.PSConsoleReadLine]::Insert(' ') [Microsoft.PowerShell.PSConsoleReadLine]::BackwardDeleteChar() } } } } Set-PSReadLineKeyHandler -Chord 'Alt+s' ` -BriefDescription "SaveInHistory" ` -LongDescription "Save the current command line in history but do not execute it" ` -ScriptBlock { $line = $null $cursor = $null # Get the current command line and cursor position [Microsoft.PowerShell.PSConsoleReadLine]::GetBufferState([ref]$line, [ref]$cursor) if ($null -ne $line -and -not [string]::IsNullOrWhiteSpace($line)) { [Microsoft.PowerShell.PSConsoleReadLine]::AddToHistory($line.Trim()) } [Microsoft.PowerShell.PSConsoleReadLine]::RevertLine() } |