-
Notifications
You must be signed in to change notification settings - Fork 1
Variable
A Variable is a reactive container that holds a value and notifies subscribers whenever that value changes.
Variables are the foundation of state management in Astal Lua and can be used directly with Bindings to create reactive widgets.
Use Variable.new() to create a new Variable with an initial value.
local Variable = require('astal.variable')
local count = Variable.new(0)
print(count:get()) -- 0You can also access the value through the value property.
local Variable = require('astal.variable')
local count = Variable.new(0)
print(count.value)Variables can be updated using :set().
local Variable = require('astal.variable')
local count = Variable.new(0)
count:set(10)
print(count:get()) -- 10Or by assigning directly to the value property.
local Variable = require('astal.variable')
local count = Variable.new(0)
count.value = 42Whenever the value changes, all subscribers will be notified automatically.
Use :subscribe() to react to value updates.
local Variable = require('astal.variable')
local count = Variable.new(0)
local unsubscribe = count:subscribe(function(value)
print('New value:', value)
end)
count:set(1)
count:set(2)
unsubscribe()The returned function disconnects the subscription.
Variables are commonly used together with Bindings to create reactive user interfaces.
local astal = require('astal')
local bind = astal.bind
local Variable = require('astal.variable')
local Widget = require('astal.gtk4.widget')
local count = Variable.new(0)
return Widget.Label {
label = bind(count):as(tostring),
}Whenever the variable changes, the widget will update automatically.
Variables can periodically update themselves using :poll().
The polling source can be either a Lua function or a shell command.
local Variable = require('astal.variable')
local clock = Variable
.new(os.date('%H:%M:%S'))
:poll(1000, function()
return os.date('%H:%M:%S')
end)The callback receives the previous value and should return the next value.
local Variable = require('astal.variable')
local counter = Variable
.new(0)
:poll(1000, function(prev)
return prev + 1
end)You can also poll the output of a command.
local Variable = require('astal.variable')
local volume = Variable
.new('')
:poll(1000, 'wpctl get-volume @DEFAULT_AUDIO_SINK@')A transform function can be provided to process the command output.
local Variable = require('astal.variable')
local uptime = Variable
.new('')
:poll(
5000,
'uptime -p',
function(out)
return out:gsub('\n', '')
end
)Use :watch() when a command continuously produces output.
local Variable = require('astal.variable')
local workspace = Variable
.new('')
:watch('some-command --follow')Whenever the process emits a new line, the variable will be updated.
A transform function can also be provided.
local Variable = require('astal.variable')
local workspace = Variable
.new('')
:watch(
'some-command --follow',
function(out)
return out:match('%S+') or ''
end
)Variables can observe GObject signals and automatically update their value.
local Variable = require('astal.variable')
local var = Variable.new('')
var:observe(
battery,
'notify::percentage',
function(bat, percentage)
return string.format('%d%%', percentage * 100)
end
)Regular signals are also supported.
local Variable = require('astal.variable')
local var = Variable.new(0)
var:observe(button, 'clicked', function()
return os.time()
end)Use Variable.derive() to create a variable from one or more reactive dependencies.
local Variable = require('astal.variable')
local first = Variable.new('Hello')
local second = Variable.new('World')
local combined = Variable.derive(
{ first, second },
function(a, b)
return a .. ' ' .. b
end
)
print(combined:get()) -- Hello WorldWhenever any dependency changes, the derived variable is updated automatically.
first:set('Goodbye')
print(combined:get()) -- Goodbye WorldPolling and watching commands may emit errors.
Use :on_error() to handle them.
local Variable = require('astal.variable')
Variable
.new('')
:watch('invalid-command')
:on_error(function(_, err)
print('Error:', err)
end)Note
If no error handler is registered, errors will be printed to stdout automatically.
Variables may allocate resources such as polling timers, subprocesses and subscriptions.
Call :drop() when the variable is no longer needed.
local Variable = require('astal.variable')
local clock = Variable
.new('')
:poll(1000, 'date')
clock:drop()Calling :drop() automatically:
- Stops active polls
- Stops active subprocesses
- Disconnects derived subscriptions
- Executes registered cleanup callbacks
Use :on_dropped() to register cleanup handlers.
local Variable = require('astal.variable')
local var = Variable.new(0)
var:on_dropped(function()
print('Variable destroyed')
end)These callbacks are executed when :drop() is called.