Skip to content

How to Load and Use Lua Scripts

Tin Švagelj edited this page Feb 3, 2025 · 1 revision

Using Lua Scripts in Conky

This tutorial was originally written by mrpeachy and posted on Crunchbang. It has been updated and modified over time by various contributors. While Lua syntax is backwards compatible with older Conky versions, the configuration structure evolves over time as new functionality is added and things get rewritten. Most scripts will, however, continue working across versions - the only thing that might change are requires and some conky specific functions (in case variables are deprecated).

If you spot areas that could use clearer explanations or improved formatting, feel free to contribute and enhance this tutorial!

Introduction

This guide is designed for beginners with little to no programming experience. It also serves as a good starting point for those interested in learning Lua. Lua does provide it's own manual, so if you feel like you don't understand some bits take a look at it as well.

Lua is one of the simplest scripting languages out there. It's got some minor quirks (like 1-based array indexing), but it should be really easy to understand to most digitally literate people.


1. Loading Lua scripts

To integrate Lua scripts into Conky they have to be loaded using lua_load in the the conky.conf file:

conky.config = {
  lua_load = "path/to/script.lua"
  -- other setings
}

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"). It can also be an absolute path, (e.g. lua_load = "/home/username/scripts/script.lua").

Multiple files may be loaded - to do so semicolon (;) can be used as a 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 package vendor).

Lua File Placement

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 file can be read by Conky. For details on Linux file permissions check out this useful guide by Red Hat.


2. Lua Hooks

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 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 the hook, it's necessary to specify the function name as hook value. For instance:

conky.config = {
  lua_load = "script.lua",
  -- other settings
  lua_draw_hook_post = "main",
}

IMPORTANT: Name of the function in the Lua file is prefixed with

List of Common Lua Hooks

For drawing, most important hooks are lua_draw_hook_*, these allow a Lua script to present information in the Conky window:

  • lua_draw_hook_pre: Runs the function before main content (specified in conky.text block) is drawn.
    • intended for drawing background graphics that should be located below any other text.
  • lua_draw_hook_post: Runs the function after the Conky window is drawn.
    • intended for drawing over everything else.

Note that drawing functionality can be disabled at compile time. If installed conky version doesn't have drawing capabilities, draw hooks will do nothing. Some distributions offer various flavors of conky with different settings, so make sure to pick the appropriate one. Check your Linux distribution's documentation for installation instructions.

Conky also provides some additional hooks which might be useful for specific use cases:

  • lua_startup_hook: Runs once when Conky starts.
    • intended for collecting immutable system data or preconfiguring some 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 for conky or from the startup hook.
  • lua_mouse_hook: Captures mouse events within the Conky window. Covered in detail in Mouse Events section.
    • intended for adding interactivity to Conky. As Conky runs in a separate background layer, some mouse events might not be reported the best by X11.

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 meantime, or create a feature request.


3. Writing a Basic Lua Script

Let's go step by step through a simple Lua script and explain what each part does before presenting the final code.

3.1. Adding Required Libraries

At the top of the script, it's necessary to load external libraries:

require("cairo")
require("cairo_xlib")

In this case, cairo loads bindings from the Cairo library which is used for rendering in Conky. cairo_xlib is needed to create drawing surfaces on X11.

Other bindings like rsvg add their own libraries that can be required from Lua. Check the appropriate wiki pages for those.

3.2. Defining the Main Function

Previously set lua_draw_hook_post = "main" will expect a conky_main function to be defined in one of lua_loaded files. Missing this will cause warnings/errors, so let's define that function:

function conky_main()
  -- executed Lua code goes here
end

Some hooks might provide some data to the functions. If that data isn't used, the variables can be omitted because Lua doesn't care about number of provided/used arguments - if arguments aren't provided when the function is called, the value will simply be nil.

Arguments are simply a list of names:

function my_function(first, second)
end

For more details on function signatures, refer to the Lua manual.

3.3. Ensuring Conky Window Exists

Conky might try updating window content before the window has been created because window management is handled by WMs. Because windows can be a bit unpredictable at times (they get recreated), it's good practice to check whether a window currently exists from window related hooks:

if conky_window == nil then
    return
end

Not doing so might cause errors in some cases, depending on WMs, luck, current phase of the moon and star alignments.

3.4. Creating the Drawing Surface

All drawing in Cairo happens on a surface. Now that we're certain conky_window exists, values from it can be used for creation of Cairo surface:

local cairo_surface = cairo_xlib_surface_create(
    conky_window.display,
    conky_window.drawable,
    conky_window.visual,
    conky_window.width,
    conky_window.height
)
local c = cairo_create(cairo_surface)

cairo_surface is just a handle to the surface and will only be needed for proper cleanup later. c is used for all the drawing. It's common to give it a short name like c or ctx because writing something like cairo_drawing_context a lot can be tedious and hard to read.

3.5. Using Conky Variables in Lua

Conky provides a lot of variables in conky.text that will likely end up being useful from Lua code too. conky_parse is used to evaluate Conky variables. It processes any text that can go into conky.text and returns the evaluated result as a string.

Any Conky variable can be used:

cpu_usage = conky_parse("${cpu}")
memory_used = conky_parse("${memperc}")
disk_space = conky_parse("${fs_used /home}")

It can also evaluate more complex expressions:

network_status = conky_parse("${if_up wlan0}Online${else}Offline${endif}")

For this introduction, we'll be using updates variable which simply returns the number of times conky has updated its window (redrawn contents). How often the draw function is called, i.e. the delay between updates depends on update_interval setting.

In order to make conky print a message to the console after 5 updates, we can use something like:

local updates = tonumber(conky_parse("${updates}"))
if updates > 5 then
    print("conky_main counted >5 updates to its window")
end

Lua function tonumber simply parses the returned string value into a number. This will be necessary to handle numeric values correctly in most cases, so keep it in mind.

3.6. Cleaning Up Resources

Most bindings require you to clean up resources at the end. Not doing so will cause conky to consume more and more memory over time (a memory leak), but other than that isn't really that dangerous.

cairo_destroy(c)
cairo_surface_destroy(cairo_surface)

When and what you need to clean up depends on what's being used. But for Cairo, the above functions should be called (with appropriate variables) at the end of the draw hooks.


4. Complete Example Lua Script (script.lua)

Now that each part is explained, here is the complete script:

-- ~/.config/conky/script.lua

require("cairo")
require("cairo_xlib")

function conky_main()
    if conky_window == nil then
        return
    end
    
    local cairo_surface = cairo_xlib_surface_create(
        conky_window.display,
        conky_window.drawable,
        conky_window.visual,
        conky_window.width,
        conky_window.height
    )
    local c = cairo_create(cairo_surface)
    
    local updates = tonumber(conky_parse("${updates}"))
    if updates > 5 then
        print("conky_main counted >5 updates to its window")
    end
    
    cairo_destroy(c)
    cairo_surface_destroy(cairo_surface)
end

This script checks the update count and prints debug information to the console after 5 updated. Not the most exciting thing in the world, but you're ready to level-up to more advanced topics now.

Happy scripting!

Clone this wiki locally