~rkintzi/statusbar

Library for easy generation of swaybar/i3bar content
Add KeyringUnlocker widget
Update Contributions section in README.md
Update installation instructions

clone

read-only
https://git.sr.ht/~rkintzi/statusbar
read/write
git@git.sr.ht:~rkintzi/statusbar

You can also use your local clone with git send-email.

#statusbar

statusbar is a library and a program for easy generation of swaybar/i3bar content.

#Project Goals

The project goals are:

  1. To offer a variety of widgets that meet the needs of most users.
  2. To make it easy to extend the collection of widgets, either by using an external program or the project's library.
  3. To ensure that configuring widgets, including those built by other users, is simple. All configuration options supported by the swaybar protocol should be supported by this project.
  4. To deliver comprehensive documentation.

#statusbar - The Program

#Installation

#Requirements
  1. Go toolchain
  2. scdoc (to build documentation)
#Build and Install

To install the program, execute the following command:

$ make && sudo make install

Alternatively, if you are an Arch user, you can install the statusbar using the AUR statusbar package.

#Configuration

By default, the program reads its configuration from the ~/.config/statusbar/config.yaml file. The following is a good starting point for further customization:

- widget: DefaultConfig
- widget: Window
  excludeAppIDs: ["foot"]
  titlePrefix: "\uf2a3 "
  ellipsis: "\u2026"
- widget: ExternalProgram
  command: /usr/bin/i3status
- widget: SystemMonitor
  format: "\ue8b0 {cpu}% \ue8b2 {mem}%  \ue8b3 {load}%"
  separator: false
  separatorBlockWidth: 0
- widget: TempMonitor
  format: " \ue8a2 {temp}\u00B0C \ue8a1 {fan}"
- widget: Volume
  scrollDownCommand: volumeup
  scrollUpCommand: volumedown
  rightClickCommand: mute toggle
  leftClickCommand: pavuctrl
- widget: BatteryMonitor
  format: "{icon} {level}%"
  statusIcons: "\ue85b\ue85b  "
  chargingIcons: "\ue850\ue851\ue852\ue853\ue854\ue855\ue856\ue857\ue858\ue859\ue85a"
  dischargingIcons: "\ue860\ue861\ue862\ue863\ue864\ue866\ue866\ue867\ue868\ue869\ue86a"
  colors: "#9e1828,10,#968a38,20,#ccc"
  criticalLevel: 5
- widget: DateTime
  format: "\uf2ab 2006-01-02 \uf394 15:04:05"

Each item in the list corresponds to a widget on the status bar. Widgets are placed on the bar in the order they appear in the configuration file. You can configure multiple instances of the same widget if you find it useful. Please refer to the section below for the available widgets and their configuration.

To ensure that the statusbar is run in sway, you need to replace the status_command in sway's configuration file (usually ~/.config/sway/config) with the following:

bar {
    status_command statusbar
}
#Default Configuration

In the above example, the first section of the configuration file refers to the DefaultConfig widget. Despite its somewhat misleading name, it does not describe an actual widget. Instead, all the configuration options provided in this section are used to initialize other widgets, unless their configuration overwrites them. The settings that can be used to describe the default configuration are listed and explained in the next section below. In the example, no options were provided, so the section could have been omitted.

#Common options

Options described in this section can be set for every widget, as well as in the special widget DefaultConfig (described above). This options are also described in the swaybar-protocol(7).

  • color - Sets the text color of the widget using #rrggbbaa or #rrggbb notation.

  • background - Sets the background color of the widget.

  • border - Sets the border color for the widget.

  • borderTop - Sets the height in pixels of the top border. The default value is 1.

  • borderBottom - Sets the height in pixels of the bottom border. The default value is 1.

  • borderLeft - Sets the width in pixels of the left border. The default value is 1.

  • borderRight - Sets the width in pixels of the right border. The default value is 1.

  • minWidth - Sets the minimum width to use for the widget. The width can be specified in pixels or as a string to allow for dynamic calculation based on the width of the text.

  • separator - Specifies whether the bar separator should be drawn after the widget. Refer to sway-bar(5) for more information on how to set the separator text.

  • separatorBlockWidth - Sets the amount of pixels to leave blank after the block. The separator text will be displayed centered in this gap. The default value is 9 pixels.

  • align - Specifies how the text should be aligned inside the block if it does not span the full width. The options are left (default), right, or center.

#Available Widgets

Currently, the statusbar provides following widgets.

#BatteryMonitor

The BatteryMonitor widget is used to display the status and level of the system battery. It offers the following options for customization:

  • format: This option determines how the battery status is displayed. The default format is {icon} {level}. It can also include a {status} indicator that shows text describing the battery status. By default, the statuses are displayed as "Full," "Not charging," "Charging," "Discharging," and "Unknown." However, these labels can be changed using the statusFull, statusNotCharging, statusCharging, and statusDischarging options described below. The {level} placeholder can also include a formatting verb, as defined in the Golang's fmt package documentation. For example, you can use {level:%2d} to format the level with at least two-digit (the default formatting is %d).

  • statusIcons: Specifies four icons (Unicode points) that correspond to the "Full," "Not charging," "Charging," and "Discharging" statuses. These icons are used in place of the {icon} placeholder. The default icons are FNCD.

  • chargingIcons: If provided, these icons are displayed instead of the C icon defined using the statusIcons option. The icons should represent different battery levels, starting with the icon that represents the lowest level. There is no limit to the number of icons that can be used.

  • dischargingIcons: Similar to the chargingIcons above. Specifies icons that are displayed instead of the D icon defined using the statusIcons option.

  • statusFull, statusNotCharging, statusCharging, statusDischarging: These options allows to specify labels for the "Full", "Not charging", "Charging", and "Discharging" statuses.

  • colors: This option specifies the colors in which the widget will be rendered based on the battery levels. For instance, if you set this option to #9e1828,10,#968a38,20,#ccc, the widget will appear red when the battery level is below or equal to 10, yellow when the level is between 10 and 20 (inclusive), and light gray otherwise.

  • criticalLevel: If this option is set above 0, the user will receive an urgent notification when the battery level falls below the provided value. Notifications are sent using D-bus.

  • notificationTitle: Provides the title of the notification sent when the battery level reaches a critically low level. The default title is: "Critical Battery Level"

  • notificationBody: Specifies the notification body. The default message is: "Your battery level is critically low.\nPlease connect your device to a power source immediately to avoid any unexpected shutdowns."

  • notificationIcon: This option allows to set notification icon.

  • ueventFile: Specifies the file that keeps infomation about the battery status (the default file is "/sys/class/power_supply/BAT0/uevent")

#DateTime

The DateTime widget displays the current date and time. It has one configuration option, which is format. The default format is 2006-01-02 15:04:05, and you can specify any format that is accepted by Golang's time.Format method.

#ExternalProgram

The ExternalPrgram widget runs an external program that generates swaybar/i3bar content. It relays the output of the program to the bar and also forwards events from the bar to the external program. This widget is beneficial if you want to incorporate information from another content generator into your bar.

The only configuration option available for this widget is command. It allows you to specify the command that will execute the external generator.

#SystemMonitor

The SystemMonitor widget provides information regarding the utilization of the CPU and RAM, as well as the system load. It offers a single configuration option, which is the format. The default format is CPU:{cpu}% MEM:{mem}% LOAD:{load}%. You have the flexibility to change the order or remove any of the indicators.

Additionally, the format option allows you to specify the width and precision used to format floating numbers. Please refer to the Golang's fmt package documentation for more details. For example, using "{cpu:3.2f}%" will output at least three characters for the decimal part, padding it with spaces if necessary, and will display two digits for the fractional part. Please note that the width and precision specification should be followed by the 'f' suffix, but no '%' prefix should be included.

#TemperatureMonitor

The TemperatureMonitor widget displays temperature and/or fan speed. It offers the following settings:

  • format: Determines how the widget is displayed. The default format is {temp:%d} {fan:%d}.

  • tempInput: Specifies the file that keeps the current temperature (the default file is "/sys/class/hwmon/hwmon3/temp1_input")

  • fanInput: Specifies the file that keeps the current fan speed (the default file is "/sys/class/hwmon/hwmon3/fan1_input")

#Volume

The Volume widget shows and allows you to adjust the volume of an audio device. It offers the following options for customization:

  • format: Determines how the widget is displayed. The default format is {icon} {level}%.

  • icon: Specifies the icon that appears when the device is not muted.

  • muteIcon: Specifies the icon that appears when the device is muted.

  • leftClickCommand: Specifies the command that is executed when the left mouse button is clicked.

  • rightClickCommand: Specifies the command that is executed when the right mouse button is clicked.

  • scrollUpCommand: Specifies the command that is executed when the mouse scroll up event occurs.

  • scrollDownCommand: Specifies the command that is executed when the mouse scroll down event occurs.

  • volMonCommand: Specifies the program responsible for monitoring the volume level of the devices. The program should print the volume level to its standard output each time it detects a change. An example program that works with the PulseAudio (and PipeWire) server is available in the project's cmds/pavolmon directory. Please refer to its README.md for instructions on how to install it.

#Window

The window widget displays the title of the focused window. It provides the following options:

  • titlePrefix - a string that is added before the title (default: "")
  • maxTitleLength - if the length of the title exceeds the specified value, it is trimmed and an ellipsis symbol is added (default: 80, set to -1 to disable trimming)
  • ellipsis - the symbol used as an ellipsis after trimming the window's title (default: "...")
  • excludeAppIDs - to make the title appear more standardized, the Window widget first removes the app ID from the title (because different applications place them in different locations) and then appends it back. This option allows you to specify a list of application IDs that will not be appended.

#statusbar - The Library

If a widget is missing from the above collection, you have two options to add it:

  1. If there is already a program that provides the required functionality, you can utilize the ExternalProgram widget.
  2. Alternatively, you can implement the missing widget using the statusbar library.

The following example illustrates how to implement a program that adds a new widget called StaticText to the standard collection. This widget displays a text provided in the standard configuration files and supports all the common configuration options.

package main

import (
	"context"
	"fmt"
	"os"

	"gobytes.dev/statusbar"
	_ "gobytes.dev/statusbar/widgets"
)

type StaticText struct {
	Text string `yaml:"textToDisplay"`
	statusbar.BaseWidget
}

func (w StaticText) Run(ctx context.Context, update statusbar.UpdateFunc) {
	b := w.Block()
	b.FullText = w.Text
	b.Name = "static"
	update([]statusbar.Block{b})
	<-ctx.Done()
}

func main() {
	statusbar.RegisterWidget[StaticText]("StaticText")
	abortOnErr(statusbar.Run(nil))
}

func abortOnErr(err error) {
	if err != nil {
		fmt.Fprintf(os.Stderr, "%s: %s\n", os.Args[0], err)
		os.Exit(1)
	}
}

That's all! You can now install your program and add the following lines to your configuration:

- widget: StaticText
  textToDisplay: "Some nice text"

If you installed your program under a different name than statusbar, don't forget to update the swaybar configuration (as described in the Configuration section above).

#Additional notes

  1. Widgets must implement the Widget interface as defined by the statusbar library. This means that they must provide the Run method, as shown in the example above.

  2. Widgets should be structs with a pointer receiver. They should also embed the BaseWidget struct, as demonstrated above. This allows them to accept default configurations and be registered using the statusbar.RegisterWidget function.

  3. The Run method is executed by a status bar in a dedicated goroutine. It is responsible for updating the contents of the status bar blocks. In the provided example, the update function is called only once, but usually it should be called within the loop whenever a status change is detected.

  4. The Block method provided by the BaseWidget returns the block that has been preinitialized with common configuration options.

  5. In general, the Run method should continue running until the context is canceled. However, it may exit earlier if necessary. In such cases, the status bar will preserve the last version of the widget's blocks. To remove the widget's blocks from the status bar, you can pass nil to the update function.

  6. Note that in the provided example, the <-ctx.Done() statement could be omitted.

#Contributions

If you notice any bugs or have any suggestions, feel free to contact me. I welcome patches, too.