Rebind Escape в PSReadline для Vi-Mode
Я установил модуль PSReadline для PowerShell, чтобы получать привязки клавиш из Bash в PowerShell. Я включил Vi-Mode, и он работает хорошо.
Проблема в том, что в Vim я всегда использую j, k для выхода из режима вставки. Это означает: сначала я набираю j, а затем k очень быстро. Если я действительно хочу ввести j и k, тогда я просто жду времени ожидания после ввода j.
Как я могу сделать то же самое в Vi-Mode в PSReadline? Я уже попробовал: Set-PSReadlineKeyHandler -Chord 'j', 'k' ViCommandMode
, но тогда я не мог набрать j
или же k
больше. Есть идеи?
0 ответов
Я удивлен, что этот вопрос не так популярен. Проблема с ответом Корбена заключается в том, что после нажатия 'j', если следующая нажатая клавиша является return или модификатором, например ctrl, вместо клавиши, которую вы ожидаете использовать, вставляется литерал.
Я переписал ответ, чтобы исправить эти две проблемы, а также превратил его в функцию, чтобы упростить повторное использование (например, при связывании двух разных букв, например jk).
Set-PSReadLineKeyHandler -vimode insert -Chord "k" -ScriptBlock { mapTwoLetterNormal 'k' 'j' }
Set-PSReadLineKeyHandler -vimode insert -Chord "j" -ScriptBlock { mapTwoLetterNormal 'j' 'k' }
function mapTwoLetterNormal($a, $b){
mapTwoLetterFunc $a $b -func $function:setViCommandMode
}
function setViCommandMode{
[Microsoft.PowerShell.PSConsoleReadLine]::ViCommandMode()
}
function mapTwoLetterFunc($a,$b,$func) {
if ([Microsoft.PowerShell.PSConsoleReadLine]::InViInsertMode()) {
$key = $host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
if ($key.Character -eq $b) {
&$func
} else {
[Microsoft.Powershell.PSConsoleReadLine]::Insert("$a")
# Representation of modifiers (like shift) when ReadKey uses IncludeKeyDown
if ($key.Character -eq 0x00) {
return
} else {
# Insert func above converts escape characters to their literals, e.g.
# converts return to ^M. This doesn't.
$wshell = New-Object -ComObject wscript.shell
$wshell.SendKeys("{$($key.Character)}")
}
}
}
}
# Bonus example
function replaceWithExit {
[Microsoft.PowerShell.PSConsoleReadLine]::BackwardKillLine()
[Microsoft.PowerShell.PSConsoleReadLine]::KillLine()
[Microsoft.PowerShell.PSConsoleReadLine]::Insert('exit')
}
Set-PSReadLineKeyHandler -Chord ";" -ScriptBlock { mapTwoLetterFunc ';' 'q' -func $function:replaceWithExit }
Для этого добавьте в свой $Profile следующее:
Set-PSReadLineKeyHandler -Chord 'j' -ScriptBlock {
if ([Microsoft.PowerShell.PSConsoleReadLine]::InViInsertMode()) {
$key = $host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
if ($key.Character -eq 'k') {
[Microsoft.PowerShell.PSConsoleReadLine]::ViCommandMode()
}
else {
[Microsoft.Powershell.PSConsoleReadLine]::Insert('j')
[Microsoft.Powershell.PSConsoleReadLine]::Insert($key.Character)
}
}
}
Однако это может вызвать проблемы с вставкой j.