Part 11 FOR LOOPS and A CPU HISTORY CHART
for loops are extremely useful when you need to do the same thing a number of times
there are many ways you can use the FOR operator, but the way that I use the most is like so:
for example
for i=1,10 do
print (i)
end
the i=1,10 is telling the script to perform the code within the loop (everything from the do to the end) for a certain number of times
when just written as i=1,10, the code will be repeated 10 times for every whole number between 1 and 10, starting at 1 and ending at 10 (you can tell the code to count in different increments or even in reverse but i usually find counting by whole numbers to work)
change the numbers in the line to get different numbers of passes of the loop, different starting points and different ending points
BUT not only is the loop repeated for the designated number of times, the useful part is that for each pass of the loop the value of "i" changes when it is used inside the loop.
so in our loop above:
- the loop starts, "i" is set to a value of 1 inside the loop,
- the code within the loop is executed and we print 1 to the terminal
because i=1 and we are printing i
(i is a just like other strings we have set values to)
the loop repeats, "i" is set to a value of 2 inside the loop, the code is executed, we print 2 to the terminal
loop repeats, i=3, print 3 to terminal
loop repeats, i=4, print 4 to terminal
and so on until i=10 and then the loop is done
so in the terminal we see
what makes this useful is that we can then use the changing values for i in calculations.
Say you wanted a horizontal row of 10 filled in white circles with each circle center 20 pixels away from the next with the first circle starting at coordinates 10,10
we would set our colors and set up the cairo_arc function (x,y,radius,start_angle, end_angle) then draw the circle like this
cairo_set_source_rgba (cr,1,1,1,1)
cairo_arc (cr,10,10,10,0,2*math.pi)
cairo_fill (cr)
then we could copy and paste the code a further 9 times and edit the x coordinates for every subsequent circle
or we could use a for loop and have it do the repeats for us
we can set our color outside of the loop as we want all our circles to be white
cairo_set_source_rgba (cr,1,1,1,1)
for i=1,10 do
x=10+((i-1)*20)
cairo_arc (cr,x,10,10,0,2*math.pi)
cairo_fill (cr)
end
in the above code ive separated the calculation for x out of the arc function and set a string called "x" to the value of the equation
this equation takes the value of i and subtracts 1 from it (so our first circle is drawn at x = 10)
it then multiplies i-1 by 20 which is the gap we want between our circles
then adds 10 which is the staring x for our first circle
so the for loop is activated and "i" is set to 1 so our equation works out so that x=10
and our first circle is drawn at coordinates 10,10 as we wanted
the loop repeats and "i" is set to 2. The equation works out so that x=30
and our next circle is drawn at coordinates 30,10 (ie 20 pixels further on from our first circle)
the loop continues until "i" = 10 and we end up with 10 circles positioned as we wanted
using equations you can do a lot with a simple progression of numbers as you get in this version of the for loop!
Another good use of the for loop is to put data into tables or read the data that is in a table.
Here is another lua display project to work on that uses these techniques:
the cpu history chart
conky has the ability to display a chart showing your cpu usage history with just a short command. It takes a little more to do the same thing in lua, but when you are done you have much more flexibility in how to use it
the first thing we need to be able to do it record out cpu usage over a period of time so that we have something to display. To do this we are going to use a table and we are going to get the data into the table using a for loop.
The type of table we will use is an indexed table, and in this case our table will only contain numbers
Indexed tables
these kinds of tables usually look like this when you write them out (i'll only put numbers into the table for now, but it can hold other things too)
somedata={13,44,25,26,10}
so unlike the "dictionary" takes we used before, this table only has one part to each bit of information.
commas are always used in tables to separate values
in an indexed table, we are concerned about the order in which the data is in the table.
in the table above
position 1 in the table holds the number 13,
position 2 holds the number 44 and so on
to get the data out of the table we have to use a slightly different method
tablename[tableposition]
you have to use the square brackets for this purpose
so i called the table "somedata", so to get the first entry in the table we put:
NOTE we can also use the square brackets to get data out of dictionary tables
dosettings={--set table and open
red=1,
green=0,
blue=0,
alpha=1,--alpha of 0 = full transparent, 1=full opaque
font="mono",
fontsize=12,
}--closes table
print (dosettings["font"]) -->prints "mono" in the terminal
getting data into a table
Tables can be constructed by putting data into them via code rather than having to write the consent into the table directly
We can use the square brackets to get information into tables (just thinking about indexed tables for now)
we can set up a blank table like this
then we can use this code to put the number 16 into the first position of the table
and we can continue adding values using the same method
AS LONG AS we don't skip over any positions
datatable[2]=18
datatable[3]=20
datatable[4]=22
if we were able to look at the contents of "datatable" directly it would look like this
in fact is is quite easy to take a look at what is in a table using a for loop
reading a table with a for loop
the first thing we need to know is how many repeats we need the loop to do in order to see all the values in the table. In the above case we know that we have put 4 values into the table, but sometimes you dont know ahead of time how many things there are in a table.
an easy way to find out is to put # in front of the table name like so
--set blank table
datatable={}
--put data into table
datatable[1]=16
datatable[2]=18
datatable[3]=20
datatable[4]=22
--count entries
entries=#datatable
print (entries) --> 4 is printed to the terminal
then we can do this
for i=1,entries do
print ( datatable[i] )
end
so what happening in the loop?
loop starts, "i"=1 inside the loop
the code in the loop is executed
and since i=1, we print the number in the first position of the table "datatable" and we see
printed in the terminal.
The loop repeats, "i"=2
18 is printed in the terminal
The loop repeats, "i"=3
20 is printed to the terminal
The loop repeats, "i"=4 (the upper limit of the loop since entries=4)
22 is printed to the terminal
end of loop.
NOTE the loop is activated and repeats until done before any subsequent code in the script is executed
So lets think about what is required to get our cpu history chart
The first thing to consider is that we want to information in our cpu table to be persistent from one execution of the lua script to the next and that leads us to think a bit more about how the whole lua script within conky works!
EXECUTING THE LUA SCRIPT
every conky cycle the entire lua script is executed BUT we can write code in the lua script with conditions, using if statements for example, to control the operation of different bits of code. We already saw this in the setup lines required by the conky main function.
we used the line
if updates>5 then
--all the code stuff
end--if updates>5
the point of this condition is so that you don't get a segmentation fault if you try and access cpu values via the lua script
conky updates are quite useful for controlling other things too.
now if we had a setup like this:
function conky_main()
--main conky function setup lines
if updates>5 then
--##############################
--set blank table
cputable={}
--put data into table
cputable[1]=conky_parse("${cpu}")
--##############################
end-- if updates>5
--main function close out lines
end-- end main function
then every cycle of conky, as long as the update number is above 5 the script is executed
beginning "updates=6" (since updates>5) the table called "cputable" is set blank and then subsequently the cpu usage value is put into it
the next conky cycle "updates=7" (since updates is still > than 5 and will be for every additional cycle)
the lua script is executed from the beginning and "cputable" is set blank again and again the current cpu% is put into it
clearly this isnt going to get us anywhere because we are blanking our table each cycle
we want the script to "remember" the values for cpu from previous conky cycles
SO
we have to come up with a situation where the table "cputable" is set up blank only once and not blanked each time the lua script is executed
something like this will do it
function conky_main()
--main conky function setup lines
--setup cpu table
if updates=4 then
cputable={}
end
if updates>5 then
--##############################
cputable[1]=conky_parse("${cpu}")
--##############################
end-- if updates>5
--main function close out lines
end-- end main function
there will be only one time when "updates=4" so only one occasion for the table to be created
every subsequent conky cycle "updates" will not equal 4 so the table isnt blanked and will be persistent from
but the next problem is that we are writing (and then overwriting) the current cpu% to position1 in the table each cycle!
to be continued 
OOOOPS i tried making my text within code brackets bold, but it didnt work, just put and into the code!
ive removed these now
also saw that i had missed a bracket on my equations, also fixed
Last edited by mrpeachy (2012-01-31 03:02:08)
It's hard to find something if you don't know what you're looking for.
I have a blog, it's mostly about conky and lua stuff... go
here.