PSReadLine 系列

about_PSReadLine

简短说明

PSReadLine 在 PowerShell 控制台中提供了改进的命令行编辑体验。

详细说明

PSReadLine 为 PowerShell 控制台提供了强大的命令行编辑体验。 它提供:

  • 命令行的语法着色
  • 语法错误的可视化提示
  • 更好的多行体验(编辑和历史记录)
  • 可自定义密钥绑定
  • Cmd 和 Emacs 模式
  • 许多配置选项
  • Bash 风格补全(Cmd 模式下为可选,Emacs 模式下为默认)
  • Emacs 拉扯/杀伤环
  • 基于 PowerShell 令牌的“单词”移动和终止

[Microsoft.PowerShell.PSConsoleReadLine] 中提供了以下函数。

游标移动

Line终点

  • Cmd:<End>
  • Emacs: <End><Ctrl+E>

如果输入具有多行,则移动到当前行的末尾,或者如果已在行末尾,则移动到输入的末尾。 如果输入有一行,则移动到输入的末尾。

行的起点

  • Cmd:<Home>
  • Emacs: <Home><Ctrl+A>

如果输入具有多行,则移动到当前行的开头,或者如果已在行的开头,则移动到输入的开头。 如果输入有一行,请移动到输入的开头。

NextLine 系列

  • Cmd:unbound
  • Emacs:未绑定

如果输入有多行,请将光标移动到下一行。

上一页

  • Cmd:unbound
  • Emacs:未绑定

如果输入有多行,请将光标移动到上一行。

ForwardChar

  • Cmd:<RightArrow>
  • Emacs: <RightArrow><Ctrl+F>

将光标向右移动一个字符。 这可能会将光标移动到多行输入的下一行。

BackwardChar (向后字符)

  • Cmd:<LeftArrow>
  • Emacs: <LeftArrow><Ctrl+B>

将光标向左移动一个字符。 这可能会将光标移动到多行输入的上一行。

转发 Word

  • Cmd:unbound
  • Emacs 的: <Alt+F>

将光标向前移动到当前单词的末尾,或者在单词之间移动至下一个单词的末尾。 您可以使用以下方法设置单词分隔符:

Set-PSReadLineOption -WordDelimiters `<string of delimiter characters>`

下一页

  • Cmd:<Ctrl+RightArrow>
  • Emacs:未绑定

将光标向前移动到下一个单词的开头。 您可以使用以下方法设置单词分隔符:

Set-PSReadLineOption -WordDelimiters `<string of delimiter characters>`

BackwardWord

  • Cmd:<Ctrl+LeftArrow>
  • Emacs 的: <Alt+B>

将光标移回当前单词的开头,或者在单词之间移动前一个单词的开头。 您可以使用以下方法设置单词分隔符:

Set-PSReadLineOption -WordDelimiters `<string of delimiter characters>`

壳前字

  • Cmd:unbound
  • Emacs:未绑定

与 ForwardWord 一样,单词边界由 PowerShell 令牌边界定义。

ShellNextWord

  • Cmd:unbound
  • Emacs:未绑定

与 NextWord 一样,单词边界由 PowerShell 令牌边界定义。

ShellBackwardWord

  • Cmd:unbound
  • Emacs:未绑定

与 BackwardWord 一样,单词边界由 PowerShell 令牌边界定义。

GotoBrace

  • Cmd:<Ctrl+}>
  • Emacs:未绑定

转到匹配的括号、大括号或方括号。

AddLine (添加线路)

  • Cmd:<Shift-Enter>
  • Emacs 的: <Shift-Enter>

延续提示显示在下一行上,PSReadLine 等待键编辑当前输入。 这可用于将多行输入作为单个命令输入,即使单行本身完成输入也是如此。

基本编辑

CancelLine (取消线)

  • Cmd:unbound
  • Emacs:未绑定

取消对该行的所有编辑,将输入行保留在屏幕上,但从 PSReadLine 返回而不执行输入。

还原线

  • Cmd:<ESC>
  • Emacs 的: <Alt+R>

还原自上次接受并运行输入以来的所有输入。 这相当于使用 Undo 命令直到没有要撤消的内容。

BackwardDeleteChar

  • Cmd:<Backspace>
  • Emacs: <Backspace><Ctrl+H>

删除光标前的字符。

删除字符

  • Cmd:<Delete>
  • Emacs 的: <Delete>

删除光标下的字符。

DeleteCharOrExit

  • Cmd:unbound
  • Emacs 的: <Ctrl+D>

与 DeleteChar 类似,除非该行为空,在这种情况下,请退出进程。

接受线

  • Cmd:<Enter>
  • Emacs: <Enter><Ctrl+M>

尝试执行当前输入。 如果当前输入不完整 (例如,缺少右括号、方括号或引号) ,则下一行会显示延续提示,并且 PSReadLine 会等待键编辑当前输入。

接受并GetNext

  • Cmd:unbound
  • Emacs 的: <Ctrl+O>

与 AcceptLine 类似,但在行完成后,开始编辑 history 中的下一行。

验证和接受线

  • Cmd:unbound
  • Emacs:未绑定

与 AcceptLine 类似,但执行其他验证,包括:

  • 检查其他解析错误
  • 验证是否找到所有命令名称
  • 如果运行的是 PowerShell 4.0 或更高版本,请验证参数和参数

如果有任何错误,则会显示错误消息,并且不会接受或将其添加到历史记录中,除非您在显示错误消息时更正命令行或再次执行 AcceptLine 或 ValidateAndAcceptLine。

向后删除线

  • Cmd:<Ctrl+Home>
  • Emacs:未绑定

删除从输入开始到光标的文本。

转发删除线

  • Cmd:<Ctrl+End>
  • Emacs:未绑定

删除从光标到输入末尾的文本。

SelectBackwardChar

  • Cmd:<Shift+LeftArrow>
  • Emacs 的: <Shift+LeftArrow>

调整当前所选内容以包含上一个字符。

SelectForwardChar

  • Cmd:<Shift+RightArrow>
  • Emacs 的: <Shift+RightArrow>

调整当前所选内容以包含下一个字符。

SelectBackwardWord

  • Cmd:<Shift+Ctrl+LeftArrow>
  • Emacs 的: <Alt+Shift+B>

调整当前所选内容以包含上一个单词。

选择转发词

  • Cmd:unbound
  • Emacs 的: <Alt+Shift+F>

调整当前所选内容以使用 ForwardWord 包含下一个单词。

选择下一个单词

  • Cmd:<Shift+Ctrl+RightArrow>
  • Emacs:未绑定

使用 NextWord 调整当前选择以包含下一个单词。

选择 ShellForwardWord

  • Cmd:unbound
  • Emacs:未绑定

调整当前所选内容以使用 ShellForwardWord 包含下一个单词。

SelectShellNextWord

  • Cmd:unbound
  • Emacs:未绑定

调整当前所选内容以使用 ShellNextWord 包含下一个单词。

SelectShellBackwardWord

  • Cmd:unbound
  • Emacs:未绑定

调整当前所选内容以使用 ShellBackwardWord 包含上一个单词。

选择BackwardsLine

  • Cmd:<Shift+Home>
  • Emacs 的: <Shift+Home>

调整当前所选内容,以便从光标包含到行的开头。

选择线

  • Cmd:<Shift+End>
  • Emacs 的: <Shift+End>

调整当前所选内容,以便从光标包含到行尾。

全选

  • Cmd:<Ctrl+A>
  • Emacs:未绑定

选择整行。 将光标移动到行尾。

SelfInsert (自我插入)

  • Cmd: <a><b>, ...
  • Emacs: <a><b>, ...

插入输入的密钥。

重做

  • Cmd:<Ctrl+Y>
  • Emacs:未绑定

重做由 Undo 撤消的插入或删除。

撤消

  • Cmd:<Ctrl+Z>
  • Emacs 的: <Ctrl+_>

撤消先前的插入或删除作。

历史

清除历史记录

  • Cmd:<Alt+F7>
  • Emacs:未绑定

清除 PSReadLine 中的历史记录。 这不会影响 PowerShell 历史记录。

上一页历史

  • Cmd:<UpArrow>
  • Emacs: <UpArrow><Ctrl+P>

将当前输入替换为 PSReadLine 历史记录中的上一项。

下一页历史

  • Cmd:<DownArrow>
  • Emacs: <DownArrow><Ctrl+N>

将当前输入替换为 PSReadLine 历史记录中的下一项。

ForwardSearch历史

  • Cmd:<Ctrl+S>
  • Emacs 的: <Ctrl+S>

从当前历史记录行交互向前搜索。

ReverseSearch历史

  • Cmd:<Ctrl+R>
  • Emacs 的: <Ctrl+R>

从当前历史记录行交互地向后搜索。

历史搜索向后

  • Cmd:<F8>
  • Emacs:未绑定

将当前输入替换为 PSReadLine 历史记录中与开头和输入与光标之间的字符匹配的上一项。

历史搜索转发

  • Cmd:<Shift+F8>
  • Emacs:未绑定

将当前输入替换为 PSReadLine 历史记录中与开头和输入与光标之间的字符匹配的下一项。

历史的开端

  • Cmd:unbound
  • Emacs 的: <Alt+<>

将当前输入替换为 PSReadLine 历史记录中的最后一项。

历史结束

  • Cmd:unbound
  • Emacs 的: <Alt+>>

将当前输入替换为 PSReadLine 历史记录中的最后一项,该项可能是在任何历史记录命令之前输入的空输入。

Tab 键补全

TabCompleteNext

  • Cmd:<Tab>
  • Emacs:未绑定

尝试完成光标周围的文本,并完成下一个可用完成。

TabCompletePrevious (选项卡上一页)

  • Cmd:<Shift-Tab>
  • Emacs:未绑定

尝试使用下一个前一个完成完成光标周围的文本。

完成

  • Cmd:unbound
  • Emacs 的: <Tab>

尝试对光标周围的文本执行完成作。 如果有多个可能的完成,则最长的明确前缀用于完成。 如果您尝试完成最长的明确完成,则会显示可能的完成列表。

  • Cmd:<Ctrl+Space>
  • Emacs 的: <Ctrl+Space>

尝试对光标周围的文本执行完成作。 如果有多个可能的完成,则会显示可能的完成列表,您可以使用箭头键或 Tab/Shift+Tab 选择正确的完成。Escape 和 Ctrl+G 将取消菜单选择,并将行恢复到调用 MenuComplete 之前的状态。

可能的Completions

  • Cmd:unbound
  • Emacs 的: <Alt+Equals>

显示可能的完成列表。

赛特马克

  • Cmd:unbound
  • Emacs 的: <Alt+Space>

标记光标的当前位置,以便在后续编辑命令中使用。

ExchangePointAndMark

  • Cmd:unbound
  • Emacs 的: <Ctrl+X,Ctrl+X>

光标放置在标记的位置,标记将移动到光标的位置。

杀死/拉扯

Kill 和 Yank 在 PSReadLine 模块中的剪贴板上运行。 有一个称为 kill ring 的环形缓冲区 - killed 文本被添加到 kill ring up 中,yank 将从最近的 kill 中复制文本。 YankPop 在杀戮环中的项目之间循环。 当杀戮环已满时,新物品会替换最旧的物品。 紧接在另一个 kill作之前的 kill作会附加前一个 kill,而不是在 kill ring 中添加新项或替换项。 例如,您可以使用多个 KillWord作剪切一行的一部分,然后将它们作为一次拉回其他位置。

杀戮线

  • Cmd:unbound
  • Emacs 的: <Ctrl+K>

清除从光标到行尾的输入。 清除的文本将放置在 kill ring 中。

向后杀戮线

  • Cmd:unbound
  • Emacs: <Ctrl+U><Ctrl+X,Backspace>

清除从输入开始到游标的输入。 清除的文本将放置在 kill ring 中。

杀戮词

  • Cmd:unbound
  • Emacs 的: <Alt+D>

清除从光标到当前单词末尾的输入。 如果光标位于单词之间,则输入将从光标清除到下一个单词的末尾。 清除的文本将放置在 kill ring 中。

向后杀字

  • Cmd:unbound
  • Emacs 的: <Alt+Backspace>

从当前单词的开头清除到光标的输入。 如果光标位于单词之间,则从上一个单词的开头清除输入到游标。 清除的文本将放置在 kill ring 中。

ShellKillWord (贝壳杀字)

  • Cmd:unbound
  • Emacs:未绑定

与 KillWord 一样,单词边界由 PowerShell 令牌边界定义。

ShellBackwardKillWord (贝壳向后杀字)

  • Cmd:unbound
  • Emacs:未绑定

与 BackwardKillWord 一样,单词边界由 PowerShell 令牌边界定义。

UnixWordRubout

  • Cmd:unbound
  • Emacs 的: <Ctrl+W>

与 BackwardKillWord 一样,单词边界由空格定义。

KillRegion (杀戮区域)

  • Cmd:unbound
  • Emacs:未绑定

终止光标和标记之间的文本。

复制

  • Cmd:<Ctrl+Shift+C>
  • Emacs:未绑定

将所选区域复制到系统剪贴板。 如果未选择任何区域,请复制整行。

CopyOrCancelLine (复制或取消线)

  • Cmd:<Ctrl+C>
  • Emacs 的: <Ctrl+C>

将所选文本复制到剪贴板,或者如果未选择任何文本,则使用 CancelLine 取消编辑该行。

剪切

  • Cmd:<Ctrl+X>
  • Emacs:未绑定

删除在系统剪贴板中放置已删除文本的选定区域。

美国 佬

  • Cmd:unbound
  • Emacs 的: <Ctrl+Y>

将最近终止的文本添加到输入中。

洋克波普

  • Cmd:unbound
  • Emacs 的: <Alt+Y>

如果上一个作是 Yank 或 YankPop,请将之前拉出的文本替换为 kill ring 中的下一个终止文本。

ClearKillRing (清除杀戮环)

  • Cmd:unbound
  • Emacs:未绑定

杀戮环的内容将被清除。

粘贴

  • Cmd:<Ctrl+V>
  • Emacs:未绑定

这与 Yank 类似,但使用系统剪贴板而不是 kill ring。

[!重要提示]

使用 粘贴 函数时,剪贴板缓冲区的全部内容将粘贴到 PSReadLine 的输入缓冲区中。 然后,输入缓冲区将传递给 PowerShell 分析器。 使用控制台应用程序的 右键单击 粘贴方法粘贴的输入一次复制到输入缓冲区一个字符。 复制换行符时,输入缓冲区将传递给分析器。 因此,输入一次分析一行。 粘贴方法之间的差异会导致不同的执行行为。

YankLastArg

  • Cmd:<Alt+.>
  • Emacs: <Alt+.><Alt+_>

在历史记录中插入上一个命令的最后一个参数。 重复作将最后一个插入的参数替换为上一个命令中的最后一个参数(因此 Alt+.Alt+.将插入倒数第二个历史行的最后一个参数)。

使用参数时,YankLastArg 第一次的行为类似于 YankNthArg。 后续 YankLastArg 调用的否定参数会在浏览历史记录时更改方向。 例如,如果按 Alt+. 太多次,您可以键入 Alt+- Alt+。 反转方向。

参数基于 PowerShell 令牌。

YankNthArg

  • Cmd:unbound
  • Emacs 的: <Alt+Ctrl+Y>

在历史记录中插入前一个命令的第一个参数(不是命令名称)。

使用参数,插入第 n 个参数,其中 0 通常是命令。 否定论点从结尾开始。

参数基于 PowerShell 令牌。

其他

中止

  • Cmd:unbound
  • Emacs 的: <Ctrl+G>

中止当前作;例如,Stop Interactive History Search(停止交互式历史记录搜索)。 不会像 CancelLine 那样取消输入。

角色搜索

  • Cmd:<F3>
  • Emacs 的: <Ctrl+]>

读取一个键并向前搜索该字符。 使用参数,向前搜索该参数的第 n 个匹配项。 使用否定参数,向后搜索。

字符搜索向后

  • Cmd:<Shift+F3>
  • Emacs 的: <Alt+Ctrl+]>

与 CharacterSearch 类似,但向后搜索。 使用否定参数,向前搜索。

清屏

  • Cmd:<Ctrl+L>
  • Emacs 的: <Ctrl+L>

清除屏幕并在屏幕顶部显示当前提示和输入。

DigitArgument (数字参数)

  • Cmd:unbound
  • Emacs: <Alt+[0..9]><any char><Alt+->

用于将数字参数传递给 CharacterSearch 或 YankNthArg 等函数。 Alt+- 将参数切换为负/非负数。 要输入 80 个 '*' 字符,您可以键入 Alt+8 Alt+0 *。

捕获屏幕

  • Cmd:unbound
  • Emacs:未绑定

将所选行以文本和 RTF 格式复制到剪贴板。 使用向上/向下箭头键选择第一行,然后使用 Shift+UpArrow/Shift+DownArrow 选择多行。 选择后,按 Enter 键复制文本。 Escape/Ctrl+C/Ctrl+G 取消作,因此不会将任何内容复制到剪贴板。

调用提示

  • Cmd:unbound
  • Emacs:未绑定

清除当前提示并调用提示函数以重新显示提示。 对于更改状态的自定义键处理程序(例如更改当前目录)很有用。

WhatIsKey

  • Cmd:<Alt+?>
  • Emacs 的: <Alt+?>

读取 key 或 chord 并显示 key binding。

ShowKeyBindings

  • Cmd:<Ctrl+Alt+?>
  • Emacs 的: <Ctrl+Alt+?>

显示当前绑定的所有键。

ScrollDisplayUp (滚动显示向上)

  • Cmd:<PageUp>
  • Emacs 的: <PageUp>

向上滚动显示一个屏幕。

ScrollDisplayUpLine 系列

  • Cmd:<Ctrl+PageUp>
  • Emacs 的: <Ctrl+PageUp>

向上滚动显示一行。

ScrollDisplayDown (滚动显示向下)

  • Cmd:<PageDown>
  • Emacs 的: <PageDown>

向下滚动一个屏幕。

ScrollDisplayDownLine

  • Cmd:<Ctrl+PageDown>
  • Emacs 的: <Ctrl+PageDown>

向下滚动一行显示。

ScrollDisplayTop (滚动显示顶部)

  • Cmd:unbound
  • Emacs 的: <Ctrl+Home>

将显示器滚动到顶部。

ScrollDisplayToCursor (滚动显示到光标)

  • Cmd:unbound
  • Emacs 的: <Ctrl+End>

将显示器滚动到光标。

自定义键绑定

PSReadLine 支持使用 cmdlet Set-PSReadLineKeyHandler的自定义键绑定。 大多数自定义键绑定调用上述函数之一,例如

Set-PSReadLineKeyHandler -Key UpArrow -Function HistorySearchBackward

可以将 ScriptBlock 绑定到密钥。 ScriptBlock 几乎可以执行所需的任何操作。 一些有用的示例包括

  • 编辑命令行
  • 打开一个新窗口(例如 Help)
  • 更改目录而不更改命令行

ScriptBlock 接收两个参数:

  • $key - 一个 [ConsoleKeyInfo] 对象,它是触发自定义绑定的键。 如果你将同一个 ScriptBlock 绑定到多个 key,并且需要根据 key 执行不同的作,可以检查 $key。 许多自定义绑定忽略此参数。

  • $arg - 任意参数。 通常,这将是用户从键绑定 DigitArgument 传递的整数参数。 如果绑定不接受参数,则忽略此参数是合理的。

让我们看看一个示例,该示例将命令行添加到历史记录中,而无需执行它。 当你意识到忘记执行某些操作,但不想重新输入已输入的命令行时,这非常有用。

$parameters = @{
    Key = 'Alt+w'
    BriefDescription = 'SaveInHistory'
    LongDescription = 'Save current line in history but do not execute'
    ScriptBlock = {
      param($key, $arg)   # The arguments are ignored in this example

      # GetBufferState gives us the command line (with the cursor position)
      $line = $null
      $cursor = $null
      [Microsoft.PowerShell.PSConsoleReadLine]::GetBufferState([ref]$line,
        [ref]$cursor)

      # AddToHistory saves the line in history, but does not execute it.
      [Microsoft.PowerShell.PSConsoleReadLine]::AddToHistory($line)

      # RevertLine is like pressing Escape.
      [Microsoft.PowerShell.PSConsoleReadLine]::RevertLine()
  }
}
Set-PSReadLineKeyHandler @parameters

您可以在安装在 PSReadLine 模块文件夹中的文件中看到更多示例 SamplePSReadLineProfile.ps1

大多数键绑定使用一些帮助程序函数来编辑命令行。 这些 API 将在下一节中介绍。

自定义密钥绑定支持 API

以下函数在 Microsoft.PowerShell.PSConsoleReadLine 中是公共的,但不能直接绑定到键。 大多数在自定义密钥绑定中都很有用。

void AddToHistory(string command)

将命令行添加到历史记录中,而无需执行它。

void ClearKillRing()

清除 kill 环。 这主要用于测试。

void Delete(int start, int length)

从头开始删除长度字符。 此作支持撤消/重做。

void Ding()

根据用户首选项执行 Ding作。

void GetBufferState([ref] string input, [ref] int cursor)
void GetBufferState([ref] Ast ast, [ref] Token[] tokens,
  [ref] ParseError[] parseErrors, [ref] int cursor)

这两个函数检索有关输入缓冲区的当前状态的有用信息。 第一个更常用于简单情况。 如果绑定使用 Ast 执行更高级的内容,则使用第二个。

IEnumerable[Microsoft.PowerShell.KeyHandler]
  GetKeyHandlers(bool includeBound, bool includeUnbound)

此函数由 Get-PSReadLineKeyHandler 使用,在自定义键绑定中可能没有用。

Microsoft.PowerShell.PSConsoleReadLineOptions GetOptions()

此函数由 Get-PSReadLineOption 使用,在自定义键绑定中可能不太有用。

void GetSelectionState([ref] int start, [ref] int length)

如果命令行上没有选择,则 -1 将同时返回 start 和 length。 如果命令行上有选择项,则返回选择的开始和长度。

void Insert(char c)
void Insert(string s)

在光标处插入字符或字符串。 此作支持撤消/重做。

string ReadLine(runspace remoteRunspace,
  System.Management.Automation.EngineIntrinsics engineIntrinsics)

这是 PSReadLine 的主要入口点。 它不支持递归,因此在自定义键绑定中没有用。

void RemoveKeyHandler(string[] key)

此函数由 Remove-PSReadLineKeyHandler 使用,在自定义键绑定中可能不太有用。

void Replace(int start, int length, string replacement)

替换一些输入。 此作支持撤消/重做。 这比 Delete 后跟 Insert 更可取,因为它被视为撤消的单个作。

void SetCursorPosition(int cursor)

将光标移动到给定偏移量。 不跟踪光标移动以进行撤消。

void SetOptions(Microsoft.PowerShell.SetPSReadLineOption options)

此函数是 cmdlet Set-PSReadLineOption 使用的帮助程序方法,但对于想要临时更改设置的自定义键绑定可能很有用。

bool TryGetArgAsInt(System.Object arg, [ref] int numericArg,
  int defaultNumericArg)

此帮助程序方法用于遵循 DigitArgument 的自定义绑定。 典型的调用如下所示

[int]$numericArg = 0
[Microsoft.PowerShell.PSConsoleReadLine]::TryGetArgAsInt($arg,
  [ref]$numericArg, 1)

注释

POWERSHELL 兼容性

PSReadLine 需要 PowerShell 3.0 或更高版本以及控制台主机。 它在 PowerShell ISE 中不起作用。 它可以在 Visual Studio Code 的控制台中运行。

命令历史记录

PSReadLine 维护一个历史记录文件,其中包含您从命令行输入的所有命令和数据。 这可能包含敏感数据,包括密码。 例如,如果使用 ConvertTo-SecureString cmdlet,则密码将以纯文本形式记录在历史记录文件中。 历史记录文件是一个名为 $($host.Name)_history.txt的文件。 在 Windows 系统上,历史记录文件存储在 $env:APPDATA\Microsoft\Windows\PowerShell\PSReadLine

反馈并贡献给PSReadLine

GitHub 上的 PSReadLine

您可以随时在 GitHub 页面上提交拉取请求或反馈意见。

另请参阅

PSReadLine 深受 GNU readline 库的影响。