Using Lua scripts (Part 13): Useful functions and code - brndnmtthws/conky GitHub Wiki
xiii: Useful functions and code
In general I like to work out my own functions and write them myself, but sometimes its just easier to use existing functions that other people have made,
Here are some examples of function that I use regularly in scripts.
Split string function
function string:split (delimiter)
local result = {}
local from = 1
local delim_from, delim_to = string.find (self, delimiter, from)
while delim_from do
table.insert (result, string.sub (self, from , delim_from - 1))
from = delim_to + 1
delim_from, delim_to = string.find (self, delimiter, from)
end
table.insert ( result, string.sub (self, from))
return result
end
This function takes a string and splits it up at a given delimiter then puts all the pieces into a table.
You put this function into your Lua script (either above the main function, or below (which will work due to the way Conky and Lua work together)).
In the main function you use it like this:
text_string = "this is some text I want to split up into individual words"
split_table = string.split (text_string," ")
So, text_string
contains the stuff we want to split up.
split_table
is the name of the table that we will be putting the pieces into.
string.split ()
is how we call the function.
This looks a little bit different from how we have called functions in the past: the function itself is set up a little differently too, but it works!
Then inside the ()
we send the function the information it needs.
First the string we want to split up (text_string
, " ") then the
delimiter, the place at which we want to split the string. In this
case I have set a single space (text_string, " "
).
You can use anything you like to split the string up.
So what you get is a table called split_table
which looks like this.
split_table = {
"this",
"is",
"some",
"text",
"i",
"want",
"to",
"split",
"up",
"into",
"individual",
"words",
}
So we can access each entry in the table individually, for example:
print (split_table[1]) --> "this"
print (split_table[6]) --> "want"
This has a great number of applications.
Color conversion function
Lua uses RGBA values to set colors like so: cairo_set_source_rgba (cr, 1, 1, 1, 1)
.
Each number in the ()
brackets is between 0 and 1 so in this case 1,
1, 1, 1 will give me fully opaque white.
BUT if you are more familiar with setting colors with hexidecimal values then you need to convert the hexidecimal values to RGBA values.
You can do it using this function:
function color_convert (c, a)
return ((c / 0x10000) % 0x100) / 255, ((c / 0x100) % 0x100) / 255,
(c % 0x100) / 255, a
end
There are several variations of this function floating around. As with all functions, put it in the script outside of the main function, either above or below. Just remember that it is only due to the way that Conky and Lua work together that you can have function below the main function. If you ever write a standalone Lua script (I do this as an alternative to bash scripts) then you HAVE to define your functions BEFORE they are used, ie ABOVE.
There are a few different ways you can use this:
hex_color = 0xffffff
alpha = 1
red, green, blue, alpha = color_convert (hex_color, alpha)
cairo_set_source_rgba (cr, red, green, blue, alpha)
Sometimes breaking code up into steps like above can be helpful.
NOTE on red, green, blue, alpha = color_convert (hex_color, alpha)
. Lua has the ability to return multiple values from the same
function. In this case the colorconvert funtion is returning 4 values,
so we need to set 4 strings to accept those values.
When we do this we get the string set in the same order that they are returned:
For example, you have in your function:
function number ()
return 1, 2, 3, 4
end
And you call it like this:
one, two, three, four = numbers ()
print (one) --> 1
print (three) --> 3
two, three, one, four = numbers ()
print (one) --> 3
print (three) -->2
HOWEVER, you could do the same thing in fewer lines like this:
cairo_set_source_rgba (cr, color_convert (0xffffff, 1))
. In this case
the returned vales are being fed directly to the color setting
function.
Image display function
function image (im)--
x = nil
x = (im.x or 0)
y = nil
y = (im.y or 0)
w = nil
w = (im.w or 0)
h = nil
h = (im.h or 0)
file = nil
file = tostring (im.file)
if file == nil then print ("set image file") end
---------------------------------------------
local show = imlib_load_image (file)
if show == nil then return end
imlib_context_set_image (show)
if tonumber (w) == 0 then
width = imlib_image_get_width ()
else
width = tonumber (w)
end
if tonumber (h) == 0 then
height = imlib_image_get_height ()
else
height = tonumber (h)
end
imlib_context_set_image (show)
local scaled = imlib_create_cropped_scaled_image (0, 0,
imlib_image_get_width (), imlib_image_get_height (), width, height)
imlib_free_image ()
imlib_context_set_image (scaled)
imlib_render_image_on_drawable (x, y)
imlib_free_image ()
show = nil
end
You use it like this: image ({x = 100, y = 100, h = 50, w = 50, file = "/home/username/cute_puppy.png"})
.
when I was writing this function I wanted the input part to be as streamlined as possible, and I also wanted the ability to set default values so that you dont have to enter every setting every time you wanted to display an image.
To achieve this, you need to set and send a TABLE, and this is what
I am doing by using the curly brackets {}
inside the curved brackets
()
.
This also means that you DONT have to enter the values in any
particular order either, ie image ({x = 100, y = 100, h = 50, w = 50, file = "/home/username/cute_puppy.png"})
does the same thing as:
image ({file = "/home/username/cute_puppy.png",h = 50, x = 100, y = 100, w = 50})
.
NOTE, the function contains these lines:
function image (im)
x = nil
x = (im.x or 0)
y = nil
y = (im.y or 0)
w = nil
w = (im.w or 0)
h = nil
h = (im.h or 0)
file = nil
file = tostring (im.file)
So everything you send the function is received by the function and put as separate entries in a table called "im". If we sent the info as described above and were then to look in the table "im" we would see this:
im = {
x = 100,
y = 100,
h = 50,
w = 50,
file = "/home/username/cute_puppy.png"
}
So im is a dictionary-type table and we can access dictionary type tables in a couple of ways. In this case I am accessing the info using this method:
table_name.
entry_in_table.
So to get the vale of x that we set in the main function when we called the function:
x_value = im.x
print (x_value) --> 100
Also note that i am doing this:
x = nil
x = (im.x or 0)
Setting x = nil
is just a kind of maintenance line to catch and
remove any other values of x that might be floating around in Lua
space.
THEN (and this is a handy trick i picked up recently), x = (im.x or 0)
.
Which does the following ...
- Checks the table "im" for a value for x.
- If the table has an x value set in it then, set a string within the function called "x" that equals the value of x in table "im".
- If there is NOT an entry for x in table "im", then
im.x
will returnnil
and if this is the case then x is set to 0.
This is where the defaults can be used; so when I call the function, say I want my image to be set to coordinates 0, 0 (I have the same lines for y as for x in the function) then I wouldn't need to enter a value for x.
image ({h = 50, w = 50, file = "/home/username/cute_puppy.png"})
.
I sey the table to the function, the table gets read, there is no values for x or y so the script sets x both to 0.
Text output
I also wanted to streamline the output of text onto the Conky display
function out (tx)--
c = nil
c = (tx.c or 0xffffff)
a = nil
a = (tx.a or 1)
f = nil
f = (tx.f or "mono")
fs = nil
fs = (tx.fs or 12)
x = nil
x = (tx.x or 0)
y = nil
y = (tx.y or 0)
txt = nil
txt = (tx.txt or "set txt")
local function col (c, a)
return ((c / 0x10000) % 0x100) / 255,((c / 0x100) % 0x100) / 255,
(c % 0x100) / 255, a
end
cairo_select_font_face (cr, f, CAIRO_FONT_SLANT_NORMAL,
CAIRO_FONT_WEIGHT_NORMAL);
cairo_set_font_size (cr, fs)
cairo_set_source_rgba (cr, col (c, a))
cairo_move_to (cr, x, y)
cairo_show_text (cr, txt)
cairo_stroke (cr)
end
Called like this in the main function: out ({x = 10, y = 10, c = 0xffffff, a = 1, f = "mono",fs = 12, txt = "hello world"})
.
It works in a very similar way to the image function you only need to set those values that are different from the defaults.
NOTE: I am using the color conversion function (I called it "col" for brevity) that I described earlier in the out () function. However, I am using it as a local function, a function that is only available to the function which contains it. I put in the color conversion function as a local function in the out () function so that it would always be there and I wouldn't have to remember to put in 2 separate function every time I wanted to use out ().
Think of it like a dependency out () requires the ability to use the col () function. I could put the col function as a separate function in the script and use it that way BUT if I were to forget to put the col function in then I would get errors.
OK, thats it for this section.