Eww (Elkowars Wacky Widgets)
repository·master·Indexed 11 days ago
https://github.com/elkowar/ewwA standalone, Rust-based widget system designed to allow users to implement custom UI widgets in any window manager. Version 0.6.0 supports Wayland and X11 backends, utilizing a .yuck configuration language for defining windows, widgets, and variables.
What's inside Eww
- simplexpr is a parser and interpreter designed for a simple expression syntax. It is intended to be embedded into other applications or Rust crates. While it is being developed for use within eww, it is currently considered highly experimental, unstable, and not recommended for production use.
Implement dynamic content with variables
masterTo display changing data (like time, battery, or volume) in your widgets, use eww variables. Variables are globally available, and widgets automatically update whenever the variable's value changes. There are four types:
- Basic variables (
defvar): Static values that only change when you explicitly calleww update <var>=<value>. Use these for user-toggled states or rare external updates. - Polling variables (
defpoll): Runs a shell script at a specified interval. Ideal for time, date, or system stats. You can provide an:initialvalue to speed up startup and use:run-whileto control when polling occurs. - Listening variables (
deflisten): Runs a script once and updates whenever the script outputs a new line. This is the most efficient way to handle instantaneous changes like volume, brightness, or workspace switches (e.g., usingtail -Forplayerctl --follow). - Built-in "magic" variables: Pre-defined values like CPU and RAM usage, often provided as JSON.
; Basic variable (defvar foo "initial value") ; Polling variable (defpoll time :interval "1s" :initial "00:00:00" `date +%H:%M:%S") ; Listening variable (deflisten foo :initial "whatever" `tail -F /tmp/some_file")- Basic variables (
Render children in custom widgets
masterYou can create wrapper widgets that accept children by using the
childrenplaceholder. This allows you to build reusable layout components.Using the
childrenplaceholderTo allow a widget to wrap other widgets, include
(children)in its body:(defwidget labeled-container [name] (box :class "container" name (children)))Accessing specific children with
nthYou can target specific children within a widget using the
:nthattribute on thechildrenplaceholder. This is useful for complex layouts where children need to be placed in different parts of the widget structure:(defwidget two-boxes [] (box (box :class "first" (children :nth 0)) (box :class "second" (children :nth 1))))(labeled-container :name "foo" (button :onclick "notify-send hey ho" "click me"))Use magic variables in Eww
masterEww provides 'magic variables' that are globally available within your configuration without requiring explicit imports.
Update Frequency:
EWW_TIME: Updates every 1s.- All other magic variables: Update every 2s.
Configure windows with arguments
masterArguments allow you to pass constant values to a window at the time it is opened. This is useful for varying geometry, size, or classes for different instances of the same window config.
Note: Arguments are CONSTANT and cannot be updated after the window is opened.
Defining Arguments in Yuck
Arguments are defined in the
defwindowdeclaration using[arg1 ?arg2]syntax (where?denotes an optional argument).(defwindow my_bar [arg1 ?arg2] :geometry (geometry :width { arg1 == "small" ? "100px" : "200px" }) (my_widget :arg2 arg2))Passing Arguments via CLI
- Using
open: Use the--argflag.eww open my_bar --arg arg1=some_value --arg arg2=another_value - Using
open-many: Use the--argflag after all window names. Arguments can be scoped to a specific ID usingid:arg_name=value.eww open-many my_bar:primary --arg primary:arg1=val1 --arg primary:arg2=val2
If you don't specify an ID for an argument in
open-many, it is applied to all windows in that command.eww open my_bar --id primary --arg arg1=some_value --arg arg2=another_value eww open-many my_bar:primary --arg primary:arg1=some_value --arg primary:arg2=another_value- Using
Explore eww configuration examples
masterYou can find various eww configuration examples in the
examples/directory of the official repository. These examples demonstrate different use cases, such as creating a status bar or working with complex data structures.Key example types include:
- Eww Bar: A complete configuration for a status bar.
- Data Structures: A demonstration of how to declare and use data structures within your configuration.
https://github.com/elkowar/eww/tree/master/examplesSplit eww configuration into multiple files
masterAs your configuration grows, you can manage it using two methods:
- Using
include: Import one.yuckfile into another using theincludedirective.(include "./path/to/your/file.yuck") - Using a separate configuration directory: You can point eww to a different config directory by passing the
--config /path/to/your/config/dirflag to every command (includingeww kill,eww logs, etc.). This creates a separate instance with its own daemon, logs, and state.
(include "./path/to/your/file.yuck")eww --config /path/to/your/config/dir open my_bar- Using
Setup eww configuration files
masterEww uses two primary files for configuration, which must be placed in
$XDG_CONFIG_HOME/eww(typically~/.config/eww):eww.yuck: Defines the structure, content, geometry, and behavior of widgets and windows using theyucklanguage (an S-expression based language).eww.scssoreww.css: Defines the visual styling. Eww uses the GTK CSS engine, so while it supports much of standard CSS, layout properties likeflexbox,float,absolute position, andwidth/heightare generally unsupported.
For editor support, you can use
yuck.vim(Vim) oryuck-vscode(VSCode). Usingparinferis also recommended for easier S-expression manipulation.mkdir -p ~/.config/eww touch ~/.config/eww/eww.yuck ~/.config/eww/eww.scssUse the Yuck expression language
masterYuck includes a small expression language for performing operations on data within your configuration. You can use expressions to show different values based on conditions, perform mathematical operations, or access values within JSON structures.
Expressions can be placed in two ways:
- Anywhere within your configuration inside curly braces:
{ ... }. - Within strings using string-interpolation blocks:
"foo ${ ... } bar".
Example
(box "Some math: ${12 + foo * 10}" (button :class {button_active ? "active" : "inactive"} :onclick "toggle_thing" {button_active ? "disable" : "enable"}))- Anywhere within your configuration inside curly braces:
Install and build Eww
masterEww is a widget system configured in
yuckand themed usingCSS. To install it, you must first ensure you haverustcandcargoinstalled (ideally viarustup).Because Eww compiles against several dynamic libraries, you will likely need the
-develvariants of these packages on your distribution. For Arch Linux, the required packages include:gtk3(libgdk-3, libgtk-3)gtk-layer-shell(required for Wayland)pango(libpango)gdk-pixbuf2(libgdk_pixbuf-2)libdbusmenu-gtk3cairo(libcairo, libcairo-gobject)glib2(libgio, libglib-2, libgobject-2)gcc-libs(libgcc)glibc
git clone https://github.com/elkowar/eww cd eww # Build for X11: cargo build --release --no-default-features --features x11 # OR Build for Wayland: cargo build --release --no-default-features --features=waylandUse the GTK Debugger to inspect styles
masterThe GTK Debugger is useful for troubleshooting styling issues or identifying the structure of your widgets.
- Launch the debugger by running
eww inspector. - Use the selection icon (top left) to click on the specific widget or element that is not styled correctly.
- Open the dropdown menu in the top right corner and select CSS Nodes. This view displays the element's structure, applied CSS properties, and styling details.
eww inspector- Launch the debugger by running
Run the Eww daemon and open windows
masterAfter building Eww, navigate to the release directory and ensure the binary is executable. To use Eww, you must first start the
daemon, and then you canopenspecific windows defined in your configuration.- Navigate to
target/release. - Make the binary executable with
chmod +x ./eww. - Start the daemon:
./eww daemon. - Open a window:
./eww open <window_name>.
cd target/release chmod +x ./eww ./eww daemon ./eww open <window_name>- Navigate to