Eww (Elkowars Wacky Widgets)

repository·master·Indexed 11 days ago

https://github.com/elkowar/eww

A 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.

Tokens
22.2K
Snippets
83
Records
106
Agent score
92%

What's inside Eww

  1. Overview of simplexpr

    master
    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.
  2. Implement dynamic content with variables

    master

    To 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:

    1. Basic variables (defvar): Static values that only change when you explicitly call eww update <var>=<value>. Use these for user-toggled states or rare external updates.
    2. Polling variables (defpoll): Runs a shell script at a specified interval. Ideal for time, date, or system stats. You can provide an :initial value to speed up startup and use :run-while to control when polling occurs.
    3. 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., using tail -F or playerctl --follow).
    4. 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")
  3. Render children in custom widgets

    master

    You can create wrapper widgets that accept children by using the children placeholder. This allows you to build reusable layout components.

    Using the children placeholder

    To 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 nth

    You can target specific children within a widget using the :nth attribute on the children placeholder. 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"))
  4. Configure windows with arguments

    master

    Arguments 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 defwindow declaration 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 --arg flag. eww open my_bar --arg arg1=some_value --arg arg2=another_value
    • Using open-many: Use the --arg flag after all window names. Arguments can be scoped to a specific ID using id: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
  5. Explore eww configuration examples

    master

    You 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/examples
  6. Split eww configuration into multiple files

    master

    As your configuration grows, you can manage it using two methods:

    1. Using include: Import one .yuck file into another using the include directive. (include "./path/to/your/file.yuck")
    2. Using a separate configuration directory: You can point eww to a different config directory by passing the --config /path/to/your/config/dir flag to every command (including eww 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
  7. Setup eww configuration files

    master

    Eww uses two primary files for configuration, which must be placed in $XDG_CONFIG_HOME/eww (typically ~/.config/eww):

    1. eww.yuck: Defines the structure, content, geometry, and behavior of widgets and windows using the yuck language (an S-expression based language).
    2. eww.scss or eww.css: Defines the visual styling. Eww uses the GTK CSS engine, so while it supports much of standard CSS, layout properties like flexbox, float, absolute position, and width/height are generally unsupported.

    For editor support, you can use yuck.vim (Vim) or yuck-vscode (VSCode). Using parinfer is also recommended for easier S-expression manipulation.

    mkdir -p ~/.config/eww
    touch ~/.config/eww/eww.yuck ~/.config/eww/eww.scss
  8. Use the Yuck expression language

    master

    Yuck 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:

    1. Anywhere within your configuration inside curly braces: { ... }.
    2. 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"}))
  9. Install and build Eww

    master

    Eww is a widget system configured in yuck and themed using CSS. To install it, you must first ensure you have rustc and cargo installed (ideally via rustup).

    Because Eww compiles against several dynamic libraries, you will likely need the -devel variants 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-gtk3
    • cairo (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=wayland
  10. Use the GTK Debugger to inspect styles

    master

    The GTK Debugger is useful for troubleshooting styling issues or identifying the structure of your widgets.

    1. Launch the debugger by running eww inspector.
    2. Use the selection icon (top left) to click on the specific widget or element that is not styled correctly.
    3. 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
  11. Run the Eww daemon and open windows

    master

    After 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 can open specific windows defined in your configuration.

    1. Navigate to target/release.
    2. Make the binary executable with chmod +x ./eww.
    3. Start the daemon: ./eww daemon.
    4. Open a window: ./eww open <window_name>.
    cd target/release
    chmod +x ./eww
    ./eww daemon
    ./eww open <window_name>