4

我已经为 PowerShell 安装了 PSReadline 模块,以从 PowerShell 中的 Bash 获取键绑定。我启用了 Vi-Mode,它运行良好。

问题是:在 Vim 中,我总是使用 j, k 来退出插入模式。这意味着:首先我输入 j 然后 k 非常快。如果我真的想输入 j 和 k,那么我只需在输入 j 后等待超时。

如何在 PSReadline 的 Vi-Mode 中执行相同的操作?我已经尝试过:Set-PSReadlineKeyHandler -Chord 'j', 'k' ViCommandMode,但后来我无法输入jk不再输入。有任何想法吗?

4

2 回答 2

1

我很惊讶这个问题没有更受欢迎。Corben 的答案的问题是,在按下“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 }

于 2020-06-17T09:46:22.123 回答
1

为此,请在您的 $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”时出现问题。

于 2020-02-12T16:25:23.773 回答