Skip to main content

i3

i3 is a tiling window manager. See my notes below on various settings, modules, etc

Status Bars

Polybar

Polybar is a simple community driven solution to configuring custom status bars. Generally, configurations are handled within the ~/.config/polybar/config file, but some specific cases may require editing other files.

Install

The general requirements of using Polybar is installation via your package manager, for me, this is pacman. After installing, we need to define our polybars, then configure i3 to handle these settings for us.

sudo pacman -Syu polybar

After installing, we need to configure our bars within ~/.config/polybar/config, then we can simply run polybar top to run a polybar titled top within said config file.

Polybar Using i3

To start, a default ~/.config/i3/config will contain a block defining the i3status and its settings

bar {
	i3bar_command i3bar
	status_command i3status
	position bottom

# please set your primary output first. Example: 'xrandr --output eDP1 --primary'
	tray_output primary
	tray_output eDP1

	bindsym button4 nop
	bindsym button5 nop
   font xft:URWGothic-Book 11
	strip_workspace_numbers yes

    colors {
        background #222D31
        statusline #F9FAF9
        separator  #454947

                      border  backgr. text
        focused_workspace  #F9FAF9 #16a085 #292F34
        active_workspace   #595B5B #353836 #FDF6E3
       inactive_workspace #595B5B #222D31 #EEE8D5
       binding_mode       #16a085 #2C2C2C #F9FAF9
       urgent_workspace   #16a085 #FDF6E3 #E5201D
   }
}

We are going to remove this, or comment it all out, and replace it with the exec_always line below. Now copy the start-polybar.sh script to ~/.config/polybar/ for use with i3 startup configuration below. This is just telling i3 that we are starting Polybar from a script we've written and stored within the ~/.config/polybar/ directory on initial startup.

My bar { ... } define within ~/.config/i3/config -

# Custom startup apps
exec_always --no-startup-id $HOME/.config/polybar/start-polybar.sh

# Don't use i3 status bar, comment out this block or remove it entirely
#bar { }

Now just press the <Mod><Shift><R> (i3 default setting) to reload i3 and your Polybars should start up instead of the default i3status

Define Polybars / Modules

For example, my ~/.config/polybar/config -

[bar/top]
monitor = ${env:MONITOR}
width = 100%
height = 34
background = #00000000
foreground = #ccffffff
line-color = ${bar/bottom.background}
line-size = 16
spacing = 2
padding-right = 5
module-margin = 4
font-0 = NotoSans-Regular:size=8;-1
font-1 = MaterialIcons:size=10;0
font-2 = Termsynu:size=8:antialias=false;-2
font-3 = FontAwesome:size=10;0
font-4 = Unifont:size=8;0
modules-left = powermenu
modules-center = ki3
modules-right = volume wired-network clock

[bar/bottom]
monitor = ${env:MONITOR}
bottom = true
width = 100%
height = 27
background = ${bar/top.background}
foreground = ${bar/top.foreground}
line-color = ${bar/top.background}
line-size = 2
spacing = 3
padding-right = 4
module-margin-left = 0
module-margin-right = 6
font-0 = NotoSans-Regular:size=8;0
font-1 = unifont:size=6;-3
font-2 = FontAwesome:size=8;-2
font-3 = NotoSans-Regular:size=8;-1
font-4 = MaterialIcons:size=10;-1
font-5 = Termsynu:size=8:antialias=false;0

These first two blocks define our top and bottom status bars. Continuing on in the ~/.config/polybar/config file, we see the defines for the modules -

[module/powermenu]
type = custom/menu
format-padding = 5
label-open = ䷡
label-close = X
menu-0-0 = Terminate WM
menu-0-0-foreground = #fba922
menu-0-0-exec = bspc quit -1
menu-0-1 = Reboot
menu-0-1-foreground = #fba922
menu-0-1-exec = menu_open-1
menu-0-2 = Power off
menu-0-2-foreground = #fba922
menu-0-2-exec = menu_open-2
menu-1-0 = Cancel
menu-1-0-foreground = #fba922
menu-1-0-exec = menu_open-0
menu-1-1 = Reboot
menu-1-1-foreground = #fba922
menu-1-1-exec = sudo reboot
menu-2-0 = Power off
menu-2-0-foreground = #fba922
menu-2-0-exec = sudo poweroff
menu-2-1 = Cancel
menu-2-1-foreground = #fba922
menu-2-1-exec = menu_open-0

[module/cpu]
type = internal/cpu
interval = 0.5
format = <label> <ramp-coreload>
label = CPU
ramp-coreload-0 = ▁
ramp-coreload-0-font = 2
ramp-coreload-0-foreground = #aaff77
ramp-coreload-1 = ▂
ramp-coreload-1-font = 2
ramp-coreload-1-foreground = #aaff77
ramp-coreload-2 = ▃
ramp-coreload-2-font = 2
ramp-coreload-2-foreground = #aaff77
ramp-coreload-3 = ▄
ramp-coreload-3-font = 2
ramp-coreload-3-foreground = #aaff77
ramp-coreload-4 = ▅
ramp-coreload-4-font = 2
ramp-coreload-4-foreground = #fba922
ramp-coreload-5 = ▆
ramp-coreload-5-font = 2
ramp-coreload-5-foreground = #fba922
ramp-coreload-6 = ▇
ramp-coreload-6-font = 2
ramp-coreload-6-foreground = #ff5555
ramp-coreload-7 = █
ramp-coreload-7-font = 2
ramp-coreload-7-foreground = #ff5555

[module/clock]
type = internal/date
interval = 2
date = %%{F#999}%Y-%m-%d%%{F-}  %%{F#fff}%H:%M%%{F-}

[module/date]
type = internal/date
date =    %%{F#99}%Y-%m-%d%%{F-}  %%{F#fff}%H:%M%%{F-}
date-alt = %%{F#fff}%A, %d %B %Y  %%{F#fff}%H:%M%%{F#666}:%%{F#fba922}%S%%{F-}

[module/memory]
type = internal/memory
format = <label> <bar-used>
label = RAM
bar-used-width = 30
bar-used-foreground-0 = #aaff77
bar-used-foreground-1 = #aaff77
bar-used-foreground-2 = #fba922
bar-used-foreground-3 = #ff5555
bar-used-indicator = |
bar-used-indicator-font = 6
bar-used-indicator-foreground = #ff
bar-used-fill = ─
bar-used-fill-font = 6
bar-used-empty = -
bar-used-empty-font = 6
bar-used-empty-foreground = #444444

[module/ki3]
type = internal/i3
; Only show workspaces defined on the same output as the bar
;
; Useful if you want to show monitor specific workspaces
; on different bars
;
; Default: false
pin-workspaces = true
; This will split the workspace name on ':'
; Default: false
strip-wsnumbers = true
; Sort the workspaces by index instead of the default
; sorting that groups the workspaces by output
; Default: false
index-sort = true
; Create click handler used to focus workspace
; Default: true
enable-click = false
; Create scroll handlers used to cycle workspaces
; Default: true
enable-scroll = true
; Wrap around when reaching the first/last workspace
; Default: true
wrapping-scroll = true
; Set the scroll cycle direction 
; Default: true
reverse-scroll = false
; Use fuzzy (partial) matching on labels when assigning 
; icons to workspaces
; Example: code;♚ will apply the icon to all workspaces 
; containing 'code' in the label
; Default: false
fuzzy-match = true

[module/volume]
type = internal/alsa
speaker-mixer = IEC958
headphone-mixer = Headphone
headphone-id = 9

format-volume = <ramp-volume> <label-volume>
label-muted =   muted
label-muted-foreground = #66
ramp-volume-0 = 
ramp-volume-1 = 
ramp-volume-2 = 
ramp-volume-3 = 


[module/wired-network]
type = internal/network
interface = net0
interval = 3.0
label-connected =    %{T3}%local_ip%%{T-}
label-disconnected-foreground = #66

[module/wireless-network]
type = internal/network
interface = net1
interval = 3.0
ping-interval = 10
format-connected = <ramp-signal> <label-connected>
label-connected = %essid%
label-disconnected =    not connected
label-disconnected-foreground = #66
ramp-signal-0 = 
ramp-signal-1 = 
ramp-signal-2 = 
ramp-signal-3 = 
ramp-signal-4 = 
animation-packetloss-0 = 
animation-packetloss-0-foreground = #ffa64c
animation-packetloss-1 = 
animation-packetloss-1-foreground = ${bar/top.foreground}
animation-packetloss-framerate = 500

Now that we have our status bars and Polybar Modules defined, we need to configure i3 to use Polybar instead of the default i3status that comes configured within the bar { ... } block of the i3 config file. See below for details.

Starting Polybar

If you have one monitor, you can simply run polybar top to start the top status bar created above, and creating a start script should be straight-forward. If you are using multiple monitors and want to replicate the status bars across all displays, create the below script within ~/.config/polybar/, name it what you wish, but be sure it corresponds with how you choose to exec_always in your i3 config later on.

#!/bin/bash
## Author: Shaun Reed | Contact: shaunrd0@gmail.com | URL: www.shaunreed.com ##
##  A script placed in ~/.config/polybar/ - Uses ${env:MONITOR}              ##
##  Starts polybars top and bottom on multiple displays                      ##
###############################################################################
# start-polybar.sh

# Kill any previous polybars
pkill -f polybar

# For each monitor in list up to ':'
for m in $(polybar --list-monitors | cut -d":" -f1); do
  # Reload polybars with monitor device name
  MONITOR=$m polybar --reload top &
  MONITOR=$m polybar --reload bottom &
done

Polybar Startup Script Source

Now, in your ~/.config/polybar/config file, ensure the ${env:MONITOR} environment variable is used to define the monitors -

[bar/top]
monitor = ${env:MONITOR}
width = 100%
height = 34
background = #00000000
foreground = #ccffffff
# Reduced..

Make the script executable and run it, polybar will start with your custom configs -

sudo chmod a+x start-polybar.sh
./start-polybar.sh

You may see errors for symbols used in fonts you do not have installed, see below for troubleshooting information.

To kill all Polybars, run pkill -f polybar

Verify / Install Fonts

You may run into issues with Unicode characters used in these configurations, see the links / commands below for help troubleshooting. The goal is usually to track down the font you are missing and install it, preferably via your system package manager. If you see an error like the below when starting your Polybars, this is likely the issue

warn: Dropping unmatched character ▁ (U+2581)

It is important to note that not defining the relevant font in the Polybar definition within ~/.config/polybar/config will result in the same error.

Cross-check that you have the supported fonts installed by searching up your character in a Unicode Character Search and checking that a relevant font is installed with the below command

fc-match -s monospace:charset=04de1

This matches the Great Power Hexagram, which I use for my system power options / context menu.

The fc-match command above will output all fonts compatible with that symbol, if there is no output, see the Supporting Fonts link from the character's search result, and install it via your package manager.

If it is not installed, search fonts available to install via pacman package manager

sudo pacman -Ss ttf- |grep unicode
sudo pacman -Ss otf- |grep unicode

If it is installed an the error is still present, see that the corresponding font for the character is included in the define for the status bar it is used in. For example, to use the Hexagram above, I added the Unifont:size=8;0 line to my top Polybar definition in ~/.config/polybar/config -

[bar/top]
monitor = ${env:MONITOR}
font-0 = NotoSans-Regular:size=8;-1
font-1 = MaterialIcons:size=10;0
font-2 = Termsynu:size=8:antialias=false;-2
font-3 = FontAwesome:size=10;0
font-4 = Unifont:size=8;0

If still having issues, check the following commands for more info / useful output

# Search for installed fonts
fc-list | grep fontname

Arch Wiki - Fonts

Because this is such a broad topic, I'll pot links here for the sources I used to configure my own Manjaro Linux system running the i3wm and polybar.

Alsa / Volume Mixers - Cannot find simple element

Vim Unicode Plugin

Insertinf Unicode Characters Into Vim

Polybar Module Documentation

Bumblebee-status

A easy to setup, customizable status bar with community created themes. See the GitHub for more information.

Within your users ~/.i3 directory,

git clone git://github.com/tobi-wan-kenobi/bumblebee-status

Customize the ~/.i3/config file's status_command -

bar {
	font pango:Inconsolata 10
	position top
	tray_output none
	status_command ~/.i3/bumblebee-status/bumblebee-status -m nic disk:root cpu memory battery date time pasink pasource dnf -p root.path=/ time.format="%H:%M CW %V" date.format="%a, %b %d %Y" -t solarized-powerline
}

Add Modules and parameters to change how the bar is displayed. Restart i3 to apply settings.

Modules

When using this status bar, it is common to refer to various *.py files within the ~/.i3/bumblebee-status/bumblebee/modules/ directory for information on how modules work. For quick reference, I cross-post the headers within these files for the modules I use here.

GitHub
"""Displays the unread GitHub notifications for a GitHub user

Requires the following library:
    * requests

Parameters:
    * github.token: GitHub user access token, the token needs to have the 'notifications' scope.
    * github.interval: Interval in minutes between updates, default is 5.
"""
Indicator
"""Displays the indicator status, for numlock, scrolllock and capslock 

Parameters:
    * indicator.include: Comma-separated list of interface prefixes to include (defaults to "numlock,capslock")
    * indicator.signalstype: If you want the signali type color to be "critical" or "warning" (defaults to "warning")
"""
Sun
"""Displays sunrise and sunset times

Parameters:
    * cpu.lat : Latitude of your location
    * cpu.lon : Longitude of your location
"""
NVidia GPU
"""Displays GPU name, temperature and memory usage.

Parameters:
   * nvidiagpu.format: Format string (defaults to "{name}: {temp}°C %{usedmem}/{totalmem} MiB")
                       Available values are: {name} {temp} {mem_used} {mem_total} {fanspeed} {clock_gpu} {clock_mem}

Requires nvidia-smi
"""
Ping
"""Periodically checks the RTT of a configurable host using ICMP echos

Requires the following executable:
    * ping

Parameters:
    * ping.interval: Time in seconds between two RTT checks (defaults to 60)
    * ping.address : IP address to check
    * ping.timeout : Timeout for waiting for a reply (defaults to 5.0)
    * ping.probes  : Number of probes to send (defaults to 5)
    * ping.warning : Threshold for warning state, in seconds (defaults to 1.0)
    * ping.critical: Threshold for critical state, in seconds (defaults to 2.0)
"""
Caffeine
"""Enable/disable automatic screen locking.

Requires the following executables:
    * xdg-screensaver
    * xdotool
    * xprop (as dependency for xdotool)
    * notify-send
"""
Disk
"""Shows free diskspace, total diskspace and the percentage of free disk space.

Parameters:
    * disk.warning: Warning threshold in % of disk space (defaults to 80%)
    * disk.critical: Critical threshold in % of disk space (defaults ot 90%)
    * disk.path: Path to calculate disk usage from (defaults to /)
    * disk.open: Which application / file manager to launch (default xdg-open)
    * disk.format: Format string, tags {path}, {used}, {left}, {size} and {percent} (defaults to "{path} {used}/{size} ({percent:05.02f}%)")
    * (deprecated) disk.showUsed: Show used space (defaults to yes)
    * (deprecated) disk.showSize: Show total size (defaults to yes)
    * (deprecated) disk.showPercent: Show usage percentage (defaults to yes)
"""
CPU
"""Displays CPU utilization across all CPUs.

Parameters:
    * cpu.warning : Warning threshold in % of CPU usage (defaults to 70%)
    * cpu.critical: Critical threshold in % of CPU usage (defaults to 80%)
    * cpu.format  : Format string (defaults to "{:.01f}%")
"""
Memory
"""Displays available RAM, total amount of RAM and percentage available.

Parameters:
    * memory.warning : Warning threshold in % of memory used (defaults to 80%)
    * memory.critical: Critical threshold in % of memory used (defaults to 90%)
    * memory.format: Format string (defaults to "{used}/{total} ({percent:05.02f}%)")
    * memory.usedonly: Only show the amount of RAM in use (defaults to False). Same as memory.format="{used}"
"""
Datetimetz
"""Displays the current date and time with timezone options.

Parameters:
    * datetimetz.format   : strftime()-compatible formatting string
    * datetimetz.timezone : IANA timezone name
    * datetz.format       : alias for datetimetz.format
    * timetz.format       : alias for datetimetz.format
    * timetz.timezone     : alias for datetimetz.timezone
    * datetimetz.locale   : locale to use rather than the system default
    * datetz.locale       : alias for datetimetz.locale
    * timetz.locale       : alias for datetimetz.locale
    * timetz.timezone     : alias for datetimetz.timezone
"""
Pacman
"""Displays update information per repository for pacman.

Parameters:
    * pacman.sum: If you prefere displaying updates with a single digit (defaults to "False")

Requires the following executables:
    * fakeroot
    * pacman
"""
Weather
"""Displays the temperature on the current location based on the ip

Requires the following python packages:
    * requests

Parameters:
    * weather.location: Set location, defaults to 'auto' for getting location from http://ipinfo.io
                        If set to a comma-separated list, left-click and right-click can be used to rotate the locations.
                        Locations should be city names or city ids.
    * weather.unit: metric (default), kelvin, imperial
    * weather.showcity: If set to true, show location information, otherwise hide it (defaults to true)
    * weather.apikey: API key from http://api.openweathermap.org
"""
Date / Time (datetime)

This module is passed as individual parts when building the status_command as date and time, but defined in a single pythong file - ~/.i3/bumblebee-status/bumblebee/modules/datetime.py

"""Displays the current date and time.

Parameters:
    * datetime.format: strftime()-compatible formatting string
    * date.format    : alias for datetime.format
    * time.format    : alias for datetime.format
    * datetime.locale: locale to use rather than the system default
    * date.locale    : alias for datetime.locale
    * time.locale    : alias for datetime.locale
"""