Linux中國

i3 窗口管理器終極定製指南

在這份超詳細的指南中了解如何通過 i3 窗口管理器來自定義系統的外觀和體驗。

你可能在網上(尤其是通過 r/unixporn 子區)看到過很多炫酷的截圖,用戶可以根據個人喜好自定義他們的桌面並與大家分享。

這是因為 Linux 允許你自定義桌面體驗的方方面面。

而結果?就是比任何 Mac 或 Windows 系統更具視覺和感知效果

來看一下這個 ?

看起來像一個 Linux Mint 系統嗎? ?

但是你怎樣才能做到這樣呢?自定義你的 Linux 桌面外觀是很困難的

答案就在於 窗口管理器。如果你能配置好窗口管理器,你就能自定義外觀。

在本指南中,我將引導你完成使用 i3 窗口管理器 進行基本配置。它是 Linux 上最好的窗口管理器之一

? 「 加料 Rice 」 是一個常用的辭彙,用來指代在桌面上進行視覺改進和自定義。引用自 /r/unixporn (LCTT 譯註:「加料」一詞來自於購買便宜的亞洲汽車,並給它們安裝售後零件,以讓它更好地類似於賽車。)

在遵循本指南之前,你需要了解以下內容:

  • 在本指南中,我將使用 Arch Linux 來演示步驟,但你可以使用你喜歡的任何發行版,結果也是一樣的。
  • 請記住,本指南是 i3 進行「加料」定製的基礎

在按照本指南進行操作後,你應該得到以下預期結果:

如何在 Linux 中配置 i3 窗口管理器、i3blocks 和 i3gaps

? 為了節省你的時間,我已經在 GitHub 上上傳了與本文相關的所有 i3 配置文件,你可以通過這些文件實現我們在本文中所期望的最終外觀。

下載 i3 配置文件

首先,讓我們開始安裝 i3 窗口管理器

在 Linux 上安裝 i3 窗口管理器

基於 Ubuntu/Debian:

sudo apt install xorg lightdm lightdm-gtk-greeter i3-wm i3lock i3status i3blocks dmenu terminator

Arch Linux:

sudo pacman -S xorg lightdm lightdm-gtk-greeter i3-wm i3lock i3status i3blocks dmenu terminator

當你完成安裝後,使用以下命令啟用 lightdm 服務:

sudo systemctl enable lightdm.service

然後啟動 lightdm 服務:

sudo systemctl start lightdm.service

這將啟動 lightdm 登錄界面,並要求你輸入用戶名密碼。

如果你安裝了多個桌面環境,你可以從選擇菜單中選擇 i3:

在 Arch Linux 上使用 lightdm 使用 i3 窗口管理器

當首次登錄 i3 時,它會詢問你是否要創建一個 i3 配置文件。

按下回車鍵創建一個新的 i3 配置文件:

生成 i3 配置文件

接下來,它會詢問你選擇 WinAlt 鍵哪個作為修飾鍵(mod)。

我建議你選擇 Win(或者 Super 鍵),因為大多數用戶已經習慣將其用作快捷鍵:

現在你可以開始使用 i3 窗口管理器了。

但在我們開始定製之前,讓我先介紹一下你如何使用 i3。

i3 窗口管理器的按鍵綁定

讓我們從基礎知識開始。

窗口管理器的基本功能是將多個窗口水平和垂直地組合在一起,這樣你就可以同時監視多個進程。

結果是這樣的:

在 Arch Linux 上使用 i3

你可以使用以下按鍵綁定執行更多操作:

按鍵綁定 描述
Mod + Enter 打開終端。
Mod + ← 切換到左側窗口。
Mod + → 切換到右側窗口。
Mod + ↑ 切換到上方窗口。
Mod + ↓ 切換到下方窗口。
Mod + Shift + ← 將窗口移動到左側。
Mod + Shift + → 將窗口移動到右側。
Mod + Shift + ↑ 將窗口移動到上方。
Mod + Shift + ↓ 將窗口移動到下方。
Mod + f 將焦點窗口切換到全屏模式。
Mod + v 下一個窗口將垂直放置。
Mod + h 下一個窗口將水平放置。
Mod + s 啟用堆疊式窗口布局。
Mod + w 啟用選項卡式窗口布局。
Mod + Shift + Space 啟用浮動窗口(針對焦點窗口)。
Mod + 滑鼠左鍵單擊 使用滑鼠拖動整個窗口。
Mod + 0-9 切換到另一個工作區。
Mod + Shift + 0-9 將窗口移動到另一個工作區。
Mod + d 打開應用程序啟動器(D 菜單)。
Mod + Shift + q 關閉焦點窗口。
Mod + Shift + c 重新載入 i3 配置文件。
Mod + Shift + r 重啟 i3 窗口管理器。
Mod + Shift + e 退出 i3 窗口管理器。

我知道按鍵綁定很多,但如果你每天練習它們,你很快就會習慣。

如果你想知道,你可以根據需要更改按鍵綁定,後面的指南中我會分享如何做到這一點。

現在,讓我們來看看配置部分。

在 Arch Linux 中啟用 AUR

如果你剛剛安裝了 Arch Linux,可能還沒有啟用 AUR。

這意味著你錯過了 Arch Linux 最重要的特性。

啟用 AUR,你需要使用 AUR 包管理器。在這裡,我將使用 yay

首先,安裝 git

sudo pacman -S git

現在,克隆 yay 存儲庫並切換到 yay 目錄:

git clone https://aur.archlinux.org/yay-git.git && cd yay

最後,構建包:

makepkg -si

還有其他一些 AUR 包管理器,比如 Paru,如果你想使用除 yay 之外的其他工具,你可以繼續或者探索其他選項。

更改 i3 窗口管理器的解析度

如果你使用虛擬機運行窗口管理器,可能會遇到問題,尤其是顯示解析度可能被鎖定在 1024x768 上,就像我一樣。

因此,你需要執行以下命令,指定所需的顯示解析度:

xrandr --output [顯示名稱] --mode [解析度]

要找到已連接顯示器的名稱,你需要使用以下形式的 xrandr 命令:

xrandr | grep -w 'connected'

在 i3 中查找已連接顯示器

在我的情況下,顯示名稱是 Virtual-1

因此,如果我想將解析度更改為 1920*1080,我需要執行以下命令:

xrandr --output Virtual-1 --mode 1920x1080

但這只是暫時生效。要使其永久生效,你需要在 i3 配置文件中進行更改。

首先,打開配置文件:

nano ~/.config/i3/config

通過按下 Alt + / 來在 nano跳到文件末尾,並使用以下語法來永久更改顯示解析度:

# 顯示解析度
exec_always xrandr --output [顯示名稱] --mode [解析度]

結果應該是這樣的:

在 i3 中永久更改顯示解析度

完成後,保存更改並退出 nano 文本編輯器。

現在,使用 Mod + Shift + r 重新啟動 i3 窗口管理器,以使你對配置文件所做的更改生效!

在 i3 窗口管理器中更改壁紙

默認情況下,i3 的外觀比較陳舊,你可能想切換回之前的桌面環境。

但是通過更改壁紙,你可以改變整個系統的氛圍。

在 i3 中有多種方式可以更改壁紙,但在這裡,我將向你展示如何使用 feh 實用工具。

首先,讓我們從安裝開始:

對於基於 Arch 的發行版

sudo pacman -S feh

對於 Ubuntu/Debian 系的發行版:

sudo apt install feh

安裝完成後,你可以從互聯網上下載你喜歡的壁紙。接下來,打開 i3 配置文件

nano ~/.config/i3/config

跳到文件的末尾,使用如下所示的 feh 命令:

# 顯示壁紙
exec_always feh --bg-fill /path/to/wallpaper

在我的情況下,壁紙位於 Downloads 目錄中,所以我的命令如下:

使用 feh 實用工具在 I3 窗口管理器中更改背景

保存更改並退出 nano 文本編輯器。

為了使配置文件的更改生效,使用 Mod + Shift + r 重新啟動 i3 窗口管理器。

我的效果如下:

在 i3 窗口管理器中更改壁紙

自定義 i3 鎖屏界面

默認情況下,如果你想鎖定系統,你需要執行以下命令:

i3lock

鎖屏界面如下所示:

鎖定 i3 窗口管理器

下面,我將向你展示:

  • 如何創建自定義快捷方式以鎖定 i3 會話
  • 如何更改鎖屏界面的壁紙

為了使鎖屏界面更加美觀,你需要使用 i3lock-color 包。

但首先,你需要移除現有的 i3lock,因為它會與 i3lock-color 衝突:

在 Arch Linux 上移除它:

sudo pacman -R i3lock

對於 Ubuntu/Debian 用戶:

sudo apt remove i3lock

完成後,你可以使用 AUR 包管理器安裝 i3lock-color

yay i3lock-color

如果你使用的是基於 Ubuntu 的系統,你需要從頭編譯它。你可以在他們的 GitHub 頁面上找到 詳細的說明

安裝完成後,讓我們創建一個新目錄並創建一個新文件來存儲鎖屏界面的配置:

安裝好 i3lock-color 後,你可以創建一個新目錄並創建一個新文件來存儲鎖屏界面的配置:

mkdir ~/.config/scripts && nano ~/.config/scripts/lock

將以下文件內容粘貼到文件中,定義鎖屏界面的樣式:

#!/bin/sh

BLANK='#00000000'
CLEAR='#ffffff22'
DEFAULT='#00897bE6'
TEXT='#00897bE6'
WRONG='#880000bb'
VERIFYING='#00564dE6'

i3lock 
--insidever-color=$CLEAR     
--ringver-color=$VERIFYING   

--insidewrong-color=$CLEAR   
--ringwrong-color=$WRONG     

--inside-color=$BLANK        
--ring-color=$DEFAULT        
--line-color=$BLANK          
--separator-color=$DEFAULT   

--verif-color=$TEXT          
--wrong-color=$TEXT          
--time-color=$TEXT           
--date-color=$TEXT           
--layout-color=$TEXT         
--keyhl-color=$WRONG         
--bshl-color=$WRONG          

--screen 1                   
--blur 9                     
--clock                      
--indicator                  
--time-str="%H:%M:%S"        
--date-str="%A, %Y-%m-%d"       
--keylayout 1                

保存更改並退出文本編輯器。

? 在網上可以找到各種不同的 i3 鎖屏樣式的 bash 腳本。這只是一個示例,對於大多數情況來說是一個較為簡單的選項。

現在,使用 chmod 命令 將該文件設置為可執行文件:

sudo chmod +x .config/scripts/lock

接下來,你需要對配置文件進行一些更改,以添加該配置文件的路徑以使其生效。

此外,我將向你展示如何使用自定義鍵盤快捷鍵鎖定屏幕。

首先,打開配置文件:

nano ~/.config/i3/config

使用 Alt + / 跳至行尾並粘貼以下內容:

# 鎖屏快捷鍵
bindsym $mod+x exec /home/$USER/.config/scripts/lock

在上面的示例中,我將 mod + x 作為鎖定屏幕的快捷鍵,你可以選擇任何你喜歡的快捷鍵。

最後的配置文件將如下所示:

如何在 Arch Linux 中使用 i3lock-color

相當不錯,不是嗎?

在 i3 窗口管理器中更改主題和圖標

我知道你可能會想到這個問題。

你為什麼需要圖標呢?你並不僅僅使用窗口管理器來使用命令行工具。

有時候,使用圖形界面更加方便,比如使用文件管理器。所以,在處理這些工具時,你希望界面看起來更好看?

因此,在本部分中,我將向你展示:

  • 如何在 i3 中更改主題
  • 如何在 i3 中更改圖標

讓我們從安裝主題開始。

在這裡,我將使用 materia-gtk-themepapirus 圖標,但你可以使用任何你喜歡的主題和圖標。

在 Arch 中安裝主題,使用以下命令:

sudo pacman -S materia-gtk-theme papirus-icon-theme

在 Ubuntu/Debian 系統中:

sudo apt install materia-gtk-theme papirus-icon-theme

但僅僅安裝還不能完成任務。你需要像使用 GNOME 「 調整 Tweaks 」 應用更改主題一樣來應用主題。

在 i3 中,你可以使用 lxappearance 工具 來更改主題和圖標。

在 Arch 中安裝 lxappearance,使用以下命令:

sudo pacman -S lxappearance

在 Ubuntu/Debian 系統中:

sudo apt install lxappearance

安裝完成後,使用 Mod + d 啟動 D 菜單,然後輸入 lxappearance,並在第一個結果上按回車鍵。

在這裡,選擇你喜歡的主題。我這裡選擇 Materia-dark

選擇主題後,點擊應用按鈕以應用更改:

同樣地,要更改圖標,選擇 「 圖標主題 Icon Theme 」,選擇圖標主題,然後點擊應用按鈕:

使用 lxappearance 更改 i3 窗口管理器中的圖標

應用主題和圖標後,我的文件管理器如下所示:

在 i3 窗口管理器中更改主題和圖標

在 i3 窗口管理器中為工作區設置圖標

默認情況下,工作區僅由數字表示,這並不是你想要使用工作區的最理想方式。

因此,在本部分中,我將引導你如何使用合適的圖標更改工作區的名稱。

為了在配置文件中使用圖標,首先你需要安裝名為 Awesome 的新字體:

對於基於 Arch 的發行版:

sudo pacman -S ttf-font-awesome

對於 Ubuntu/Debian 系統:

sudo apt install fonts-font-awesome

安裝完成後,打開 i3 配置文件:

nano ~/.config/i3/config

在這個配置文件中,找到工作區的部分,你將會看到為每個工作區給出的變數:

在 i3 配置文件中的工作區變數

在這個部分,你需要用你想要的名稱替換給出的工作區數字。

我將把第一個工作區命名為 「programs」,因為在本教程的後面部分,我將展示如何將特定的應用程序分配到特定的工作區。

我主要使用前 5 個工作區,所以我會相應地命名它們:

# 定義默認工作區的名稱,稍後我們將在其中配置鍵綁定。
# 我們使用變數來避免在多個地方重複使用名稱。
set $ws1 "1: Terminal"
set $ws2 "2: Firefox"
set $ws3 "3: VMWare"
set $ws4 "4: Spotify"
set $ws5 "5: Shutter"
set $ws6 "6"
set $ws7 "7"
set $ws8 "8"
set $ws9 "9"
set $ws10 "10"

現在讓我們為配置文件中提到的每個應用程序添加圖標。

你可以 參考 awesome 字體的備忘單 來找到合適的圖標。

將圖標複製粘貼到名稱前面:

# 定義默認工作區的名稱,稍後我們將在其中配置鍵綁定。
# 我們使用變數來避免在多個地方重複使用名稱。
set $ws1 "1:  Terminal"
set $ws2 "2:  Firefox"
set $ws3 "3:  VMWare"
set $ws4 "4:  Spotify"
set $ws5 "5:  Shutter"
set $ws6 "6"
set $ws7 "7"
set $ws8 "8"
set $ws9 "9"
set $ws10 "10"

不要擔心它看起來可怕!

完成後,使用 Mod + e 退出 i3,然後再次登錄以應用你剛剛所做的更改。

我的效果如下圖所示:

字體看起來太小?是時候解決這個問題了!

在 i3 中更改標題窗口和狀態欄的字體

首先,讓我們安裝新的字體(我將在這裡使用 Ubuntu 字體)。

要在 Arch 上安裝 Ubuntu 字體,請執行以下操作:

sudo pacman -S ttf-ubuntu-font-family

如果你使用的是 Ubuntu,你已經安裝了這些字體!

安裝完成後,打開配置文件:

nano ~/.config/i3/config

在配置文件中,找到 font pango:monospace 8 這一行,這是默認字體。

找到那行後,添加字體名稱和大小,如下所示:

font pango:Ubuntu Regular 14

然後,使用 Mod + Shift + r 重新啟動窗口管理器,這樣就完成了工作:

在 i3 窗口管理器中分配應用程序到工作區

在給工作區命名之後,你會想要將特定的軟體分配到相應的工作區中。

例如,如果我將第二個工作區命名為 「Firefox」,那麼我只想在該工作區中使用 Firefox。

那麼要如何實現呢?

為了做到這一點,你需要找到每個要分配的應用程序的類名。

聽起來複雜? 讓我告訴你如何做。

首先,將應用程序和終端並排打開。例如,在這個例子中,我將 Firefox 和終端並排打開:

並排打開應用程序和終端

現在,在終端中執行 xprop 命令,它會改變滑鼠指針的形狀:

xprop

接下來,將滑鼠懸停在應用程序上,並在應用程序窗口內的任何位置單擊,如圖所示:

在 i3 窗口管理器中查找類名

類名將在以下行的最後一個字元串中找到:

WM_CLASS(STRING) = "Navigator", "firefox"

在我的情況下,Firefox 瀏覽器的類名將是 firefox

對所有你想要分配到工作區的應用程序重複這個過程。

一旦你知道每個你想要分配到工作區的應用程序的類名,打開配置文件:

nano ~/.config/i3/config

使用 Alt + /nano 定位到文件末尾,並使用以下語法將應用程序分配到工作區:

# 分配應用到工作區
for_window [class="類名"] move to workspace $[工作區變數]

作為參考,下面是我為不同應用程序分配了 4 個工作區後的配置文件示例:

將應用分配到工作區

現在,無論在哪個工作區打開任何應用程序,它都會自動放置在配置的工作區中。非常方便! ?

在 i3 窗口管理器中讓終端變透明

要啟用透明效果,你需要安裝 picom 合成器並對配置文件進行一些更改。

讓我們從安裝開始。

對於基於 Arch 的發行版:

sudo pacman -S picom

對於基於 Ubuntu/Debian 的發行版:

sudo apt install picom

安裝完成後,你需要告訴系統使用 picom

首先打開配置文件:

nano ~/.config/i3/config

在配置文件的末尾插入以下行:

# 使用 picom 合成器實現透明效果
exec_always picom -f

這裡,我使用 -f 標誌來在切換工作區、打開新應用程序等時啟用淡入淡出效果。

保存並退出文本編輯器。

現在,使用 Mod + Shift + r 重新啟動 i3。

接下來,打開終端,打開 「 首選項 Preference 」,然後選擇「 配置文件 Profiles 」,選擇「 背景 Background 」,然後選擇「 透明背景 Transparent background 」選項。

從這裡,你可以調整透明度:

在 i3 窗口管理器中更改終端背景透明度

在 i3 窗口管理器中自定義狀態欄

默認情況下,狀態欄顯示各種信息,但沒有圖標。

因此,在這個部分,我將展示如何從狀態欄中刪除一些元素以及如何為它們添加圖標。

但是,在這裡,我將在 /etc/i3status.conf 中創建一個原始狀態欄的副本,以便如果出現任何錯誤,你可以隨時恢復到默認配置。

首先,在 .config 目錄下創建一個新的目錄:

mkdir .config/i3status

在以下命令中,我使用了 cp 命令來複制文件

sudo cp /etc/i3status.conf ~/.config/i3status/i3status.conf

接下來,使用 chown 命令更改所有者,以便你可以進行所需的更改:

sudo chown $USER:$USER ~/.config/i3status/i3status.conf

現在,你需要通過修改 i3 配置文件來指示窗口管理器使用新的 i3status 配置文件。首先打開配置文件:

nano ~/.config/i3/config

在該配置文件中查找 status_command i3status 這一行。這是你將提供新狀態配置文件路徑的行。

找到該行後,進行以下更改:

bar {
    status_command i3status -c /home/$USER/.config/i3status/i3status.conf
}

最終的結果應該如下所示:

在 i3 窗口管理器中更改 i3 狀態配置路徑

保存更改並退出文本編輯器。

現在,讓我們從狀態欄中刪除不必要的指示器。

首先,打開 i3status 配置文件:

nano .config/i3status/i3status.conf

在這裡,你可以將以 order 開頭的行注釋掉,這些行實際上是指示器的變數。

例如,在這裡,我禁用了 ipv6wireless _first_battery allload 這些對我來說不必要的指示器:

#order += "ipv6"
#order += "wireless _first_"
order += "ethernet _first_"
#order += "battery all"
order += "disk /"
#order += "load"
order += "memory"
order += "tztime local"

然後,在瀏覽器中打開 awesome font 列表,找到與狀態欄中列出的項目相關的適當圖標。

在我的設置中,我刪除了以下內容:

  • 刪除了顯示可用內存的行
  • 刪除了顯示乙太網連接速度的行

最終,我的狀態欄如下所示:

自定義 i3 窗口管理器中的狀態欄

在 i3 窗口管理器中改變顏色方案

更改 i3 窗口管理器中的顏色方案是這個指南中最重要的部分,因為窗口管理器最吸引人的地方就是你選擇的窗口裝飾顏色。

? 我將為每個顏色聲明變數,這樣你只需更改變數本身的值,就可以輕鬆地獲得新的顏色方案。

首先,打開 i3 配置文件:

nano ~/.config/i3/config

使用 Alt + / 快捷鍵到達文件末尾,並使用以下語法添加變數來存儲顏色:

# 窗口的色彩方案
set $bgcolor    #523d64
set $in-bgcolor #363636
set $text       #ffffff
set $u-bgcolor  #ff0000
set $indicator  #a8a3c1
set $in-text    #969696
#                       邊框            背景            文本            指示器(顯示下一個窗口位置的線條)     
client.focused          $bgcolor        $bgcolor        $text           $indicator
client.unfocused        $in-bgcolor     $in-bgcolor     $in-text        $in-bgcolor
client.focused_inactive $in-bgcolor     $in-bgcolor     $in-text        $in-bgcolor
client.urgent           $u-bgcolor      $u-bgcolor      $text           $u-bgcolor

在這裡:

  • bgcolor 表示背景色。
  • in-bgcolor 表示非活動窗口的背景色。
  • text 是文本顏色。
  • u-bgcolor 表示緊急操作的背景色。
  • indicator 是標示下一個窗口位置的線條的顏色。
  • in-text 是非活動窗口的文本顏色。

對於本指南,我僅使用了四個基本類別:

  • client.focused 定義了焦點窗口的顏色。
  • client.unfocused 定義了失去焦點時窗口的裝飾。
  • client.focused_inactive 當其中一個容器處於焦點但當前沒有焦點時,顯示的顏色。
  • client.urgent 定義了緊急操作時的顏色。

? 除了這四個類別,還有更多類別,請參考 官方 i3 配置手冊 以了解更多信息。

一旦你對配置文件進行了更改,請使用 Mod + Shift + r 重新啟動 i3。

如果你按照我的顏色方案,設置應該如下所示:

更改 I3 窗口管理器中的窗口顏色

那麼,狀態欄的顏色怎麼辦?當然可以改!

更改 i3 窗口管理器中狀態欄的顏色方案

在本節中,你將意識到為什麼我使用變數來存儲顏色,因為我將使用相同的變數來為我的狀態欄上色!

要在狀態欄中使用顏色,你需要在 i3 配置文件的 bar {...} 部分進行更改。

首先,打開配置文件:

nano ~/.config/i3/config

在配置文件中查找 bar {...} 部分。

找到該部分後,創建一個顏色部分,並為狀態欄定義顏色和類別,與你為窗口所做的相同:

bar {
        status_command i3status -c /home/$USER/.config/i3status/i3status.conf
        colors {
                background $bgcolor
                separator #191919
                #                       border          background      text
                focused_workspace       $bgcolor        $bgcolor        $text
                inactive_workspace      $in-bgcolor     $in-bgcolor     $text
                urgent_workspace        $u-bgcolor      $u-bgcolor      $text   

        }
}

在這裡,我使用了 focused_workspaceinactive_workspaceurgent_workspace 這三個類別,根據需要定義了相應的顏色。

保存更改後,重新啟動 i3,狀態欄也會顯示顏色。

設置 i3 狀態欄的透明度

本節將向你展示如何使 i3 狀態欄透明。

在此之前,讓我們先更改 i3 狀態欄的字體。

這裡,我將使用 Droid 字體,使其看起來乾淨而帶有一種極客風格。

要在 Arch Linux 上安裝 Droid 字體,請使用以下命令:

sudo pacman -S ttf-droid

對於 Ubuntu/Debian 系統,請使用以下命令:

sudo apt install fonts-droid-fallback

安裝完成後,打開配置文件:

nano ~/.config/i3/config

進入 bar {...} 部分,並按下面的示例輸入字體名稱和大小:

font pango: Droid Sans Mono 11

在 i3 狀態欄中更改字體

完成後,請重新啟動 i3,字體將會被更改!

要使狀態欄透明,你可以使用現有十六進位代碼中的額外兩個數字來定義透明度。

如果你想要控制透明度,我建議你查看 此指南,其中提供了從 0 到 100% 透明度的代碼範圍

為此,我將在配置文件中使用兩個新變數。首先,打開配置文件:

nano ~/.config/i3/config

在這裡,我為背景顏色添加了 60% 的透明度,並為非活躍背景顏色添加了 30% 的透明度:

set $bgcolor    #523d6499
set $in-bgcolor #3636364D

如果你仔細觀察,我在現有的十六進位顏色代碼中添加了兩位數字來定義透明度。例如,使用 99 來表示 60% 的透明度,而使用 4D 來表示 30% 的透明度。

此外,我添加了兩個新變數,透明度不同但顏色相同,作為背景使用,使其看起來更好:

set $focused-ws #523d6480
set $bar-color  #523d640D

完成後,讓我們修改 bar {...} 部分來應用透明度。

bar {...} 中添加兩行代碼:

i3bar_command i3bar --transparency
tray_output none

請注意,使用 tray_output none,它將不會在托盤中顯示任何圖標。如果你不希望出現這種行為,則可以跳過此行,只添加第一行以實現透明度。

一旦完成,修改狀態欄的顏色方案,例如更改背景顏色、邊框和活動工作區的背景。

修改後,配置文件應如下所示:

使 i3 狀態欄透明的配置文件(i3 窗口管理器)

為了使你所做的更改生效,請重新啟動 i3,你將得到透明的窗口和狀態欄:

在 i3 窗口管理器中使狀態欄和窗口透明

在窗口管理器中使用 i3blocks

默認的 i3 狀態欄在我看來毫無用處;怎麼樣讓它變得有用起來呢?

在本部分,我將解釋如何添加以下功能:

  • 軟體包更新
  • 內存使用情況
  • 磁碟使用情況
  • 音量指示器
  • Spotify 指示器

? 要實現這些功能,你需要使用一些腳本,這些腳本將允許你向狀態欄添加所需的操作。不用擔心,我不會讓你手動輸入腳本;GitHub 上有各種腳本可供選擇,幾乎涵蓋了你所需的所有方面。

但在此之前,你需要進行一些配置,以存儲腳本並指示 i3 使用 i3block 的配置,而不是使用 i3bar。

如果你在本指南的開頭按照給定的說明進行操作,那麼 i3blocks 已經安裝好了,並且配置文件位於 /etc/i3blocks.conf

如果你希望快速下載塊配置文件以進行設置而不閱讀其他內容,請點擊以下鏈接:

i3 配置文件

在本教程中,我將創建一個副本,使用它代替原始的配置文件,因此首先我們要創建一個目錄來存儲配置文件的副本:

mkdir ~/.config/i3blocks

現在,創建一個原始配置文件的副本:

sudo cp /etc/i3blocks.conf ~/.config/i3blocks/

最後,使用 chown 命令更改文件的所有者,以便你進行所需的更改:

sudo chown $USER:$USER ~/.config/i3blocks/i3blocks.conf

要啟用 i3blocks,在 i3 配置文件中進行一些更改:

nano ~/.config/i3/config

進入 bar {...} 部分,在這裡,你需要將 status_command 更改為 i3blocks 並添加 i3blocks 配置文件的路徑,如下所示:

在 i3 窗口管理器中啟用 i3blocks

完成後,使用 Mod + Shift + r 重新啟動 i3 窗口管理器,整個狀態欄都會被更改,並顯示如下:

i3 窗口管理器中 i3blocks 的默認外觀

不要擔心,你將很快使狀態欄比以前的 i3bar 更有價值和好看。

添加磁碟塊

如果你想要顯示磁碟剩餘空間,可以添加此塊。

在這裡,我將使用 nano 創建並打開用於磁碟塊的配置文件。

nano ~/.config/scripts/disk

然後粘貼以下行:

#!/usr/bin/env sh
DIR="${DIR:-$BLOCK_INSTANCE}"
DIR="${DIR:-$HOME}"
ALERT_LOW="${ALERT_LOW:-$1}"
ALERT_LOW="${ALERT_LOW:-10}" # color will turn red under this value (default: 10%)

LOCAL_FLAG="-l"
if [ "$1" = "-n" ] || [ "$2" = "-n" ]; then
    LOCAL_FLAG=""
fi

df -h -P $LOCAL_FLAG "$DIR" | awk -v label="$LABEL" -v alert_low=$ALERT_LOW '
//.*/ {
    # full text
    print label $4
    # short text
    print label $4
    use=$5
    # no need to continue parsing
    exit 0
}
END {
    gsub(/%$/,"",use)
    if (100 - use < alert_low) {
        # color
        print "#FF0000"
    }
}
&apos;

保存更改並從文本編輯器中退出。

現在,將此文件設置為可執行:

sudo chmod +x ~/.config/scripts/disk

接下來,打開 I3blocks 配置文件:

nano ~/.config/i3blocks/i3blocks.conf

根據你想要放置磁碟塊的位置,粘貼以下行:

[disk]
command=/home/$USER/.config/scripts/disk
LABEL=
#DIR=$HOME
#ALERT_LOW=10
interval=30

完成後,保存更改並使用 Mod + Shift + r 重新啟動 i3,狀態欄中將顯示帶有磁碟圖標的可用磁碟空間。

添加內存塊

這將是狀態欄中指示系統中已使用內存的塊。

首先,創建並打開一個新文件用於新的塊:

nano ~/.config/scripts/memory

然後在新文件中粘貼以下行:

#!/usr/bin/env sh
TYPE="${BLOCK_INSTANCE:-mem}"
PERCENT="${PERCENT:-true}"

awk -v type=$TYPE -v percent=$PERCENT &apos;
/^MemTotal:/ {
    mem_total=$2
}
/^MemFree:/ {
    mem_free=$2
}
/^Buffers:/ {
    mem_free+=$2
}
/^Cached:/ {
    mem_free+=$2
}
/^SwapTotal:/ {
    swap_total=$2
}
/^SwapFree:/ {
    swap_free=$2
}
END {
    if (type == "swap") {
        free=swap_free/1024/1024
        used=(swap_total-swap_free)/1024/1024
        total=swap_total/1024/1024
    } else {
        free=mem_free/1024/1024
        used=(mem_total-mem_free)/1024/1024
        total=mem_total/1024/1024
    }
    pct=0
    if (total > 0) {
        pct=used/total*100
    }
    # full text
    if (percent == "true" ) {
        printf("%.1fG/%.1fG (%.f%%)n", used, total, pct)
    } else {
        printf("%.1fG/%.1fGn", used, total)
    }
    # short text
    printf("%.f%%n", pct)
    # color
    if (pct > 90) {
        print("#FF0000")
    } else if (pct > 80) {
        print("#FFAE00")
    } else if (pct > 70) {
        print("#FFF600")
    }
}
&apos; /proc/meminfo

保存更改並從文本編輯器中退出。

現在,要使其生效,你需要使用以下命令將此文件設置為可執行:

sudo chmod +x ~/.config/scripts/memory

接下來,打開 i3blocks 配置文件:

nano ~/.config/i3blocks/i3blocks.conf

並將以下內容粘貼到你希望在狀態欄中顯示內存使用情況的位置:

[memory]
command=/home/$USER/.config/scripts/memory
label=
interval=30

保存更改並從文本編輯器中退出。重新啟動 i3 以使更改生效!

添加更新指示塊

這是最有幫助的指示器,它顯示需要更新的舊軟體包數量。

首先,使用以下命令安裝依賴項以使其正常工作:

sudo pacman -S pacman-contrib

現在,創建一個新文件來存儲腳本:

nano ~/.config/scripts/arch-update

然後粘貼以下內容:

#!/usr/bin/env python3
import subprocess
from subprocess import check_output
import argparse
import os
import re

def create_argparse():
    def _default(name, default=&apos;&apos;, arg_type=str):
        val = default
        if name in os.environ:
            val = os.environ[name]
        return arg_type(val)

    strbool = lambda s: s.lower() in [&apos;t&apos;, &apos;true&apos;, &apos;1&apos;]
    strlist = lambda s: s.split()

    parser = argparse.ArgumentParser(description=&apos;Check for pacman updates&apos;)
    parser.add_argument(
        &apos;-b&apos;,
        &apos;--base_color&apos;,
        default = _default(&apos;BASE_COLOR&apos;, &apos;green&apos;),
        help=&apos;base color of the output(default=green)&apos;
    )
    parser.add_argument(
        &apos;-u&apos;,
        &apos;--updates_available_color&apos;,
        default = _default(&apos;UPDATE_COLOR&apos;, &apos;yellow&apos;),
        help=&apos;color of the output, when updates are available(default=yellow)&apos;
    )
    parser.add_argument(
        &apos;-a&apos;,
        &apos;--aur&apos;,
        action = &apos;store_const&apos;,
        const = True,
        default = _default(&apos;AUR&apos;, &apos;False&apos;, strbool),
        help=&apos;Include AUR packages. Attn: Yaourt must be installed&apos;
    )
    parser.add_argument(
        &apos;-y&apos;,
        &apos;--aur_yay&apos;,
        action = &apos;store_const&apos;,
        const = True,
        default = _default(&apos;AUR_YAY&apos;, &apos;False&apos;, strbool),
        help=&apos;Include AUR packages. Attn: Yay must be installed&apos;
    )
    parser.add_argument(
        &apos;-q&apos;,
        &apos;--quiet&apos;,
        action = &apos;store_const&apos;,
        const = True,
        default = _default(&apos;QUIET&apos;, &apos;False&apos;, strbool),
        help = &apos;Do not produce output when system is up to date&apos;
    )
    parser.add_argument(
        &apos;-w&apos;,
        &apos;--watch&apos;,
        nargs=&apos;*&apos;,
        default = _default(&apos;WATCH&apos;, arg_type=strlist),
        help=&apos;Explicitly watch for specified packages. &apos;
        &apos;Listed elements are treated as regular expressions for matching.&apos;
    )
    return parser.parse_args()

def get_updates():
    output = &apos;&apos;
    try:
        output = check_output([&apos;checkupdates&apos;]).decode(&apos;utf-8&apos;)
    except subprocess.CalledProcessError as exc:
        # checkupdates exits with 2 and no output if no updates are available.
        # we ignore this case and go on
        if not (exc.returncode == 2 and not exc.output):
            raise exc
    if not output:
        return []

    updates = [line.split(&apos; &apos;)[0]
               for line in output.split(&apos;n&apos;)
               if line]

    return updates

def get_aur_yaourt_updates():
    output = &apos;&apos;
    try:
        output = check_output([&apos;yaourt&apos;, &apos;-Qua&apos;]).decode(&apos;utf-8&apos;)
    except subprocess.CalledProcessError as exc:
        # yaourt exits with 1 and no output if no updates are available.
        # we ignore this case and go on
        if not (exc.returncode == 1 and not exc.output):
            raise exc
    if not output:
        return []

    aur_updates = [line.split(&apos; &apos;)[0]
                   for line in output.split(&apos;n&apos;)
                   if line.startswith(&apos;aur/&apos;)]

    return aur_updates

def get_aur_yay_updates():
    output = check_output([&apos;yay&apos;, &apos;-Qua&apos;]).decode(&apos;utf-8&apos;)
    if not output:
        return []

    aur_updates = [line.split(&apos; &apos;)[0] for line in output.split(&apos;n&apos;) if line]

    return aur_updates

def matching_updates(updates, watch_list):
    matches = set()
    for u in updates:
        for w in watch_list:
            if re.match(w, u):
                matches.add(u)

    return matches

label = os.environ.get("LABEL","")
message = "{0}<span color=&apos;{1}&apos;>{2}</span>"
args = create_argparse()

updates = get_updates()
if args.aur:
    updates += get_aur_yaourt_updates()
elif args.aur_yay:
    updates += get_aur_yay_updates()

update_count = len(updates)
if update_count > 0:
    if update_count == 1:
      info = str(update_count) + &apos; update available&apos;
      short_info = str(update_count) + &apos; update&apos;
    else:
      info = str(update_count) + &apos; updates available&apos;
      short_info = str(update_count) + &apos; updates&apos;

    matches = matching_updates(updates, args.watch)
    if matches:
        info += &apos; [{0}]&apos;.format(&apos;, &apos;.join(matches))
        short_info += &apos;*&apos;
    print(message.format(label, args.updates_available_color, info))
    print(message.format(label, args.updates_available_color, short_info))
elif not args.quiet:
    print(message.format(label, args.base_color, &apos;system up to date&apos;))

保存更改並從文本編輯器中退出。

現在,使用以下命令將此文件設置為可執行:

sudo chmod +x ~/.config/scripts/arch-update

接下來,打開 i3blocks 配置文件:

nano ~/.config/i3blocks/i3blocks.conf

並將以下內容粘貼到所需的位置:

[arch-update]
command=/home/$USER/.config/scripts/arch-update
interval=3600
markup=pango
LABEL=

保存更改並重新載入 i3 窗口管理器,它將顯示需要更新的軟體包數量。

如果你正在使用 Ubuntu,你可以 按照 GitHub 頁面上的說明 進行操作。

添加音量指示塊

添加音量指示塊需要一些努力,因為你希望它的行為符合預期。你需要實現以下功能:

  • 使用媒體控制鍵管理音量的鍵綁定
  • 添加一個指示音量的音量塊

但要做到這一點,首先你需要安裝一些依賴項。

如果你使用的是 Arch Linux,請使用以下命令:

sudo pacman -S pulseaudio-alsa pulseaudio-bluetooth pulseaudio-equalizer pulseaudio-jack alsa-utils playerctl

如果你使用的是 Ubuntu/Debian 系統,請使用以下命令:

sudo apt install pulseaudio-module-bluetooth pulseaudio-equalizer pulseaudio-module-jack alsa-utils playerctl

接下來,讓我們看看如何在 i3 窗口管理器中啟用媒體控制鍵。

首先,打開 i3 配置文件:

nano ~/.config/i3/config

轉到文件的末尾,並粘貼以下內容:

# Key bindings for Media control keys
bindsym XF86AudioPlay exec playerctl play
bindsym XF86AudioPause exec playerctl pause
bindsym XF86AudioNext exec playerctl next
bindsym XF86AudioPrev exec playerctl previous

現在,讓我們為此塊創建一個新文件:

nano ~/.config/scripts/volume

然後粘貼以下內容:

#!/usr/bin/env bash
if [[ -z "$MIXER" ]] ; then
    MIXER="default"
    if command -v pulseaudio >/dev/null 2>&1 && pulseaudio --check ; then
        # pulseaudio is running, but not all installations use "pulse"
        if amixer -D pulse info >/dev/null 2>&1 ; then
            MIXER="pulse"
        fi
    fi
    [ -n "$(lsmod | grep jack)" ] && MIXER="jackplug"
    MIXER="${2:-$MIXER}"
fi
if [[ -z "$SCONTROL" ]] ; then
    SCONTROL="${BLOCK_INSTANCE:-$(amixer -D $MIXER scontrols |
                      sed -n "s/Simple mixer control &apos;([^&apos;]*)&apos;,0/1/p" |
                      head -n1
                    )}"
fi

# The first parameter sets the step to change the volume by (and units to display)
# This may be in in % or dB (eg. 5% or 3dB)
if [[ -z "$STEP" ]] ; then
    STEP="${1:-5%}"
fi

NATURAL_MAPPING=${NATURAL_MAPPING:-0}
if [[ "$NATURAL_MAPPING" != "0" ]] ; then
    AMIXER_PARAMS="-M"
fi

#---------------------------------------------------------------------
capability() { # Return "Capture" if the device is a capture device
  amixer $AMIXER_PARAMS -D $MIXER get $SCONTROL |
    sed -n "s/  Capabilities:.*cvolume.*/Capture/p"
}

volume() {
  amixer $AMIXER_PARAMS -D $MIXER get $SCONTROL $(capability)
}

保存更改並退出配置文件。

接下來,打開 I3blocks 配置文件:

nano ~/.config/i3blocks/i3blocks.conf

然後粘貼以下內容:

[volume]
command=/home/$USER/.config/scripts/volume
LABEL=♪
#LABEL=VOL 
interval=1
signal=10
#STEP=5%
MIXER=default
#SCONTROL=[determined automatically]
#NATURAL_MAPPING=0

保存更改並重新載入 i3,從現在開始,音量快捷鍵將起作用,並且指示器將按預期工作!

? 如果遇到音頻/視頻不工作等問題,請使用此命令,它應該解決該問題:

systemctl --user disable --now pipewire.{socket,service} && systemctl --user mask pipewire.socket

添加 Spotify 塊

我將使用 firatakandere 的腳本來添加此功能。在繼續之前,你可以先查看一下該腳本。

首先,創建並打開一個用於 Spotify 塊的新文件:

nano ~/.config/scripts/spotify.py

然後粘貼以下內容:

#!/usr/bin/python

import dbus
import os
import sys

try:
    bus = dbus.SessionBus()
    spotify = bus.get_object("org.mpris.MediaPlayer2.spotify", "/org/mpris/MediaPlayer2")

    if os.environ.get(&apos;BLOCK_BUTTON&apos;):
        control_iface = dbus.Interface(spotify, &apos;org.mpris.MediaPlayer2.Player&apos;)
        if (os.environ[&apos;BLOCK_BUTTON&apos;] == &apos;1&apos;):
            control_iface.Previous()
        elif (os.environ[&apos;BLOCK_BUTTON&apos;] == &apos;2&apos;):
            control_iface.PlayPause()
        elif (os.environ[&apos;BLOCK_BUTTON&apos;] == &apos;3&apos;):
            control_iface.Next()

    spotify_iface = dbus.Interface(spotify, &apos;org.freedesktop.DBus.Properties&apos;)
    props = spotify_iface.Get(&apos;org.mpris.MediaPlayer2.Player&apos;, &apos;Metadata&apos;)

    if (sys.version_info > (3, 0)):
        print(str(props[&apos;xesam:artist&apos;][0]) + " - " + str(props[&apos;xesam:title&apos;]))
    else:
        print(props[&apos;xesam:artist&apos;][0] + " - " + props[&apos;xesam:title&apos;]).encode(&apos;utf-8&apos;)
    exit
except dbus.exceptions.DBusException:
    exit

完成後,使用以下命令使其可執行:

sudo chmod +x ~/.config/scripts/spotify.py

現在,打開 I3blocks 配置文件:

nano ~/.config/i3blocks/i3blocks.conf

然後粘貼以下內容(建議將其粘貼到塊的開頭):

[spotify]
label=
command=/home/$USER/.config/scripts/spotify.py
color=#81b71a
interval=5

保存更改,退出配置文件,並重新啟動 i3。

添加了我提到的塊後,狀態欄將如下所示:

在 i3 窗口管理器中定製 i3blocks

你可以查看我的主屏幕,其中包含這些塊(點擊下方的圖片查看)。

在 i3 窗口管理器中定製 i3blocks

? 如果你對那些默認塊(文檔和問候語)的位置感到困惑,我用了幾個注釋將它們禁用以實現所示的外觀!

在 Linux 中使用 i3gaps

如果你想在窗口之間添加間隙,可以使用 i3gaps。在顏色方案之後,i3gaps 是這個指南中最關鍵的元素。

要使用間隙,你必須對 i3 配置文件進行一些更改。

打開 i3 配置文件:

nano ~/.config/i3/config

轉到文件的末尾,並粘貼以下內容:

# default gaps
gaps inner 15
gaps outer 5

# gaps
set $mode_gaps Gaps: (o)uter, (i)nner, (h)orizontal, (v)ertical, (t)op, (r)ight, (b)ottom, (l)eft
set $mode_gaps_outer Outer Gaps: +|-|0 (local), Shift + +|-|0 (global)
set $mode_gaps_inner Inner Gaps: +|-|0 (local), Shift + +|-|0 (global)
set $mode_gaps_horiz Horizontal Gaps: +|-|0 (local), Shift + +|-|0 (global)
set $mode_gaps_verti Vertical Gaps: +|-|0 (local), Shift + +|-|0 (global)
set $mode_gaps_top Top Gaps: +|-|0 (local), Shift + +|-|0 (global)
set $mode_gaps_right Right Gaps: +|-|0 (local), Shift + +|-|0 (global)
set $mode_gaps_bottom Bottom Gaps: +|-|0 (local), Shift + +|-|0 (global)
set $mode_gaps_left Left Gaps: +|-|0 (local), Shift + +|-|0 (global)
bindsym $mod+Shift+g mode "$mode_gaps"

mode "$mode_gaps" {
        bindsym o      mode "$mode_gaps_outer"
        bindsym i      mode "$mode_gaps_inner"
        bindsym h      mode "$mode_gaps_horiz"
        bindsym v      mode "$mode_gaps_verti"
        bindsym t      mode "$mode_gaps_top"
        bindsym r      mode "$mode_gaps_right"
        bindsym b      mode "$mode_gaps_bottom"
        bindsym l      mode "$mode_gaps_left"
        bindsym Return mode "$mode_gaps"
        bindsym Escape mode "default"
}

mode "$mode_gaps_outer" {
        bindsym plus  gaps outer current plus 5
        bindsym minus gaps outer current minus 5
        bindsym 0     gaps outer current set 0

        bindsym Shift+plus  gaps outer all plus 5
        bindsym Shift+minus gaps outer all minus 5
        bindsym Shift+0     gaps outer all set 0

        bindsym Return mode "$mode_gaps"
        bindsym Escape mode "default"
}
mode "$mode_gaps_inner" {
        bindsym plus  gaps inner current plus 5
        bindsym minus gaps inner current minus 5
        bindsym 0     gaps inner current set 0

        bindsym Shift+plus  gaps inner all plus 5
        bindsym Shift+minus gaps inner all minus 5
        bindsym Shift+0     gaps inner all set 0

        bindsym Return mode "$mode_gaps"
        bindsym Escape mode "default"
}
mode "$mode_gaps_horiz" {
        bindsym plus  gaps horizontal current plus 5
        bindsym minus gaps horizontal current minus 5
        bindsym 0     gaps horizontal current set 0

        bindsym Shift+plus  gaps horizontal all plus 5
        bindsym Shift+minus gaps horizontal all minus 5
        bindsym Shift+0     gaps horizontal all set 0

        bindsym Return mode "$mode_gaps"
        bindsym Escape mode "default"
}
mode "$mode_gaps_verti" {
        bindsym plus  gaps vertical current plus 5
        bindsym minus gaps vertical current minus 5
        bindsym 0     gaps vertical current set 0

        bindsym Shift+plus  gaps vertical all plus 5
        bindsym Shift+minus gaps vertical all minus 5
        bindsym Shift+0     gaps vertical all set 0

        bindsym Return mode "$mode_gaps"
        bindsym Escape mode "default"
}
mode "$mode_gaps_top" {
        bindsym plus  gaps top current plus 5
        bindsym minus gaps top current minus 5
        bindsym 0     gaps top current set 0

        bindsym Shift+plus  gaps top all plus 5
        bindsym Shift+minus gaps top all minus 5
        bindsym Shift+0     gaps top all set 0

        bindsym Return mode "$mode_gaps"
        bindsym Escape mode "default"
}
mode "$mode_gaps_right" {
        bindsym plus  gaps right current plus 5
        bindsym minus gaps right current minus 5
        bindsym 0     gaps right current set 0

        bindsym Shift+plus  gaps right all plus 5
        bindsym Shift+minus gaps right all minus 5
        bindsym Shift+0     gaps right all set 0

        bindsym Return mode "$mode_gaps"
        bindsym Escape mode "default"
}
mode "$mode_gaps_bottom" {
        bindsym plus  gaps bottom current plus 5
        bindsym minus gaps bottom current minus 5
        bindsym 0     gaps bottom current set 0

        bindsym Shift+plus  gaps bottom all plus 5
        bindsym Shift+minus gaps bottom all minus 5
        bindsym Shift+0     gaps bottom all set 0

        bindsym Return mode "$mode_gaps"
        bindsym Escape mode "default"
}
mode "$mode_gaps_left" {
        bindsym plus  gaps left current plus 5
        bindsym minus gaps left current minus 5
        bindsym 0     gaps left current set 0

        bindsym Shift+plus  gaps left all plus 5
        bindsym Shift+minus gaps left all minus 5
        bindsym Shift+0     gaps left all set 0

        bindsym Return mode "$mode_gaps"
        bindsym Escape mode "default"
}

保存更改並退出配置文件。

使用 Mod + Shift + r 重新載入 i3,並會看到窗口之間的間隙:

在 i3 窗口管理器中使用 i3gaps

但是,如果你想調整間隙的大小怎麼辦?這非常簡單,只需要簡單的步驟即可完成:

  • 按下 Mod + Shift + g 進入間隙模式
  • 使用給定的選項選擇要更改的內容
  • 使用 +- 增加/減小間隙
  • 完成後,按 Esc 鍵退出間隙模式

就是這樣!

我們忘記自定義終端了嗎?

不用擔心;你可以 切換到 Zsh,這是一個不同的 shell,使終端看起來與眾不同,或者探索一些鮮為人知的 Linux Shell

無論如何,你都可以 自定義現有終端,或選擇不同的 終端模擬器

我希望你不再畏難如何美化系統! ?

如果你有任何建議或想展示你的配置,請在評論部分留言。

(題圖:MJ/2874542d-6a8f-4b27-8e65-477389a0dcca)

via: https://itsfoss.com/i3-customization/

作者:Sagar Sharma 選題:lkxed 譯者:ChatGPT 校對:wxy

本文由 LCTT 原創編譯,Linux中國 榮譽推出


本文轉載來自 Linux 中國: https://github.com/Linux-CN/archive

對這篇文章感覺如何?

太棒了
0
不錯
0
愛死了
0
不太好
0
感覺很糟
0
雨落清風。心向陽

    You may also like

    Leave a reply

    您的電子郵箱地址不會被公開。 必填項已用 * 標註

    此站點使用Akismet來減少垃圾評論。了解我們如何處理您的評論數據

    More in:Linux中國