SEARCH

Enter your search query in the box above ^, or use the forum search tool.

You are not logged in.

#1 2012-01-17 17:59:29

mrpeachy
20% cooler
From: The Everfree Forest
Registered: 2009-11-08
Posts: 3,460

HOW TO : using lua scripts in conky

Using Lua scripts in conky
this how to is based on what i know... not what is known big_smile

part 1 - how does a lua script work
this post!

part 2 - displaying text and working with colors
http://crunchbanglinux.org/forums/post/180248/#p180248

part 3 - drawing lines
http://crunchbanglinux.org/forums/post/180359/#p180359

part 4 - drawing rectangles, cirlces and arcs
http://crunchbanglinux.org/forums/post/180388/#p180388

part 5 - making a bar meter and a circle meter
http://crunchbanglinux.org/forums/post/180661/#p180661

part 6 - some more drawing calculations and introduction to IF's
http://crunchbanglinux.org/forums/post/180798/#p180798

PART 7 -  adding our alarm color change feature and looking at more complex if statements
http://crunchbanglinux.org/forums/post/181076/#p181076

PART 8 - turn our code into a function
http://crunchbanglinux.org/forums/post/181338/#p181338

PART 9 – sending information to functions
http://crunchbanglinux.org/forums/post/181629/#p181629

PART 10, sending info to functions using tables
http://crunchbanglinux.org/forums/post/183756/#p183756

Part 11a FOR LOOPS and A CPU HISTORY CHART
http://crunchbanglinux.org/forums/post/184830/#p184830

Part 11b CPU HISTORY CHART CONTINUED
http://crunchbanglinux.org/forums/post/185253/#p185253

Part 11c DRAWING THE CPU HISTORY DATA
http://crunchbanglinux.org/forums/post/185753/#p185753

Part 12a DRAWING A CLOCK and circular things
http://crunchbanglinux.org/forums/post/186112/#p186112

Part 12b CLOCK CONTINUED
http://crunchbanglinux.org/forums/post/186159/#p186159

Part 13 USEFUL FUNCTIONS AND CODE
http://crunchbanglinux.org/forums/post/202466/#p202466

Part 14 RUNNING CLI COMMANDS, TIMERS AND LINE EDITING
http://crunchbanglinux.org/forums/post/256172/#p256172

Part 14.b LINE EDITING CONTINUED and READING OUTPUT LINE BY LINE
http://crunchbanglinux.org/forums/post/256260/#p256260

Part 14.c GETTING DATA FROM WEB PAGES
http://crunchbanglinux.org/forums/post/256302/#p256302
-----------------------------------------------------------------------------------------------

PART 1 how does a lua script work?

in conky there are several lua related settings and objects
primarily for using lua script there are 2 settings

lua_load
lua_draw_hook

that come before TEXT

lua_load is where you give conky the location of the script to use
eg
lua_load /home/username/scripts/script.lua
so that one is pretty easy to understand

the second line
lua_draw_hook (can be lua_draw_hook_pre or lua_draw_hook_post)
tells conky which function to run from the lua script that was 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-- if updates>5
cairo_destroy(cr)
cairo_surface_destroy(cs)
cr=nil
end-- end main function

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'
cairo is the name of the graphics library that lua will be using to get all those fancy graphics showing up in conky
this line loads up that library
then
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

the next 3 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)

This is creating the "surface" onto which the text and graphics will be drawn.  If you want the lua script to draw anything to conky you need these setup lines.

then we have lines about conky updates

local updates=tonumber(conky_parse('${updates}'))
if updates>5 then

these lines are only important if you plan on reading cpu% in the lua script, but its generally a good idea to have these lines anyway (one less thing to cause an error)
NOTE if you are not going to be using conky_parse("${cpu}") then by all means remove these lines
BUT if you remove the line that says "if updates>5 then" you MUST also remove the matching "end" from lower down in the script.  This is why i like to comment what my ends are ending big_smile

end-- if updates>5

this lines

local updates=tonumber(conky_parse('${updates}'))

has a few important things to note about it...
1. the term "local" at the beginning (i'll cover that later)
2. the use of strings and the = sign

in lua you hold information in strings by saying:
string = information
information can be other strings, plain text, numbers etc (more about that later)
eg

string1=5
string2=9
string3=string1*string2

in this case string3 holds the value 45
string names cannot start with numbers and cannot contain spaces
if a string lower down in the script has the same name as higher, the info in the first string just gets overwirtten
eg

string1=7
print (string1) --> 7
string1=9
print (string1) --> 9

3. the use of tonumber
if you want lua to do calculations or comparisons based on a number, it can be a good idea to make sure you are setting a string as a number by using tonumber(), particularly when you are taking numbers generated by conky objects or from other means.  Just because the output of a conky object is a number DOES NOT mean that when it is set to a string lua will recognise it as a number!  It can be a big pain to go tracking down an error to realise it was because the script was not setting an output as a number

4. the use of conky_parse
you can get the output of any conky object into lua this way
eg

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 the string "internet" will have a value of 1 or 0 depending on the outcome of if_up

next line in our lua is
if updates>5 then

this if statement is closed lower in the script by an end

end-- if updates>5

i always like to comment about what exactly the "end" ends as in many script the end that closes out "if updates>5 then" can be tricky to pick out and can be a long way down the script

what we are saying is if updates (the value of which is set with conky_parse) is greater than 5 then do everything between the "then" and the closing "end"

missing ends can be a pain to locate
every "if" "for" "while" or other loop needs a matching end to close it!

NOTE the value of updates is the number of times that conky has updated as set by this line in your conkyrc

update_interval 1

because it was set using conky_parse to read the conkt object ${updates}

so if you have your interval set to 1 (ie every second), you are going to wait 6 seconds from the time conky starts to the time you see anything from lua if you are using the "if updates>5" line

if update_interval was 10, you would be waiting 60 seconds

clearly you don't want to wait that long to see your lua

later on I'll deal with executing commands in lua (analogous to exec or execi in the conkyrc)
there we will see the use of the conky update interval as a timing mechanism and in that case we can think in more detail about how conkyrc update_interval and the lua script interact

so next we have the body of the script, the stuff we want the lua script to do

--##############################
print ("hello world")
--##############################

i like to use obvious comment lines to differentiate between the setup parts of the functions and the the body of the functions so that i can navigate easier smile

the command "print ()" will not show anything up in conky, but will be printed in the terminal
always run conky from the terminal when testing out a lua script!
print ()
can be a very useful way of finding error in the script if things aren't working

then we come to closing out the function

end-- if updates>5
cairo_destroy(cr)
cairo_surface_destroy(cs)
cr=nil
end-- end main function

these lines close out the if function and do some cleaning up
one thing that lua can do is to eat up memory over time
these lines help to avoid that.
the final end ends the main function and your done.

I have a script named blank.lua which is just that, a script set up with an empty main function, so i don't have to remember to type out all the setup lines each time big_smile

NOTE about writing the code
remember! any examples i write are writte as if i were writing a real script
(in fact as i go on i'll check my code examples to make sure they really do what i say they do smile )
this is how I write my code
one point to make in particular is about the use of spaces in the code
as you can see, i like to write everything tight together

red,green,blue,alpha=1,1,1,1

and use few spaces
but in fact lua is very versatile/forgiving in terms of spaces and tabs

for example

value=16
print (value) -->16
value = 16--with spaces
print (value) -->16
value    =    16--tabbed
print (value) -->16
    value    =                     16--any kind of spacing you want
print (value) -->16

this also applies to things like the rectangle command

cairo_rectangle (cr,50,50,60,40)
cairo_rectangle (cr, 50 ,50 ,60 ,40 )
    cairo_rectangle     (cr,     50 ,    50 ,60         ,40 )

all give you the same rectangle

however, its always a good idea to keep things neat and tidy!

Last edited by mrpeachy (2012-11-06 21:19:56)

Offline

Be excellent to each other!

#2 2012-01-17 18:25:52

rhowaldt
#!*$%:)
Registered: 2011-03-09
Posts: 4,396

Re: HOW TO : using lua scripts in conky

that is very peachy Mr Peachy! great how-to which will doubtlessly be useful to many a Conky-warrior.

Offline

#3 2012-01-17 18:26:23

mrpeachy
20% cooler
From: The Everfree Forest
Registered: 2009-11-08
Posts: 3,460

Re: HOW TO : using lua scripts in conky

PART 2 displaying stuff in conky

so we have a blank main function
we can set up our conkyrc to point to the script location with lua_load
and we can activate the main function through lua_draw_hook

BUT we need something inside our lua function for conky to show!

what can lua display in conky?
really 1 of 2 things
1. text
2. graphics
    such things as
    lines
    boxes
    bars
    circles
    etc

lets look at how to get text onto the screen
first, any plain text within the lua script must be contained within quotes "plain text"
you can set strings to contain plain text like so

text="hello world"
print (text) --> hello world (in terminal)

i like to do things in a "modular" way
that is set everything to strings, then use those strings within the code
I find this is easier to keep track of variables but is not necessary

so i want to display the text "hello world" in conky...
here are the lines to do it

font="Mono"
font_size=12
text="hello world"
xpos,ypos=100,100
red,green,blue,alpha=1,1,1,1
font_slant=CAIRO_FONT_SLANT_NORMAL
font_face=CAIRO_FONT_WEIGHT_NORMAL
----------------------------------
cairo_select_font_face (cr, font, font_slant, font_face);
cairo_set_font_size (cr, font_size)
cairo_set_source_rgba (cr,red,green,blue,alpha)
cairo_move_to (cr,xpos,ypos)
cairo_show_text (cr,text)
cairo_stroke (cr)

you can see i set anything that might change to strings first, then used the strings within the code
but it would work exactly the same way like this

cairo_select_font_face (cr, "mono", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
cairo_set_font_size (cr, 12)
cairo_set_source_rgba (cr,1,1,1,1)
cairo_move_to (cr,100,100)
cairo_show_text (cr,"hello world")
cairo_stroke (cr)

with all the settings typed directly into the code
NOTE
when i write lua scripts i usually stick to having one line do one things but you don't have to
you can use a semi colon ; to separate operations on the same line for example

cairo_move_to (cr,100,100);cairo_show_text (cr,"hello world");cairo_stroke (cr)

but i find that this can make things harder to navigate when looking back through the script to track down an error for example

using either of the above code examples  we are going to:
- print "hello world"
- in white
- using the mono font
- at font size 12
- at coordinates 100,100
- normal face and slant (ie not bold or italic)

but lets look closer at what and how those things are set.

font names must be set within quotes
but note in the first example, once the font has been set to a string, the string itself is called without quotes

the same goes for plain text which must also be in quotes

numbers do not require quotes as for font_size

another thing to note is how i have set my strings
xpos,ypos=100,100
i have set 2 different strings in the same line by using commas to separate them
this is exactly the same as writing

xpos=100
ypos=100

the same goes for setting the color
red,green,blua,alpha=1,1,1,1
is the same as

red=1
green=1
blua=1
alpha=1

either way is just as good

NOTE
if you are thinking of later on making a setup section in a different area of the script (at the top most likely)
then you will have to use the string setting method and you might also want to make your string names unique

if you remember, strings with the same names simply overwrite each other base on where they appear in the script
so go for
text_1="hello world" instead of simply text="hello world"

x and y
when it comes to setting x and y values for text, the point you set will be the coordinates of the bottom left corner of the text
and is set relative to the top and left edges of the conky window

so x,y=100,100 will move 100 pixels down from the top of the window, 100 pixels across from the left
then it will display the text above and to the right of that point

color lua requires values for red green blue and alpha
these values are all in the range of 0 to 1

So how do you get your values?

in many script, you may see a separate function to turn hexadecimal color codes into rgba values
I'll discuss other function in a separate part of the guide so for now lets look at the direct way.

For example, you can open up gimp and use it to get a color you like:
screenshotfedbe72853dc84448e6e966cfce4ceee.png
here ive picked an orangey color and you can see in the window the various values for the color
for this purpose look at the RGB values
R = 246
G = 155
B = 11
these are almost the values we want, but instead of being between 0 and 1 they are between 0 and 255

one of the advantages of script is that you can do calculations, and in lua you can set a string to be the result of a calculation
so we can set something like this to get our values in the correct range (0 to 1)

red=246/255
green=155/255
blue=11/255

alpha is a little different, simply an alpha of 0 is fully transparent, ie you wont see anything
and an alpha of 1 == fully opaque, so set whatever value you want

finally for font_face and font_slant

font_slant=CAIRO_FONT_SLANT_NORMAL
font_face=CAIRO_FONT_WEIGHT_NORMAL

these do not need to be set within quotes
face can be NORMAL or BOLD
slant can be NORMAL or ITALIC

EXAMPLE
we want to display our cpu usage percent in conky via a lua script
to show

cpu usage: 23%

(or whatever cpu% is at the time)

1.  we use conky_parse to get the cpu number
remember that the string names i am using are just my examples, you can call them whatever

cpu_perc=conky_parse("${cpu}")

but our string "cpu_perc" is only the number value from conky, we need to add the other parts

there are several ways to do this but probably easiest is to "stitch together" (or concatenate to be technical)
the various elements we need.  Like this:

cpu_text="cpu usage: "..cpu_perc.."%"

we are stitching some plain text "cpu usage: " to the string that contains the cpu value we want (cpu_perc) and ending with some more plain text "%"
the use of a double period is how we put these elements together

NOTE say you only wanted the number followed by the percent you would do it like this

cpu_text=cpu_perc.."%"

there are more complex ways to use text but again for later

Last edited by mrpeachy (2012-11-09 05:58:35)

Offline

#4 2012-01-17 20:10:20

mrpeachy
20% cooler
From: The Everfree Forest
Registered: 2009-11-08
Posts: 3,460

Re: HOW TO : using lua scripts in conky

thanks rhowaldt, hopefully someone will find it useful!

and if im being too simplistic or not explaining things as full enough to make sense let me know!

Last edited by mrpeachy (2012-01-17 20:31:04)

Offline

#5 2012-01-17 22:52:03

mrpeachy
20% cooler
From: The Everfree Forest
Registered: 2009-11-08
Posts: 3,460

Re: HOW TO : using lua scripts in conky

Part 3 - graphics

how to draw a straight line!
so one of the basic things to be able to do is to draw a line
there are several commands we need to consider for lines

line thickness

cairo_set_line_width (cr,1)

NOTE, you can see here, and in other examples the general form that the cairo commands take
cairo_something (cr,settings)
we set the value of cr in our main function setup lines, and every time you use a cairo command, the first thing within the curved brackets will be "cr"

line end cap

cairo_set_line_cap  (cr, CAIRO_LINE_CAP_BUTT)
or
cairo_set_line_cap  (cr, CAIRO_LINE_CAP_ROUND)
or
cairo_set_line_cap  (cr, CAIRO_LINE_CAP_SQUARE)

see here for more info
http://cairographics.org/samples/set_line_cap/

the default is BUTT, so that is what you get if you don't setup the cap type

and then commands we have seen before

cairo_set_source_rgba (cr,1,1,1,1)

and we need to specify where the line is going to start

cairo_move_to (cr,100,100)

we could do our setup like we did for our text

line_width=1
line_cap=CAIRO_LINE_CAP_BUTT
red,green,blue,alpha=1,1,1,1
startx=100
starty=100
----------------------------
cairo_set_line_width (cr,line_width)
cairo_set_line_cap  (cr, line_cap)
cairo_set_source_rgba (cr,red,green,blue,alpha)
cairo_move_to (cr,startx,starty)

now we need to draw the line and there are 2 ways to do it
you can specify the ending coordinates directly

cairo_line_to (cr,200,100)

or you can specify where the line should go relative to the start

cairo_rel_line_to (cr,100,0)

in this case we get the same result...
in the first example we start at 100,100 and tell cairo to draw a line to 200,100

in the second example we start at 100,100 and tell cairo to draw a line to a point 100 pixels to the right of where we started and 0 pixels down from where we started

so both examples will give a horizontal line 100 pixels long

once we have finished specifying the coordinates we then tell cairo to actually draw the line

cairo_stroke (cr)

i tend to use the absolute method, "line_to" rather than the relative method
so altogether:

line_width=1
line_cap=CAIRO_LINE_CAP_BUTT
red,green,blue,alpha=1,1,1,1
startx=100
starty=100
endx=200
endy=100
----------------------------
cairo_set_line_width (cr,line_width)
cairo_set_line_cap  (cr, line_cap)
cairo_set_source_rgba (cr,red,green,blue,alpha)
cairo_move_to (cr,startx,starty)
cairo_line_to (cr,endx,endy)
cairo_stroke (cr)

NOTE about line thickness
we set a line from 100,100 to 200,100 but setting a line thickness greater than 1 will affect not only what the line looks like but where it appears to have been drawn
if we set, for example, a line width of 10, then the line will be 5 pixels wide to one side of the base line, and 5 pixels wide to the other side

that is, the top left corner of the line will actually be at 100,95 and the bottom left corner at 100,105 (remember that the larger the x and y numbers the more right and down they are)
- the line will be more of a rectangle.

making the line more interesting
but with some math and tweaking we can easily make this line change in length relative to a conky object

once you get the idea of using variables and strings to affect the coordinates and other values of drawn objects then you are a good way there and everything else is just the complexity of the interactions and what is being drawn

for example we want to make a cpu usage indicator line

cpu_perc=tonumber(conky_parse("${cpu}"))

i'll use tonumber just to make sure... it can be easy to get lost in curved brackets when using compound commands like this smile

this will output a number between 0 and 100
the line we have already drawn is 100 pixels long so its easy enough to do the following

cpu_perc=tonumber(conky_parse("${cpu}"))
line_width=1
line_cap=CAIRO_LINE_CAP_BUTT
red,green,blue,alpha=1,1,1,1
startx=100
starty=100
endx=startx+cpu_perc
endy=starty
----------------------------
cairo_set_line_width (cr,line_width)
cairo_set_line_cap  (cr, line_cap)
cairo_set_source_rgba (cr,red,green,blue,alpha)
cairo_move_to (cr,startx,starty)
cairo_line_to (cr,endx,endy)
cairo_stroke (cr)

this is what is going to make the line move
endx=startx+cpu_perc
the horizontal end point of my line will change in relation to the value of cpu_perc as measure through the conky variable ${cpu}

ive made a couple of other changes...
instead of saying "endx=100+cpu_perc" i have put "endx=startx+cpu_perc"

and instead of "endy=100" i have "endy=starty"

using this method, all i have to do is edit startx and starty and those changes will follow on to the other strings

when i am writing scripts i find it time saving to set as few "absolute" vales as possible
gives you less things to find later on when you want to make changes

you can do more with lines than just draw lines

you can use lines to draw shapes
you can then have these shapes as outlines or fill them in

a triangle for example
there are some other things to consider when using multiple lines
one thing is how to join the lines together
which is set by the following

cairo_set_line_join (cr, CAIRO_LINE_JOIN_MITER)
or
cairo_set_line_join (cr, CAIRO_LINE_JOIN_BEVEL)
or
cairo_set_line_join (cr, CAIRO_LINE_JOIN_ROUND)

see here for more details
http://cairographics.org/samples/set_line_join/

MITER is the default so that is what you get when you dont set line join type

we can also use this command

cairo_close_path (cr)

close path tells cairo that the lines should be joined together at the ends to make one continuous line

this is what you get without close_path on the left and with close_path on the right
this is using the default MITER line join also
screenshotd1385fb1f682885980eb5c32de2d92db.png

NOTE
as soon as you set cairo_close_path the setting for line cap type becomes redundant, as there are no longer any line ends

here is the code for the figure on the right above

line_width=20
line_cap=CAIRO_LINE_CAP_BUTT --we don't need this anymore after closing the path
line_join=CAIRO_LINE_JOIN_MITER --but this will still affect how the lines look
red,green,blue,alpha=1,1,1,1
startx=100
starty=100
pointx=startx+100
pointy=starty+100
endx=pointx-100
endy=pointy
----------------------------
cairo_set_line_width (cr,line_width)
cairo_set_line_cap  (cr, line_cap)
cairo_set_source_rgba (cr,red,green,blue,alpha)
cairo_move_to (cr,startx,starty)
cairo_line_to (cr,pointx,pointy)
cairo_line_to (cr,endx,endy)
cairo_line_to (cr,startx,starty)
cairo_set_line_join (cr, line_join)
cairo_close_path (cr)
cairo_stroke (cr)

NOTE
as you can see, you don't have to draw each individual line as you are instead drawing a "path" (imagine a pen being drawn on paper in one continuous line from point to point)

you only need to use cairo_stroke at the end to draw along the path you set to see the lines

it is also good to know that by using the close_path command we don't actually need to draw the third side of the triangle.  When you use close_path cairo will draw a line from wherever you stop back to the start.

if we want to fill in the triangle we use

cairo_fill (cr)

instead of

cairo_stroke (cr)

but with cairo_fill the setting for line width no longer applies. 
also with fill the line join type no longer applies

The fill fills in only the triangle bound by the coordinates we set. 

ALSO with cairo_fill, we need not use the close_path command, as the fill command will automatically close the path in order to generate a boundary area to fill in... but it never hurts to use the close_path command and nothing bad will happen if you set redundant commands big_smile

for example i could specify all 3 sides of the triangle, close_path and then cairo_fill and i will still get a filled in triangle!   lua code can be quite forgiving

here is stroke vs fill
screenshot74ce64e8f05b1e53d368b432f26b8d97.png

and if you want the shape outlined and filled (for example in different colors)
we would first use cairo_fill_preserve (instead of just cairo_fill), then set our second color and use cairo_stroke to draw the outline

cairo_set_line_width (cr,20)
cairo_move_to (cr,100,100)--start point
cairo_line_to (cr,200,200)--diagonal line down
cairo_line_to (cr,100,200)--horizontal line 
cairo_close_path (cr)--draws vertical line back to start
cairo_set_source_rgba (cr,1,1,1,1)--white
cairo_fill_preserve (cr)--fills in the triangle in white
cairo_set_source_rgba (cr,1,0,0,1)--red
cairo_stroke (cr)--draws the triangle outline in red

Last edited by mrpeachy (2012-01-18 02:41:22)

Offline

#6 2012-01-17 23:48:43

VastOne
#! Ranger
From: #! Fringe Division
Registered: 2011-04-26
Posts: 10,163
Website

Re: HOW TO : using lua scripts in conky

I solemnly swear to read all of this and absorb it.... My first new years resolution!

Nice work mrpeachy!


VSIDO | SolusOS

Words That Build Or Destroy

Offline

#7 2012-01-18 00:40:19

mrpeachy
20% cooler
From: The Everfree Forest
Registered: 2009-11-08
Posts: 3,460

Re: HOW TO : using lua scripts in conky

VastOne wrote:

I solemnly swear to read all of this and absorb it.... My first new years resolution!

Nice work mrpeachy!

well ive only begun to scratch the surface!
whose idea was this thread anyway?? big_smile

Offline

#8 2012-01-18 00:54:56

falldown
#! Samurai
Registered: 2011-09-01
Posts: 1,726

Re: HOW TO : using lua scripts in conky

Printed this 6 page monster out!!

Offline

#9 2012-01-18 00:57:41

VastOne
#! Ranger
From: #! Fringe Division
Registered: 2011-04-26
Posts: 10,163
Website

Re: HOW TO : using lua scripts in conky

@ Mr P - I believe Sector11 took sole responsibility and ownership of pushing you down this highway!


VSIDO | SolusOS

Words That Build Or Destroy

Offline

#10 2012-01-18 01:23:11

mrpeachy
20% cooler
From: The Everfree Forest
Registered: 2009-11-08
Posts: 3,460

Re: HOW TO : using lua scripts in conky

part 4 -- drawing other things

there are a few things that cairo can draw other than lines
namely:
    1. rectangles
    2. arcs (and circles)
    3. curves

rectangles

we could use lines as in the triangle to draw ourselves a rectangle, but cairo has the ability to draw rectangles built in
so might as well use it

cairo_rectangle (cr, x, y, width, height)

the x,y coordinates are the top left corner of the rectangle

just like our triangle we can set up our shape like so

--settings
line_width=5
top_left_x=20
top_left_y=20
rec_width=100
rec_height=50
red=1
green=0
blue=0
alpha=1
--draw it
cairo_set_line_width (cr,line_width)
cairo_rectangle (cr,top_left_x,top_left_y,rec_width,rec_height)
cairo_set_source_rgba (cr,red,green,blue,alpha)

then use stroke to draw the outline

cairo_stroke (cr)

or

cairo_fill (cr)

to fill it in

or if you want the rectangle filled with one color and line in a different colors
we would first fill with cairo_fill_preserve, then set our second color and draw our line with cairo_stroke

--settings
line_width=5
top_left_x=20
top_left_y=20
rec_width=100
rec_height=50
fill_red=1
fill_green=1
fill_blue=1
fill_alpha=1
line_red=1
line_green=0
line_blue=0
line_alpha=1
--draw it
cairo_set_line_width (cr,line_width)
cairo_rectangle (cr,top_left_x,top_left_y,rec_width,rec_height)
cairo_set_source_rgba (cr,fill_red,fill_green,fill_blue,fill_alpha)
cairo_fill_preserve (cr)
cairo_set_source_rgba (cr,line_red,line_green,line_blue,line_alpha)
cairo_stroke (cr)

NOTE
with rectangles there is no point in setting line_cap like we did for lines as there are no "loose ends" to the rectangle
there is also no need to use cairo_close_path, as it is closed automatically
however setting how the lines join will affect the look of the rectangle when we use cairo_stroke

cairo_set_line_join (cr, CAIRO_LINE_JOIN_ROUND)
cairo_stroke (cr)

will give rounded corners for example

line width, line join type and end cap type do not affect the fill command

2. arc and circles
there are 2 commands for arcs

cairo_arc (cr,center_x,center_y,radius,start_angle,end_angle)
and
cairo_arc_negative (cr,center_x,center_y,radius,start_angle,end_angle)

cairo_arc draws the arc clockwise while cairo_arc_negative draws the arc anticlockwise

the first obstacle to drawing arcs is that you need to enter your start and end angles in radians rather than degrees.
so we need to know how to convert between the two

radians=degrees*(pi/180)

lua has a number of built in math functions and one of them, math.pi, gives you the value of pi

the other quirk about using the arc drawing command is that angle 0 isn't the top of the circle as you would expect

rather angle 0 is the rightmost point in the circle (which i would call 90 degrees)

these things don't matter if we only want to draw a complete circle, we just need the following

center_x=100
center_y=100
radius=50
start_angle=0
end_angle=2*math.pi--same thing as 360 degrees
cairo_arc (cr,center_x,center_y,radius,start_angle,end_angle)
cairo_stroke (cr)

NOTE
whenever you use stroke to draw something you need to set a line_width.
also with stroke, if you are going to see line ends then altering the line cap type will affect those ends.
the other setting that can affect stroke is the line join type if creating a path from multiple elements
arcs along with curves and lines can be all put together to form a single path

in the example above you will also need to set color and alpha as before.

Change cairo_stroke to cairo_fill to fill the circle in
or use the previously described method for fill and line.
I wont necessarily put these setup lines, or all the available options, into code examples from now on.

BUT if we dont want a full circle then we need to worry about radians and setting angles
to get an 1/4 circle, from the topmost point of the circle,clockwise to the rightmost point, we can do several things...
my code would look like this

center_x=100
center_y=100
radius=50
start_angle=0
end_angle=90
cairo_arc (cr,center_x,center_y,radius,(start_angle-90)*(math.pi/180),(end_angle-90)*(math.pi/180))
cairo_stroke (cr)

since i only want to enter angles as degrees i can put the conversion calculations into the arc command
eg (start_angle-90)*(math.pi/180)

first i want the top of my circe to be 0 degrees (or 360 if you like)
so i have to compensate for the arc command quirk by subtracting 90 degrees from the value i set

then i need to convert to radians by multiplying by (math.pi/180)

cairo_stroke to get the line

this in the code:

cairo_close_path (cr)
cairo_stroke (cr)

will result in a straight line drawn from the end of the arc back to the beginning
and cairo_fill (cr) instead of cairo_stroke would result in a filled in bump with a flat bottom

here is cairo_stroke without close_path, cairo_stroke with close path and cairo_fill
screenshotb3c80b4b9e8e885be28cc0734c43fccb.png

using arc or arc_negative
so if you give cairo_arc a start angle of 270 and an end angle of 90 you get the top half of a circle
you could also set start=270, end=450 (360+90) and get the same things
or start=-90, end=90 and get the same thing

if you give cairo_arc_negatove a start angle of 270 and an end angle of 90 you get the bottom half of a circle

this can be important for drawing paths, as you want your path to be a continuous progression
(imagine drawing a line on some paper but not allowed to lift the pen).  Also remember that using the close_path
or fill commands (which close the path automatically) you draw a line from where you ended to where you started.  You can get unexpected fill and stroke results if you piece together your path in a non continuous manner.

The other time you may want to use are or arc negative is to make a ring meter go one way or another
while you could achieve the effect just using, for example, arc (which naturally draws in a clockwise direction) for both, you have to think a bit harder about the math to get the ring going in the opposite direction

3 curves
i'll leave curves for another time
they can be quite tricky to set up and use

Last edited by mrpeachy (2012-01-18 20:25:41)

Offline

#11 2012-01-18 05:30:43

johnraff
#!Drunkard
From: Nagoya, Japan
Registered: 2009-01-07
Posts: 2,847
Website

Re: HOW TO : using lua scripts in conky

Wow - I feel such an idiot reading this. Guess I might never be a "real" programmer, but now subscribed, and will get down and try and make something one of these days...

Meanwhile, thank you very much for making it possible!


John
--------------------
( a boring Japan blog , idle twitterings  and GitStuff )
#! forum moderator

Offline

#12 2012-01-18 14:52:40

mrpeachy
20% cooler
From: The Everfree Forest
Registered: 2009-11-08
Posts: 3,460

Re: HOW TO : using lua scripts in conky

johnraff wrote:

Wow - I feel such an idiot reading this.

it could just be that i'm not explaining things very well big_smile

Guess I might never be a "real" programmer, but now subscribed, and will get down and try and make something one of these days...

Meanwhile, thank you very much for making it possible!

lol well i am certainly not a real programmer, i just know what i need to know and if i dont know then i try and find out

and you are welcome

Offline

#13 2012-01-18 15:27:09

rhowaldt
#!*$%:)
Registered: 2011-03-09
Posts: 4,396

Re: HOW TO : using lua scripts in conky

where's part 5? tongue

Offline

#14 2012-01-18 21:06:52

mrpeachy
20% cooler
From: The Everfree Forest
Registered: 2009-11-08
Posts: 3,460

Re: HOW TO : using lua scripts in conky

i added a little to the end of part 4, and here is part 5 big_smile

PART 5 - making some indicators

make a cpu indicator bar

we made a line that changes length according to the reading of cpu% from conky

but to make that a bit more interesting we will make a vertical indicator bar to show cpu
the bar will have a colored background and a different colored indicator
it will also be resizable through settings and placeable

so where to start?

first we need to think about the order of operations
in lua with cairo, things drawn lower down in the script will be drawn over the top of things drawn above

so we are going to have a colored background, which will need to be behind the indicator, so we need to draw the background first.

we are going to define some settings
1.  where we want the indicator to be
2. how big we want the indicator
3. the colors for our background and indicator

so our setting section might look like this

--SETTINGS FOR CPU INDICATOR BAR
bar_bottom_left_x= 50
bar_bottom_left_y= 200
bar_width= 30
bar_height= 100
--set bar background colors, 1,0,0,1 = fully opaque red
bar_bg_red=1
bar_bg_green=0
bar_bg_blue=0
bar_bg_alpha=1
--set indicator colors, 1,1,1,1 = fully opaque white
bar_in_red=1
bar_in_green=1
bar_in_blue=1
bar_in_alpha=1

we want unique names so that there is no chance of names being duplicated elsewhere in the script and overwriting our settings (i  usually have my string names tell me something about the information kept in the string).  it can be a pain to type long string names over and over again but worse when you run the script and it doesnt work as expected because a string has been ovewritten

drawing the background is then pretty simple, we will used a filled in rectangle
the only thing to note is that by asking for the bottom coordinates, when we come to set the height of the rectangle, our height will be negative (because we are drawing up!)

we are using the rectangle function, so we dont need to specify an end cap type and we are using fill so we dont need to specify line join type or line width

--draw background
cairo_set_source_rgba (cr,bar_bg_red,bar_bg_green,bar_bg_blue,bar_bg_alpha)
cairo_rectangle (cr,bar_bottom_left_x,bar_bottom_left_y,bar_width,-bar_height)
cairo_fill (cr)

so we have a red rectangle, now we need to think about making the indicator bar
first we need to get our reading into a string

value=tonumber(conky_parse("${cpu}"))

we are going to use the string value to affect the height of the indicator bar,
but we have a further complication in that we want out to be able to set indicator size in our settings part
so we need some math!

if we wanted out indicator to be 100 pixels high we would just be able to substitute cpu reading for height, as cpu will give us numbers between 0 and 100

but say we wanted our indicator to be 200 pixels high or only 50 pixels high, we need to scale up or down our cpu readings so that the indicator bar grows and shrinks in the right proportions

we know our maximum value for cpu is going to be 100
we need to divide the height we want by this maximum value to get the scale right
if we set bar_height=200
and max_value=100
then
scale=bar_height/max_value

scale = 2, so that for every increase of 1 in cpu % reading the bar will move an additional 2 pixels up
so at a cpu % of 100 the bar will be 200 pixels long, which is what we want

so

indicator_height=scale*value

and this is the number we plug into our rectangle drawing command

all together for the indicator

--draw indicator
cairo_set_source_rgba (cr,bar_in_red,bar_in_green,bar_in_blue,bar_in_alpha)--set indicator color
value=tonumber(conky_parse("${cpu}"))
max_value=100
scale=bar_height/max_value
indicator_height=scale*value
cairo_rectangle (cr,bar_bottom_left_x,bar_bottom_left_y,bar_width,-indicator_height)
cairo_fill (cr)

and you have a working cpu indicator bar

NOW what you could do is copy this code chunk over and over again, edit the settings and assign a different conky object to each instance for as many bars as you want
set up some text to label each bar and your done.
HOWEVER there is a better and easier way to get multiple bars than copying and pasting code
we can turn our indicator bar drawing code into a function
but more about functions in a later part!

making a cpu indicator circle meter
im picking cpu as my object of choice for no other reason than it is the one that changes the most
so you get to see your handy work in action smile

making a circle meter is very similar to the bar, except we are using the output of cpu% from conky to change the angles passed to the arc drawing command

we will have a ring meter with a background ring one color and an indicator ring of a different color
we will make the ring sizable through settings
we will have the ring show 0 cpu at the top and then as cpu increases the indicator bar will increase in size clockwise around the ring until at 100% it makes a complete circle and ends back at the top

we are going clockwise, so we will use cairo_arc
unlike the rectangle, we will be using cairo_stroke to draw our meter
so caro_set_line_width must be set which will give us the width of our indicator lines
setting the line cap type will have an effect on what the meter looks like
but we are not joining any lines so there is no point setting line join type

first you need to think about what kind of setting you want

a reminder of how we draw an arc

cairo_arc (cr,center_x,center_y,radius,start_angle,end_angle)
--SETTINGS
--rings size
ring_center_x=200
ring_center_y=200
ring_radius=50
ring_width=20
--colors
--set background colors, 1,0,0,1 = fully opaque red
ring_bg_red=1
ring_bg_green=0
ring_bg_blue=0
ring_bg_alpha=1
--set indicator colors, 1,1,1,1 = fully opaque white
ring_in_red=1
ring_in_green=1
ring_in_blue=1
ring_in_alpha=1
--indicator value settings
value=conky_parse("${cpu}")
max_value=100

just as the rectangle, go ahead and draw the background ring like so

--draw background
cairo_set_line_width (cr,ring_width)
cairo_set_source_rgba (cr,ring_bg_red,ring_bg_green,ring_bg_blue,ring_bg_alpha)
cairo_arc (cr,ring_center_x,ring_center_y,ring_radius,0,2*math.pi)
cairo_stroke (cr)

NOTE about line_width
line width when we are drawing a circle or arc works the same way as a straight line
half the line width is drawn to one side of the base line, one half of the line width is drawn to the other side
so if you set a radius of 50 pixels and a line width of 20 pixels, then from the center point of the circle to the inner edge of the line will only be 40 pixels
and it will be 60 pixels to the outer edge of the circle

we have a red background circle
now we have to work out how to apply the cpu% number held in the string "value" to making the indicator line move.

in this case it is the arc's end angle that will be changing relative to cpu%

again we need a bit of math to get the indicator arc moving in the right proportion

degrees=360
scale=degrees/max_value--ie for every 1% increase in cpu% the arc should move an additional 3.6 degrees
end_angle=value*scale

or i could just write

end_angle=value*(360/max_value)

now we can plug everything into the arc drawing command like so

--draw indicator
cairo_set_line_width (cr,ring_width)
end_angle=value*(360/max_value)
cairo_set_source_rgba (cr,ring_in_red,ring_in_green,ring_in_blue,ring_in_alpha)
cairo_arc (cr,ring_center_x,ring_center_y,ring_radius,0,(end_angle-90)*(math.pi/180))
cairo_stroke (cr)

HUH???
if you try the above code you will notice that something doesn't quite seem right
i thought i would put this in to take a look at what to do when things go wrong big_smile

the first thing i tried was adding a print line to the code like this:

--draw indicator
cairo_set_line_width (cr,ring_width)
end_angle=value*(360/max_value)
print (end_angle)
cairo_set_source_rgba (cr,ring_in_red,ring_in_green,ring_in_blue,ring_in_alpha)
cairo_arc (cr,ring_center_x,ring_center_y,ring_radius,0,(end_angle-90)*(math.pi/180))
cairo_stroke (cr)

was i calculating something wrong??
so i took a look at the terminal and watched what end_angle was being calculated as
i also went to the conkyrc and put in ${cpu} under TEXT so i could watch cpu at the same time
(i could have just put "print (value, end_angle)" and gotten both value in the terminal i suppose)

but it looked as if the calculations were giving me the correct result, so it must be something in the cairo_arc command itself that was going wrong

cairo_arc (cr,ring_center_x,ring_center_y,ring_radius,0,(end_angle-90)*(math.pi/180))

it was the start angle, which i had left at 0
i hadn't compensated for the arc command quirk so actually my 0 line was 90 degrees further around my circle than i thought it was!

a quick modification later:

cairo_set_line_width (cr,ring_width)
end_angle=value*(360/max_value)
--print (end_angle)
cairo_set_source_rgba (cr,ring_in_red,ring_in_green,ring_in_blue,ring_in_alpha)
cairo_arc (cr,ring_center_x,ring_center_y,ring_radius,(-90)*(math.pi/180),(end_angle-90)*(math.pi/180))
cairo_stroke (cr)

and we have a circle meter

Last edited by mrpeachy (2012-01-19 01:04:11)

Offline

#15 2012-01-18 21:43:42

Sector11
77345 ¡#
From: SR11 Cockpit
Registered: 2010-05-05
Posts: 11,433
Website

Re: HOW TO : using lua scripts in conky

mrpeachy wrote:

Using Lua scripts in conky
this how to is based on what i know... not what is known big_smile

Yea ... as far as I'm concerned they are one and the same.

  But that's my opinion ... I've been wrong before! - ONCE!
  {but it lasted about 60 years}  lol

mrpeachy I cannot say enough --->> thank you for this!


#! Forum Moderator | To #! or not to #!?  That is the question!
#! Conky = 16 Threads & the Conky Archives | Conky PitStop | OHCG'er
StartPage -  protect your privacy   |   BBQ Linux

Online

#16 2012-01-18 23:02:07

zuperkoleoptera
Member
Registered: 2012-01-11
Posts: 30

Re: HOW TO : using lua scripts in conky

Well I ve tried to implement the v9000 but with no luck, maybe not enough persistence....
I think after this series of howto I need to get back to the v9000 script and make it work!!!

Thank you for your work....


If you break it, you get to keep all pieces.

Offline

#17 2012-01-19 00:59:37

mrpeachy
20% cooler
From: The Everfree Forest
Registered: 2009-11-08
Posts: 3,460

Re: HOW TO : using lua scripts in conky

zuperkoleoptera wrote:

Well I ve tried to implement the v9000 but with no luck, maybe not enough persistence....
I think after this series of howto I need to get back to the v9000 script and make it work!!!

Thank you for your work....

make a post in my "weather in conky" thread and let me know whats going on with v9000 and i can try and help you out over there!

Last edited by mrpeachy (2012-01-19 01:00:55)

Offline

#18 2012-01-19 02:54:51

mrpeachy
20% cooler
From: The Everfree Forest
Registered: 2009-11-08
Posts: 3,460

Re: HOW TO : using lua scripts in conky

PART 6 - some more drawing calculations and if statements

so we have our bar indicator
ive moved the value setting and max_value setting up into the settings part of the code
and put "bar_" in front of each just to keep to my naming convention smile

--SETTINGS FOR CPU INDICATOR BAR
bar_bottom_left_x= 750
bar_bottom_left_y= 200
bar_width= 30
bar_height= 100
bar_value=tonumber(conky_parse("${cpu}"))
bar_max_value=100
--set bar background colors, 1,0,0,1 = fully opaque red
bar_bg_red=1
bar_bg_green=0
bar_bg_blue=0
bar_bg_alpha=1
--set indicator colors, 1,1,1,1 = fully opaque white
bar_in_red=1
bar_in_green=1
bar_in_blue=1
bar_in_alpha=1
--END OF SETTINGS

--DRAW BAR INDICATOR
--draw background
cairo_set_source_rgba (cr,bar_bg_red,bar_bg_green,bar_bg_blue,bar_bg_alpha)
cairo_rectangle (cr,bar_bottom_left_x,bar_bottom_left_y,bar_width,-bar_height)
cairo_fill (cr)
--draw indicator
cairo_set_source_rgba (cr,bar_in_red,bar_in_green,bar_in_blue,bar_in_alpha)--set indicator color
scale=bar_height/bar_max_value
indicator_height=scale*bar_value
cairo_rectangle (cr,bar_bottom_left_x,bar_bottom_left_y,bar_width,-indicator_height)
cairo_fill (cr)

but we want to jazz it up a bit and add a few additional features
1. we want the ability to draw a border around our indicator
- we want the border to be optional
- we want the ability to set the border color and border line thickness
2. we want the ability to set an "alarm" value for the bar so that:
- when the value we feed the bar bar reaches or goes past a certain point the bar changes to a different color
- we want to be able to specify the alarm value and the color the bar changes to

1 - adding an border
in our settings section we need some new options

bar_border=1 --set 1 for border or 0 for no border
--set border color rgba
border_red=0
border_green=1
border_blue=1
border_alpha=1
--set border thickness
border_width=10

 
i tend to use number switches for options like this, 1=yes i want it, 0=no i dont but you could just as well use text answers

bar_border="yes" --set "yes" for border or "no" for no border

 
the downside is that "Yes" is not the same as "yes" when we come to use a comparison later on

this case specificity can be overcome by using the in built commands string.upper() or string.lower() but that would be a topic for another time smile
for now we will use either 1 or 0

another aspect of the border is that it shouldn't cover up any part of the indicator bar
and there are actually several ways i can think of achieving the desired border

we could draw a filled in rectangle behind the indicator background rectangle
our "border" rectangle would be larger than the indicator rectangles, so you would see its edges sticking out around the edges of the indicator

or we could use the rectangle command with cairo_stroke so that we only draw the lines and dont fill it in

or we could draw individual lines

each of these methods has some positives and negatives
but lets go with drawing a rectangle with cairo_stroke

the tricky part here is how line_width is applied when drawing the rectangle
screenshotdf7e94c393494d44e3581b08739af9ce.png
all 3 of these rectangles have been set a width of 60 and a height of 40
the difference you see is that they have line widths of 1,10 and 20 respectively

we need to compensate for the encroachment of the border into the middle of our rectangle

this is how i would do it

first we need to set the x and y coordinates for our border relative to bar_bottom_left_x and bar_bottom_left_y so that when we want to move our bar around we only need to edit bar_bottom_left_x and bar_bottom_left_y and all other strings change automatically  in relation to those settings

border_bottom_left_x=bar_bottom_left_x-(border_width/2)--we [u]subtract[/u] because we are going to the [u]left[/u]
border_bottom_left_y=bar_bottom_left_y+(border_width/2)--we [u]add[/u] because we are going [u]down[/u]

this starts our border rectangle to the left and lower than we start our bar to compensate for line_width
but now we also have to make the border rectangle wider and bigger than our bar rectangle so that it surrounds the bar rectangle

brec_width=bar_width+border_width
brec_height=bar_height+border_width

NOTE
when i was writing the above lines, i thought that since i had named the width and length strings for the indicator rectangles bar_width and bar_height that i would call the width and height strings for the border rectangle border_width and border_height (even had these typed out).
BUT i realised that i couldnt use "border_width" because i have already used it to name the string that holds the value of line_width for the border, so i had to come up with something else

and we can set up our border and plug those strings into the rectangle drawing command like so

cairo_set_source_rgba (cr,border_red,border_green,border_blue,border_alpha)
cairo_set_line_width (cr,border_width)
border_bottom_left_x=bar_bottom_left_x-(border_width/2)
border_bottom_left_y=bar_bottom_left_y+(border_width/2)
brec_width=bar_width+border_width
brec_height=bar_height+border_width--remember that we need to make the value of brec_height negative at some point because we are drawing up
cairo_rectangle (cr,border_bottom_left_x,border_bottom_left_y,brec_width,-brec_height)--we will set brec_height negative in this line
cairo_stroke (cr)

where should we put this code?
since we have done our calculations correctly, the border shouldnt interfere with our indicator, so you could have this code in several places, before we draw the background, affter the background and before the indicator or after the indicator.

so we have a border but we havn't used the setting "bar_border" to allow us to optionally have the border or not.
to do that we need an if statement

IF STATEMENTS
for example:

if bar_border==1 then
--border drawing code
end

this is the simplest form of the if statement
if we set bar_border=1 in our settings then the border is drawn
or more specifically, if the string "bar_border" has a value of 1 then everything between then and end is done

if we set bar_border to 0 (or if bar_border is set to anything other than 1 in this case) then the border doesn't get drawn (anything between then and end is skipped)


EVERY IF NEEDS AN END
you could also say that every if needs a then, but depending on how you set up your statement, there can be multiple thens within it

NOTE
we need a double equals sign (==) when we are making a comparison
other options for comparisons are:
> greater than
>= greater than or equal to
< less than
<= less than or equal to
~= not equal to

we'll get to a more complicated if later on

Last edited by mrpeachy (2012-01-19 03:07:43)

Offline

#19 2012-01-19 11:19:03

rhowaldt
#!*$%:)
Registered: 2011-03-09
Posts: 4,396

Re: HOW TO : using lua scripts in conky

i wanted to say 'where is part 7?', but i am sure you're going to make that as well, and i am in awe with the amount of info you have here. awesomeness!

Offline

#20 2012-01-19 20:17:27

Sector11
77345 ¡#
From: SR11 Cockpit
Registered: 2010-05-05
Posts: 11,433
Website

Re: HOW TO : using lua scripts in conky

{hand up in the back}  Yuuuu hooooo!!!!

Commenting code is always a blessing to us newer than new coders so I have a question:

Is this "no space" comment necessary like shown

if updates>5 then
--##############################
print ("hello world")
--##############################
end-- if updates>5

or can it be spaced or tabbed?

if updates>5 then
--     ##############################
print ("hello world")
--     ##############################
end                  -- if updates>5

It may sound silly to a coder but - I'm not one.

Last edited by Sector11 (2012-01-19 20:18:31)


#! Forum Moderator | To #! or not to #!?  That is the question!
#! Conky = 16 Threads & the Conky Archives | Conky PitStop | OHCG'er
StartPage -  protect your privacy   |   BBQ Linux

Online

#21 2012-01-19 20:38:44

mrpeachy
20% cooler
From: The Everfree Forest
Registered: 2009-11-08
Posts: 3,460

Re: HOW TO : using lua scripts in conky

actually ive been meaning to write a short bit about spaces and such...
lua seems to be pretty forgiving in terms of allowing spaces and tabs

for example

value=16
print (value) -->16
value = 16--with spaces
print (value) -->16
value    =    16--tabbed
print (value) -->16
    value    =                     16--any kind of spacing you want
print (value) -->16

this also applies to things like the rectangle command

cairo_rectangle (cr,50,50,60,40)
cairo_rectangle (cr, 50 ,50 ,60 ,40 )
    cairo_rectangle     (cr,     50 ,    50 ,60         ,40 )

all give you the same rectangle

my preference is to keep everything tight together

so to answer you comment question specifically, you can have any amount of spaces before the -- without a problem

ill update part 1 with a section about spacing

Last edited by mrpeachy (2012-01-19 20:41:14)

Offline

#22 2012-01-19 23:56:40

mrpeachy
20% cooler
From: The Everfree Forest
Registered: 2009-11-08
Posts: 3,460

Re: HOW TO : using lua scripts in conky

PART 7 -  adding our alarm color change feature and looking at more complex if statements

we were jazzing up our bar meter
we added an optional border as feature 1

and we are going to have the bar change color for feature 2

to get the color change we i'll need to add a few more settings!
most likely if you are going to set an alarm color, you'll think of red (as i did)
so we would have to re-color our background bar also (which is also currently red)
im feeling a little lazy so im going to go for some shorter string names, particularly for all the reds green blue and alphas coming up smile

--set alarm value, this is the value at which bar color will change
alarm_value=80
--set alarm bar color, 1,0,0,1 = red fully opaque
ar,ag,ab,aa=1,0,0,1

we already have a base bar color
so we want the bar to be our base color unless the cpu% reading equals or goes above 80%

we are going to be using another IF to get the colors to change
as with most code, there are multiple ways we could go about doing things
lets first remind ourselves of the code that is drawing the indicator part of the bar
it is that part that we will be editing as it is that part which will change color

cairo_set_source_rgba (cr,bar_in_red,bar_in_green,bar_in_blue,bar_in_alpha)--set indicator color
scale=bar_height/bar_max_value
indicator_height=scale*bar_value
cairo_rectangle (cr,bar_bottom_left_x,bar_bottom_left_y,bar_width,-indicator_height)
cairo_fill (cr)

to apply our if statement to colors we could do the following:
remember, "bar_value" is the name of the string holds the value of cpu%
and we set "alarm_value" above to 80

if bar_value<alarm_value then
cairo_set_source_rgba (cr,bar_in_red,bar_in_green,bar_in_blue,bar_in_alpha)
else
cairo_set_source_rgba (cr,ar,ag,ab,aa)
end

hopefully it should be quite self explanatory what is going on in the above code big_smile
if the string named "bar_value" has a value of less than 80 then the color is set to the base indicator color (which we have set to white in settings)
-all code between then and else is done
if the value of "bar_value" is not less than 80 (ie equal to or greater than 80) then color is set to the alarm color
-all the code between then and else is skipped and everything between else and end is done

this would have also worked

if bar_value>=80 then
cairo_set_source_rgba (cr,ar,ag,ab,aa)
else
cairo_set_source_rgba (cr,bar_in_red,bar_in_green,bar_in_blue,bar_in_alpha)
end

how do we know its working?
we think that we have our code right and we expect that if our cpu% gets to 80% or more that our bar color will change from white to red
but its always a good idea to check that things are working the way we expect.

We could do something on the computer that would drive the actual cpu% reading up to 80 or above
but there is an easier way
in our settings we have the line that sets the value of bar_value

bar_value=tonumber(conky_parse("${cpu}"))

just edit that line and "hard code" bar_value to a test value like this

bar_value=80--tonumber(conky_parse("${cpu}"))

i dont like to completely replace the line with our test value as it simply harder to reinstate the line afterwards
with the test value in place and the rest of the line commented out, once we are sure our feature is working
we just delete the test value and the comments and everything is back to being operational

now we like the color change, and we want to implement another color change
we want the bar to be one color when cpu% is low, say green up to 50%
then we want the color to change to a different color, yellow for example, between 50% and 80%
then if our reading gets to 80 or over it goes to red

so back to the settings
we already have our alarm (or high cpu usage) value and color

--set value for first color change, low cpu usage to mid cpu usage
mid_value=50
--set "low" cpu usage color and alpha, ie bar color below 50% - 0,1,0,1=fully opaque green
lr,lg,lb,la=0,1,0,1
--set "mid" cpu usage color, between 50 and 79 - 1,1,0,1=fully opaque yellow
mr,mg,mb,ma=1,1,0,1

while we could reuse our base bar color settings, and just change the numbers to green or yellow

bar_in_red=1
bar_in_green=1
bar_in_blue=1
bar_in_alpha=1

since we are making some significant changes to how our colors are working i would just go ahead and delete them and replace them with the new low mid and alarm values
i tend to like to stick to a single naming convention also which helps me to remember what i have named strings (and maybe because of some mild OCD))
but again, thats just me, you can call your string whatever you want to!

so now we need to think about how to set up our if statement
when cpu is between 0 and 49 we want green
when cpu is between 50 and 79 we want yellow
and when cpu is 80 or above we want red

so lets put them into a statement

if bar_value>=mid_value then --ie if value is greater or equal to 50
cairo_set_source_rgba (cr,mr,mg,mb,ma)--yellow (mid color)
elseif bar_value>=alarm_value then --ie if bar_value is greater or equal to 80
cairo_set_source_rgba (cr,ar,ag,ab,aa)--red (alarm color)
else
cairo_set_source_rgba (cr,lr,lg,lb,la)--green (low color)
end

we use an elseif, because it is no longer an either or situation, there are 3 possibilities we need to sort out

test the setup by setting bar_value to some test value
we set
bar_value=49 and we get a green bar, and it is green for any number below 50
we set
bar_value=50 and we get a yellow bar
then try
bar_value=80 and the bar is still yellow! and it is yellow all the way up to 100

our statement seems entirely logical, but this is one of the pitfalls you can get stuck in
to understand it we need to think about how our if statement works and we can see that the problem is in the order of our comparisons

if bar_value>=mid_value then --ie if value is greater or equal to 50
cairo_set_source_rgba (cr,mr,mg,mb,ma)--yellow (mid color)

this first line does indeed match any number from 50 to 100 and so any cpu vale from 50 to 100 will result in a yellow bar.

the script comes to the line, takes the value of "bar_value" calculates if it is greater or equal to the value of mid_value
if it passes the comparison, the script runs the corresponding code and then its done with the if statement

only if bar_vale is less than 50 then the first comparison will fail and the script will move on to the next comparison
but of course this comparison will fail also as if a value is not greater or equal to 50 then it wont be greater or equal to 80

once past the if and the following elseif the script automatically runs the code following else which doesnt require a comparison
again there are plenty of ways we can fix this
we can try and reorder our comparisons like so

if bar_value>=alarm_value then --ie if value is greater or equal to 80
cairo_set_source_rgba (cr,ar,ag,ab,aa)--red (alarm color)
elseif bar_value>=mid_value then --ie if bar_value is greater or equal to 50
cairo_set_source_rgba (cr,mr,mg,mb,ma)--yellow (mid color)
else
cairo_set_source_rgba (cr,lr,lg,lb,la)--green (low color)
end

take a value of say 90
check 1) is 90 greater or equal to 80?
yes -> pass the first comparison and run the code to set color to red
done!

set a value of 60
check 1) is 60 greater or equal to 80?
no -> fail the first comparison, move onto the next
check 2) is 60 greater or equal to 50?
yes -> pass the second comparison and run the code to set color to yellow
done!

set a value of 48
check 1) is 48 greater or equal to 80?
no -> fail the first comparison, move onto the next
check 2) is 48 greater or equal to 50?
no -> fail the second comparison, move onto the next
no more checks, run code following else and set color to green
done!

Last edited by mrpeachy (2012-01-20 00:10:45)

Offline

#23 2012-01-20 22:05:54

mrpeachy
20% cooler
From: The Everfree Forest
Registered: 2009-11-08
Posts: 3,460

Re: HOW TO : using lua scripts in conky

PART 8 - turn our code into a function

take the example of the bar indicator with all the features we added and the entire lua script might look something like this

--[[this lua script draws vertical bar indicators]]

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
--#########################################################################################################
--SETTINGS FOR INDICATOR BAR
bar_bottom_left_x= 100
bar_bottom_left_y= 100
bar_width= 30
bar_height= 100
bar_value=tonumber(conky_parse("${cpu}"))
bar_max_value=100
--set bar background colors, 0.5,0.5,0.5,1 = fully opaque grey
bar_bg_red=0.5
bar_bg_green=0.5
bar_bg_blue=0.5
bar_bg_alpha=1
--bar border settings
bar_border=1 --set 1 for border or 0 for no border
--set border color rgba
border_red=0
border_green=1
border_blue=1
border_alpha=1
--set border thickness
border_width=10
--color change
--set value for first color change, low cpu usage to mid cpu usage
mid_value=50
--set "low" cpu usage color and alpha, ie bar color below 50% - 0,1,0,1=fully opaque green
lr,lg,lb,la=0,1,0,1
--set "mid" cpu usage color, between 50 and 79 - 1,1,0,1=fully opaque yellow
mr,mg,mb,ma=1,1,0,1
--set alarm value, this is the value at which bar color will change
alarm_value=80
--set alarm bar color, 1,0,0,1 = red fully opaque
ar,ag,ab,aa=1,0,0,1
--end of settings
--draw bar
--draw background
cairo_set_source_rgba (cr,bar_bg_red,bar_bg_green,bar_bg_blue,bar_bg_alpha)
cairo_rectangle (cr,bar_bottom_left_x,bar_bottom_left_y,bar_width,-bar_height)
cairo_fill (cr)
--draw indicator
if bar_value>=alarm_value then --ie if value is greater or equal to 50
cairo_set_source_rgba (cr,ar,ag,ab,aa)--yellow
elseif bar_value>=mid_value then --ie if bar_value is greater or equal to 80
cairo_set_source_rgba (cr,mr,mg,mb,ma)--red
else
cairo_set_source_rgba (cr,lr,lg,lb,la)--green
end
scale=bar_height/bar_max_value
indicator_height=scale*bar_value
cairo_rectangle (cr,bar_bottom_left_x,bar_bottom_left_y,bar_width,-indicator_height)
cairo_fill (cr)
--draw border
cairo_set_source_rgba (cr,border_red,border_green,border_blue,border_alpha)
cairo_set_line_width (cr,border_width)
border_bottom_left_x=bar_bottom_left_x-(border_width/2)
border_bottom_left_y=bar_bottom_left_y+(border_width/2)
brec_width=bar_width+border_width
brec_height=bar_height+border_width--remember that we need to make this value negative at some point because we are drawing up
cairo_rectangle (cr,border_bottom_left_x,border_bottom_left_y,brec_width,-brec_height)
cairo_stroke (cr)
--#########################################################################################################
end-- if updates>5
cairo_destroy(cr)
cairo_surface_destroy(cs)
cr=nil
end-- end main function

we can run the script from conky by adding these lines to the conkyrc

lua_load /path-to-file/filename.lua
lua_draw_hook_post main 

TEXT

but as it currently stands we only get one indicator bar out of it, currently set to display cpu%

there are plenty of other conky objects that we might want use our indicator bar with.

one thing we could do is copy all the code required to draw the bar, all the settings and all the drawing code, and paste it over and over, duplicating the code within the main lua function for as many bars as you want.

then you would go to each repetition of code, edit the settings (a minimum of setting a different conky object and new coordinates)

there is nothing wrong with this approach, plenty of my script have code repetitions in them and our code isnt all that long (we would have about 60 code lines per bar)...

BUT if our code was longer, and even for code this length, if we wanted lots of bars we would end up with a pretty large main function with settings and drawing code all mixed together.  This can make harder work of editing when you want to make a change.

FUNCTIONS are a simple way to execute the same piece of code over and over again without increasing your line count and so keeping your main function free from clutter which makes it easier to navigate and edit.

before we go about editing our lua script to turn the bar code into a function, i'll do my best to explain what functions are all about!

if you look at other pre made lua scripts out there you will see that there are almost always other functions in the script in addition to the main function that is called in the conkyrc.

Functions can be as simple or as complex as you need the function to be.
for use in conky, other functions are written outside of the main function either above or below.

due to the way lua scripts work, writing other functions below the main function isnt a problem.

From a programming point of view it would be more "proper" to have your other functions above the main.  BUT many times you want to enter settings into the lua script, and more often than not these settings will go into the main function which is one reason why you may not want to bury your main function below the other functions.

all your other functions do not need the conky setup lines that the main function needs,
you will be calling these other function from within the main function, so image that whenever you call a function, the script is simple substituting the function call with the code it contains, so that in essence the code exists within the main function

so all you need for other functions is to

-start the function
-give it a name
-set out what the function is going to do
-end the function

here is an example of a simple function

function multiply(number)
return number*2
end

this function accepts a number and returns the result of that number multiplied by 2

(for the sake of brevity i wont write out all the setup code for the main function
just remember you need all the elements i described in part 1 of this how to for the main function if you want lua to display stuff in conky)

so how do we use the function i just wrote?
lets say that we put it under the main function we would have a script like so

function conky_main()
*setup lines*
--#######################
result=multiply(16)
print (result)
--#######################
*close out lines
end-- main function

function multiply(number)
return number*2
end

the round brackets are very important here
this is how we send information to our other functions

i am using the function inside main like this
result=multiply(16)
So I am sending the multiply function the number 16 inside the curved brackets

The multiply function takes the number 16 and sets a string called "number" to that value
function multiply(number)
so hopefully you can see the relationship between what is written between curved brackets when sending information to functions

This string could be called anything i wanted (as long as it didnt start with a number or have spaces)
there is nothing special about calling it "number" it could just as easily be "baboons"
but as ive said elsewhere i think its a good idea for the string name to reflect the contents of that string smile

the function takes the value held in "number", multiplies it by 2 and returns the result
in this case
result=multiply(16)
the result returned by the multiply function is assigned to a string called "result"

print(result) --> 32

A function doesnt have to return a value, they can be used for as many different purposes as you can think of

SO lets work on getting our bar drawing code into its own function

-think of what we are going to call the function
lets call it "indicator_bar"

so we can start our new function, and we will go and start the function below our main function
we might as well put our "end" in there too, and comment it so we dont forget what its for smile

function indicator_bar()
--############################
--insert function code
--############################
end--of bar_indicator function

now we need to think about what code are going to put into our function?

this is one reason why i wrote my initial code so that there was a separate settings part where we assigned all the input values to strings and a separate drawing part where we manipulated our strings and plugged them into the commands that are responsible for getting the actual bar graphics onto the screen.

the point of making the function is that we want to be able to send our function different sets of settings and have the function output the graphics for each set

SO we will retain the setup portion for each bar within the main conky function and put the bar drawing code into the "indicator_bar".

we can just go ahead and cut the code out of the main conky function and paste it into the "indicator_bar" function

once separated, the code would look something like this:

function conky_main()
*setup lines*
--#######################
--SETTINGS FOR INDICATOR BAR
bar_bottom_left_x= 100
bar_bottom_left_y= 100
bar_width= 30
bar_height= 100
bar_value=tonumber(conky_parse("${cpu}"))
bar_max_value=100
--set bar background colors, 0.5,0.5,0.5,1 = fully opaque grey
bar_bg_red=0.5
bar_bg_green=0.5
bar_bg_blue=0.5
bar_bg_alpha=1
--bar border settings
bar_border=1 --set 1 for border or 0 for no border
--set border color rgba
border_red=0
border_green=1
border_blue=1
border_alpha=1
--set border thickness
border_width=10
--color change
--set value for first color change, low cpu usage to mid cpu usage
mid_value=50
--set "low" cpu usage color and alpha, ie bar color below 50% - 0,1,0,1=fully opaque green
lr,lg,lb,la=0,1,0,1
--set "mid" cpu usage color, between 50 and 79 - 1,1,0,1=fully opaque yellow
mr,mg,mb,ma=1,1,0,1
--set alarm value, this is the value at which bar color will change
alarm_value=80
--set alarm bar color, 1,0,0,1 = red fully opaque
ar,ag,ab,aa=1,0,0,1
--end of settings
--#######################
*close out lines
end-- main function


function indicator_bar()
--############################
--draw bar
--draw background
cairo_set_source_rgba(cr,bar_bg_red,bar_bg_green,bar_bg_blue,bar_bg_alpha)
cairo_rectangle (cr,bar_bottom_left_x,bar_bottom_left_y,bar_width,-bar_height)
cairo_fill (cr)
--draw indicator
if bar_value>=alarm_value then --ie if value is greater or equal to 50
cairo_set_source_rgba (cr,ar,ag,ab,aa)--yellow
elseif bar_value>=mid_value then --ie if bar_value is greater or equal to 80
cairo_set_source_rgba (cr,mr,mg,mb,ma)--red
else
cairo_set_source_rgba (cr,lr,lg,lb,la)--green
end
scale=bar_height/bar_max_value
indicator_height=scale*bar_value
cairo_rectangle (cr,bar_bottom_left_x,bar_bottom_left_y,bar_width,-indicator_height)
cairo_fill (cr)
--draw border
cairo_set_source_rgba (cr,border_red,border_green,border_blue,border_alpha)
cairo_set_line_width (cr,border_width)
border_bottom_left_x=bar_bottom_left_x-(border_width/2)
border_bottom_left_y=bar_bottom_left_y+(border_width/2)
brec_width=bar_width+border_width
brec_height=bar_height+border_width--remember that we need to make this value negative at some point because we are drawing up
cairo_rectangle (cr,border_bottom_left_x,border_bottom_left_y,brec_width,-brec_height)
cairo_stroke (cr)
--############################
end--of bar_indicator function

the next thing is to think about how we get the settings information inside the "conky_main" function to the bar drawing code inside the "indicator_bar" function
we do this using curly brackets

--we call the function in the main function like so
indicator_bar(information to send to the function)

--and we need to set up the function to accept the information
function indicator_bar(information that was sent to the function)

there are a couple of ways to ago about this (as always)
but for this example we will be sending and receiving strings

so what strings does the drawing code in indicator_bar need?
the same strings that we set in the settings part,

we can write them in one line between our curved brackets seperating each string from the next by a comma
these are the strings that "indicator_bar" needs to receive to work properly so we can write the following:

function indicator_bar(bar_bottom_left_x,bar_bottom_left_y,bar_width,bar_height,bar_value,bar_max_value,bar_bg_red,bar_bg_green,bar_bg_blue,bar_bg_alpha,bar_border,border_red,border_green,border_blue,border_alpha,border_width,mid_value,lr,lg,lb,la,mr,mg,mb,ma,alarm_value,ar,ag,ab,aa)

that is our indicator_bar function finished.
NOTE
the first code line in this function is a color setup line

cairo_set_source_rgba(cr,bar_bg_red,bar_bg_green,bar_bg_blue,bar_bg_alpha)

and the first string this line needs is "bar_bg_red"
in our function the code takes the value for "bar_bg_red" directly from the string of the same name found in the curved brackets following the function name

the same goes for all the other string values that the code needs

so when we call the function inside conky_main, these are the things that we need to send

indicator_bar(bar_bottom_left_x,bar_bottom_left_y,bar_width,bar_height,bar_value,bar_max_value,bar_bg_red,bar_bg_green,bar_bg_blue,bar_bg_alpha,bar_border,border_red,border_green,border_blue,border_alpha,border_width,mid_value,lr,lg,lb,la,mr,mg,mb,ma,alarm_value,ar,ag,ab,aa)

NOTE
when sending the information in the function call above there are several ways we can go about it
1. we can input our values directly into the function call like so

indicator_bar(100,100,30,100,tonumber(conky_parse("${cpu}")),100,0.5,0.5,0.5,1,1,0,1,1,1,10,50,0,1,0,1,1,1,0,1,80,1,0,0,1)

we send this to indicator_bar

it takes the first string in its "string list" (the list inside the curly brackets following the functions name)
and sets that string to the value of the first thing in the "received list" which is the list of values received from the function call
bar_bottom_left_x=100
then it sets each subsequent string in its "string list" to each subsequent value the "received list"
next, 2nd entry in "string list" = 2nd entry in "received list"
bar_bottom_left_y=100
next, 3rd entry in "string list" = 3rd entry in "received list"
bar_width=30

SO every string in the functions "string list" requires a matching value in the list of things the function received from the function call

if we miss out a value (or put in an extra value) between () in the function call, the function just keeps on assigning vales in the order they are received leading to strings being assigned the wrong values

if we send 9 values in the function call but there are 10 strings to be set in the functions "string list"
then the 10th string will have no value and be set to nil

trying to perform operations on strings that have a value of nil is a sure way to an error

i'll continue with function in a next part, i think i have already over-explained everything big_smile

Last edited by mrpeachy (2012-01-21 17:11:59)

Offline

#24 2012-01-21 18:19:38

mrpeachy
20% cooler
From: The Everfree Forest
Registered: 2009-11-08
Posts: 3,460

Re: HOW TO : using lua scripts in conky

PART 9 – sending information to functions

I left off after describing how to send indicator bar setup information from the main conky (conky_main) function to a separate function called indicator_bar which takes the information sent to it and draws a bar indicator based on those settings

we did this in conky_main

indicator_bar(100,100,30,100,tonumber(conky_parse("${cpu}")),100,0.5,0.5,0.5,1,1,0,1,1,1,10,50,0,1,0,1,1,1,0,1,80,1,0,0,1)

putting all our settings right into the function call

while this way works just fine there are some drawbacks to doing it this way

first of all its just hard to keep track of what each number means
and second its easy to miss something out (or miss out a comma which are necessary to seperate values)
as I described earlier a missed entry (or comma) when sending information this way will lead to your script giving an error


i prefer to define my strings, and then duplicate each string name in the function call
for example using the multiply function it would look like this

number=16
result=multiply(number)

now we dont have to touch our function call change the number we are sending to the function, we only need change the value we are assigning to the string called "number"

so for our indicator bar setup we would just take the settings lines we already have, and add the call at the end

--SETTINGS FOR INDICATOR BAR
bar_bottom_left_x= 100
bar_bottom_left_y= 100
bar_width= 30
bar_height= 100
bar_value=tonumber(conky_parse("${cpu}"))
bar_max_value=100
--set bar background colors, 0.5,0.5,0.5,1 = fully opaque grey
bar_bg_red=0.5
bar_bg_green=0.5
bar_bg_blue=0.5
bar_bg_alpha=1
--bar border settings
bar_border=1 --set 1 for border or 0 for no border
--set border color rgba
border_red=0
border_green=1
border_blue=1
border_alpha=1
--set border thickness
border_width=10
--color change
--set value for first color change, low cpu usage to mid cpu usage
mid_value=50
--set "low" cpu usage color and alpha, ie bar color below 50% - 0,1,0,1=fully opaque green
lr,lg,lb,la=0,1,0,1
--set "mid" cpu usage color, between 50 and 79 - 1,1,0,1=fully opaque yellow
mr,mg,mb,ma=1,1,0,1
--set alarm value, this is the value at which bar color will change
alarm_value=80
--set alarm bar color, 1,0,0,1 = red fully opaque
ar,ag,ab,aa=1,0,0,1
--end of settings, call drawing function
[b]indicator_bar(bar_bottom_left_x,bar_bottom_left_y,bar_width,bar_height,bar_value,bar_max_value,bar_bg_red,bar_bg_green,bar_bg_blue,bar_bg_alpha,bar_border,border_red,border_green,border_blue,border_alpha,border_width,mid_value,lr,lg,lb,la,mr,mg,mb,ma,alarm_value,ar,ag,ab,aa)[/b]

you set values to all your strings and each string matches each entry in the function call list so that the values are transfered directly between the two

writing your code this spells out everything nice and simply which allows easy entry of settings

you dont have to remember what numbers mean what, you dont have to worry about commas and you are less likely to miss out a value (you would have to delete a whole setting line to do that)

the down side to this is that it takes a lot more lines of code this way.

ANOTHER WAY
you can do something half way between these two methods mentioned so far which takes advantage of the fact that lua doesnt mind having its code split onto multipl lines AS LONG AS the information is bounded either by curved brackets () when sending info to functions or curly brackets {} when defining a table

take the rectangle drawing command

cairo_rectangle (cr,50,50,50,-100)

this is just like the function we made, except you dont see the rectangle drawing code anywhere in the script (it's a built in function).

we call the function "cairo_rectangle" and send it the information it needs inside curved brackets ()

BUT once the curved brackets are opened (the opening bracket has to be on the same line as the function call) we can then split up our entries on to seperate lines

cairo_rectangle (cr,
50,
50,
50,
-100)

we have to make sure that we have still have commas seperating the entries
but entering data this way has the advantage that we can write comments on each line and everything still works

cairo_rectangle (cr,
50,--rectangle x position
50,--rectangle y position
50,--rectangle width
-100--rectangle height
)

we could do this just the same with out indicator bar function
you can see below i have split some entries onto seperate lines but kept others together on the same line where it makes sense

indicator_bar(
750,400,--position x,y
30,--bar width
100,--bar height
tonumber(conky_parse("${cpu}")),--value to send bar
100,--max value
0.5,0.5,0.5,1,--bar background color rgba - grey
1,--want border, 1=yes,0=no
0,1,1,1,--border color rgba - light blue
10,--border width
50,--mid value, point of first color change
0,1,0,1,--low cpu% color rgba - green
1,1,0,1,--mid cpu% color rgba - yellow
80,--alarm value, point of second color change
1,0,0,1--alarm color rgba - red
)

A MORE COMPLEX USE OF FUNCTIONS
the functions i have given as examples are pretty straightforward
set up the function, call it and give it the info it needs, the function outputs something for example a number or some graphics

but the use of functions can be more complex

here is an example
we are going to have our main conky function, and two additional functions :
one function is going to be for drawing arcs
the second function will convert degrees into radians and adjust for the cairo_arc quirk so that 0 degrees is the top of the circle

our angle conversion function might look like this

function arad(degrees)
--compensate for cairo_arc quirk
degrees=degrees-90
--convert degrees to radians
radians=degrees*(math.pi/180)
--return angle
return radians
end--function arad

NOTE this line
degrees=degrees-90
i do this quite often, as others do in their scripts

im taking the value of the string "degrees" as it was set inside ()
subtracting 90 from it but putting the result of that operation into a string also called "degrees"

as mentioned earlier, strings of the same name overwrite each other
and the second instance of a string called "degrees" will indeed overwrite the first instance BUT not until the original "degrees" string is used in the calculation

as long as you know that you will no longer need the value held in the first "degrees" string after using it in, for example, a calculation then reusing the string name just makes it so that you dont have to keep thinking u new string names!

The arc drawing function might look like this
ill use nice short string names here smile

mx will be for middle x position
my will be for middle y position
rad for radius
sa for start angle
ea for end angle
(i will be giving angles in degrees when i call the function)

i want all my circles to be white with a line thickness of 1, so im going to set color,alpha and line_width in the function itself

function circle(mx,my,rad,sa,ea)
cairo_set_source_rgba (cr,1,1,1,1)
cairo_set_line_width (cr,1)
cairo_arc (cr,mx,my,rad,arad(sa),arad(ea))
cairo_stroke (cr)
end--function circle

the important line to note is this one
cairo_arc (cr,mx,my,rad,arad(sa),arad(ea))

i can use the arad function inside the cairo_arc command to convert the degree values we send "circle" into adjusted radian values to use with cairo_arc

then last of all we have our conky_main function

function conky_main ()
--conky function setup lines
--##########################
circle(100,100,50,90,270)
--##########################
--cony function close out lines
end-- of conky main

if we think about the flow of information, we send "circle" the information in the function call inside "conky_main"

cirlce recieves the list of values and sets its list of strings to those vales in order

it uses the strings my,mx and rad directly but it ships out sa and ea to "arad"

arad recieves the value of sa, puts that value into a string called degrees and converts the value to adjusted radians and sends this new value back to "circle" where is is used as the start value directly in the cairo_arc command

then arad receives the value of ea and returns the result directly into cairo_arc

the chain of functions using functions could keep hoing for as many functions as you could write
and you can of course use as many functions within any other function as you want

next part will introduce tables

Last edited by mrpeachy (2012-01-21 20:15:15)

Offline

Help fund CrunchBang, donate to the project!

#25 2012-01-21 20:16:24

mrpeachy
20% cooler
From: The Everfree Forest
Registered: 2009-11-08
Posts: 3,460

Re: HOW TO : using lua scripts in conky

just want to mention that i added a new section to part 9 about using function within functions

this post will eventually be about tables

anyone still reading lol

Last edited by mrpeachy (2012-01-21 20:24:55)

Offline

Board footer

Powered by FluxBB

Copyright © 2012 CrunchBang Linux.
Proudly powered by Debian. Hosted by Linode.
Debian is a registered trademark of Software in the Public Interest, Inc.

Debian Logo