前言#
在幾個月前我有寫過一篇使 Windows Terminal 變得更易用,那篇文章主要是介紹了通過安裝 oh-my-posh、安裝 Nerd 字體解決 oh-my-posh 字體圖標不顯示、解決 ssh 連接長時間不操作自動斷開、啟動專注模式以及去掉煩人的啟動版權信息並默認管理員啟動等內容,事實上只是讓其變得更加好看了,易用度並沒有多大的提升,但是今天我們將再次給我們的 WT 升升級。
安裝必要工具#
首先 Windows Terminal 肯定是必要的,其次還得去安裝一個 PowerShell,這兩者都在微軟商店中下載安裝,如下圖。微軟商店打不開就檢查一下你的網絡,一般都是網絡問題。
oh-my-posh 的安裝我這裡就不說了,可以去看我之前那篇文章。最後我們再來安裝一個 ni,這是 antfu 開發的來簡化我們命令操作,自動選擇包管理器的一個命令行小工具,偷懶神器,沒用過的趕緊用起來,跟著文檔敲一行命令就安裝好了,不過 Windows 下使用可能會有別名衝突問題,我下文將會提到解決辦法。
探索過程及原理概述#
我想嘗試使用 Windows Terminal 進行開發。Windows Terminal 默認可以使用 PowerShell
、cmd
、wsl bash
作為腳本工具。既然是在 Windows 環境下嘛,還是得尊敬一下 PowerShell 的。於是我們先把 wt 的默認 shell 更換為我們剛剛安裝的微軟商店的 PowerShell,如下圖
其實最初的靈感是看 antfu 直播時,它總會在命令行敲一些我都沒見過的一些極短的命令來實現一些操作,讓我看的是一頭霧水。最後我才發現它是給他的 shell 設置了一些別名,並且還在 GitHub 開源了他的 zsh 的配置文件配置文件(Mac 党大喜,可以直接抄走了😂),但是沒錢買 Mac 現在只有 Windows 的我該如何在 Windows Terminal 上實現類似的功能呢,於是開始了我的嘗試。
如果搜索關鍵詞 windows powershell set user alias
,通常谷歌會給出微軟官方文檔,但是這個文檔只是告訴我們如何在腳本裡面設置臨時的別名,如果要設置永久別名,該怎麼辦?實際上,“別名” 這種東西,也就是 alias
,幾乎所有的腳本語言,都沒有所謂的 “永久別名”(Permanent alias),我們使用 Linux bash 、Cmder 之類的腳本工具,打開終端時,系統會默認執行一個腳本文件( bash 是用戶目錄下的 .bashrc
,Cmder 是 config/user_aliases.cmd
),而這樣的腳本文件裡,就包含了別名的定義。這也是為什麼,我們在 Linux 類系統中,修改 .bashrc
後,必須要重新登出登錄、或者 source .bashrc
的原因了。
所以,我們只要修改 PowerShell 啟動時執行的文件就行了。很多論壇裡面說,默認執行的腳本是 $Home\Documents\profile.ps1
,也就是 C:\Users\你的用戶名\Documents\profile.ps1
,但是這並不正確,最好的方式是,先啟動 PowerShell ,再執行 echo $profile
,這樣得到的文件路徑,才是 PowerShell 的默認執行文件路徑。而且這裡我們需要注意的是,如果按照我之前的那篇文章配置好後,然後今天重新安裝的 PowerShell 並且設置為了 wt 的默認 shell 的話,那麼,你得重新配置,因為這個微軟商店的 PowerShell 和 Windows 自帶的 Windows PowerShell 不是一個版本,所以不共用同一套配置文件。大概為以下路徑:
然後,創建這個文件就好啦。
在文件裡面,寫上別名設置的語句。再一次注意,假如你的別名指代的命令含有空格,就不可以使用 New-Alias
命令,因為它不能帶空格,即使你把指代的命令用引號括起來也沒用。那怎麼辦呢?問了一下 GPT,原來,正確姿勢是用 function
,也就是,我們把自己要定義的指令,定義為一個函數,就行啦。
保存文件,重新啟動 PowerShell 以後,不出意外,應該會報一個 File xxxxxxx\Microsoft.PowerShell_profile.ps1 cannot be loaded because running scripts is disabled on this system.
根據此鏈接,出現這種情況,是因為 Windows 系統為了防止惡意腳本自動執行,故默認不允許自動運行腳本。所以,在確定自己有能力把控的情況下,以管理員身份,在 PowerShell 中執行 Set-ExecutionPolicy RemoteSigned
,即可。
再次重啟 PowerShell,應該可以發現,自定義別名已經生效了。
解決別名衝突與傳參優化#
在進行了以上操作後,你會發現你設置的別名確實可用了,但是可能有一部分別名會與 PowerShell 本來就存在的一些別名有衝突,例如 ni
、gp
、gcm
,可能後續還會遇到很多,我們的解決方案是將其強制移除就好了,在你的配置文件中加入以下代碼:
Remove-Alias -Name ni -Force
Remove-Alias -Name gp -Force
Remove-Alias -Name gcm -Force
好,衝突問題解決了,但是最後還有一個問題就是,你會發現當你在使用一些需要傳遞參數的別名命令時,參數並不能傳入,使用我們需要讓我們的別名函數能夠接收參數,當然不需要參數的就不用管了。我們只需要在我們的命令後添加 $args
這個自動變量,它包含當前腳本、函數或腳本塊的未聲明參數的數組。簡而言之,它捕獲所有未被預定義參數捕獲的參數。例如下面這些:
function gcl { git clone $args }
function gst { git stash $args }
function grm { git rm $args }
function gmv { git mv $args }
如果你想上點強度,需要更高的自定義性,你也可用自己定義參數和提示如下:
function gcm {
param (
[Parameter(Mandatory=$true)]
[string]$message
)
if (-not $message) {
Write-Host "Error: You must provide a commit message." -ForegroundColor Red
return
}
git commit -m $message
}
總之,玩法很多,大家可以自己慢慢研究,給大家扔一個我目前自用的配置文件,如果想換主題的話可以按照文檔找到自己喜歡的主題更換第一行配置的 json 主題文件名即可。如果有其他的問題可以參考之前的那篇文章。
oh-my-posh init pwsh --config $env:POSH_THEMES_PATH\montys.omp.json | Invoke-Expression
cls
function s { nr start }
function d { nr dev }
function b { nr build }
function t { nr test }
function lint { nr lint }
function release { nr release }
function gs { git status }
function gp { git push }
function gpf { git push --force }
function gpl { git pull --rebase }
function gcl { git clone $args }
function gst { git stash $args }
function grm { git rm $args }
function gmv { git mv $args }
function main { git checkout main }
function gco { git checkout $args }
function gcob { git checkout -b $args }
function gb { git branch }
function gbd { git branch -d $args }
function gbD { git branch -D $args }
function grb { git rebase $args }
function grbc { git rebase --continue }
function gme { git merge $args}
function gl { git log }
function glo { git log --oneline --graph }
function ga { git add }
function gA { git add -A }
function gc { git commit }
function gcm {
param (
[Parameter(Mandatory=$true)]
[string]$message
)
if (-not $message) {
Write-Host "Error: You must provide a commit message." -ForegroundColor Red
return
}
git commit -m $message
}
function gca { git commit -a }
function gcam { git commit -am $args }
function l { cls }
function q { exit }
function fuck { shutdown /s /f /t 0 }
Remove-Alias -Name ni -Force
Remove-Alias -Name gp -Force
Remove-Alias -Name gcm -Force
Just enjoy it.