Awesome WM Clicky Widget

Awesome WM Clicky WidgetAs some of you know, whilst Emacs is my editor (et al.) of choice my favourite window manger is Awesome. Awesome is, according to the website,

.. extremely fast, small, dynamic and heavily extensible using the Lua programming language

I’ve never delved into Lua before, but since using Awesome I’ve had to play around with a bunch of config files. They have always looked very clean and simple so, this weekend, with a spare couple of hours to kill I thought I’d have a play around with Lua and see if Awesome really is as “heavily extensible” as the claims make out.

A couple of weeks ago I set up real time web analytics on a number of sites with Clicky. Clicky have an incredibly simple API which I thought would be perfect to play around with.

I decided to try and build a widget that displays the total visitors and actions for a specified website. Really simple, but also quite useful. I had never written anything in Lua before, or even played around with widgets too much in Awesome. Fortunately both Awesome and Lua made the whole thing fantastically easy and fun. What follows is the code I wrote, use it if you want to, it’s just an example of what I did with my first attempt, so feel free to extend it as you want.

First, include the code below in a file called “clicky.lua” in your ~/.config/awesome directory. Note, you will also need to add the dkjson.lua file there too, which you can find at http://www-users.rwth-aachen.de/David.Kolf/json-lua.

-- we need the dkjson library
-- can be found here:
-- http://www-users.rwth-aachen.de/David.Kolf/json-lua
json = require ("dkjson")
 
-- Site ID and Key for Clicky
site_id = "[YOUR-CLICKY-SITE-ID]"
site_key = "[YOUR-CLICKY-SITE-KEY]"
 
-- the clicky object
Clicky = {
   actions = "n/a",
   visitors = "n/a",
 
   update = function(self, widget)
               j = self:get_json()
               self:parse_json(j)
               widget.text = Clicky.visitors .. "/" .. Clicky.actions
            end,
 
   -- call the Clicky API, expecting JSON in return
   get_json = function(self)
               clicky_url = "http://api.getclicky.com/api/stats/4?site_id="..site_id.."&sitekey="..site_key.."&type=visitors,actions&date=today&output=json"
               -- get the visitors and actions for today
               command = 'curl -s "'..clicky_url..'"'
               f = io.popen(command)
               if (not f) then return 0 end
               -- store the returned json as a string
               return f:read("*all")
            end,
 
   -- parse the JSON from Clicky
   parse_json = function(self, j)
                   local obj, pos, err = json.decode (j, 1, nil)
                   if err then
                      self.actions = "e"
                      self.visitors = "e"
                   else
                      for k,v in pairs(obj) do
                         if v["type"] == "actions" then
                            self.actions = v["dates"][1]["items"][1]["value"]
                         end
                         if v["type"] == "visitors" then
                            self.visitors = v["dates"][1]["items"][1]["value"]
                         end
                      end
                   end
                end
}
 
-- init the widget
myclickystats = widget({ type = "textbox", name = "clicky", align = "right" })
myclickystats.text = "Clicky"
 
-- get the initial update
Clicky:update(myclickystats)
 
-- now poll every 15 minutes
minutes = 15
myclickytimer = timer({ timeout = 60 * minutes })
myclickytimer:add_signal("timeout", function() Clicky:update(myclickystats) end)
myclickytimer:start()

Now, in your ~/.config/awesome/rc.lua file you need to insert two snippets.

Towards the top of the file, add

-- Include my Clicky stats
require("clicky")

and within the screen loop add the myclickystats widget

for s = 1, screen.count() do
   ...
    -- Add widgets to the wibox - order matters
    mywibox[s].widgets = {
        ...
        s == 1 and myclickystats or nil,
        ...
    }
end

and that should be it. Restart awesome with <Super> – <Ctrl> – r and if you have done everything right you should see something like x/y in the top right of your screen. (Disclaimer: the above setup works for me on Ubuntu 9.10 and Arch, but if Awesome doesn’t restart you’re on your own!)

After building this simple widget I have learnt a lot about both Lua and Awesome.

On this, my first impression of Lua, it seems very simple and clean but also probably quite powerful, something I’ll definitely play with more.

Update: added screenshot after tweet from @getclicky.

  • http://twitter.com/divergenta Jonas

    Today I decided to learn the basics of lua and I found this post my a happy coincidence. I think your little script will be helpful. Looked around on your blog and I like it very much. Will add you to my rss reader. keep it up!

    • http://www.robsearles.com Rob Searles

      Thanks Jonas, glad you found it helpful. I’ve been playing around with Lua a little bit more, so hopefully I’ll add a few more Lua focused blog posts.

  • http://twitter.com/divergenta Jonas

    Today I decided to learn the basics of lua and I found this post my a happy coincidence. I think your little script will be helpful. Looked around on your blog and I like it very much. Will add you to my rss reader. keep it up!

  • http://www.robsearles.com Rob Searles

    Thanks Jonas, glad you found it helpful. I've been playing around with Lua a little bit more, so hopefully I'll add a few more Lua focused blog posts.

  • Pingback: Node with Lua bindings? Luvit!