4

缩短命令、调整按键、自动补全,这些代码值得你放进 PowerShell 配置文件

 2 years ago
source link: https://sspai.com/post/73019
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

缩短命令、调整按键、自动补全,这些代码值得你放进 PowerShell 配置文件

缩短命令、调整按键、自动补全,这些代码值得你放进 PowerShell 配置文件

如果你在 PowerShell 上频繁运行外部命令,例如用 adb 调试 Android、使用 ffmpeg 批量处理音视频,那么难免会有「有什么办法能让这么长的命令短一点」的疑问;如果你常常用 PowerShell 和系统交互,例如批量处理文件和文本,可能总是不太习惯默认的 Tab 功能和按键映射;而如果你正在用 PowerShell 开发,需要使用 git、npm、dotnet 等命令行工具,或者要用 winget、choco 安装软件,那么一定会感叹「PowerShell 竟然默认不支持这些命令的自动补全」。

一劳永逸的解决方案是修改 PowerShell 的配置文件。

一般来说,PowerShell 中用户创建的变量、函数等只能在当前的窗口会话生效。但配置文件非常特殊,PowerShell 每次启动前都会加载该文件。如果将某些命令写入这个文件,修改就能全局生效。新建或修改配置文件最简单的方法是输入 notepad $profile,在弹出的编辑窗口添加命令即可。

下文我将用一系列例子向大家展示我是如何定制一个顺手的 PowerShell 的,希望可以帮助到你。

利用别名和函数缩短命令

别名对于提升幸福感的作用不言而喻。很多 PowerShell 轻度用户可能不知道,自己一直在用的 cdls 并非命令的本体,而是微软为了兼容而设计的别名。cd 的全名是 Set-Location,而 ls 的全称是 Get-ChildItem,前后长度一对比,为了键盘和手指关节着想,选哪个无需多言。

我们可以给常用的命令自定义别名,设置别名的命令是 Set-Alias ,这样能大大减少输入量。下面的三行代码分配了 Select-Object 、脚本 Get-IPInfo.ps1 和外部命令 C:\tools\qshell.exe 的别名:

Set-alias 's' 'Select-Object'
Set-alias 'IP' 'Get-IPInfo.ps1'
Set-alias 'QN' 'C:\tools\qshell.exe'

将这三行添加到 PowerShell 配置文件中,保存文件后重启 PowerShell 或者运行 . $Profile 别名就能生效:

1

别名的所有功能和原命令一致,为外部命令创建别名后也省去了将其添加至环境变量的麻烦:

1

如果需要在配置文件中设置很多别名,不想一遍遍地写 Set-Alias 的话,可以考虑利用哈希表 + ForEach 循环的方式:

$ShortName = @{
    'IP' = 'Get-IPInfo'
    's' = 'Select-Object'
    'qn' = 'C:\tools\qshell.exe'
#  ...
}
$ShortName.Keys | ForEach-Object { Set-Alias $_ $ShortName.$_}

不过,Set-Alias 只能给不含参数的命令设置别名,真正让人抓狂的,反而是那些参数极多的命令,举例来说,用 magick 将图片调整大小后转换为 ico 的命令为:

magick -set filename:name '%t' -resize '128x128>' '%[filename:name].ico'

又比如,我需要下载十几个视频的字幕和封面,用 youtube-dl 实现起来是这样的:

youtube-dl --write-sub --write-thumbnail --skip-download --quiet

仔细观察不难发现,上面两个命令实际上需要输入的参数值只有一个:图片的路径或者是视频的链接,其他参数则是一成不变,记下以及输入这么一长串参数完全是折磨,此时,我们可以用 PowerShell 的函数功能,将这些命令包装一下:

function 2ico { magick $args[0] -set filename:name '%t' -resize '128x128>' '%[filename:name].ico'} 
function dl { youtube-dl $args[0] --write-sub --write-thumbnail --skip-download --quiet }

函数中的 $args 变量是 PowerShell 根据用户的输入自动生成的,后面的索引值 0 则表示取第一个传入函数中,如需要传递第二、第三个参数需要递增索引值。将这两个命令写入配置文件后,就再也不用重复劳动了:

c9ot13db34tfvbjiihbg.gif为了能让大家看到过程,去掉了 quiet 参数

除了改善命令参数冗长的问题,一些虽然不长但频繁使用的命令,也可以进一步包装。例如,Chocolatey 包管理器最近 宣布 将在下个大版本取消 cupcinst 等别名,同时也会取消 choco list 检索联网数据库的能力,那么我们不妨借机用 function 将其改造得更短,因为 choco 参数数量无法确定,因而可以 使用 @args 传递 所有参数:

function cs { choco search @args} 

c9ot13lb34tfv76jt590.gif

当然,别名只适合用户和 PowerShell 交互时提升自己的输入体验,如果需要编辑公开发布的脚本,还应该尽量使用全称,函数的命名也应该符合 PowerShell 的习惯。

设置 PowerShell 按键功能

相信很多人都和我一样不太满意 PowerShell 的某些按键功能。例如,其 Tab 键一次只补全一个结果,根本不知道什么时候能找到想要的东西,而 bash 补全似乎更加舒服,如果不确定,就一次展示所有结果;再比如,命令键入错误时有发生,此时跋山涉水去修改十几个字符前的错字很不值得,不如直接用 Ctrl + C 推倒重来……

然而,PowerShell 的各种按键功能都是可以自定义的,甚至能在 Shell 中启用 Vi 或 Emacs 模式,只要你愿意,总能找到顺心如意的组合。

这一切都依赖于内置的 PSReadLine 模块,在开始配置之前,请以管理身份运行 Install-Module -Name PSReadLine 将其更新到最新版本(截稿时为 2.2.3,可以使用 Get-Module 查看)。也建议配合最新的 PowerShell Core 使用,以获得最佳体验。

利用 Set-PSReadlineKeyHandler 命令可以设置 PowerShell 中所有按键及按键组合的功能。默认情况下,Tab 键的补全是行内补全,我们可以将其调整为带菜单的补全:

Set-PSReadlineKeyHandler -Chord Tab -Function MenuComplete

c9ot13tb34tfv76jt59g.gif

Tab 键此时会弹出所有的可能选项,上下左右按键可切换候选,Esc 键取消补全。需要注意,-Chord 参数后面的按键区分大小写,也就是说,Ctrl + BCtrl + b 是两个按键组合,假如想要将其分配为清空整行功能的话,应该在配置文件中填写:

Set-PSReadlineKeyHandler -Chord Ctrl+b,Ctrl+B -Function DeleteLine

PowerShell 支持的所有按键功能可以在此 页面 查看。

读者可能已经在前面的动图中发现,我的 PowerShell 还会根据历史输入提供建议。假如你跟着本文正在配置自己的 PowerShell,那么可能需要反复执行 . $Profile 命令,此时根据历史记录补全就非常有用了,只要输入点源符号,再选择某个历史记录即可:

c9ot14db34tfvlbobau0.gif

这个功能可以使用命令 Set-PSReadLineOption -PredictionSource History 打开,默认为行内补全,如果需要用动图所示的列表形式补全的话,添加 -PredictionViewStyle ListView 参数即可。列表视图对 PowerShell 窗口尺寸有要求(大于 54x15),如果你习惯于把 PowerShell 放在 VScode 等应用的两侧,还是建议使用行内补全。

另外值得称道的是,PowerShell 也能切换到 Vim / Emacs 按键组合,同样需要用命令 Set-PSReadLineOption -EditMode Vi/Emacs 开启。以 Vim 模式为例,默认为插入模式,在按下 Esc 后,可以用 ddpdwgg 等组合快速编辑文本,移动光标。如果读者是这两个软件的熟手,想必键入效率会有较大的提升。

Set-PSReadLineOption 命令还有很多有用的选项可供 探索,为了可读性和方便维护,建议将所有选项存入哈希表:

$PSOption = @{
    PredictionSource = 'History'
    EditMode = 'Vi'
    PredictionViewStyle = 'ListView'
    ShowToolTips = $false
# ...
}
Set-PSReadLineOption @PSOption

配置外部命令自动补全

PowerShell 对内置命令、函数、变量的自动补全支持非常到位,不过,默认情况下无法补全外部命令。但如果愿意要花上一点时间把一些命令写入配置文件,部分常用的软件安装工具以及命令工具也能够做到自动补全。

比如说软件包安装管理工具 Chocolatey,在这则 2015 年提出的 GitHub issues 中,开发者就已经提供 PowerShell 中的 Tab 补全功能。只是因为「并非核心功能」,一直需要用户手动配置。在 PowerShell 的配置文件中,新增如下命令:

Import-Module “$env:ChocolateyInstall\helpers\chocolateyProfile.psm1” -Force

如果没有网络问题,此时的体验足以媲美一些 Linux 包管理工具:

c9ot14lb34tfvbjiihc0.gif

同样由非官方维护的 Scoop 可以参考 此法;至于官方维护的 Winget,可以 将 Winget 更新至最新的预览版本,或者在 PowerShell 配置文件中新增如下代码:

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', $_)
        }
}

git、npm 等常用 CLI 工具,补全功能往往由 PowerShell 模块提供,git 可以使用 posh-git 模块,yarn 和 npm 可以使用 posh-yarn-completion 以及 posh-npm-completion。以 npm 为例,首先安装模块:

Set-ExecutionPolicy RemoteSigned -Scope CurrentUser
Install-Module npm-completion -Scope CurrentUser

然后,将 Import-Module npm-completion 写入配置文件:

c9ot14tb34tfvbjiihcg.gif

其他的工具可以在 PSGallery 或者 GitHub 搜索试试看,诸如 adb 等工具我一时并没有找到解决方案。

除了上文提到的三种设置,配置文件还是定义 PowerShell 提示符(Prompt)的地方,可以参考 官方文档 自定义提示符函数。和 oh-my-posh 或者 starship 这类第三方工具相比,自己写的函数运行效率绝对更高,但想要做到丰富多彩比较麻烦,因而有相关需求的话还是建议使用这类主题定制工具。

另外,配置文件过于复杂,尤其是加载了大量模块时,会影响本就不快的 PowerShell 启动速度。因而,在调用 PowerShell 执行脚本时,一般建议附加 -nop 参数,例如 pwsh -nologo -nop -file script.ps1

封面:Business flat vector created by pch.vector

> 下载 少数派 2.0 客户端、关注 少数派公众号,解锁全新阅读体验 📰

> 实用、好用的 正版软件,少数派为你呈现 🚀


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK