## Sunday, February 7, 2010

Here is an annotated copy of my screen.lua

First off, this Lua uses more than 1 function. I can still only call a single function in conky, but in that function (called conky_draw_it below) I can use other functions.

This first 2 functions are simple enough, but show an important principal of using functions. What these functions do is to add zeros to numbers. So that percentages are always 3 digits so that when cpu usage is 5 % then 005 is displayed. Similarly time in hours, for example, is always 2 digits so that 2am is displayed as 02. This is important otherwise the changing number of digits will move everything around or overlap.
The (num) part is important. This is a string that will be set later when the function is used. Here is an example of how this function will be called "cairo_show_text (cr, (addzero100(swap)));" As you can see the place of (num) has been taken by (swap) when the function is used. The information stored in the string "swap" is given to the addzero100 function and is stored as "num". Then the function operates on the information stored in "num" and returns the result in the place of (addzero100(swap)). So if the information is "swap" was 8 (ie 8% of swap was in used) then 008 will be displayed.
if tonumber(num)
return "00" .. num
So if a number can have 3 digits, but has only a 1 digit value, 2 zeros are added.
elseif tonumber(num)
return "0" .. num
Otherwise if it has a 2 digit value 1 zero is added
else
return num
Otherwise if it has a 3 digit value nothing is added. The function below shold be self explanatory. :)
end
end
if tonumber(num)
return "0" .. num
else
return num
end
end

Here is another function. I found this here. It performs a very useful function in that it takes a string and splits it up into bits and puts the bits into a table. I'm a little hazy about how it works, but it works.
function string:split(delimiter)
local result = { }
local from = 1
local delim_from, delim_to = string.find( self, delimiter, from )
while delim_from do
table.insert( result, string.sub( self, from , delim_from-1 ) )
from = delim_to + 1
delim_from, delim_to = string.find( self, delimiter, from )
end
table.insert( result, string.sub( self, from ) )
return result
end
Ok, here we get to the function that contains all the stuff that I want displayed. This function will be using the functions above. Note that you cant use a function until it has been written... meaning that the function you are going to use must be above the function in which you want to use it.
function conky_draw_it()
if update_num > 5 then
if conky_window==nil then return end
local w=conky_window.width
local h=conky_window.height
local cs=cairo_xlib_surface_create(conky_window.display, conky_window.drawable, conky_window.visual, w, h)
cr=cairo_create(cs)
The above sets the delay and the "canvas".
--sets font, font size and color
cairo_select_font_face (cr, "White Rabbit", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD);
cairo_set_font_size (cr, 200);
cairo_set_source_rgba (cr, 1, 1, 1, 1);
In this case I initially wanted to use the same font, font size and color for all the text so I set that all up above.
--this section generates numbers only uptime ddhhmm
This section takes the output of the conky object \${uptime} which would normally be, for example, "1d 3h 25m 12s" and turns it into "010325" (no seconds)
local uptime=conky_parse("\${uptime}")
utdcalc=string.gsub(uptime, "[%d ]", "")
string.gsub was anew Lua command for me. The above takes the string "uptime" finds all numerical digits and spaces and replaces them with nothing... ie it deletes them. This is what is being looked for: "[%d ]". %d means any digit, and when placed in [] it finds digits and spaces. It would be different if the search was for "%d ". Without the [] it is now searching for a digit followed by a space only. The end result is 1d 3h 25m 12s -> dhms. This will be used in an if command below.
utime=string.split(uptime, "%a ")
Above I'm using the string split function as defined earlier in the script. As you can see, I am feeding the split string function 2 things... a string (uptime) and a search object "%a ". %a matches any letter. I am searching for a letter followed by a space. So it takes "1d 3h 25m 12s" and turns it into:
1
3
25
12
so that:
utime[1] = 1 (days)
utime[2] = 3 (hours)
utime[3] = 25 (minutes)
utime[4]= 12 (seconds)
if utdcalc=="hms" then
If uptime is less than 24 hours there will be no days in the output and therefore the following will be set as strings...
utd="00"
Also here we are using the addzero10 function, so that 3 (hours) -> 03
else
If there is a day component to uptime then "utdcalc" will not be "hms" (it will be dhms), so instead the following strings will be set.
end
Kernel, Down speed and Up speed uses a similar process as used for uptime; a combination of string.gsub and string.split.
--this section prints number only kernel information
local kernel1=conky_parse("\${kernel}")
kernel=string.gsub(kernel1, "[%a .-]", "")
--this section formats downspeed
local downspeed=conky_parse("\${downspeed}")
downnum=string.gsub(downspeed, "[%a ]", "")
dwnspcalc=string.split(downnum, "%p")
dwnumunit1=string.gsub(downspeed, "[%p%d]", "")
dwnumunit=string.gsub(dwnumunit1, "iB", "")
if dwnumunit=="M" then
dspmb=string.gsub(downnum, ".\$", "")
dsnum=(math.random(5,20))/100
Here is a feature of the conky that I implimented later on. math.random(5,20) generates a random number between 5 and 20 every cycle. I used this number divided by 100 in the line below to adjust the aplha of the text cairo displays.
cairo_set_source_rgba (cr, 1, 1, 1, dsnum);
.................................................^ here is the random number string dsnum
cairo_move_to (cr, 784, 800);
cairo_show_text (cr, (dspmb) .. (dwnumunit));
else
dsnum=(math.random(5,20))/100
cairo_set_source_rgba (cr, 1, 1, 1, dsnum);
cairo_move_to (cr, 784, 800);
end
--this section formats upspeed
local upspeed=conky_parse("\${upspeed}")
upnum=string.gsub(upspeed, "[%a ]", "")
upspcalc=string.split(upnum, "%p")
upumunit1=string.gsub(upspeed, "[%p%d]", "")
upumunit=string.gsub(upumunit1, "iB", "")
Below is the section that formats the name of the top process, as measured by cpu usage so that only the first 4 characters of the name are displayed, as I only had space for 4 characters in the conky. This one gave me some trouble as when you use the string:split function, the search criteria used to delineate the splits is deleted when the string is split. But I discovered a string.gsub trick below that solved the problem.
--this section formats top process
local topproc1=conky_parse("\${top name 1}")
topproc=string.gsub(topproc1, "[%p]", "")
First I removed all the punctuation characters. %p matches all punctuation.
top1=string.upper(topproc)
Then I put all the text into uppercase
top2=string.gsub(top1, "%a", "%1-")
Abpve is the gsub trick... it matches all letters (%a) and puts a hyphen (-) between them. So that CONKY becomes C-O-N-K-Y-
top=string.split(top2, "%p")
I was then able to split the string based on punctuation and turn the resulted split into a table.

Time outputs below use Lua os.date rather than conky_parse('\${time}')
--this section formats time outputs
--hours
hrs=os.date("%H")
--minutes
min=os.date("%M")
--seconds
sec=os.date("%S")
--year
yr=os.date("%y")
--month
mnt=os.date("%m")
--day
day=os.date("%d")

Below are all the common conky outputs to parse
--this sectiion formats common conky outputs
--cpu
local cpunum=conky_parse("\${cpu}")
cpu=tonumber(cpunum)
--mem
local memnum=conky_parse("\${memperc}")
mem=tonumber(memnum)
--hdd
local hddnum=conky_parse("\${fs_used_perc /}")
hdd=tonumber(hddnum)
--swap
local swapnum=conky_parse("\${swapperc}")
swap=tonumber(swapnum)

Below is the section that displays all of the above pieces through cairo.
--prints text
--uptime
utmnum=(math.random(5,20))/100
Above is the random alpha generator in use again.
cairo_set_source_rgba (cr, 1, 1, 1, utmnum);
cairo_move_to (cr, 261, 480);
cairo_show_text (cr, (utd .. uth .. utm))
--kernel
knum=(math.random(5,20))/100
cairo_set_source_rgba (cr, 1, 1, 1, knum);
cairo_move_to (cr, 0, 800);
cairo_show_text (cr, (kernel))
--upspeed
upsdnum=(math.random(5,20))/100
cairo_set_source_rgba (cr, 1, 1, 1, upsdnum);
cairo_move_to (cr, 261, 320);
--top process
tpnum=(math.random(5,20))/100
cairo_set_source_rgba (cr, 1, 1, 1, tpnum);
cairo_move_to (cr, 0, 640);
cairo_show_text (cr, (top[1]) .. (top[2]) .. (top[3]) .. (top[4]));
Above is how to print the first 4 characters from the name of the top process. In cairo a space followed by 2 periods and then another space, such as above, basically means print next to. So that if the top process is conky, top[1]=C, top[2]=O, top[3]=N and top[4]=K and cairo is told to display this as "CONK"
--time hours
thnum=(math.random(5,20))/100
cairo_set_source_rgba (cr, 1, 1, 1, thnum);
cairo_move_to (cr, 0, 160);
cairo_show_text (cr, (hrs));
--swapperc
swnum=(math.random(5,20))/100
cairo_set_source_rgba (cr, 1, 1, 1, swnum);
cairo_move_to (cr, 261, 160);
--month
monnum=(math.random(5,20))/100
cairo_set_source_rgba (cr, 1, 1, 1, monnum);
cairo_move_to (cr, 653, 160);
cairo_show_text (cr, (mnt));
--cpu
cnum=(math.random(5,20))/100
cairo_set_source_rgba (cr, 1, 1, 1, cnum);
cairo_move_to (cr, 915, 160);
--time minutes
cairo_set_source_rgba (cr, 1, 1, 1, thnum);
cairo_move_to (cr, 0, 320);
cairo_show_text (cr, (min));
--day
cairo_set_source_rgba (cr, 1, 1, 1, monnum);
cairo_move_to (cr, 784, 320);
cairo_show_text (cr, (day));
--year 20
yrnum=(math.random(5,20))/100
cairo_set_source_rgba (cr, 1, 1, 1, yrnum);
cairo_move_to (cr, 1043, 320);
cairo_show_text (cr, "20");
--time seconds
cairo_set_source_rgba (cr, 1, 1, 1, thnum);
cairo_move_to (cr, 0, 480);
cairo_show_text (cr, (sec));
--year 10
cairo_set_source_rgba (cr, 1, 1, 1, yrnum);
cairo_move_to (cr, 1043, 480);
cairo_show_text (cr, (yr));
--hdd used
hdnum=(math.random(5,20))/100
cairo_set_source_rgba (cr, 1, 1, 1, hdnum);
cairo_move_to (cr, 522, 640);
--memory
mnum=(math.random(5,20))/100
cairo_set_source_rgba (cr, 1, 1, 1, mnum);
cairo_move_to (cr, 915, 640);