Rofi: a window switcher, application launcher and dmenu replacement

2021/03/14 by Paulo Pereira

~/categories/Linux #Linux #Arch Linux #i3-gaps #Rofi

Rofi is a window switcher, application launcher and dmenu replacement.

I’ve been using rofi with i3-gaps since early 2019. I had played with it before, but I’ve been using it daily the last couple of years.

I use it to launch applications, open ssh sessions, with pass and with a set of useful custom scripts.

Installation

You need to install the rofi package. I also installed rofi-dmenu for dmenu compatibility, rofi-pass to use with pass and the extra rofi-emoji and rofi-calc.

paru -S rofi rofi-dmenu rofi-pass rofi-emoji rofi-calc

Executing

You can run Rofi in different modes depending if you want to launch an application, open a ssh session, change windows or executing a command in the terminal.

Check Rofi at github and man rofi for more details.

In my setup, and using i3-gaps (learn more here) I use it to accomplish a series of tasks:

bindsym    $mod+d     exec --no-startup-id "rofi -modi combi -show combi -combi-modi drun,run"

rofi

bindsym    $mod+p    exec --no-startup-id rofi-pass

pass

bindsym    $mod+s    exec --no-startup-id rofi -show ssh
bindsym    $mod+f    exec --no-startup-id websearch

websearch

Here’s my websearch script, inspired by ditrotube.

cat .local/bin/websearch

#!/usr/bin/env bash

DMBROWSER="/usr/bin/librewolf"

declare -a options=(
"searx - https://searx.tuxcloud.net/?q="
"amazon - https://www.amazon.com/s?k="
"kindlebooks - https://www.amazon.com/s?rh=n%3A154606011&ref=nb_sb_noss&k="
"youtube - https://www.youtube.com/results?search_query="
"goodreads - https://www.goodreads.com/search?q="
"archaur - https://aur.archlinux.org/packages/?O=0&K="
"archpkg - https://archlinux.org/packages/?sort=&q="
"archwiki - https://wiki.archlinux.org/index.php?search="
"audible - https://audible.com/search?keywords="
"duckduckgo - https://duckduckgo.com/lite/?q="
"github - https://github.com/search?q="
"gitlab - https://gitlab.com/search?search="
"google - https://www.google.com/search?q="
"reddit - https://www.reddit.com/search/?q="
"quit"
)

while [ -z "$engine" ]; do
  enginelist=$(printf '%s\n' "${options[@]}" | rofi -dmenu -p 'Choose search engine:') || exit
  engineurl=$(echo "$enginelist" | awk '{print $NF}')
  engine=$(echo "$enginelist" | awk '{print $1}')
done

while [ -z "$query" ]; do
  if [[ "$engine" == "quit" ]]; then
    echo "Program terminated." && exit 0
  else
    query=$(echo "$engine" | rofi -dmenu -p 'Enter search query:') || exit
  fi
done

$DMBROWSER "$engineurl""$query"

#eof

Configuration

The rofi configuration file is located at .config/rofi/config.rasi.

cat .config/rofi/config.rasi

configuration {
    modi:                   "run,ssh,window,combi,drun,windowcd";
    matching:               "fuzzy";
    show-icons:             true;
    theme:                  "~/.config/rofi/themes/dmenu.rasi";
    font:                   "Cantarell Regular 11";
    icon-theme:             "oomox-gruvbox-dark";
    lines:                  7;
    separator-style:        "solid";
    hide-scrollbar:         true;
    kb-row-down:            "Control+j";
    kb-row-up:              "Control+k";
    kb-accept-entry:        "Return,KP_Enter";
    kb-remove-to-eol:       "";
    display-drun:           "Open";
    display-run:            "❯ sh";
    display-combi:          "";
    display-window:         "Change window";
    display-windowcd:       "Change window (same workspace)";
    terminal:               "/usr/bin/alacritty";
    ssh-command:            "{terminal} -e {ssh-client} {host}";
}

I’m using a theme to emulate dmenu, but I used a gruvbox inspired on until recently.

cat .config/rofi/themes/dmenu.rasi

* {
    background-color:   Black;
    border-color:       White;
    text-color:         White;
    font:               "Cantarell Regular 12";
}

#window {
    anchor:     north;
    location:   north;
    width:      100%;
    padding:    4px;
    children:   [ horibox ];
}

#horibox {
    orientation: horizontal;
    children:   [ prompt, entry, listview ];
}

#listview {
    layout:     horizontal;
    spacing:    5px;
    lines:      100;
}

#entry {
    expand:     false;
    width:      10em;
}

#element {
    padding: 0px 2px;
}
#element selected {
    background-color: SteelBlue;
}
cat .config/rofi/themes/gruvbox-common.inc.rasi

window {
    background-color: @background;
    border:           2;
    padding:          2;
}

mainbox {
    border:  0;
    padding: 0;
}

message {
    border:       2px 0 0;
    border-color: @separatorcolor;
    padding:      1px;
}

textbox {
    highlight:  @highlight;
    text-color: @foreground;
}

listview {
    border:       2px solid 0 0;
    padding:      2px 0 0;
    border-color: @separatorcolor;
    spacing:      2px;
    scrollbar:    @scrollbar;
}

element {
    border:  0;
    padding: 2px;
}

element.normal.normal {
    background-color: @normal-background;
    text-color:       @normal-foreground;
}

element.normal.urgent {
    background-color: @urgent-background;
    text-color:       @urgent-foreground;
}

element.normal.active {
    background-color: @active-background;
    text-color:       @active-foreground;
}

element.selected.normal {
    background-color: @selected-normal-background;
    text-color:       @selected-normal-foreground;
}

element.selected.urgent {
    background-color: @selected-urgent-background;
    text-color:       @selected-urgent-foreground;
}

element.selected.active {
    background-color: @selected-active-background;
    text-color:       @selected-active-foreground;
}

element.alternate.normal {
    background-color: @alternate-normal-background;
    text-color:       @alternate-normal-foreground;
}

element.alternate.urgent {
    background-color: @alternate-urgent-background;
    text-color:       @alternate-urgent-foreground;
}

element.alternate.active {
    background-color: @alternate-active-background;
    text-color:       @alternate-active-foreground;
}

scrollbar {
    width:        4px;
    border:       0;
    handle-color: @scrollbar-handle;
    handle-width: 8px;
    padding:      0;
}

sidebar {
    border:       2px 0 0;
    border-color: @separatorcolor;
}

inputbar {
    spacing:    0;
    text-color: @normal-foreground;
    padding:    2px;
    children:   [ prompt, textbox-prompt-sep, entry, case-indicator ];
}

case-indicator,
entry,
prompt,
button {
    spacing:    0;
    text-color: @normal-foreground;
}

button.selected {
    background-color: @selected-normal-background;
    text-color:       @selected-normal-foreground;
}

textbox-prompt-sep {
    expand:     false;
    str:        ":";
    text-color: @normal-foreground;
    margin:     0 0.3em 0 0;
}
cat .config/rofi/themes/gruvbox-dark.rasi

* {
    /* Theme settings */
    highlight: bold italic;
    scrollbar: true;

    /* Gruvbox dark colors */
    gruvbox-dark-bg0:          #282828;
    gruvbox-dark-bg0-soft:     #32302f;
    gruvbox-dark-bg3:          #665c54;
    gruvbox-dark-fg0:          #fbf1c7;
    gruvbox-dark-fg1:          #ebdbb2;
    gruvbox-dark-red-dark:     #cc241d;
    gruvbox-dark-red-light:    #fb4934;
    gruvbox-dark-yellow-dark:  #d79921;
    gruvbox-dark-yellow-light: #fabd2f;
    gruvbox-dark-gray:         #a89984;

    /* Theme colors */
    background:                  @gruvbox-dark-bg0;
    background-color:            @background;
    foreground:                  @gruvbox-dark-fg1;
    border-color:                @gruvbox-dark-gray;
    separatorcolor:              @border-color;
    scrollbar-handle:            @border-color;

    normal-background:           @background;
    normal-foreground:           @foreground;
    alternate-normal-background: @gruvbox-dark-bg0-soft;
    alternate-normal-foreground: @foreground;
    selected-normal-background:  @gruvbox-dark-bg3;
    selected-normal-foreground:  @gruvbox-dark-fg0;

    active-background:           @gruvbox-dark-yellow-dark;
    active-foreground:           @background;
    alternate-active-background: @active-background;
    alternate-active-foreground: @active-foreground;
    selected-active-background:  @gruvbox-dark-yellow-light;
    selected-active-foreground:  @active-foreground;

    urgent-background:           @gruvbox-dark-red-dark;
    urgent-foreground:           @background;
    alternate-urgent-background: @urgent-background;
    alternate-urgent-foreground: @urgent-foreground;
    selected-urgent-background:  @gruvbox-dark-red-light;
    selected-urgent-foreground:  @urgent-foreground;
}

@import "gruvbox-common.inc"