Skip to content

Rendering and Best Practices

As your configuration grows, you might want to improve its structure by factoring out pieces into reusable functions.

In Ewwii’s Rhai-based configuration system, you can define wrapper functions that return widgets and accept a children parameter (or any parameter that you prefer), just like built-in widgets such as box() or button().

Here’s an example of a custom container that adds a label before its children:

example.rhai
fn labeled_container(name, children = []) {
return box(#{ class: "container" }, [label(#{text: name})] + children)
}

You can call it like this:

example.rhai
labeled_container("foo", [
button(#{ onclick: "notify-send hey ho", label: "Click me" })
]);

Because children are just a list of widgets, you can also write functions that structure them however you’d like. For example, here’s a layout that places the first two children side by side:

example.rhai
fn two_boxes(children = []) {
return box(#{}, [
box(#{ class: "first" }, [children[0]]),
box(#{ class: "second" }, [children[1]])
]);
}

And call it like this:

example.rhai
two_boxes([
label(#{ text: "First" }),
label(#{ text: "Second" })
]);

If a child is missing (e.g., children[1] doesn’t exist), make sure to handle that gracefully or document the expected number of children.

In some cases you may want to use the same window configuration for multiple widgets, e.g. for multiple windows. This is where arguments and ids come in.

Firstly let us start off with ids. An id can be specified in the open command with --id, by default the id will be set to the name of the window configuration. These ids allow you to spawn multiple of the same windows. So for example you can do:

Terminal window
ewwii open my_bar --screen 0 --id primary
ewwii open my_bar --screen 1 --id secondary

Generating a list of widgets from array using for

Section titled “Generating a list of widgets from array using for”

If you want to display a list of values, you can use the for-Element to fill a container with a list of elements generated from a JSON-array.

example2.rhai
let my_array = [1, 2, 3];
// Then, inside your widget, you can use
box(#{}, [
for entry in my_array {
button(#{ onclick: `notify-send 'click' 'button ${entry}'`, label: entry.to_string() })
}
])

This can be useful in many situations, for example when generating a workspace list from an array representation of your workspaces. In many cases, this can be used instead of literal, and should most likely be preferred in those cases.

As time passes, your configuration might grow larger and larger. Luckily, you can easily split up your configuration into multiple files!

There are two options to achieve this:

baz.rhai
// in ./foo/baz.rhai
fn greet() { return "Greetings!" }
export greet;
ewwii.rhai
// in ./ewwii.rhai
import "foo/baz" as example;
print(example::greet()); // output: Greetings!

A rhai file may import the contents of any other rhai file that they export. For this, make use of the import directive. If you are exporting a variable/function, make use the export directive.

Using a separate ewwii configuration directory

Section titled “Using a separate ewwii configuration directory”

If you want to separate different widgets even further, you can create a new ewwii config folder anywhere else. Then, you can tell ewwii to use that configuration directory by passing every command the --config /path/to/your/config/dir flag. Make sure to actually include this in all your ewwii calls, including ewwii kill, eww logs, etc. This launches a separate instance of the ewwii daemon that has separate logs and state from your main ewwii configuration.

Terminal window
ewwii --config "/path/to/your/config/dir"