Variable
import { Variable } from "astal"
Variable is just a simple object which holds a single value. It also has some shortcuts for hooking up subprocesses, intervals and other gobjects.
INFO
The Variable
object imported from the "astal"
package is not Astal.Variable.
Example Usage
const myvar = Variable("initial-value")
// whenever its value changes, callback will be executed
myvar.subscribe((value: string) => {
console.log(value)
})
// settings its value
myvar.set("new value")
// getting its value
const value = myvar.get()
// binding them to widgets
Widget.Label({
label: bind(myvar).as((value) => `transformed ${value}`),
label: myvar((value) => `transformed ${value}`), // shorthand for the above
})
WARNING
Make sure to the transform functions you pass to :as()
are pure. The .get()
function can be called anytime by astal
especially when deriving
, so make sure there are no sideeffects.
Variable Composition
Using Variable.derive
any Subscribable
object can be composed.
const v1: Variable<number> = Variable(1)
const v2: Binding<number> = bind(obj, "prop")
const v3: Subscribable<number> = {
get: () => 3,
subscribe: () => () => {},
}
// first argument is a list of dependencies
// second argument is a transform function,
// where the parameters are the values of the dependencies in the order they were passed
const v4: Variable<number> = Variable.derive(
[v1, v2, v3],
(v1: number, v2: number, v3: number) => {
return v1 * v2 * v3
}
)
INFO
The types are only for demonstration purposes, you do not have to declare the type of a Variable, they will be inferred from their initial value.
Subprocess shorthands
Using .poll
and .watch
we can start subprocesses and capture their output. They can poll and watch at the same time, but they can only poll/watch once.
WARNING
The command parameter is passed to execAsync which means they are not executed in a shell environment, they do not expand ENV variables like $HOME
, and they do not handle logical operators like &&
and ||
.
If you want bash, run them with bash.
Variable("").poll(1000, ["bash", "-c", "command $VAR && command"])
const myVar = Variable(0)
.poll(1000, "command", (out: string, prev: number) => parseInt(out))
.poll(1000, ["bash", "-c", "command"], (out, prev) => parseInt(out))
.poll(1000, (prev) => prev + 1)
const myVar = Variable(0)
.watch("command", (out: string, prev: number) => parseInt(out))
.watch(["bash", "-c", "command"], (out, prev) => parseInt(out))
You can temporarily stop them and restart them whenever.
myvar.stopWatch() // this kills the subprocess
myvar.stopPoll()
myvar.startListen() // launches the subprocess again
myvar.startPoll()
console.log(myvar.isListening())
console.log(myvar.isPolling())
Gobject connection shorthands
Using .observe
you can connect gobject signals and capture their value.
const myvar = Variable("")
.observe(obj1, "signal", () => "")
.observe(obj2, "signal", () => "")
Dispose if no longer needed
This will stop the interval, force exit the subprocess and disconnect gobjects.
myVar.drop()
WARNING
Don't forget to drop derived variables or variables with either .poll
, .watch
or .observe
when they are defined inside closures.
function MyWidget() {
const myvar = Variable().poll()
const derived = Variable.derive()
return <box
onDestroy={() => {
myvar.drop()
derived.drop()
}}
/>
}