美化 Powershell

1. 本文涉及的内容

本篇博客主要涉及了在 windows 下利用 oh-my-posh 来美化,以及利用简单地自定义主题的方法。

另外声明,本人没学过 powershell,基本上遇到什么问题都是百度搜的,我在末尾附上了我参考过的一些资料,希望有用。

2. 安装 oh-my-posh

安装

略,见参考博客。

字体问题

如果你在 powershell 下执行这个命令。

1
Write-Host "$([char] 0xE0A0; [char] 0xE0A1; [char] 0xE0A2; [char] 0xE0A3; [char] 0xE0B0; [char] 0xE0B1; [char] 0xE0B2; [char] 0xE0B3; [char] 0xE0B8; [char] 0xE0B9; [char] 0xE0BA; [char] 0xE0BB; [char] 0xE0BC; [char] 0xE0BD; [char] 0xE0BE; [char] 0xE0BF;)"

如果出来的内容中,有一些空方框,说明你当前使用的字体是无法完全支持 powershell 的字符的。

建议安装其他 powerling 的字体。一个比较推荐的是更纱黑体。

3. 简单的自定义主题

在我的 C:\Users\zyp\Documents\WindowsPowerShell\Modules\oh-my-posh\2.0.311\Themes 目录下(具体目录视情况而定),你可以看到一堆 psm1 文件,这就是主题了。

通过重写:

1
2
3
4
5
6
7
8
9
function Write-Theme {
param(
[bool]
$lastCommandFailed,
[string]
$with
)
...
}

可以进行主题的自定义。

一些简单的解释

对于编写过程中,我在这里做一些简单的说明。

  1. 如何自定义

之前说了,我们可以在 theme 目录下新建一个 psm1 文件,然后在里面实现 Write-Theme 函数。那么这个函数要怎么实现呢?

在这个函数里,我们需要实现对于 prompt 的打印

什么叫 prompt? 简单来讲:

  1. Write-Theme 在干什么

Write-Theme 这个函数会在每次显示命令行之前被调用,实现 prompt 的打印。举个例子,我们新建一个 Temp.psm1,然后实现一个最简单的主题:

1
2
3
4
5
6
7
8
9
10
11
function Write-Theme {
param(
[bool]
$lastCommandFailed,
[string]
$with
)

$prompt = Write-Prompt -Object ">>> "
$prompt
}

然后在 powershell 下运行:Set-Theme Temp

  1. $sl

如果你仔细阅读会发现在主题文件里,有大量的 $sl。这是对于全局变量 $global:ThemeSettings 的一个局部化引用。

default.ps1 里定义了该全局变量,用于保存一些全局的基础设定, 如果要自定义修改,必须先局部化引用,否则会更改全局的设定。

我的主题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
#requires -Version 2 -Modules posh-git

function Write-Theme {
param(
[bool]
$lastCommandFailed,
[string]
$with
)

$prompt += Set-Newline
# -------------------- 第一行 --------------------
# 第一部分: 上次运行错误 + 管理员身份 + 用户@主机
$prompt = Write-Prompt -Object $sl.PromptSymbols.StartSymbol -ForegroundColor $sl.Colors.PromptForegroundColor -BackgroundColor $sl.Colors.SessionInfoBackgroundColor
#check the last command state and indicate if failed
If ($lastCommandFailed) {
$prompt += Write-Prompt -Object "$($sl.PromptSymbols.FailedCommandSymbol) " -ForegroundColor $sl.Colors.CommandFailedIconForegroundColor -BackgroundColor $sl.Colors.SessionInfoBackgroundColor
}
#check for elevated prompt
If (Test-Administrator) {
$prompt += Write-Prompt -Object "$($sl.PromptSymbols.ElevatedSymbol) " -ForegroundColor $sl.Colors.AdminIconForegroundColor -BackgroundColor $sl.Colors.SessionInfoBackgroundColor
}
$user = [System.Environment]::UserName
$computer = [System.Environment]::MachineName
$path = Get-FullPath -dir $pwd
if (Test-NotDefaultUser($user)) {
$prompt += Write-Prompt -Object "$user@$computer " -ForegroundColor $sl.Colors.SessionInfoForegroundColor -BackgroundColor $sl.Colors.SessionInfoBackgroundColor
}

# 第二部分: 路径
$prompt += Write-Prompt -Object $sl.PromptSymbols.SegmentForwardSymbol -ForegroundColor $sl.Colors.SessionInfoBackgroundColor -BackgroundColor $sl.Colors.PromptBackgroundColor
# Writes the drive portion
$prompt += Write-Prompt -Object "$path " -ForegroundColor $sl.Colors.PromptForegroundColor -BackgroundColor $sl.Colors.PromptBackgroundColor
$lastBgColor = $sl.Colors.PromptBackgroundColor
$prompt += Write-Prompt -Object $sl.PromptSymbols.SegmentForwardSymbol -ForegroundColor $lastBgColor

# -------------------- 第二行 --------------------

$ifHasVEnv = Test-VirtualEnv
$status = Get-VCSStatus

if ($ifHasVEnv -or $status) {
# 开启新的一行
$prompt += Set-Newline
}

# 第三部分: 虚拟环境 (比如conda)
if ($ifHasVEnv) {
$prompt = Write-Prompt -Object $sl.PromptSymbols.StartSymbol -ForegroundColor $sl.Colors.PromptForegroundColor -BackgroundColor $sl.Colors.SessionInfoBackgroundColor
# 绘制
$prompt += Write-Prompt -Object " env:$(Get-VirtualEnvName) " -ForegroundColor $sl.Colors.VirtualEnvForegroundColor -BackgroundColor $sl.Colors.VirtualEnvBackgroundColor
$lastBgColor = $sl.Colors.VirtualEnvBackgroundColor
}


# git
if ($status) {
$themeInfo = Get-VcsInfo -status ($status)
# 如果有虚拟环境,就需要把箭头画出来
if ($ifHasVEnv) {
$prompt += Write-Prompt -Object "$($sl.PromptSymbols.SegmentForwardSymbol) " -ForegroundColor $sl.Colors.VirtualEnvBackgroundColor -BackgroundColor $themeInfo.BackgroundColor
}
$lastBgColor = $themeInfo.BackgroundColor
$prompt += Write-Prompt -Object " $($themeInfo.VcInfo) " -BackgroundColor $themeInfo.BackgroundColor -ForegroundColor $sl.Colors.GitForegroundColor
# Writes the postfix to the prompt
$prompt += Write-Prompt -Object $sl.PromptSymbols.SegmentForwardSymbol -ForegroundColor $lastBgColor
}
else {
if ($ifHasVEnv) {
$prompt += Write-Prompt -Object $sl.PromptSymbols.SegmentForwardSymbol -ForegroundColor $lastBgColor
}
}

$timeStamp = Get-Date -UFormat %R
$timestamp = "[$timeStamp]"

$prompt += Set-CursorForRightBlockWrite -textLength ($timestamp.Length + 1)
$prompt += Write-Prompt $timeStamp -ForegroundColor $sl.Colors.PromptForegroundColor

$prompt += Set-Newline

if ($with) {
$prompt += Write-Prompt -Object "$($with.ToUpper()) " -BackgroundColor $sl.Colors.WithBackgroundColor -ForegroundColor $sl.Colors.WithForegroundColor
}

$prompt += Write-Prompt -Object $sl.PromptSymbols.PromptIndicator -ForegroundColor $sl.Colors.CommandFailedIconForegroundColor
$prompt += Write-Prompt -Object $sl.PromptSymbols.PromptIndicator -ForegroundColor $sl.Colors.AdminIconForegroundColor
$prompt += Write-Prompt -Object $sl.PromptSymbols.PromptIndicator -ForegroundColor $sl.Colors.GitNoLocalChangesAndAheadColor
$prompt += ' '
$prompt
}

$sl = $global:ThemeSettings #local settings
$sl.PromptSymbols.StartSymbol = ''
# $s1.PromptSymbols.VirtualEnvSymbol = [char]::ConvertFromUtf32(0xe0a2)
# > 符号
$sl.PromptSymbols.PromptIndicator = [char]::ConvertFromUtf32(0x276F)
# 实心右箭头符号
$sl.PromptSymbols.SegmentForwardSymbol = [char]::ConvertFromUtf32(0xE0B0)
$sl.Colors.PromptForegroundColor = [ConsoleColor]::White
$sl.Colors.PromptSymbolColor = [ConsoleColor]::White
$sl.Colors.PromptHighlightColor = [ConsoleColor]::DarkBlue
$sl.Colors.GitForegroundColor = [ConsoleColor]::Black
$sl.Colors.WithForegroundColor = [ConsoleColor]::DarkRed
$sl.Colors.WithBackgroundColor = [ConsoleColor]::Magenta
$sl.Colors.VirtualEnvBackgroundColor = [System.ConsoleColor]::Red
$sl.Colors.VirtualEnvForegroundColor = [System.ConsoleColor]::White

效果图:

4. 参考资料

  • https://www.cnblogs.com/magicking/p/9776200.html

  • https://www.jianshu.com/p/533955b84cd6

  • https://sspai.com/post/52907

  • https://github.com/spencerwooo/dotfiles

  • https://github.com/JanDeDobbeleer/oh-my-posh