Windows Terminal 美化(wsl2、zsh、天气、数字时钟、ASCII Logo、彩色动画)

上次用 WSL(Windows Subsystem for Linux)要追溯到好几年前了。当时 WSL 刚出来不久,抱着尝鲜的态度试着装了,想着万一能用,就不用装虚拟机了。

结果遇到了 BUG,就再也没用过。最近才听说 WSL2 已经有了,类似虚拟机的机制,好用很多。再次装来试试,目前还没遇到啥问题。记录下初始的美化步骤。

一、效果截图

天气、日历、数字时钟、Linux 发行版的 logo、系统信息
weather-calendar-clock-logo-sysinfo

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
Weather report: Hangzhou                May 2021
Su Mo Tu We Th Fr Sa ┌────────────────────────────┐
_`/"".-. Rain shower, mist 1 │ ┏━┓┏━┓ ┏━┓┏━┓ ┏━┓┏┳┓ │
,\_( ). 21 °C 2 3 4 5 6 7 8 │ ┃┃┃┣━┓╹┃┃┃┣━┓ ┣━┛┃┃┃ │
/(___(__) ↓ 15 km/h 9 10 11 12 13 14 15 │ ┗━┛┗━┛╹┗━┛┗━┛ ╹ ╹ ╹ │
‘ ‘ ‘ ‘ 3 km 16 17 18 19 20 21 22 └────────────────────────────┘
‘ ‘ ‘ ‘ 0.8 mm 23 24 25 26 27 28 29
30 31

_-`````-, ,- '- . starky@xxxxxx
.' .- - | | - -. `. ----------------
/.' / `. \ OS: Ubuntu 20.04.2 LTS on Windows 10 x86_64
:/ : _... ..._ `` : Kernel: 5.4.72-microsoft-standard-WSL2
:: : /._ .`:'_.._\. || : Uptime: 38 mins
:: `._ ./ ,` : \ . _.'' . Packages: 736 (dpkg)
`:. / | -. \-. \_ / Shell: zsh 5.8
\:._ _/ .' .@) \@) ` `\ ,.' Terminal: /dev/pts/0
_/,--' .- .\,-.`--`. CPU: Intel i7-10850H (12) @ 2.712GHz
,'/'' (( \ ` ) Memory: 118MiB / 12466MiB (0%)
/'/' \ `-' ( CPU Usage: 1%
'/'' `._,-----' Disk (/): 3.3G / 251G (2%)
''/' .,---' Battery1: 100% [Full]
''/' ;: Local IP: xx.xx.xx.xx
''/'' ''/ Public IP: xx.xx.xx.xx
''/''/''
'/'/'
`;


GNU

启动动画
splash animation

动图(加载慢)
pipes

二、安装 WSL2 和 Windows Terminal

参考微软官方文档 Windows Subsystem for Linux Installation Guide for Windows 10

很详细,不用再看其他文章了。

三、oh-my-zsh

进入 wsl,安装 zsh
sudo apt update
sudo apt install zsh -y

安装 oh-my-zshsh -c "$(curl -fsSL https://raw.githubusercontent.com/robbyrussell/oh-my-zsh/master/tools/install.sh)"

安装 Powerline9k 主题:git clone https://github.com/bhilburn/powerlevel9k.git ~/.oh-my-zsh/custom/themes/powerlevel9k

启用 Powerline9k 主题:编辑 ~/.zshrc 配置文件,修改 ZSH_THEME 项的内容为 ZSH_THEME="powerlevel9k/powerlevel9k"

安装字体:访问 nerd-fonts 的 Github release 页,下载某种字体的压缩包(如 JetBrainsMono.zip),解压后在 Windows 系统上安装字体文件(有些时候可能需要使用管理员权限安装)

修改 Windows Terminal 的默认字体:fonts

四、oh-my-zh 插件

安装 zsh-autosuggestions
git clone https://github.com/zsh-users/zsh-autosuggestions ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-autosuggestions

安装 zsh-syntax-highlighting
git clone https://github.com/zsh-users/zsh-syntax-highlighting.git ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-syntax-highlighting

启用插件(包含默认插件):修改 ~/.zshrc 配置文件的 plugins 项,内容如下(可按需添加或删减)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
plugins=(
cargo
command-not-found
docker
git
golang
npm
nvm
rust
sudo
systemd
web-search
zsh-autosuggestions
zsh-syntax-highlighting
)

zsh-autosuggestions
插件安装完成后,如上图中的情况,直接按键盘上的右方向键即可自动补全命令。

五、neofetch 获取 Linux 发行版 ASCII logo 和系统信息

安装 neofetch:sudo apt install neofetch

效果如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
$ neofetch --ascii_distro raspbian        
`.::///+:/-. --///+//-:`` starky@xxxxxx
`+oooooooooooo: `+oooooooooooo: ----------------
/oooo++//ooooo: ooooo+//+ooooo. OS: Ubuntu 20.04.2 LTS on Windows 10 x86_64
`+ooooooo:-:oo- +o+::/ooooooo: Kernel: 5.4.72-microsoft-standard-WSL2
`:oooooooo+`` `.oooooooo+- Uptime: 11 mins
`:++ooo/. :+ooo+/.` Packages: 736 (dpkg)
...` `.----.` ``.. Shell: zsh 5.8
.::::-``:::::::::.`-:::-` Terminal: /dev/pts/0
-:::-` .:::::::-` `-:::- CPU: Intel i7-10850H (12) @ 2.712GHz
`::. `.--.` `` `.---.``.::` Memory: 107MiB / 12466MiB (0%)
.::::::::` -::::::::` ` CPU Usage: 0%
.::` .:::::::::- `::::::::::``::. Disk (/): 3.3G / 251G (2%)
-:::` ::::::::::. ::::::::::.`:::- Battery1: 100% [Full]
:::: -::::::::. `-:::::::: :::: Local IP: xx.xx.xx.xx
-::- .-:::-.``....``.-::-. -::- Public IP: xx.xx.xx.xx
.. `` .::::::::. `..`..
-:::-` -::::::::::` .:::::`
:::::::` -::::::::::` :::::::.
.::::::: -::::::::. ::::::::
`-:::::` ..--.` ::::::.
`...` `...--..` `...`
.::::::::::
`.-::::-`

neofetch --ascii_distro raspbian

neofetch 默认会输出当前系统的 logo,这里写个脚本(random_distro.sh)随机获取某个 Linux 发行版的 logo。

1
2
3
4
5
6
7
8
# random_distro.sh
distro_list=('Alpine' 'Anarchy' 'Android' 'Antergos' 'antiX' 'AOSC' 'ArcoLinux' 'ArchBox' 'ARCHlabs' 'ArchStrike' 'XFerience' 'ArchMerge' 'Arch' 'Artix' 'Arya' 'Bedrock' 'BlackArch' 'BLAG' 'BlankOn' 'BlueLight' 'bonsai' 'BSD' 'BunsenLabs' 'Calculate' 'Carbs' 'CentOS' 'Chakra' 'Chapeau' 'Chrom' 'Cleanjaro' 'ClearOS' 'Clear_Linux' 'Clover' 'Condres' 'Container_Linux' 'CRUX' 'Debian' 'Deepin' 'DesaOS' 'Devuan' 'DracOS' 'DragonFly' 'Drauger' 'Elementary' 'EndeavourOS' 'Endless' 'Exherbo' 'Fedora' 'Feren' 'FreeBSD' 'FreeMiNT' 'Frugalware' 'Funtoo' 'GalliumOS' 'Gentoo' 'Pentoo' 'GNU' 'GoboLinux' 'Grombyang' 'Guix' 'Haiku' 'Huayra' 'Hyperbola' 'janus' 'Kali' 'KaOS' 'KDE_neon' 'Kogaion' 'Korora' 'KSLinux' 'Kubuntu' 'LEDE' 'LFS' 'Linux_Lite' 'LMDE' 'Lubuntu' 'Lunar' 'macos' 'Mageia' 'Mandriva' 'Manjaro' 'Maui' 'Mer' 'Minix' 'LinuxMint' 'MX_Linux' 'Namib' 'Neptune' 'NetBSD' 'Netrunner' 'NixOS' 'Nurunner' 'NuTyX' 'OBRevenge' 'OpenBSD' 'OpenIndiana' 'OpenMandriva' 'OpenWrt' 'osmc' 'Oracle' 'Parabola' 'Pardus' 'Parrot' 'Parsix' 'TrueOS' 'PCLinuxOS' 'Peppermint' 'popos' 'Porteus' 'PostMarketOS' 'Puppy' 'PureOS' 'Qubes' 'Radix' 'Raspbian' 'Reborn_OS' 'Redstar' 'Redcore' 'Redhat' 'Refracted_Devuan' 'Rosa' 'sabotage' 'Sabayon' 'Sailfish' 'SalentOS' 'Scientific' 'Septor' 'SharkLinux' 'Siduction' 'SliTaz' 'SmartOS' 'Solus' 'Source_Mage' 'Sparky' 'Star' 'SteamOS' 'SunOS' 'openSUSE_Leap' 'openSUSE' 'SwagArch' 'Tails' 'Trisquel' 'Ubuntu-Budgie' 'Ubuntu-GNOME' 'Ubuntu-MATE' 'Ubuntu-Studio' 'Void' 'Obarun' 'windows10' 'Windows7' 'Xubuntu')

length=${#distro_list[@]}

distro=${distro_list[$RANDOM % $length]}

neofetch --ascii_distro $distro

运行 bash random_distro.sh 即可获取随机的 Linux 发行版 logo。

为了使该脚本可以在 Terminal 启动时自动运行,可以添加如下一条命令到 ~/.zshrc 配置文件末尾:
bash /path/to/random_distro.sh

六、Shell 脚本显示天气和数字时钟

weather-clock.sh 脚本从网上找的,没做改动(参考文章 Terminal splash screen with Weather, Calendar, Time & Sysinfo?)。代码如下:

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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
#!/bin/bash

# NAME: now
# PATH: $HOME/bin
# DESC: Display current weather, calendar and time
# CALL: Called from terminal or ~/.bashrc
# DATE: Apr 6, 2017. Modified: May 24, 2019.

# UPDT: 2019-05-24 If Weather unavailable nicely formatted error message.

# NOTE: To display all available toilet fonts use this one-liner:
# for i in ${TOILET_FONT_PATH:=/usr/share/figlet}/*.{t,f}lf; do j=${i##*/}; toilet -d "${i%/*}" -f "$j" "${j%.*}"; done

# Setup for 92 character wide terminal
DateColumn=34 # Default is 27 for 80 character line, 34 for 92 character line
TimeColumn=61 # Default is 49 for " " " " 61 " " " "

# Replace Edmonton with your city name, GPS, etc. See: curl wttr.in/:help
curl wttr.in/Hangzhou?0 --silent --max-time 3 > /tmp/now-weather
# Timeout #. Increase for slow connection---^

readarray aWeather < /tmp/now-weather
rm -f /tmp/now-weather

# Was valid weather report found or an error message?
if [[ "${aWeather[0]}" == "Weather report:"* ]] ; then
WeatherSuccess=true
echo "${aWeather[@]}"
else
WeatherSuccess=false
echo "+============================+"
echo "| Weather unavailable now!!! |"
echo "| Check reason with command: |"
echo "| |"
echo "| curl wttr.in/Edmonton?0 |" # Replace Edmonton with your city
echo "| --silent --max-time 3 |"
echo "+============================+"
echo " "
fi
echo " " # Pad blank lines for calendar & time to fit

#--------- DATE -------------------------------------------------------------

# calendar current month with today highlighted.
# colors 00=bright white, 31=red, 32=green, 33=yellow, 34=blue, 35=purple,
# 36=cyan, 37=white

tput sc # Save cursor position.
# Move up 9 lines
i=0
while [ $((++i)) -lt 10 ]; do tput cuu1; done

if [[ "$WeatherSuccess" == true ]] ; then
# Depending on length of your city name and country name you will:
# 1. Comment out next three lines of code. Uncomment fourth code line.
# 2. Change subtraction value and set number of print spaces to match
# subtraction value. Then place comment on fourth code line.
Column=$((DateColumn - 10))
tput cuf $Column # Move x column number
# Blank out ", country" with x spaces
printf " "
else
tput cuf $DateColumn # Position to column 27 for date display
fi

# -h needed to turn off formating: https://askubuntu.com/questions/1013954/bash-substring-stringoffsetlength-error/1013960#1013960
cal > /tmp/terminal1
# -h not supported in Ubuntu 18.04. Use second answer: https://askubuntu.com/a/1028566/307523
tr -cd '\11\12\15\40\60-\136\140-\176' < /tmp/terminal1 > /tmp/terminal

CalLineCnt=1
Today=$(date +"%e")

printf "\033[32m" # color green -- see list above.

while IFS= read -r Cal; do
printf "%s" "$Cal"
if [[ $CalLineCnt -gt 2 ]] ; then
# See if today is on current line & invert background
tput cub 22
for (( j=0 ; j <= 18 ; j += 3 )) ; do
Test=${Cal:$j:2} # Current day on calendar line
if [[ "$Test" == "$Today" ]] ; then
printf "\033[7m" # Reverse: [ 7 m
printf "%s" "$Today"
printf "\033[0m" # Normal: [ 0 m
printf "\033[32m" # color green -- see list above.
tput cuf 1
else
tput cuf 3
fi
done
fi

tput cud1 # Down one line
tput cuf $DateColumn # Move 27 columns right
CalLineCnt=$((++CalLineCnt))
done < /tmp/terminal

printf "\033[00m" # color -- bright white (default)
echo ""

tput rc # Restore saved cursor position.

#-------- TIME --------------------------------------------------------------

tput sc # Save cursor position.
# Move up 8 lines
i=0
while [ $((++i)) -lt 9 ]; do tput cuu1; done
tput cuf $TimeColumn # Move 49 columns right

# Do we have the toilet package?
if hash toilet 2>/dev/null; then
echo " $(date +"%I:%M %P") " | \
toilet -f future --filter border > /tmp/terminal
# Do we have the figlet package?
elif hash figlet 2>/dev/null; then
# echo $(date +"%I:%M %P") | figlet > /tmp/terminal
date +"%I:%M %P" | figlet > /tmp/terminal
# else use standard font
else
# echo $(date +"%I:%M %P") > /tmp/terminal
date +"%I:%M %P" > /tmp/terminal
fi

while IFS= read -r Time; do
printf "\033[01;36m" # color cyan
printf "%s" "$Time"
tput cud1 # Up one line
tput cuf $TimeColumn # Move 49 columns right
done < /tmp/terminal

tput rc # Restore saved cursor position.

exit 0

运行效果:

1
2
3
4
5
6
7
8
9
$ bash weather-clock.sh
Weather report: Hangzhou May 2021
Su Mo Tu We Th Fr Sa ┌────────────────────────────┐
_`/"".-. Rain shower, mist 1 │ ┏━┓┏━┓ ┏━┓┏━┓ ┏━┓┏┳┓ │
,\_( ). 21 °C 2 3 4 5 6 7 8 │ ┃┃┃┣━┓╹┃┃┃┗━┫ ┣━┛┃┃┃ │
/(___(__) ↓ 15 km/h 9 10 11 12 13 14 15 │ ┗━┛┗━┛╹┗━┛┗━┛ ╹ ╹ ╹ │
‘ ‘ ‘ ‘ 3 km 16 17 18 19 20 21 22 └────────────────────────────┘
‘ ‘ ‘ ‘ 0.8 mm 23 24 25 26 27 28 29
30 31

weather-clock

其中获取天气的关键代码为 curl wttr.in/Hangzhou?0 --silent --max-time 3,可自行改为自己所在的城市。

同样,为了使 Terminal 在启动时能自动运行该脚本,在 ~/.zshrc 配置文件的末尾(random-distro.sh 上面一行)添加如下内容:
bash /path/to/weather-clock.sh

PS:数字时钟的正常显示需要依赖 toilet 软件。
安装 toiletsudo apt install toilet

七、pipe.sh 生成 Terminal 启动动画

获取 pipe.sh 程序:git clone https://github.com/pipeseroni/pipes.sh.git

提取项目中的 pipes.sh/pipes.sh 源文件到任意路径下。
为了使 Terminal 在启动时能自动运行该脚本,在 ~/.zshrc 配置文件的末尾(weather-clock.sh 上面一行)添加如下内容:
bash /path/to/pipes.sh -p 5

运行效果:pipes.sh

按下空格键可终止动画。

GIF 版本:pipes