statusbar

package module
v0.5.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 13, 2023 License: Apache-2.0 Imports: 16 Imported by: 0

README

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

To install the program, execute the following command:

$ go install gobytes.dev/statusbar/cmds/statusbar@latest
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.

Documentation

Index

Constants

This section is empty.

Variables

View Source
var DefaultConfigFile = filepath.Join(xdg.ConfigHome, "statusbar", "config.yaml")

Functions

func NoBuiltinWidgets

func NoBuiltinWidgets()

func RegisterInternalWidget

func RegisterInternalWidget[T any, pT widget[T]](m internal.Mark, name string)

func RegisterWidget

func RegisterWidget[T any, pT widget[T]](name string)

func RegisterWidgetIn

func RegisterWidgetIn[T any, pT widget[T]](c *Configuration, name string)

func Run

func Run(args []string) error

func SetLogger

func SetLogger(l *slog.Logger)

Types

type BaseWidget

type BaseWidget struct {
	Color               string    `yaml:"color,omitempty"`
	Background          string    `yaml:"background,omitempty"`
	Border              string    `yaml:"border"`
	BorderTop           *int      `yaml:"borderTop"`
	BorterBottom        *int      `yaml:"borderBottom"`
	BorderLeft          *int      `yaml:"borderLeft"`
	BorderRight         *int      `yaml:"borderRight"`
	MinWidth            *MinWidth `yaml:"minWidth"`
	Separator           *bool     `yaml:"separator"`
	SeparatorBlockWidth *int      `yaml:"separatorBlockWidth"`
	Align               string    `yaml:"align,omitempty"`
}

func (*BaseWidget) Block

func (p *BaseWidget) Block() Block

type Block

type Block struct {
	FullText            string    `json:"full_text,omitempty"`
	ShortText           string    `json:"short_text,omitempty"`
	Color               string    `json:"color,omitempty"`
	Background          string    `json:"background,omitempty"`
	Border              string    `json:"border,omitempty"`
	BorderTop           *int      `json:"border_top,omitempty"`
	BorderBottom        *int      `json:"border_bottom,omitempty"`
	BorderLeft          *int      `json:"border_left,omitempty"`
	BorderRight         *int      `json:"border_right,omitempty"`
	MinWidth            *MinWidth `json:"min_width,omitempty"`
	Align               string    `json:"align,omitempty"`
	Name                string    `json:"name,omitempty"`
	Instance            string    `json:"instance,omitempty"`
	Separator           *bool     `json:"separator,omitempty"`
	SeparatorBlockWidth *int      `json:"separator_block_width,omitempty"`
	Markup              string    `json:"markup,omitempty"`
}

func (*Block) SetBorder

func (b *Block) SetBorder(top, right, bottom, left int)

func (*Block) SetMinWidthInt

func (b *Block) SetMinWidthInt(i int)

func (*Block) SetMinWidthString

func (b *Block) SetMinWidthString(s string)

func (*Block) SetSeparator

func (b *Block) SetSeparator(show bool, width int)

type Configuration

type Configuration struct {
	// contains filtered or unexported fields
}

func (*Configuration) NoBuiltinWidgets

func (c *Configuration) NoBuiltinWidgets()

func (*Configuration) Parse

func (c *Configuration) Parse(r io.Reader) error

func (*Configuration) ParseFile

func (c *Configuration) ParseFile(filename string) error

func (*Configuration) Run

func (c *Configuration) Run(args []string) error

func (*Configuration) SetLogger

func (c *Configuration) SetLogger(l *slog.Logger)

func (*Configuration) StatusBar

func (c *Configuration) StatusBar() *StatusBar

func (*Configuration) UnmarshalYAML

func (c *Configuration) UnmarshalYAML(n *yaml.Node) error

func (*Configuration) Widgets

func (c *Configuration) Widgets() []Widget

type Event

type Event struct {
	Name      string `json:"name"`
	Instance  string `json:"instance"`
	X         int    `json:"x"`
	Y         int    `json:"y"`
	Button    int    `json:"button"`
	Event     int    `json:"event"`
	RelativeX int    `json:"relative_x"`
	RelativeY int    `json:"relative_y"`
	Width     int    `json:"width"`
	Height    int    `json:"height"`
}

type EventHandler

type EventHandler interface {
	Event(e Event)
}
type Header struct {
	Version     int  `json:"version"`
	ClickEvents bool `json:"click_events"`
	ContSignal  int  `json:"cont_signal"`
	StopSignal  int  `json:"stop_signal"`
}

type MinWidth

type MinWidth struct {
	// contains filtered or unexported fields
}

func (MinWidth) MarshalJSON

func (w MinWidth) MarshalJSON() ([]byte, error)

func (MinWidth) MarshalYAML

func (w MinWidth) MarshalYAML() (interface{}, error)

func (*MinWidth) UnmarshalJSON

func (w *MinWidth) UnmarshalJSON(bs []byte) error

func (*MinWidth) UnmarshalYAML

func (w *MinWidth) UnmarshalYAML(n *yaml.Node) error

type StatusBar

type StatusBar struct {
	LogFile string
	// contains filtered or unexported fields
}

func GlobalStatusBar

func GlobalStatusBar() *StatusBar

func New

func New(ws ...Widget) *StatusBar

func (*StatusBar) Run

func (b *StatusBar) Run(ctx context.Context)

func (*StatusBar) SetLogger

func (b *StatusBar) SetLogger(l *slog.Logger)

type UpdateFunc

type UpdateFunc func([]Block)

type Widget

type Widget interface {
	Run(ctx context.Context, fn UpdateFunc)
}

func Widgets

func Widgets() []Widget

Directories

Path Synopsis
cmds

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL