TOPO.TW

Rofi 簡易入門

目前我使用的 Linux Distro 是基於 Arch 的 Archcraft, 它是個相當簡約的系統。 作者 aditya 並沒有為常用功能在裡面安裝太多的 GUI 軟體, 例如 APP Launcher, wifi 選單或是休眠/關機選單等。 取而代之的,是許多基於 Rofi 的簡短腳本。

既然我都用了這麼久的 Archcraft,自然也要了解一下這個重要的元件如何運作。 研究了一下才發現,這個元件真是不可多得的好工具啊!

Rofi 的作用

因為常見的 Package Manager 應該都有支援 Rofi 這個套件, 這邊就先略過安裝/編譯步驟不談。

官網上,Rofi 是如此定義自己的:

A window switcher, application launcher and dmenu replacement

Window Switcher

就是按下 Alt + Tab 會出現的那個東東! 在持續壓下 Alt 的情況下,連續按下 Tab 可以快速切換已開啟的應用程式。 這個特性在微軟的 Windows 和不少 Linux Distro 都有實作, 可算是個人電腦桌面環境中公認的超實用選項。

Application Launcher

這個功能則更容易理解!對於一般 Windows 使用者來講,就是「開始」選單嘛。 而在其它 Linux Distro 中,則會顯示 XDG (X桌面工作群組)中事先定義的應用程式。 使用者可以輸入關鍵字縮小搜索範圍,並用 tab 或其它按鍵選擇想要啟動的應用程式。 在我的桌面中,它是長這樣的:

dmenu

dmenu 可能就比較小眾了。 有接觸過輕量級 Linux 桌面環境的朋友可能會比較熟悉。 簡單來說,這個指令可以:

  1. 將標準輸入中每一行的內容當作可選選項,
  2. 在桌面環境顯示選單
  3. 使用者可以在輸入欄位鍵入關鍵字縮小搜索範圍,再用 Enter 選擇其中一個選項
  4. 最後選中的選項將作為 dmenu 的標準輸出

由文字理解可能不太容易,這邊就來示範一下

# 印出 1~100,共 100 行內容。經由 STDIN 交給 dmenu 處理
# dmenu 的輸出會被印在螢幕上
seq 100 | dmenu | xargs -i echo Entry {} is selected

在 shell 中執行以上指令,會馬上在螢幕頂端看到像這樣的選單:

最左邊是輸入欄位,往右以後就是可選的選項。 可以在上圖看到,一旦進行了輸入,右邊的選項馬上就會縮減匹配的 Entry。 在選擇了數字 3 按下 Enter 後,shell 馬上會印出 Entry 3 is selected

可以知道,dmenu 最大的作用就是方便使用者從一堆選項中快速取得目標, 再交由其它應用程式處理該選項。

接著說回 Rofi。我們可以用 -dmenu 這個參數來模擬 dmenu 的行為。 現在用上面的例子來啟動 Rofi:

seq 100 | rofi -dmenu | xargs -i echo Entry {} is selected

和之前一樣出現了選單,不過不再像 dmenu 是用單行列出所有選項。 而是視覺元素更加豐富的選單:

可以看到,Rofi 自稱是 dmenu replacement 也不是沒有道理的, 它將原本簡陋的介面大大強化。 另外,它也為不同使用情境提供更多自訂選項。 下面就來一一解說:

使用 Rofi

雖然將標準輸入作為選單乍一看好像是很樸素的功能, 但對於每天接觸 Command Line 的使用者來說, 能夠用如此直覺的方式來與選單互動,dmenu 和 Rofi 其實是相當強力的工具。

想像一下,你有許多已經寫好的腳本,但每次使用時總是在參數的輸入上花費大量時間, 這時這類選單軟體的優勢就出來了。

不過在談到自訂的腳本之前,可以看看 Rofi 預先提供的幾個實用模式(mode)。 Rofi 使用參數 -show 來指定要啟動的預設模式。

視窗切換

rofi -show window

window mode。使用以上的指令,即可呼叫出視窗選單。 使用者選擇要切換的視窗後,即可將桌面環境的焦點引導到選中的視窗。

啟動指令

rofi -show run

run mode。使用以上的指令,即可呼叫出指令選單。 和 shell 中一樣,選單中的指令是從環境變數 PATH 來的, 所以會有相當多的 Entry。

啟動應用程式

rofi -show drun

drun mode。這就是大家平常熟悉的 APP Launcher 啦!。 選單中的指令是從 XDG 來的。所以幾乎每一個都帶有專用圖標。

建立 SSH 連線

rofi -show ssh

是的!還可以在 Rofi 中選擇主機連線。 Rofi 會自動從 ~/.ssh/known_hosts~/.ssh/config裡讀取 SSH 的相關設定。 選擇主機後,即可自動開啟 Terminal Emulator 進行連線。

同時使用多個模式

rofi -show drun -modes window,drun,run,ssh

Rofi 可以同時啟動多種模式。 使用 -modes 可以指定這些模式,它們彼此間用逗號分隔。 其實在不指定 -modes 的情況下,Rofi 預設就會同時啟動以上四種模式。 (注意一下上面的幾個選單圖片,在最底下都有可切換的模式)

-show 參數指定啟動時要第一個使用的模式,這邊我們選擇可以啟動應用程式的 drun。 若要切換模式,使用 Ctrl + Tab 便可以依序切換。

其它預設模式

Rofi 還包含 filebrowser(檔案選擇器), keys(快捷鍵選單) 等其它模式, 詳情可以參考 man page

使用自訂的指令新增模式

當然除了標準輸入和以上的幾個預設 mode 之外, 也可以使用自訂的指令來創造選單,並設定選擇之後要執行的動作

rofi -show foo -modes foo:./bar

自訂的模式用參數 -modes 指定,名稱和指令以 : 分隔。 以上是利用名叫 bar 的指令為 Rofi 新增名為 foo 的 mode。 然後再用 -show 參數來指定這個新的 mode。

在撰寫指令時(也就是上方的 bar ),只需要掌握幾點:

  • 指令若不接受任何參數,其標準輸出就是最初的選單內容
  • 選中選項後,該選項會作為指令的參數,並再次執行指令
  • 若指令產生了任何標準輸出,則 Rofi 會再次將它們作為選單內容,供使用者選擇
  • 被選中選項又會作為指令的參數,重覆上面的步驟
  • 最後,若指令沒有任何標準輸出,則整個選單就算大功告成, Rofi 順利退出
sequenceDiagram
  autonumber
  Note left of bar: 不帶參數執行
  bar ->>Rofi: 未加參數的標準輸出
  Note right of Rofi: 使用者選擇 Entry
  Rofi->>bar: 將選中的 Entry 作為 bar 的參數
  Note left of bar: 以被選中的參數執行
  bar ->>Rofi: 新的標準輸出
  Note over bar, Rofi: 重複2和3,直到標準輸出為空
  Note right of Rofi: 結束執行,將最後選中的 Entry 作為標準輸出。

由以上的流程可以了解到,自訂的指令需要考慮有參數和無參數兩種情況。 若是你的使用情境僅僅是想讓使用者在選單選擇一次, 則在有參數時直接退出,不作任何標準輸出即可。

當然如同上面提到的多模式參數, 你也可以用多個指令讓 Rofi 同時執行多個模式:

rofi -show mode1 -modes mode1:./mode1.sh,mode2:./mode2.sh,mode3:./mode3.sh

上面使用 ./mode1.sh, ./mode2.sh, ./mode3.sh 3 個指令,分別新增 mode1, mode2, mode3 三個模式。並預設使用 mode1 的選單。 和上面介紹的一樣,使用者可以用 Ctrl + Tab 切換要套用的模式。

調整風格

若你是從主流的 Package Manager 安裝 Rofi 的話, 很可能會連帶把一些預設的風格檔案(以 .rasi 結尾)和相關的腳本一併安裝。 其中一個好用的腳本就是 rofi-theme-selector。 它精巧的地方在於,利用 Rofi 的特性為你羅列可用的風格檔, 在選擇後,馬上為你更改 Rofi 的介面風格, 直至你使用快捷鍵 Alt-A 確定更改風格。使用起來像這樣:

對了!影片中我在啟動 rofi-theme-selector 前的 APP Launcher 也是 Rofi。 只不過套用的是不同的風格檔案。

風格檔案的撰寫格式這邊就略過不提了,有興趣的話可以參考 man page

另外若是你有稍為讀過這個腳本, 就會知道 Rofi 預設是使用 ~/.config/rofi/config.rasi 這個檔案作為預設風格。 除此之外,我們也可以用參數 -theme 直接為 Rofi 指定風格檔案:

rofi -theme /path/to/your/theme

結語

簡而言之,Rofi, dmenu 和其它類似的工具, 其目的就是讓常用 Command Line 的開發者有個利用 STDIN/STDOUT 迅速製作選單的途徑, 不用費神藉由 GTK/QT 等傳統手段製作 GUI 介面。 只要使用得當,在桌面環境下的工作效率真的會大大提高!

前一陣子我也把 Rofi 和常用的密碼管理工具 PasswordStore 相結合, 製作出了屬於自己的選單工具。 之後有時間也寫一篇文章來分享。