-
-
Notifications
You must be signed in to change notification settings - Fork 659
Lua: Evaluation
This guide covers how Conky loads and runs Lua scripts. It assumes basic familiarity with editing configuration files. If you're new to Lua itself, see Lua Basics for the language fundamentals. Lua also provides its own manual for comprehensive reference.
Lua is one of the simplest scripting languages. It's got some minor quirks (like 1-based array indexing), but it should be easy to understand for most digitally literate people.
To integrate Lua scripts into Conky they have to be loaded using lua_load in
the conky.conf file:
conky.config = {
lua_load = "path/to/script.lua"
-- other settings
}The config file is usually placed in ~/.config/conky/conky.conf. On a fresh
install it might need to be copied over from /etc/conky/conky.conf.
lua_load specifies the paths to the Lua scripts that Conky will execute. These
paths can be relative if the script is placed in the same directory as
conky.conf (e.g. lua_load = "./script.lua"), or an absolute path (e.g.
lua_load = "/home/username/scripts/script.lua").
Multiple files may be loaded — use a semicolon (;) as the file path separator.
If Inotify is supported by the system (it is for most Linux distributions), these files should reload automatically when they're changed. This depends on the Conky build environment (of the package vendor).
Lua script files should be placed in a directory where Conky can access them. Most commonly, people place Conky scripts alongside the config file because that makes them easier to edit, copy and store on git.
If Conky is unable to load the file, double-check the file path. If it's
correct, use system utilities like ls, chown and chmod to ensure the file
can be read by Conky. For details on Linux file permissions check out this
useful guide by Red Hat.
While lua_load loads Lua scripts, Conky allows executing functions from the
scripts using hooks. Hooks are called as part of the update cycle of the window,
as well as on startup/closing and for some events. All Lua hooks start with
lua_ and can be found in the
Conky documentation.
To connect a Lua function to a hook, specify the function name as the hook value:
conky.config = {
lua_load = "script.lua",
-- other settings
lua_draw_hook_post = "main",
}Important
The function name in the Lua file must be prefixed with conky_. So
lua_draw_hook_post = "main" will call conky_main() in the script.
For drawing, the most important hooks are lua_draw_hook_* — these allow a Lua
script to render content in the Conky window:
-
lua_draw_hook_pre: Runs the function before main content (specified inconky.textblock) is drawn.- Intended for drawing background graphics that should appear below text.
-
lua_draw_hook_post: Runs the function after the Conky window is drawn.- Intended for drawing over everything else.
Warning
Drawing functionality can be disabled at compile time. If the installed Conky version doesn't have drawing capabilities, draw hooks will silently do nothing. Some distributions offer various flavors of the Conky package with different features enabled — make sure to pick the appropriate one. Check your Linux distribution's documentation for installation instructions.
Conky also provides some additional hooks for specific use cases:
-
lua_startup_hook: Runs once when Conky starts.- Intended for collecting immutable system data or preconfiguring things in Lua that might be expensive to do every update.
-
lua_shutdown_hook: Runs once when Conky exits.- Intended for cleanup of temporary files or resources that were created from the startup hook.
-
lua_mouse_hook: Captures mouse events within the Conky window. Covered in detail in Mouse Events.- Intended for adding interactivity to Conky.
These are all the supported hooks at the moment, but more might be added in
future. See lua_ prefixed variables in the
documentation to check if anything else has
been added in the meantime, or create a
feature request.
Caution
Some events (dragging windows, overlapping Conky instances) can trigger additional calls to draw hooks beyond the normal update cycle. This can cause issues if your script accumulates data on every call (e.g. pushing values into a history table). To guard against this, use a time-based interval to ensure data collection runs at most once per real second — see Time-Based Intervals.
Let's go step by step through a simple Lua script and explain what each part does before presenting the final code.
At the top of the script, load the external libraries needed for drawing:
require("cairo")This loads bindings from the Cairo library which is used for rendering in Conky.
Other bindings like rsvg and imlib2 add their own libraries that can be
required from Lua. See Image Rendering for details on image rendering.
Note
During transition period, require("cairo_xlib") was used to import
X11-specific functions, this is no longer needed.
conky_surface() works for both X11 and Wayland and is provided by conky
directly. See Creating the Drawing Surface.
The lua_draw_hook_post = "main" setting expects a conky_main function to be
defined in one of the lua_loaded files. Missing this will cause
warnings/errors:
function conky_main()
-- drawing code goes here
endAll drawing in Cairo happens on a surface. conky_surface() returns the
current Cairo surface for the active display output, or nil if no graphical
surface is available:
local surface = conky_surface()
if not surface then return end
local cr = cairo_create(surface)The surface returned by conky_surface() is only valid for the current draw
cycle. Call it each time your draw hook is invoked — do not cache it across
frames.
cr is the drawing context used for all rendering.
Tip
It's common to give the drawing context a short name like cr or ctx
because it appears in almost every drawing call. The examples in this wiki
use cr throughout.
Note
Older scripts created the surface manually using X11-specific functions:
require("cairo_xlib")
local surface = cairo_xlib_surface_create(
conky_window.display, conky_window.drawable,
conky_window.visual, conky_window.width, conky_window.height)This still works on X11 but is deprecated. The conky_window.display,
conky_window.drawable, and conky_window.visual fields are X11-specific
and will be removed in a future release.
conky_parse() evaluates Conky variables from
Lua. It processes the same syntax used in conky.text and returns the fully
evaluated result as a string.
Simple variable access:
local cpu_usage = conky_parse("${cpu}")
local memory_used = conky_parse("${memperc}")
local disk_space = conky_parse("${fs_used /home}")conky_parse() isn't limited to single variables — it can evaluate the full
Conky text syntax, including conditionals, multiple variables, and formatting:
-- Conditional evaluation
local net_status = conky_parse("${if_up wlan0}Online${else}Offline${endif}")
-- Combining multiple variables into a formatted string
local summary = conky_parse("${cpu}% @ ${freq_g}GHz")
-- Conditionals with nested variable substitution
local charge = conky_parse(
"${if_match ${battery_percent} > 20}OK${else}Low${endif}"
)Use tonumber() to convert the result when you need numeric values for
calculations. See Dynamic Content
in the drawing guide for practical examples.
The drawing context created with cairo_create() must be destroyed at the end
of each draw hook. Not doing so will cause Conky to consume more and more memory
over time (a memory leak):
cairo_destroy(cr)Note
The surface from conky_surface() is managed by Conky — do not call
cairo_surface_destroy() on it. Only destroy the cairo_t context you
created. Older scripts that create their own surface via
cairo_xlib_surface_create() do need to destroy it.
Now that each part is explained, here is the complete script:
-- ~/.config/conky/script.lua
require("cairo")
function conky_main()
local surface = conky_surface()
if not surface then return end
local cr = cairo_create(surface)
local updates = tonumber(conky_parse("${updates}"))
if updates > 5 then
print("conky_main counted >5 updates to its window")
end
cairo_destroy(cr)
endThis script checks the update count and prints debug information to the console after 5 updates. From here, see Drawing with Cairo for how to render text, shapes, and data-driven widgets.
As Lua is called by Conky, it's important to detail how precisely it gets
executed. Normally, Lua runtime has a single entry point script and just runs
the code from that script. In Conky this is also pretty much the case (except
for hooks), and the entry point is ~/.config/conky/conky.conf file, or some
other config file provided to Conky with -c command line argument:
conky -c "./my custom.config"When Conky starts, it will do some work in the background to create a window and
set up the Lua context. Before anything else happens, Conky will load and run
the config file in order to get conky.config and conky.text variable values.
As the config file is technically a Lua script, it can contain code and
variables. This means that both conky.config and conky.text can contain
variables instead of discrete values.
This allows things like constructing the final conky.config by joining
multiple Lua tables together, and concatenating strings into the final
conky.text. These variables are read only once after Conky is done evaluating
the entry script, so changing their values later will have no effect on
Conky's output/rendering.
As the main configuration file is a script, other scripts can be required at
the top of it.
After the main config file is evaluated, Conky will process the conky.config
value, and evaluate all files listed in lua_load.
Finally, if specified, the function named in lua_startup_hook will get called
(with the added conky_ prefix).
After that, Conky enters the draw loop where it continuously calls draw hooks
and draws the contents of previously stored conky.text.
When it receives a signal to close, the function from lua_shutdown_hook is
called. This function shouldn't be relied on to always run, as it will not be
called if Conky crashes or is abruptly terminated by the system. It can be used
to clean up resources or store some non-critical data however.
When passing data from one run to the next, the startup hook should always check whether data that was supposed to be provided by the shutdown hook is available.
At startup, Conky appends the following paths to LUA_PATH:
- XDG config directory (
~/.config/conky/?.lua) - Script parent directory (e.g.
./script/parent/directory/?.lua)
That means require will be able to locate any scripts that are next to the
used config file, as well as all scripts stored in the Conky XDG config
directory.