Skip to content

Using Lua scripts (Part 01): How does a lua script work

lasers edited this page Jan 5, 2019 · 3 revisions

About "Using Lua scripts"

This tutorial has been written by mrpeachy and was posted on Crunchbang, all credit goes to him. The tutorial was slightly adapted for Conky 1.10 and onwards. The Lua syntax did not change between Conky 1.9 and 1.10 so the scripts themselves are usable in both.

The tutorial could use a rewrite with proper punctuation and sometimes more explanation, if you feel like helping out please feel free to edit/expand this tutorial! Much appreciated.

The tutorial is friendly for people new to programming, besides this tutorial is a good starting point for those who want to learn to program in Lua.

i: How does a Lua script work?

In Conky there are several Lua related settings and objects. Two of them are necessary for a Lua script to work:

lua_load
lua_draw_hook

These configs should be put in the conky.config={ ... } section.

lua_load is pretty easy to understand, it gives Conky the location of the script it will use, e.g.

lua_load = '/home/username/scripts/script.lua'.

The second line lua_draw_hook (there are two kind of lua_draw_hook including lua_draw_hook_pre and lua_draw_hook_post) tells Conky which function to run from the Lua script that was loaded, where post and pre is indication for when those function is loaded.

This takes a little more explanation.


A bare bones Lua script for use in Conky might look like this.

--this is a lua script for use in conky
require 'cairo'

function conky_main()
    if conky_window == nil then
        return
    end
    local cs = cairo_xlib_surface_create(conky_window.display,
                                         conky_window.drawable,
                                         conky_window.visual,
                                         conky_window.width,
                                         conky_window.height)
    cr = cairo_create(cs)
    local updates=tonumber(conky_parse('${updates}'))
    if updates>5 then
        print ("hello world")
    end
    cairo_destroy(cr)
    cairo_surface_destroy(cs)
    cr=nil
end

to test this lua script add these lines into conky configuration file inside

conky.config = { ... } section

lua_load = "/path/to/luascript"
lua_draw_hook_post = "main"

Line by line we have:

--this is a lua script for use in conky

Anything preceded by -- is a comment in lua.

You can write a longer comment section starting with --[[ and ending with ]] like so:

--[[ this is a comment
and it can span multiple
lines until you end it with ]]

Next we have

require 'cairo'

This line loads cairo, which is a popular graphics library designed to draw graphical vectors to a screen. We use them in Conky to write anything (texts, drawings, etc.) via Lua scripts. Have a look at the Cairo samples for usage examples.

function conky_main()

This is our main function and the one we will set in the conkyrc for lua_draw_hook. If you open a Lua script and not sure which function to set in conkyrc, look for conky_ in the function name. This function is called again and again while Conky is open.


The next lines are standard setup lines and are ONLY required for the main function that will be called in the conkyrc:

    if conky_window == nil then
        return
    end
    local cs = cairo_xlib_surface_create(conky_window.display,
                                         conky_window.drawable,
                                         conky_window.visual,
                                         conky_window.width,
                                         conky_window.height)
    cr = cairo_create(cs)

The first three lines give a taste on Lua syntax. There's no brackets or parenthesis in an if statement, for example. Rather, the if block starts on then and ends on end.

The rest of the code are necessary for the drawing using cairo. This creates the "surface" onto which the text and graphics will be drawn. In this case, the surface will be the Conky window itself.


Lua scripts can also make use of Conky objects:

    local updates=tonumber(conky_parse('${updates}'))
    if updates>5 then
        print ("hello world")
    end

The function conky_parse does what it says it does: parses to our script a Conky object. Then we use the function tonumber because we want the number of updates to be a number. In the if statement, we say that after 5 Conky updates, we want to print "hello world". How much time it will take to print depends on the value of update_interval variable in the conkyrc file. If the interval is 1, it will take 5 seconds, if 2, 10, and so on.

NOTE: The print function only prints to the terminal (in the next tutorial we will see how to show into the Conky window), which makes a good debugging tool. You can use print to check what your Lua Script is really doing by executing the conkyrc on the terminal: conky -c [conkyrc file] and seeing the output in the terminal.

Notice that even though this part of the script is not inside of a loop, the value of updates still increments. That's because, as said before, the Lua script is executed in a loop by Conky.

Of course, these lines are only important if you plan on reading something that requires such handling of updates, like cpu%, in the Lua script. But it's generally a good idea to have these lines anyway (one less thing to cause an error).

With conky_parse, you can get the output of any Conky object into Lua this way):

cpu=conky_parse("${cpu}")
memory=conky_parse("${memperc}")
home_used=conky_parse("${fs_used /home}")

You can even use things like if_ objects from Conky using conky_parse, which can be useful as switches:

internet=conky_parse("${if_up wlan0}1${else}0${endif}")

Now internet will have a value of 1 or 0 depending on the outcome of if_up


Then we come to closing out the function

    cairo_destroy(cr)
    cairo_surface_destroy(cs)
    cr=nil

These lines do some clean up. One thing that Lua can do is to eat up memory over time, especially with memory leaks, and these lines help to avoid that. Be aware that your script can cause memory leaks. You can check if your script is causing that by checking the memory consumption as the time passes. If it's getting abnormally huge, then something is wrong. One (very cheap) workaround is killing the Conky processes and restarting it again.

You can’t perform that action at this time.