From aedf4ef0ec9712789310b5b6d7d06af90f4f6261 Mon Sep 17 00:00:00 2001
From: xero <x@xero.nu>
Date: Sat, 8 Mar 2014 22:14:34 -0500
Subject: add awesome wm config files and v0.1.0 of ghost theme.

---
 .config/awesome/lain/widgets/alsa.lua              |  65 +++++++
 .config/awesome/lain/widgets/alsabar.lua           | 175 ++++++++++++++++++
 .config/awesome/lain/widgets/base.lua              |  40 +++++
 .config/awesome/lain/widgets/bat.lua               | 149 +++++++++++++++
 .config/awesome/lain/widgets/borderbox.lua         |  61 +++++++
 .config/awesome/lain/widgets/calendar.lua          | 125 +++++++++++++
 .config/awesome/lain/widgets/contrib/ccurr.lua     |  82 +++++++++
 .config/awesome/lain/widgets/contrib/init.lua      |  20 +++
 .config/awesome/lain/widgets/contrib/task.lua      | 133 ++++++++++++++
 .../awesome/lain/widgets/contrib/tpbat/init.lua    | 166 +++++++++++++++++
 .../awesome/lain/widgets/contrib/tpbat/smapi.lua   | 102 +++++++++++
 .config/awesome/lain/widgets/cpu.lua               |  77 ++++++++
 .config/awesome/lain/widgets/fs.lua                | 120 +++++++++++++
 .config/awesome/lain/widgets/imap.lua              |  87 +++++++++
 .config/awesome/lain/widgets/init.lua              |  20 +++
 .config/awesome/lain/widgets/maildir.lua           |  95 ++++++++++
 .config/awesome/lain/widgets/mem.lua               |  61 +++++++
 .config/awesome/lain/widgets/mpd.lua               | 110 ++++++++++++
 .config/awesome/lain/widgets/net.lua               | 102 +++++++++++
 .config/awesome/lain/widgets/sysload.lua           |  46 +++++
 .config/awesome/lain/widgets/temp.lua              |  48 +++++
 .../lain/widgets/yawn/icons/BlowingSnow.png        | Bin 0 -> 11454 bytes
 .config/awesome/lain/widgets/yawn/icons/Cloudy.png | Bin 0 -> 7469 bytes
 .../awesome/lain/widgets/yawn/icons/DayClear.png   | Bin 0 -> 6147 bytes
 .../awesome/lain/widgets/yawn/icons/DayFair.png    |   1 +
 .../lain/widgets/yawn/icons/DayMostlyCloudy.png    | Bin 0 -> 8016 bytes
 .../lain/widgets/yawn/icons/DayPartlyCloudy.png    | Bin 0 -> 7478 bytes
 .../awesome/lain/widgets/yawn/icons/Drizzle.png    |   1 +
 .config/awesome/lain/widgets/yawn/icons/Fog.png    |   1 +
 .config/awesome/lain/widgets/yawn/icons/Foggy.png  | Bin 0 -> 7325 bytes
 .../lain/widgets/yawn/icons/FreezingDrizzle.png    | Bin 0 -> 13166 bytes
 .../lain/widgets/yawn/icons/FreezingRain.png       | Bin 0 -> 13979 bytes
 .config/awesome/lain/widgets/yawn/icons/Hail.png   | Bin 0 -> 7325 bytes
 .config/awesome/lain/widgets/yawn/icons/Haze.png   |   1 +
 .../awesome/lain/widgets/yawn/icons/HeavyRain.png  |   1 +
 .../awesome/lain/widgets/yawn/icons/HeavySnow.png  | Bin 0 -> 12733 bytes
 .../awesome/lain/widgets/yawn/icons/LightRain.png  |   1 +
 .../awesome/lain/widgets/yawn/icons/LightSnow.png  |   1 +
 .../lain/widgets/yawn/icons/LightSnowShowers.png   | Bin 0 -> 8779 bytes
 .config/awesome/lain/widgets/yawn/icons/Mist.png   |   1 +
 .../lain/widgets/yawn/icons/MixedRainAndHail.png   | Bin 0 -> 9060 bytes
 .../lain/widgets/yawn/icons/MixedRainAndSleet.png  | Bin 0 -> 10978 bytes
 .../lain/widgets/yawn/icons/MixedRainAndSnow.png   | Bin 0 -> 10808 bytes
 .../awesome/lain/widgets/yawn/icons/NightClear.png | Bin 0 -> 5198 bytes
 .../awesome/lain/widgets/yawn/icons/NightFair.png  |   1 +
 .../lain/widgets/yawn/icons/NightMostlyCloudy.png  | Bin 0 -> 7058 bytes
 .../lain/widgets/yawn/icons/NightPartlyCloudy.png  | Bin 0 -> 6583 bytes
 .config/awesome/lain/widgets/yawn/icons/README.md  |   6 +
 .config/awesome/lain/widgets/yawn/icons/Rain.png   | Bin 0 -> 8052 bytes
 .../lain/widgets/yawn/icons/RainThunder.png        | Bin 0 -> 9879 bytes
 .../awesome/lain/widgets/yawn/icons/Showers.png    | Bin 0 -> 9694 bytes
 .config/awesome/lain/widgets/yawn/icons/Sleet.png  |   1 +
 .config/awesome/lain/widgets/yawn/icons/Snow.png   |   1 +
 .../lain/widgets/yawn/icons/SnowFlurries.png       |   1 +
 .../lain/widgets/yawn/icons/SnowShowers.png        | Bin 0 -> 9961 bytes
 .config/awesome/lain/widgets/yawn/icons/Sunny.png  | Bin 0 -> 14018 bytes
 .../widgets/yawn/icons/ThunderintheVicinity.png    |   1 +
 .config/awesome/lain/widgets/yawn/icons/Wind.png   | Bin 0 -> 8726 bytes
 .config/awesome/lain/widgets/yawn/icons/na.png     | Bin 0 -> 11160 bytes
 .config/awesome/lain/widgets/yawn/init.lua         | 200 +++++++++++++++++++++
 .../awesome/lain/widgets/yawn/localizations/it_IT  |  60 +++++++
 .../yawn/localizations/localization_template       |  60 +++++++
 62 files changed, 2223 insertions(+)
 create mode 100644 .config/awesome/lain/widgets/alsa.lua
 create mode 100644 .config/awesome/lain/widgets/alsabar.lua
 create mode 100644 .config/awesome/lain/widgets/base.lua
 create mode 100644 .config/awesome/lain/widgets/bat.lua
 create mode 100644 .config/awesome/lain/widgets/borderbox.lua
 create mode 100644 .config/awesome/lain/widgets/calendar.lua
 create mode 100644 .config/awesome/lain/widgets/contrib/ccurr.lua
 create mode 100644 .config/awesome/lain/widgets/contrib/init.lua
 create mode 100644 .config/awesome/lain/widgets/contrib/task.lua
 create mode 100644 .config/awesome/lain/widgets/contrib/tpbat/init.lua
 create mode 100644 .config/awesome/lain/widgets/contrib/tpbat/smapi.lua
 create mode 100644 .config/awesome/lain/widgets/cpu.lua
 create mode 100644 .config/awesome/lain/widgets/fs.lua
 create mode 100644 .config/awesome/lain/widgets/imap.lua
 create mode 100644 .config/awesome/lain/widgets/init.lua
 create mode 100644 .config/awesome/lain/widgets/maildir.lua
 create mode 100644 .config/awesome/lain/widgets/mem.lua
 create mode 100644 .config/awesome/lain/widgets/mpd.lua
 create mode 100644 .config/awesome/lain/widgets/net.lua
 create mode 100644 .config/awesome/lain/widgets/sysload.lua
 create mode 100644 .config/awesome/lain/widgets/temp.lua
 create mode 100755 .config/awesome/lain/widgets/yawn/icons/BlowingSnow.png
 create mode 100755 .config/awesome/lain/widgets/yawn/icons/Cloudy.png
 create mode 100755 .config/awesome/lain/widgets/yawn/icons/DayClear.png
 create mode 120000 .config/awesome/lain/widgets/yawn/icons/DayFair.png
 create mode 100755 .config/awesome/lain/widgets/yawn/icons/DayMostlyCloudy.png
 create mode 100755 .config/awesome/lain/widgets/yawn/icons/DayPartlyCloudy.png
 create mode 120000 .config/awesome/lain/widgets/yawn/icons/Drizzle.png
 create mode 120000 .config/awesome/lain/widgets/yawn/icons/Fog.png
 create mode 100755 .config/awesome/lain/widgets/yawn/icons/Foggy.png
 create mode 100755 .config/awesome/lain/widgets/yawn/icons/FreezingDrizzle.png
 create mode 100755 .config/awesome/lain/widgets/yawn/icons/FreezingRain.png
 create mode 100755 .config/awesome/lain/widgets/yawn/icons/Hail.png
 create mode 120000 .config/awesome/lain/widgets/yawn/icons/Haze.png
 create mode 120000 .config/awesome/lain/widgets/yawn/icons/HeavyRain.png
 create mode 100755 .config/awesome/lain/widgets/yawn/icons/HeavySnow.png
 create mode 120000 .config/awesome/lain/widgets/yawn/icons/LightRain.png
 create mode 120000 .config/awesome/lain/widgets/yawn/icons/LightSnow.png
 create mode 100755 .config/awesome/lain/widgets/yawn/icons/LightSnowShowers.png
 create mode 120000 .config/awesome/lain/widgets/yawn/icons/Mist.png
 create mode 100755 .config/awesome/lain/widgets/yawn/icons/MixedRainAndHail.png
 create mode 100755 .config/awesome/lain/widgets/yawn/icons/MixedRainAndSleet.png
 create mode 100755 .config/awesome/lain/widgets/yawn/icons/MixedRainAndSnow.png
 create mode 100755 .config/awesome/lain/widgets/yawn/icons/NightClear.png
 create mode 120000 .config/awesome/lain/widgets/yawn/icons/NightFair.png
 create mode 100755 .config/awesome/lain/widgets/yawn/icons/NightMostlyCloudy.png
 create mode 100755 .config/awesome/lain/widgets/yawn/icons/NightPartlyCloudy.png
 create mode 100644 .config/awesome/lain/widgets/yawn/icons/README.md
 create mode 100755 .config/awesome/lain/widgets/yawn/icons/Rain.png
 create mode 100755 .config/awesome/lain/widgets/yawn/icons/RainThunder.png
 create mode 100755 .config/awesome/lain/widgets/yawn/icons/Showers.png
 create mode 120000 .config/awesome/lain/widgets/yawn/icons/Sleet.png
 create mode 120000 .config/awesome/lain/widgets/yawn/icons/Snow.png
 create mode 120000 .config/awesome/lain/widgets/yawn/icons/SnowFlurries.png
 create mode 100755 .config/awesome/lain/widgets/yawn/icons/SnowShowers.png
 create mode 100755 .config/awesome/lain/widgets/yawn/icons/Sunny.png
 create mode 120000 .config/awesome/lain/widgets/yawn/icons/ThunderintheVicinity.png
 create mode 100755 .config/awesome/lain/widgets/yawn/icons/Wind.png
 create mode 100755 .config/awesome/lain/widgets/yawn/icons/na.png
 create mode 100644 .config/awesome/lain/widgets/yawn/init.lua
 create mode 100644 .config/awesome/lain/widgets/yawn/localizations/it_IT
 create mode 100644 .config/awesome/lain/widgets/yawn/localizations/localization_template

(limited to '.config/awesome/lain/widgets')

diff --git a/.config/awesome/lain/widgets/alsa.lua b/.config/awesome/lain/widgets/alsa.lua
new file mode 100644
index 0000000..28bb05c
--- /dev/null
+++ b/.config/awesome/lain/widgets/alsa.lua
@@ -0,0 +1,65 @@
+
+--[[
+                                                  
+     Licensed under GNU General Public License v2 
+      * (c) 2013, Luke Bonham                     
+      * (c) 2010, Adrian C. <anrxc@sysphere.org>  
+                                                  
+--]]
+
+local newtimer        = require("lain.helpers").newtimer
+
+local wibox           = require("wibox")
+
+local io              = { popen  = io.popen }
+local string          = { match  = string.match }
+
+local setmetatable    = setmetatable
+
+-- ALSA volume
+-- lain.widgets.alsa
+local alsa = {}
+
+local function worker(args)
+    local args     = args or {}
+    local timeout  = args.timeout or 5
+    local channel  = args.channel or "Master"
+    local settings = args.settings or function() end
+
+    alsa.widget = wibox.widget.textbox('')
+
+    function alsa.update()
+        local f = assert(io.popen('amixer get ' .. channel))
+        local mixer = f:read("*all")
+        f:close()
+
+        volume_now = {}
+
+        volume_now.level, volume_now.status = string.match(mixer, "([%d]+)%%.*%[([%l]*)")
+
+        if volume_now.level == nil
+        then
+            volume_now.level  = "0"
+            volume_now.status = "off"
+        end
+
+        if volume_now.status == ""
+        then
+            if volume_now.level == "0"
+            then
+                volume_now.status = "off"
+            else
+                volume_now.status = "on"
+            end
+        end
+
+        widget = alsa.widget
+        settings()
+    end
+
+    newtimer("alsa", timeout, alsa.update)
+
+    return setmetatable(alsa, { __index = alsa.widget })
+end
+
+return setmetatable(alsa, { __call = function(_, ...) return worker(...) end })
diff --git a/.config/awesome/lain/widgets/alsabar.lua b/.config/awesome/lain/widgets/alsabar.lua
new file mode 100644
index 0000000..365ac2d
--- /dev/null
+++ b/.config/awesome/lain/widgets/alsabar.lua
@@ -0,0 +1,175 @@
+
+--[[
+                                                  
+     Licensed under GNU General Public License v2 
+      * (c) 2013, Luke Bonham                     
+      * (c) 2013, Rman                            
+                                                  
+--]]
+
+local newtimer     = require("lain.helpers").newtimer
+
+local awful        = require("awful")
+local beautiful    = require("beautiful")
+local naughty      = require("naughty")
+
+local io           = { popen  = io.popen }
+local math         = { modf   = math.modf }
+local string       = { format = string.format,
+                       match  = string.match,
+                       rep    = string.rep }
+local tonumber     = tonumber
+
+local setmetatable = setmetatable
+
+-- ALSA volume bar
+-- lain.widgets.alsabar
+local alsabar =
+{
+  channel = "Master",
+  step    = "5%",
+
+  colors =
+  {
+     background = beautiful.bg_normal,
+     mute       = "#EB8F8F",
+     unmute     = "#A4CE8A"
+  },
+
+  terminal = terminal or "xterm",
+  mixer    = terminal .. " -e alsamixer",
+
+  notifications =
+  {
+     font      = beautiful.font:sub(beautiful.font:find(""), beautiful.font:find(" ")),
+     font_size = "11",
+     color     = beautiful.fg_normal,
+     bar_size  = 18
+  },
+
+  _current_level = 0,
+  _muted         = false
+}
+
+function alsabar.notify()
+  alsabar.update()
+
+	local preset =
+	{
+      title   = "",
+      text    = "",
+      timeout = 4,
+      font    = alsabar.notifications.font .. " " ..
+                alsabar.notifications.font_size,
+      fg      = alsabar.notifications.color
+	}
+
+	if alsabar._muted
+  then
+		preset.title = alsabar.channel .. " - Muted"
+	else
+		preset.title = alsabar.channel .. " - " .. alsabar._current_level * 100 .. "%"
+	end
+
+  int = math.modf(alsabar._current_level * alsabar.notifications.bar_size)
+  preset.text = "["
+                .. string.rep("|", int)
+                .. string.rep(" ", alsabar.notifications.bar_size - int)
+                .. "]"
+
+  if alsabar._notify ~= nil then
+		alsabar._notify = naughty.notify ({
+        replaces_id = alsabar._notify.id,
+			  preset      = preset
+    })
+	else
+		alsabar._notify = naughty.notify ({
+        preset = preset
+    })
+	end
+end
+
+local function worker(args)
+    local args = args or {}
+    local timeout = args.timeout or 4
+    local settings = args.settings or function() end
+    local width = args.width or 63
+    local height = args.heigth or 1
+    local ticks = args.ticks or false
+    local ticks_size = args.ticks_size or 7
+    local vertical = args.vertical or false
+
+    alsabar.channel = args.channel or alsabar.channel
+    alsabar.step = args.step or alsabar.step
+    alsabar.colors = args.colors or alsabar.colors
+    alsabar.notifications = args.notifications or alsabar.notifications
+
+    alsabar.bar = awful.widget.progressbar()
+
+    alsabar.bar:set_background_color(alsabar.colors.background)
+    alsabar.bar:set_color(alsabar.colors.unmute)
+    alsabar.tooltip = awful.tooltip({ objects = { alsabar.bar } })
+    alsabar.bar:set_width(width)
+    alsabar.bar:set_height(height)
+    alsabar.bar:set_ticks(ticks)
+    alsabar.bar:set_ticks_size(ticks_size)
+    alsabar.bar:set_vertical(vertical)
+
+    function alsabar.update()
+        -- Get mixer control contents
+        local f = io.popen("amixer get " .. alsabar.channel)
+        local mixer = f:read("*all")
+        f:close()
+
+        -- Capture mixer control state:          [5%] ... ... [on]
+        local volu, mute = string.match(mixer, "([%d]+)%%.*%[([%l]*)")
+
+        if volu == nil then
+            volu = 0
+            mute = "off"
+        end
+
+        alsabar._current_level = tonumber(volu) / 100
+        alsabar.bar:set_value(alsabar._current_level)
+
+        if not mute and tonumber(volu) == 0 or mute == "off"
+        then
+            alsabar._muted = true
+            alsabar.tooltip:set_text (" [Muted] ")
+            alsabar.bar:set_color(alsabar.colors.mute)
+        else
+            alsabar._muted = false
+            alsabar.tooltip:set_text(string.format(" %s:%s ", alsabar.channel, volu))
+            alsabar.bar:set_color(alsabar.colors.unmute)
+        end
+
+        volume_now = {}
+        volume_now.level = tonumber(volu)
+        volume_now.status = mute
+        settings()
+    end
+
+    newtimer("alsabar", timeout, alsabar.update)
+
+    alsabar.bar:buttons (awful.util.table.join (
+          awful.button ({}, 1, function()
+            awful.util.spawn(alsabar.mixer)
+          end),
+          awful.button ({}, 3, function()
+            awful.util.spawn(string.format("amixer set %s toggle", alsabar.channel))
+            alsabar.update()
+          end),
+          awful.button ({}, 4, function()
+            awful.util.spawn(string.format("amixer set %s %s+", alsabar.channel, alsabar.step))
+            alsabar.update()
+          end),
+          awful.button ({}, 5, function()
+            awful.util.spawn(string.format("amixer set %s %s-", alsabar.channel, alsabar.step))
+            alsabar.update()
+          end)
+    ))
+
+    return alsabar
+end
+
+return setmetatable(alsabar, { __call = function(_, ...) return worker(...) end })
diff --git a/.config/awesome/lain/widgets/base.lua b/.config/awesome/lain/widgets/base.lua
new file mode 100644
index 0000000..3d4ce9e
--- /dev/null
+++ b/.config/awesome/lain/widgets/base.lua
@@ -0,0 +1,40 @@
+
+--[[
+                                                  
+     Licensed under GNU General Public License v2 
+      * (c) 2014, Luke Bonham                     
+                                                  
+--]]
+
+local newtimer     = require("lain.helpers").newtimer
+local wibox        = require("wibox")
+
+local io           = io
+local setmetatable = setmetatable
+
+-- Basic template for custom widgets 
+-- lain.widgets.base
+local base = {}
+
+local function worker(args)
+    local args     = args or {}
+    local timeout  = args.timeout or 5
+    local cmd      = args.cmd or ""
+    local settings = args.settings or function() end
+
+    base.widget = wibox.widget.textbox('')
+
+    function base.update()
+        local f = assert(io.popen(cmd))
+        output = f:read("*all")
+        f:close()
+        widget = base.widget
+        settings()
+    end
+
+    newtimer(cmd, timeout, base.update)
+
+    return setmetatable(base, { __index = base.widget })
+end
+
+return setmetatable(base, { __call = function(_, ...) return worker(...) end })
diff --git a/.config/awesome/lain/widgets/bat.lua b/.config/awesome/lain/widgets/bat.lua
new file mode 100644
index 0000000..485fd57
--- /dev/null
+++ b/.config/awesome/lain/widgets/bat.lua
@@ -0,0 +1,149 @@
+
+--[[
+                                                  
+     Licensed under GNU General Public License v2 
+      * (c) 2013,      Luke Bonham                
+      * (c) 2010-2012, Peter Hofmann              
+                                                  
+--]]
+
+local newtimer     = require("lain.helpers").newtimer
+local first_line   = require("lain.helpers").first_line
+
+local naughty      = require("naughty")
+local wibox        = require("wibox")
+
+local math         = { floor  = math.floor }
+local string       = { format = string.format }
+local tonumber     = tonumber
+
+local setmetatable = setmetatable
+
+-- Battery infos
+-- lain.widgets.bat
+local bat = {}
+
+local function worker(args)
+    local args = args or {}
+    local timeout = args.timeout or 30
+    local battery = args.battery or "BAT0"
+    local notify = args.notify or "on"
+    local settings = args.settings or function() end
+
+    bat.widget = wibox.widget.textbox('')
+
+    bat_notification_low_preset = {
+        title = "Battery low",
+        text = "Plug the cable!",
+        timeout = 15,
+        fg = "#202020",
+        bg = "#CDCDCD"
+    }
+
+    bat_notification_critical_preset = {
+        title = "Battery exhausted",
+        text = "Shutdown imminent",
+        timeout = 15,
+        fg = "#000000",
+        bg = "#FFFFFF"
+    }
+
+    function update()
+        bat_now = {
+            status = "Not present",
+            perc   = "N/A",
+            time   = "N/A",
+            watt   = "N/A"
+        }
+
+        local bstr  = "/sys/class/power_supply/" .. battery
+
+        local present = first_line(bstr .. "/present")
+
+        if present == "1"
+        then
+            local rate  = first_line(bstr .. "/power_now") or
+                          first_line(bstr .. "/current_now")
+
+            local ratev = first_line(bstr .. "/voltage_now")
+
+            local rem   = first_line(bstr .. "/energy_now") or
+                          first_line(bstr .. "/charge_now")
+
+            local tot   = first_line(bstr .. "/energy_full") or
+                          first_line(bstr .. "/charge_full")
+
+            bat_now.status = first_line(bstr .. "/status") or "N/A"
+
+            rate  = tonumber(rate) or 1
+            ratev = tonumber(ratev)
+            rem   = tonumber(rem)
+            tot   = tonumber(tot)
+
+            local time_rat = 0
+            if bat_now.status == "Charging"
+            then
+                time_rat = (tot - rem) / rate
+            elseif bat_now.status == "Discharging"
+            then
+                time_rat = rem / rate
+            end
+
+            local hrs = math.floor(time_rat)
+            if hrs < 0 then hrs = 0 elseif hrs > 23 then hrs = 23 end
+
+            local min = math.floor((time_rat - hrs) * 60)
+            if min < 0 then min = 0 elseif min > 59 then min = 59 end
+
+            bat_now.time = string.format("%02d:%02d", hrs, min)
+
+            bat_now.perc = first_line(bstr .. "/capacity")
+
+            if not bat_now.perc then
+                local perc = (rem / tot) * 100
+                if perc <= 100 then
+                    bat_now.perc = string.format("%d", perc)
+                elseif perc > 100 then
+                    bat_now.perc = "100"
+                elseif perc < 0 then
+                    bat_now.perc = "0"
+                end
+            end
+
+            if rate ~= nil and ratev ~= nil then
+                bat_now.watt = string.format("%.2fW", (rate * ratev) / 1e12)
+            else
+                bat_now.watt = "N/A"
+            end
+
+        end
+
+        widget = bat.widget
+        settings()
+
+        -- notifications for low and critical states
+        bat_now.perc = tonumber(bat_now.perc)
+        if bat_now.status == "Discharging" and notify == "on" and bat_now.perc ~= nil
+        then
+            if bat_now.perc <= 5
+            then
+                bat.id = naughty.notify({
+                    preset = bat_notification_critical_preset,
+                    replaces_id = bat.id
+                }).id
+            elseif bat_now.perc <= 15
+            then
+                bat.id = naughty.notify({
+                    preset = bat_notification_low_preset,
+                    replaces_id = bat.id
+                }).id
+            end
+        end
+    end
+
+    newtimer("bat", timeout, update)
+
+    return bat.widget
+end
+
+return setmetatable(bat, { __call = function(_, ...) return worker(...) end })
diff --git a/.config/awesome/lain/widgets/borderbox.lua b/.config/awesome/lain/widgets/borderbox.lua
new file mode 100644
index 0000000..c251ea8
--- /dev/null
+++ b/.config/awesome/lain/widgets/borderbox.lua
@@ -0,0 +1,61 @@
+
+--[[
+                                                  
+     Licensed under GNU General Public License v2 
+      * (c) 2013,      Luke Bonham                
+      * (c) 2010-2012, Peter Hofmann              
+                                                  
+--]]
+
+local wibox        = require("awful.wibox")
+local setmetatable = setmetatable
+
+-- Creates a thin wibox at a position relative to another wibox
+-- lain.widgets.borderbox
+local borderbox = {}
+
+local function worker(relbox, s, args)
+    local where = args.position or 'top'
+    local color = args.color or '#FFFFFF'
+    local size = args.size or 1
+    local box = nil
+    local wiboxarg = {
+        position = nil,
+        bg = color
+    }
+
+    if where == 'top'
+    then
+        wiboxarg.width = relbox.width
+        wiboxarg.height = size
+        box = wibox(wiboxarg)
+        box.x = relbox.x
+        box.y = relbox.y - size
+    elseif where == 'bottom'
+    then
+        wiboxarg.width = relbox.width
+        wiboxarg.height = size
+        box = wibox(wiboxarg)
+        box.x = relbox.x
+        box.y = relbox.y + relbox.height
+    elseif where == 'left'
+    then
+        wiboxarg.width = size
+        wiboxarg.height = relbox.height
+        box = wibox(wiboxarg)
+        box.x = relbox.x - size
+        box.y = relbox.y
+    elseif where == 'right'
+    then
+        wiboxarg.width = size
+        wiboxarg.height = relbox.height
+        box = wibox(wiboxarg)
+        box.x = relbox.x + relbox.width
+        box.y = relbox.y
+    end
+
+    box.screen = s
+    return box
+end
+
+return setmetatable(borderbox, { __call = function(_, ...) return worker(...) end })
diff --git a/.config/awesome/lain/widgets/calendar.lua b/.config/awesome/lain/widgets/calendar.lua
new file mode 100644
index 0000000..c9e265a
--- /dev/null
+++ b/.config/awesome/lain/widgets/calendar.lua
@@ -0,0 +1,125 @@
+
+--[[
+                                                  
+     Licensed under GNU General Public License v2 
+      * (c) 2013, Luke Bonham                     
+                                                  
+--]]
+
+local icons_dir    = require("lain.helpers").icons_dir
+
+local awful        = require("awful")
+local beautiful    = require("beautiful")
+local naughty      = require("naughty")
+
+local io           = io
+local os           = { date = os.date }
+local tonumber     = tonumber
+
+local setmetatable = setmetatable
+
+-- Calendar notification
+-- lain.widgets.calendar
+local calendar = {}
+local cal_notification = nil
+
+function calendar:hide()
+    if cal_notification ~= nil then
+        naughty.destroy(cal_notification)
+        cal_notification = nil
+    end
+end
+
+function calendar:show(t_out, inc_offset)
+    calendar:hide()
+
+    local offs = inc_offset or 0
+    local tims = t_out or 0
+    local f, c_text
+    local today = tonumber(os.date('%d'))
+    local init_t = '/usr/bin/cal | sed -r -e "s/(^| )( '
+
+    if offs == 0
+    then -- current month showing, today highlighted
+        if today >= 10
+        then
+           init_t = '/usr/bin/cal | sed -r -e "s/(^| )('
+        end
+
+        calendar.offset = 0
+        calendar.notify_icon = calendar.icons .. today .. ".png"
+
+        -- bg and fg inverted to highlight today
+        f = io.popen( init_t .. today ..
+                      ')($| )/\\1<b><span foreground=\\"'
+                      .. calendar.bg ..
+                      '\\" background=\\"'
+                      .. calendar.fg ..
+                      '\\">\\2<\\/span><\\/b>\\3/"' )
+
+    else -- no current month showing, no day to highlight
+       local month = tonumber(os.date('%m'))
+       local year = tonumber(os.date('%Y'))
+
+       calendar.offset = calendar.offset + offs
+       month = month + calendar.offset
+
+       if month > 12 then
+           month = month % 12
+           year = year + 1
+           if month <= 0 then
+               month = 12
+           end
+       elseif month < 1 then
+           month = month + 12
+           year = year - 1
+           if month <= 0 then
+               month = 1
+           end
+       end
+
+       calendar.notify_icon = nil
+
+       f = io.popen('/usr/bin/cal ' .. month .. ' ' .. year)
+    end
+
+    c_text = "<tt><span font='" .. calendar.font .. " "
+             .. calendar.font_size .. "'><b>"
+             .. f:read() .. "</b>\n\n"
+             .. f:read() .. "\n"
+             .. f:read("*all"):gsub("\n*$", "")
+             .. "</span></tt>"
+    f:close()
+
+    cal_notification = naughty.notify({
+        text = c_text,
+        icon = calendar.notify_icon,
+        position = calendar.position,
+        fg = calendar.fg,
+        bg = calendar.bg,
+        timeout = tims
+    })
+end
+
+function calendar:attach(widget, args)
+    local args = args or {}
+    calendar.icons     = args.icons or icons_dir .. "cal/white/"
+    calendar.font      = args.font or beautiful.font:sub(beautiful.font:find(""),
+                         beautiful.font:find(" "))
+    calendar.font_size = tonumber(args.font_size) or 11
+    calendar.fg        = args.fg or beautiful.fg_normal or "#FFFFFF"
+    calendar.bg        = args.bg or beautiful.bg_normal or "#FFFFFF"
+    calendar.position  = args.position or "top_right"
+
+    calendar.offset = 0
+    calendar.notify_icon = nil
+
+    widget:connect_signal("mouse::enter", function () calendar:show() end)
+    widget:connect_signal("mouse::leave", function () calendar:hide() end)
+    widget:buttons(awful.util.table.join( awful.button({ }, 1, function ()
+                                              calendar:show(0, -1) end),
+                                          awful.button({ }, 3, function ()
+                                              calendar:show(0, 1) end) ))
+end
+
+return setmetatable(calendar, { __call = function(_, ...) return create(...) end })
diff --git a/.config/awesome/lain/widgets/contrib/ccurr.lua b/.config/awesome/lain/widgets/contrib/ccurr.lua
new file mode 100644
index 0000000..f696a35
--- /dev/null
+++ b/.config/awesome/lain/widgets/contrib/ccurr.lua
@@ -0,0 +1,82 @@
+
+--[[
+                                                  
+     Licensed under GNU General Public License v2 
+      * (c) 2014, Aaron Lebo                      
+                                                  
+--]]
+
+local newtimer = require("lain.helpers").newtimer
+
+local wibox    = require("wibox")
+local json     = require("dkjson")
+
+local string   = { format = string.format }
+local tonumber = tonumber
+
+-- Crypto currencies widget
+-- lain.widgets.contrib.ccurr
+local ccurr = {}
+
+-- Currently gets
+--   * BTC/USD
+--   * DOGE/USD
+-- using Coinbase and Cryptsy APIs.
+
+-- requires   http://dkolf.de/src/dkjson-lua.fsl/home
+-- based upon http://awesome.naquadah.org/wiki/Bitcoin_Price_Widget
+
+local function get(url)
+    local f = io.popen('curl -m 5 -s "' .. url .. '"')
+    if not f then
+        return 0
+    else
+        local s = f:read("*all")
+        f:close()
+        return s
+    end
+end
+
+local function parse(j)
+    local obj, pos, err = json.decode(j, 1, nil)
+    if err then
+        return nil
+    else
+        return obj
+    end
+end
+
+local function worker(args)
+    local args     = args or {}
+    local timeout  = args.timeout  or 600
+    local btc_url  = args.btc_url  or "https://coinbase.com/api/v1/prices/buy"
+    local doge_url = args.doge_url or "http://pubapi.cryptsy.com/api.php?method=singlemarketdata&marketid=132"
+    local settings = args.settings or function() end
+
+    ccurr.widget = wibox.widget.textbox('')
+
+    local function update()
+        price_now = {
+            btc  = "N/A",
+            doge = "N/A"
+        }
+
+        btc  = parse(get(btc_url))
+        doge = parse(get(doge_url))
+
+        if btc and doge then
+            price_now.btc  = tonumber(btc["subtotal"]["amount"])
+            price_now.doge = tonumber(doge["return"]["markets"]["DOGE"]["lasttradeprice"])
+            price_now.doge = string.format("%.4f", price_now.btc * price_now.doge)
+        end
+
+        widget = ccurr.widget
+        settings()
+    end
+
+    newtimer("ccurr", timeout, update)
+
+    return ccurr.widget
+end
+
+return setmetatable(ccurr, { __call = function(_, ...) return worker(...) end })
diff --git a/.config/awesome/lain/widgets/contrib/init.lua b/.config/awesome/lain/widgets/contrib/init.lua
new file mode 100644
index 0000000..9a9fa63
--- /dev/null
+++ b/.config/awesome/lain/widgets/contrib/init.lua
@@ -0,0 +1,20 @@
+
+--[[
+                                                   
+     Lain                                          
+     Layouts, widgets and utilities for Awesome WM 
+                                                   
+     Users contributed widgets section             
+                                                   
+     Licensed under GNU General Public License v2  
+      * (c) 2013,      Luke Bonham                 
+      * (c) 2010-2012, Peter Hofmann               
+                                                   
+--]]
+
+local wrequire     = require("lain.helpers").wrequire
+local setmetatable = setmetatable
+
+local widgets = { _NAME = "lain.widgets.contrib" }
+
+return setmetatable(widgets, { __index = wrequire })
diff --git a/.config/awesome/lain/widgets/contrib/task.lua b/.config/awesome/lain/widgets/contrib/task.lua
new file mode 100644
index 0000000..a6c9f31
--- /dev/null
+++ b/.config/awesome/lain/widgets/contrib/task.lua
@@ -0,0 +1,133 @@
+
+--[[
+                                                  
+     Licensed under GNU General Public License v2 
+      * (c) 2013, Luke Bonham                     
+      * (c) 2013, Jan Xie                         
+                                                  
+--]]
+
+local icons_dir    = require("lain.helpers").icons_dir
+
+local awful        = require("awful")
+local beautiful    = require("beautiful")
+local naughty      = require("naughty")
+
+local io           = io
+local string       = { len = string.len }
+local tonumber     = tonumber
+
+local setmetatable = setmetatable
+
+-- Taskwarrior notification
+-- lain.widgets.task
+local task = {}
+
+local task_notification = nil
+
+function task:hide()
+    if task_notification ~= nil then
+        naughty.destroy(task_notification)
+        task_notification = nil
+    end
+end
+
+function task:show()
+    task:hide()
+
+    local f, c_text
+
+    f = io.popen('task')
+    c_text = "<span font='"
+             .. task.font .. " "
+             .. task.font_size .. "'>"
+             .. f:read("*all"):gsub("\n*$", "")
+             .. "</span>"
+    f:close()
+
+    task_notification = naughty.notify({ title = "[task next]",
+                                         text = c_text,
+                                         icon = task.notify_icon,
+                                         position = task.position,
+                                         fg = task.fg,
+                                         bg = task.bg,
+                                         timeout = task.timeout })
+end
+
+function task:prompt_add()
+  awful.prompt.run({ prompt = "Add task: " },
+      mypromptbox[mouse.screen].widget,
+      function (...)
+          local f = io.popen("task add " .. ...)
+          c_text = "\n<span font='" 
+                   .. task.font .. " "
+                   .. task.font_size .. "'>"
+                   .. f:read("*all")
+                   .. "</span>"
+          f:close()
+
+          naughty.notify({
+              text     = c_text,
+              icon     = task.notify_icon,
+              position = task.position,
+              fg       = task.fg,
+              bg       = task.bg,
+              timeout  = task.timeout
+          })
+      end,
+      nil,
+      awful.util.getdir("cache") .. "/history_task_add")
+end
+
+function task:prompt_search()
+  awful.prompt.run({ prompt = "Search task: " },
+      mypromptbox[mouse.screen].widget,
+      function (...)
+          local f = io.popen("task " .. ...)
+          c_text = f:read("*all"):gsub(" \n*$", "")
+          f:close()
+
+          if string.len(c_text) == 0
+          then
+              c_text = "No results found."
+          else
+              c_text = "<span font='"
+                       .. task.font .. " "
+                       .. task.font_size .. "'>"
+                       .. c_text 
+                       .. "</span>"
+          end
+
+          naughty.notify({
+              title    = "[task next " .. ... .. "]",
+              text     = c_text,
+              icon     = task.notify_icon,
+              position = task.position,
+              fg       = task.fg,
+              bg       = task.bg,
+              timeout  = task.timeout
+          })
+      end,
+      nil,
+      awful.util.getdir("cache") .. "/history_task")
+end
+
+function task:attach(widget, args)
+    local args     = args or {}
+
+    task.font_size = tonumber(args.font_size) or 12
+    task.font      = beautiful.font:sub(beautiful.font:find(""),
+                     beautiful.font:find(" "))
+    task.fg        = args.fg or beautiful.fg_normal or "#FFFFFF"
+    task.bg        = args.bg or beautiful.bg_normal or "#FFFFFF"
+    task.position  = args.position or "top_right"
+    task.timeout   = args.timeout or 7
+
+    task.notify_icon = icons_dir .. "/taskwarrior/task.png"
+    task.notify_icon_small = icons_dir .. "/taskwarrior/tasksmall.png"
+
+    widget:connect_signal("mouse::enter", function () task:show() end)
+    widget:connect_signal("mouse::leave", function () task:hide() end)
+end
+
+return setmetatable(task, { __call = function(_, ...) return create(...) end })
diff --git a/.config/awesome/lain/widgets/contrib/tpbat/init.lua b/.config/awesome/lain/widgets/contrib/tpbat/init.lua
new file mode 100644
index 0000000..72d6453
--- /dev/null
+++ b/.config/awesome/lain/widgets/contrib/tpbat/init.lua
@@ -0,0 +1,166 @@
+
+--[[
+                                                               
+     tpbat.lua                                                 
+     Battery status widget for ThinkPad laptops that use SMAPI 
+     lain.widgets.contrib.tpbat                                
+                                                               
+     More on tp_smapi: http://www.thinkwiki.org/wiki/Tp_smapi  
+                                                               
+     Licensed under GNU General Public License v2              
+      * (c) 2013,      Conor Heine                             
+      * (c) 2013,      Luke Bonham                             
+      * (c) 2010-2012, Peter Hofmann                           
+                                                               
+--]]
+
+local debug        = { getinfo = debug.getinfo }
+local newtimer     = require("lain.helpers").newtimer
+local first_line   = require("lain.helpers").first_line
+local beautiful    = require("beautiful")
+local naughty      = require("naughty")
+local wibox        = require("wibox")
+
+local string       = { format = string.format }
+local math         = { floor = math.floor }
+local tostring     = tostring
+local setmetatable = setmetatable
+
+package.path       = debug.getinfo(1,"S").source:match[[^@?(.*[\/])[^\/]-$]] .. "?.lua;" .. package.path
+local smapi        = require("smapi")
+
+-- ThinkPad SMAPI-enabled battery info widget
+-- lain.widgets.contrib.tpbat
+local tpbat = { }
+local tpbat_notification = nil
+
+function tpbat:hide()
+    if tpbat_notification ~= nil
+    then
+        naughty.destroy(tpbat_notification)
+        tpbat_notification = nil
+    end
+end
+
+function tpbat:show(t_out)
+    tpbat:hide()
+
+    local bat   = self.bat
+    local t_out = t_out or 0
+
+    if bat == nil or not bat:installed() then return end
+
+    local mfgr   = bat:get('manufacturer') or "no_mfgr"
+    local model  = bat:get('model') or "no_model"
+    local chem   = bat:get('chemistry') or "no_chem"
+    local status = bat:get('state') or "nil"
+    local time   = bat:remaining_time()
+    local msg    = "\t"
+
+    if status ~= "idle" and status ~= "nil"
+    then
+        if time == "N/A"
+        then
+            msg = "...Calculating time remaining..."
+        else
+            msg = time .. (status == "charging" and " until charged" or " remaining")
+        end
+    else
+        msg = "On AC Power"
+    end
+
+    local str = string.format("%s : %s %s (%s)\n", bat.name, mfgr, model, chem)
+                .. string.format("\n%s \t\t\t %s", status:upper(), msg)
+
+    tpbat_notification = naughty.notify({
+        preset = { fg = beautiful.fg_normal },
+        text = str,
+        timeout = t_out
+    })
+end
+
+function tpbat.register(args)
+    local args = args or {}
+    local timeout = args.timeout or 30
+    local battery = args.battery or "BAT0"
+    local settings = args.settings or function() end
+
+    tpbat.bat = smapi:battery(battery) -- Create a new battery
+    local bat = tpbat.bat
+
+    tpbat.widget = wibox.widget.textbox('')
+
+    bat_notification_low_preset = {
+        title = "Battery low",
+        text = "Plug the cable!",
+        timeout = 15,
+        fg = "#202020",
+        bg = "#CDCDCD"
+    }
+
+    bat_notification_critical_preset = {
+        title = "Battery exhausted",
+        text = "Shutdown imminent",
+        timeout = 15,
+        fg = "#000000",
+        bg = "#FFFFFF"
+    }
+
+    if bat:get('state') == nil
+    then
+        local n = naughty.notify({
+            preset = bat_notification_low_preset,
+            title = "SMAPI Battery Warning: Unable to read battery state!",
+            text = "This widget is intended for ThinkPads. Is tp_smapi installed? Check your configs & paths."
+        })
+    end
+
+    function update()
+        bat_now = {
+            status = "Not present",
+            perc   = "N/A",
+            time   = "N/A",
+            watt   = "N/A"
+        }
+
+        if bat:installed()
+        then
+            bat_now.status = bat:status() or "N/A"
+            bat_now.perc   = bat:percent()
+            bat_now.time   = bat:remaining_time()
+            -- bat_now.watt = string.format("%.2fW", (VOLTS * AMPS) / 1e12)
+
+            -- notifications for low and critical states (when discharging)
+            if bat_now.status == "discharging"
+            then
+                if bat_now.perc <= 5
+                then
+                    tpbat.id = naughty.notify({
+                        preset = bat_notification_critical_preset,
+                        replaces_id = tpbat.id
+                    }).id
+                elseif bat_now.perc <= 15
+                then
+                    tpbat.id = naughty.notify({
+                        preset = bat_notification_low_preset,
+                        replaces_id = tpbat.id
+                    }).id
+                end
+            end
+
+            bat_now.perc = tostring(bat_now.perc)
+        end
+
+        widget = tpbat.widget
+        settings()
+    end
+
+    newtimer("tpbat", timeout, update)
+
+    widget:connect_signal('mouse::enter', function () tpbat:show() end)
+    widget:connect_signal('mouse::leave', function () tpbat:hide() end)
+
+    return tpbat.widget
+end
+
+return setmetatable(tpbat, { __call = function(_, ...) return tpbat.register(...) end })
diff --git a/.config/awesome/lain/widgets/contrib/tpbat/smapi.lua b/.config/awesome/lain/widgets/contrib/tpbat/smapi.lua
new file mode 100644
index 0000000..862d4cd
--- /dev/null
+++ b/.config/awesome/lain/widgets/contrib/tpbat/smapi.lua
@@ -0,0 +1,102 @@
+
+--[[
+                                                  
+     smapi.lua                                    
+     Interface with thinkpad battery information  
+                                                  
+     Licensed under GNU General Public License v2 
+      * (c) 2013, Conor Heine                     
+                                                  
+--]]
+
+local first_line   = require("lain.helpers").first_line
+
+local string       = { format = string.format }
+local tonumber     = tonumber
+local setmetatable = setmetatable
+
+local smapi = {}
+
+local apipath = "/sys/devices/platform/smapi"
+
+-- Most are readable values, but some can be written to (not implemented, yet?)
+local readable = {
+    barcoding                  = true,
+    charging_max_current       = true,
+    charging_max_voltage       = true,
+    chemistry                  = true,
+    current_avg                = true,
+    current_now                = true,
+    cycle_count                = true,
+    design_capacity            = true,
+    design_voltage             = true,
+    dump                       = true,
+    first_use_date             = true,
+    force_discharge            = false,
+    group0_voltage             = true,
+    group1_voltage             = true,
+    group2_voltage             = true,
+    group3_voltage             = true,
+    inhibit_charge_minutes     = false,
+    installed                  = true,
+    last_full_capacity         = true,
+    manufacture_date           = true,
+    manufacturer               = true,
+    model                      = true,
+    power_avg                  = true,
+    power_now                  = true,
+    remaining_capacity         = true,
+    remaining_charging_time    = true,
+    remaining_percent          = true,
+    remaining_percent_error    = true,
+    remaining_running_time     = true,
+    remaining_running_time_now = true,
+    serial                     = true,
+    start_charge_thresh        = false,
+    state                      = true,
+    stop_charge_thresh         = false,
+    temperature                = true,
+    voltage                    = true,
+}
+
+function smapi:battery(name)
+    local bat = {}
+
+    bat.name = name
+    bat.path = apipath .. "/" .. name
+
+    function bat:get(item)
+        return self.path ~= nil and readable[item] and first_line(self.path .. "/" .. item) or nil
+    end
+
+    function bat:installed()
+        return self:get("installed") == "1"
+    end
+
+    function bat:status()
+        return self:get('state')
+    end
+
+    -- Remaining time can either be time until battery dies or time until charging completes
+    function bat:remaining_time()
+        local time_val = bat_now.status == 'discharging' and 'remaining_running_time' or 'remaining_charging_time'
+        local mins_left = self:get(time_val)
+
+        if mins_left:find("^%d+") == nil
+        then
+            return "N/A"
+        end
+
+        local hrs = mins_left / 60
+        local min = mins_left % 60
+        return string.format("%02d:%02d", hrs, min)
+    end
+
+    function bat:percent()
+        return tonumber(self:get("remaining_percent"))
+    end
+
+    return setmetatable(bat, {__metatable = false, __newindex = false})
+end
+
+return smapi
diff --git a/.config/awesome/lain/widgets/cpu.lua b/.config/awesome/lain/widgets/cpu.lua
new file mode 100644
index 0000000..0b21edc
--- /dev/null
+++ b/.config/awesome/lain/widgets/cpu.lua
@@ -0,0 +1,77 @@
+
+--[[
+                                                  
+     Licensed under GNU General Public License v2 
+      * (c) 2013,      Luke Bonham                
+      * (c) 2010-2012, Peter Hofmann              
+                                                  
+--]]
+
+local first_line   = require("lain.helpers").first_line
+local newtimer     = require("lain.helpers").newtimer
+
+local wibox        = require("wibox")
+
+local math         = { ceil   = math.ceil }
+local string       = { format = string.format,
+                       gmatch = string.gmatch }
+local tostring     = tostring
+
+local setmetatable = setmetatable
+
+-- CPU usage
+-- lain.widgets.cpu
+local cpu = {
+    last_total = 0,
+    last_active = 0
+}
+
+local function worker(args)
+    local args     = args or {}
+    local timeout  = args.timeout or 5
+    local settings = args.settings or function() end
+
+    cpu.widget = wibox.widget.textbox('')
+
+    function update()
+        -- Read the amount of time the CPUs have spent performing
+        -- different kinds of work. Read the first line of /proc/stat
+        -- which is the sum of all CPUs.
+        local times = first_line("/proc/stat")
+        local at = 1
+        local idle = 0
+        local total = 0
+        for field in string.gmatch(times, "[%s]+([^%s]+)")
+        do
+            -- 3 = idle, 4 = ioWait. Essentially, the CPUs have done
+            -- nothing during these times.
+            if at == 3 or at == 4
+            then
+                idle = idle + field
+            end
+            total = total + field
+            at = at + 1
+        end
+        local active = total - idle
+
+        -- Read current data and calculate relative values.
+        local dactive = active - cpu.last_active
+        local dtotal = total - cpu.last_total
+
+        cpu_now = {}
+        cpu_now.usage = tostring(math.ceil((dactive / dtotal) * 100))
+
+        widget = cpu.widget
+        settings()
+
+        -- Save current data for the next run.
+        cpu.last_active = active
+        cpu.last_total = total
+    end
+
+    newtimer("cpu", timeout, update)
+
+    return cpu.widget
+end
+
+return setmetatable(cpu, { __call = function(_, ...) return worker(...) end })
diff --git a/.config/awesome/lain/widgets/fs.lua b/.config/awesome/lain/widgets/fs.lua
new file mode 100644
index 0000000..7406e05
--- /dev/null
+++ b/.config/awesome/lain/widgets/fs.lua
@@ -0,0 +1,120 @@
+
+--[[
+                                                      
+     Licensed under GNU General Public License v2     
+      * (c) 2013, Luke Bonham                         
+      * (c) 2010, Adrian C.      <anrxc@sysphere.org> 
+      * (c) 2009, Lucas de Vries <lucas@glacicle.com> 
+                                                      
+--]]
+
+local helpers      = require("lain.helpers")
+
+local beautiful    = require("beautiful")
+local wibox        = require("wibox")
+local naughty      = require("naughty")
+
+local io           = io
+local pairs        = pairs
+local string       = { match  = string.match,
+                       format = string.format }
+local tonumber     = tonumber
+
+local setmetatable = setmetatable
+
+-- File system disk space usage
+-- lain.widgets.fs
+local fs = {}
+
+local notification  = nil
+fs_notification_preset = { fg = beautiful.fg_normal }
+
+function fs:hide()
+    if notification ~= nil then
+        naughty.destroy(notification)
+        notification = nil
+    end
+end
+
+function fs:show(t_out)
+    fs:hide()
+
+    local f = io.popen(helpers.scripts_dir .. "dfs")
+    ws = f:read("*all"):gsub("\n*$", "")
+    f:close()
+
+    notification = naughty.notify({
+        preset = fs_notification_preset,
+        text = ws,
+      	timeout = t_out
+    })
+end
+
+-- Units definitions
+local unit = { ["mb"] = 1024, ["gb"] = 1024^2 }
+
+local function worker(args)
+    local args      = args or {}
+    local timeout   = args.timeout or 600
+    local partition = args.partition or "/"
+    local settings  = args.settings or function() end
+
+    fs.widget = wibox.widget.textbox('')
+
+    helpers.set_map("fs", false)
+
+    function update()
+        fs_info = {}
+        fs_now  = {}
+
+        local f = io.popen("LC_ALL=C df -kP")
+
+        for line in f:lines() do -- Match: (size) (used)(avail)(use%) (mount)
+            local s     = string.match(line, "^.-[%s]([%d]+)")
+            local u,a,p = string.match(line, "([%d]+)[%D]+([%d]+)[%D]+([%d]+)%%")
+            local m     = string.match(line, "%%[%s]([%p%w]+)")
+
+            if u and m then -- Handle 1st line and broken regexp
+                fs_info[m .. " size_mb"]  = string.format("%.1f", tonumber(s) / unit["mb"])
+                fs_info[m .. " size_gb"]  = string.format("%.1f", tonumber(s) / unit["gb"])
+                fs_info[m .. " used_p"]   = tonumber(p)
+                fs_info[m .. " avail_p"]  = 100 - tonumber(p)
+            end
+        end
+
+        f:close()
+
+        -- chosen partition easy stuff
+        -- you can however check whatever partition else
+        fs_now.used      = tonumber(fs_info[partition .. " used_p"])  or 0
+        fs_now.available = tonumber(fs_info[partition .. " avail_p"]) or 0
+        fs_now.size_mb   = tonumber(fs_info[partition .. " size_mb"]) or 0
+        fs_now.size_gb   = tonumber(fs_info[partition .. " size_gb"]) or 0
+
+        widget = fs.widget
+        settings()
+
+        if fs_now.used >= 99 and not helpers.get_map("fs")
+        then
+            naughty.notify({
+                title = "warning",
+                text = partition .. " ran out!\nmake some room",
+                timeout = 8,
+                fg = "#000000",
+                bg = "#FFFFFF"
+            })
+            helpers.set_map("fs", true)
+        else
+            helpers.set_map("fs", false)
+        end
+    end
+
+    helpers.newtimer(partition, timeout, update)
+
+    widget:connect_signal('mouse::enter', function () fs:show(0) end)
+    widget:connect_signal('mouse::leave', function () fs:hide() end)
+
+    return setmetatable(fs, { __index = fs.widget })
+end
+
+return setmetatable(fs, { __call = function(_, ...) return worker(...) end })
diff --git a/.config/awesome/lain/widgets/imap.lua b/.config/awesome/lain/widgets/imap.lua
new file mode 100644
index 0000000..39518bd
--- /dev/null
+++ b/.config/awesome/lain/widgets/imap.lua
@@ -0,0 +1,87 @@
+
+--[[
+                                                  
+     Licensed under GNU General Public License v2 
+      * (c) 2013, Luke Bonham                     
+                                                  
+--]]
+
+local helpers      = require("lain.helpers")
+
+local naughty      = require("naughty")
+local wibox        = require("wibox")
+
+local io           = { popen  = io.popen }
+local string       = { format = string.format,
+                       gsub   = string.gsub }
+local tonumber     = tonumber
+
+local setmetatable = setmetatable
+
+-- Mail IMAP check
+-- lain.widgets.imap
+local imap = {}
+
+local function worker(args)
+    local args     = args or {}
+
+    local server   = args.server
+    local mail     = args.mail
+    local password = args.password
+
+    local port     = args.port or 993
+    local timeout  = args.timeout or 60
+    local is_plain = args.is_plain or false
+    local settings = args.settings or function() end
+
+    local head_command  = "curl --connect-timeout 1 -fsm 3"
+    local request = "-X 'SEARCH (UNSEEN)'"
+
+    helpers.set_map(mail, 0)
+
+    if not is_plain
+    then
+        local f = io.popen(password)
+        password = f:read("*all"):gsub("\n", "")
+        f:close()
+    end
+
+    imap.widget = wibox.widget.textbox('')
+
+    function update()
+        mail_notification_preset = {
+            icon     = helpers.icons_dir .. "mail.png",
+            position = "top_left"
+        }
+
+        curl = string.format("%s --url imaps://%s:%s/INBOX -u %s:%s %s -k",
+               head_command, server, port, mail, password, request)
+
+        f = io.popen(curl)
+        ws = f:read("*all")
+        f:close()
+
+        _, mailcount = string.gsub(ws, "%d+", "")
+        _ = nil
+
+        widget = imap.widget
+        settings()
+
+        if mailcount > helpers.get_map(mail) and mailcount >= 1
+        then
+            if mailcount == 1 then
+                nt = mail .. " has one new message"
+            else
+                nt = mail .. " has <b>" .. mailcount .. "</b> new messages"
+            end
+            naughty.notify({ preset = mail_notification_preset, text = nt })
+        end
+
+        helpers.set_map(mail, mailcount)
+    end
+
+    helpers.newtimer(mail, timeout, update, true)
+    return imap.widget
+end
+
+return setmetatable(imap, { __call = function(_, ...) return worker(...) end })
diff --git a/.config/awesome/lain/widgets/init.lua b/.config/awesome/lain/widgets/init.lua
new file mode 100644
index 0000000..0e863ba
--- /dev/null
+++ b/.config/awesome/lain/widgets/init.lua
@@ -0,0 +1,20 @@
+
+--[[
+                                                   
+     Lain                                          
+     Layouts, widgets and utilities for Awesome WM 
+                                                   
+     Widgets section                               
+                                                   
+     Licensed under GNU General Public License v2  
+      * (c) 2013,      Luke Bonham                 
+      * (c) 2010-2012, Peter Hofmann               
+                                                   
+--]]
+
+local wrequire     = require("lain.helpers").wrequire
+local setmetatable = setmetatable
+
+local widgets = { _NAME = "lain.widgets" }
+
+return setmetatable(widgets, { __index = wrequire })
diff --git a/.config/awesome/lain/widgets/maildir.lua b/.config/awesome/lain/widgets/maildir.lua
new file mode 100644
index 0000000..d460881
--- /dev/null
+++ b/.config/awesome/lain/widgets/maildir.lua
@@ -0,0 +1,95 @@
+
+--[[
+                                                  
+     Licensed under GNU General Public License v2 
+      * (c) 2013,      Luke Bonham                
+      * (c) 2010-2012, Peter Hofmann              
+                                                  
+--]]
+
+local newtimer        = require("lain.helpers").newtimer
+
+local wibox           = require("wibox")
+
+local io              = io
+local os              = { getenv = os.getenv }
+local pairs           = pairs
+local string          = { len    = string.len,
+                          match  = string.match }
+local table           = { sort   = table.sort }
+
+local setmetatable    = setmetatable
+
+-- Maildir check
+-- lain.widgets.maildir
+local maildir = {}
+
+local function worker(args)
+    local args         = args or {}
+    local timeout      = args.timeout or 60
+    local mailpath     = args.mailpath or os.getenv("HOME") .. "/Mail"
+    local ignore_boxes = args.ignore_boxes or {}
+    local settings     = args.settings or function() end
+
+    maildir.widget = wibox.widget.textbox('')
+
+    function update()
+        -- Find pathes to mailboxes.
+        local p = io.popen("find " .. mailpath ..
+                           " -mindepth 1 -maxdepth 1 -type d" ..
+                           " -not -name .git")
+        local boxes = {}
+        repeat
+            line = p:read("*l")
+            if line ~= nil
+            then
+                -- Find all files in the "new" subdirectory. For each
+                -- file, print a single character (no newline). Don't
+                -- match files that begin with a dot.
+                -- Afterwards the length of this string is the number of
+                -- new mails in that box.
+                local np = io.popen("find " .. line ..
+                                    "/new -mindepth 1 -type f " ..
+                                    "-not -name '.*' -printf a")
+                local mailstring = np:read("*all")
+
+                -- Strip off leading mailpath.
+                local box = string.match(line, mailpath .. "/*([^/]+)")
+                local nummails = string.len(mailstring)
+                if nummails > 0
+                then
+                    boxes[box] = nummails
+                end
+            end
+        until line == nil
+
+        table.sort(boxes)
+
+        newmail = "no mail"
+
+        local count = 0
+        for box, number in pairs(boxes)
+        do
+            count = count + 1
+            -- Add this box only if it's not to be ignored.
+            if not util.element_in_table(box, ignore_boxes)
+            then
+                if newmail == ""
+                then
+                    newmail = box .. "(" .. number .. ")"
+                else
+                    newmail = newmail .. ", " ..
+                              box .. "(" .. number .. ")"
+                end
+            end
+        end
+
+        widget = maildir.widget
+        settings()
+    end
+
+    newtimer(mailpath, timeout, update, true)
+    return maildir.widget
+end
+
+return setmetatable(maildir, { __call = function(_, ...) return worker(...) end })
diff --git a/.config/awesome/lain/widgets/mem.lua b/.config/awesome/lain/widgets/mem.lua
new file mode 100644
index 0000000..986fa76
--- /dev/null
+++ b/.config/awesome/lain/widgets/mem.lua
@@ -0,0 +1,61 @@
+
+--[[
+                                                  
+     Licensed under GNU General Public License v2 
+      * (c) 2013,      Luke Bonham                
+      * (c) 2010-2012, Peter Hofmann              
+                                                  
+--]]
+
+local newtimer        = require("lain.helpers").newtimer
+
+local wibox           = require("wibox")
+
+local io              = { lines  = io.lines }
+local math            = { floor  = math.floor }
+local string          = { format = string.format,
+                          gmatch = string.gmatch,
+                          len    = string.len }
+
+local setmetatable    = setmetatable
+
+-- Memory usage (ignoring caches)
+-- lain.widgets.mem
+local mem = {}
+
+local function worker(args)
+    local args     = args or {}
+    local timeout  = args.timeout or 3
+    local settings = args.settings or function() end
+
+    mem.widget = wibox.widget.textbox('')
+
+    function update()
+        mem_now = {}
+        for line in io.lines("/proc/meminfo")
+        do
+            for k, v in string.gmatch(line, "([%a]+):[%s]+([%d]+).+")
+            do
+                if     k == "MemTotal"  then mem_now.total = math.floor(v / 1024)
+                elseif k == "MemFree"   then mem_now.free  = math.floor(v / 1024)
+                elseif k == "Buffers"   then mem_now.buf   = math.floor(v / 1024)
+                elseif k == "Cached"    then mem_now.cache = math.floor(v / 1024)
+                elseif k == "SwapTotal" then mem_now.swap  = math.floor(v / 1024)
+                elseif k == "SwapFree"  then mem_now.swapf = math.floor(v / 1024)
+                end
+            end
+        end
+
+        mem_now.used = mem_now.total - (mem_now.free + mem_now.buf + mem_now.cache)
+        mem_now.swapused = mem_now.swap - mem_now.swapf
+
+        widget = mem.widget
+        settings()
+    end
+
+    newtimer("mem", timeout, update)
+
+    return mem.widget
+end
+
+return setmetatable(mem, { __call = function(_, ...) return worker(...) end })
diff --git a/.config/awesome/lain/widgets/mpd.lua b/.config/awesome/lain/widgets/mpd.lua
new file mode 100644
index 0000000..600dbac
--- /dev/null
+++ b/.config/awesome/lain/widgets/mpd.lua
@@ -0,0 +1,110 @@
+
+--[[
+                                                  
+     Licensed under GNU General Public License v2 
+      * (c) 2013, Luke Bonham                     
+      * (c) 2010, Adrian C. <anrxc@sysphere.org>  
+                                                  
+--]]
+
+local helpers      = require("lain.helpers")
+
+local escape_f     = require("awful.util").escape
+local naughty      = require("naughty")
+local wibox        = require("wibox")
+
+local io           = { popen    = io.popen }
+local os           = { execute  = os.execute,
+                       getenv   = os.getenv }
+local string       = { format   = string.format,
+                       gmatch   = string.gmatch }
+
+local setmetatable = setmetatable
+
+-- MPD infos
+-- lain.widgets.mpd
+local mpd = {}
+
+local function worker(args)
+    local args        = args or {}
+    local timeout     = args.timeout or 2
+    local password    = args.password or ""
+    local host        = args.host or "127.0.0.1"
+    local port        = args.port or "6600"
+    local music_dir   = args.music_dir or os.getenv("HOME") .. "/Music"
+    local cover_size  = args.cover_size or 100
+    local default_art = args.default_art or ""
+    local settings    = args.settings or function() end
+
+    local mpdcover = helpers.scripts_dir .. "mpdcover"
+    local mpdh = "telnet://" .. host .. ":" .. port
+    local echo = "echo 'password " .. password .. "\nstatus\ncurrentsong\nclose'"
+
+    mpd.widget = wibox.widget.textbox('')
+
+    mpd_notification_preset = {
+        -- title   = "now playing\n░░░░▒▒▒▒▓▓▓▓▓▓████████▓▓▓▓▓▓▒▒▒▒░░░░",
+        title   = "now playing",
+        timeout = 6
+    }
+
+    helpers.set_map("current mpd track", nil)
+
+    function mpd.update()
+        mpd_now = {
+            state  = "N/A",
+            file   = "N/A",
+            artist = "N/A",
+            title  = "N/A",
+            album  = "N/A",
+            date   = "N/A"
+        }
+
+        local f = io.popen(echo .. " | curl --connect-timeout 1 -fsm 3 " .. mpdh)
+
+        for line in f:lines() do
+            for k, v in string.gmatch(line, "([%w]+):[%s](.*)$") do
+                if     k == "state"  then mpd_now.state  = v
+                elseif k == "file"   then mpd_now.file   = v
+                elseif k == "Artist" then mpd_now.artist = escape_f(v)
+                elseif k == "Title"  then mpd_now.title  = escape_f(v)
+                elseif k == "Album"  then mpd_now.album  = escape_f(v)
+                elseif k == "Date"   then mpd_now.date   = escape_f(v)
+                end
+            end
+        end
+
+        f:close()
+
+        mpd_notification_preset.text = string.format("%s (%s) - %s\n%s", mpd_now.artist,
+                                       mpd_now.album, mpd_now.date, mpd_now.title)
+        widget = mpd.widget
+        settings()
+
+        if mpd_now.state == "play"
+        then
+            if mpd_now.title ~= helpers.get_map("current mpd track")
+            then
+                helpers.set_map("current mpd track", mpd_now.title)
+
+                os.execute(string.format("%s %q %q %d %q", mpdcover, music_dir,
+                           mpd_now.file, cover_size, default_art))
+
+                mpd.id = naughty.notify({
+                    preset = mpd_notification_preset,
+                    icon = "/tmp/mpdcover.png",
+                    replaces_id = mpd.id
+                }).id
+            end
+        elseif mpd_now.state ~= "pause"
+        then
+            helpers.set_map("current mpd track", nil)
+	      end
+    end
+
+    helpers.newtimer("mpd", timeout, mpd.update)
+
+    return setmetatable(mpd, { __index = mpd.widget })
+end
+
+return setmetatable(mpd, { __call = function(_, ...) return worker(...) end })
diff --git a/.config/awesome/lain/widgets/net.lua b/.config/awesome/lain/widgets/net.lua
new file mode 100644
index 0000000..af97201
--- /dev/null
+++ b/.config/awesome/lain/widgets/net.lua
@@ -0,0 +1,102 @@
+
+--[[
+                                                  
+     Licensed under GNU General Public License v2 
+      * (c) 2013,      Luke Bonham                
+      * (c) 2010-2012, Peter Hofmann              
+                                                  
+--]]
+
+local helpers      = require("lain.helpers")
+
+local notify_fg    = require("beautiful").fg_focus
+local naughty      = require("naughty")
+local wibox        = require("wibox")
+
+local io           = io
+local tostring     = tostring
+local string       = { format = string.format,
+                       gsub   = string.gsub }
+
+local setmetatable = setmetatable
+
+-- Network infos
+-- lain.widgets.net
+local net = {
+    last_t = 0,
+    last_r = 0
+}
+
+function net.get_device()
+    f = io.popen("ip link show | cut -d' ' -f2,9")
+    ws = f:read("*all")
+    f:close()
+    ws = ws:match("%w+: UP")
+    if ws ~= nil then
+        return ws:gsub(": UP", "")
+    else
+        return "network off"
+    end
+end
+
+local function worker(args)
+    local args = args or {}
+    local timeout = args.timeout or 2
+    local iface = args.iface or net.get_device()
+    local units = args.units or 1024 --kb
+    local settings = args.settings or function() end
+
+    net.widget = wibox.widget.textbox('')
+
+    helpers.set_map(iface, true)
+
+    function update()
+        net_now = {}
+
+        if iface == "" then iface = net.get_device() end
+
+        net_now.carrier = helpers.first_line('/sys/class/net/' .. iface ..
+                                           '/carrier') or "0"
+        net_now.state = helpers.first_line('/sys/class/net/' .. iface ..
+                                           '/operstate') or "down"
+        local now_t = helpers.first_line('/sys/class/net/' .. iface ..
+                                           '/statistics/tx_bytes') or 0
+        local now_r = helpers.first_line('/sys/class/net/' .. iface ..
+                                           '/statistics/rx_bytes') or 0
+
+        net_now.sent = tostring((now_t - net.last_t) / timeout / units)
+        net_now.sent = string.gsub(string.format('%.1f', net_now.sent), ",", ".")
+
+        net_now.received = tostring((now_r - net.last_r) / timeout / units)
+        net_now.received = string.gsub(string.format('%.1f', net_now.received), ",", ".")
+
+        widget = net.widget
+        settings()
+
+        net.last_t = now_t
+        net.last_r = now_r
+
+        if net_now.carrier ~= "1"
+        then
+            if helpers.get_map(iface)
+            then
+                naughty.notify({
+                    title    = iface,
+                    text     = "no carrier",
+                    timeout  = 7,
+                    position = "top_left",
+                    icon     = helpers.icons_dir .. "no_net.png",
+                    fg       = notify_fg or "#FFFFFF"
+                })
+                helpers.set_map(iface, false)
+            end
+        else
+            helpers.set_map(iface, true)
+        end
+    end
+
+    helpers.newtimer(iface, timeout, update)
+    return net.widget
+end
+
+return setmetatable(net, { __call = function(_, ...) return worker(...) end })
diff --git a/.config/awesome/lain/widgets/sysload.lua b/.config/awesome/lain/widgets/sysload.lua
new file mode 100644
index 0000000..2abac33
--- /dev/null
+++ b/.config/awesome/lain/widgets/sysload.lua
@@ -0,0 +1,46 @@
+
+--[[
+                                                  
+     Licensed under GNU General Public License v2 
+      * (c) 2013,      Luke Bonham                
+      * (c) 2010-2012, Peter Hofmann              
+                                                  
+--]]
+
+local newtimer     = require("lain.helpers").newtimer
+
+local wibox        = require("wibox")
+
+local io           = { open = io.open }
+local string       = { format = string.format,
+                       match  = string.match }
+
+local setmetatable = setmetatable
+
+-- System load
+-- lain.widgets.sysload
+local sysload = {}
+
+local function worker(args)
+    local args = args or {}
+    local timeout = args.timeout or 5
+    local settings = args.settings or function() end
+
+    sysload.widget = wibox.widget.textbox('')
+
+    function update()
+        local f = io.open("/proc/loadavg")
+        local ret = f:read("*all")
+        f:close()
+
+        load_1, load_5, load_15 = string.match(ret, "([^%s]+) ([^%s]+) ([^%s]+)")
+
+        widget = sysload.widget
+        settings()
+    end
+
+    newtimer("sysload", timeout, update)
+    return sysload.widget
+end
+
+return setmetatable(sysload, { __call = function(_, ...) return worker(...) end })
diff --git a/.config/awesome/lain/widgets/temp.lua b/.config/awesome/lain/widgets/temp.lua
new file mode 100644
index 0000000..61a9aa5
--- /dev/null
+++ b/.config/awesome/lain/widgets/temp.lua
@@ -0,0 +1,48 @@
+
+--[[
+                                                  
+     Licensed under GNU General Public License v2 
+      * (c) 2013, Luke Bonham                     
+                                                  
+--]]
+
+local newtimer     = require("lain.helpers").newtimer
+
+local wibox        = require("wibox")
+
+local io           = io
+local tonumber     = tonumber
+
+local setmetatable = setmetatable
+
+-- coretemp
+-- lain.widgets.temp
+local temp = {}
+
+local function worker(args)
+    local args     = args or {}
+    local timeout  = args.timeout or 5
+    local tempfile = args.tempfile or "/sys/class/thermal/thermal_zone0/temp"
+    local settings = args.settings or function() end
+
+    temp.widget = wibox.widget.textbox('')
+
+    function update()
+        local f = io.open(tempfile)
+        if f ~= nil
+        then
+            coretemp_now = tonumber(f:read("*all")) / 1000
+            f:close()
+        else
+            coretemp_now = "N/A"
+        end
+
+        widget = temp.widget
+        settings()
+    end
+
+    newtimer("coretemp", timeout, update)
+    return temp.widget
+end
+
+return setmetatable(temp, { __call = function(_, ...) return worker(...) end })
diff --git a/.config/awesome/lain/widgets/yawn/icons/BlowingSnow.png b/.config/awesome/lain/widgets/yawn/icons/BlowingSnow.png
new file mode 100755
index 0000000..6223f8f
Binary files /dev/null and b/.config/awesome/lain/widgets/yawn/icons/BlowingSnow.png differ
diff --git a/.config/awesome/lain/widgets/yawn/icons/Cloudy.png b/.config/awesome/lain/widgets/yawn/icons/Cloudy.png
new file mode 100755
index 0000000..bac1e7e
Binary files /dev/null and b/.config/awesome/lain/widgets/yawn/icons/Cloudy.png differ
diff --git a/.config/awesome/lain/widgets/yawn/icons/DayClear.png b/.config/awesome/lain/widgets/yawn/icons/DayClear.png
new file mode 100755
index 0000000..d9e2745
Binary files /dev/null and b/.config/awesome/lain/widgets/yawn/icons/DayClear.png differ
diff --git a/.config/awesome/lain/widgets/yawn/icons/DayFair.png b/.config/awesome/lain/widgets/yawn/icons/DayFair.png
new file mode 120000
index 0000000..8ee94d1
--- /dev/null
+++ b/.config/awesome/lain/widgets/yawn/icons/DayFair.png
@@ -0,0 +1 @@
+DayClear.png
\ No newline at end of file
diff --git a/.config/awesome/lain/widgets/yawn/icons/DayMostlyCloudy.png b/.config/awesome/lain/widgets/yawn/icons/DayMostlyCloudy.png
new file mode 100755
index 0000000..22b929c
Binary files /dev/null and b/.config/awesome/lain/widgets/yawn/icons/DayMostlyCloudy.png differ
diff --git a/.config/awesome/lain/widgets/yawn/icons/DayPartlyCloudy.png b/.config/awesome/lain/widgets/yawn/icons/DayPartlyCloudy.png
new file mode 100755
index 0000000..8fd0a5b
Binary files /dev/null and b/.config/awesome/lain/widgets/yawn/icons/DayPartlyCloudy.png differ
diff --git a/.config/awesome/lain/widgets/yawn/icons/Drizzle.png b/.config/awesome/lain/widgets/yawn/icons/Drizzle.png
new file mode 120000
index 0000000..df34463
--- /dev/null
+++ b/.config/awesome/lain/widgets/yawn/icons/Drizzle.png
@@ -0,0 +1 @@
+Rain.png
\ No newline at end of file
diff --git a/.config/awesome/lain/widgets/yawn/icons/Fog.png b/.config/awesome/lain/widgets/yawn/icons/Fog.png
new file mode 120000
index 0000000..b615645
--- /dev/null
+++ b/.config/awesome/lain/widgets/yawn/icons/Fog.png
@@ -0,0 +1 @@
+Foggy.png
\ No newline at end of file
diff --git a/.config/awesome/lain/widgets/yawn/icons/Foggy.png b/.config/awesome/lain/widgets/yawn/icons/Foggy.png
new file mode 100755
index 0000000..009039f
Binary files /dev/null and b/.config/awesome/lain/widgets/yawn/icons/Foggy.png differ
diff --git a/.config/awesome/lain/widgets/yawn/icons/FreezingDrizzle.png b/.config/awesome/lain/widgets/yawn/icons/FreezingDrizzle.png
new file mode 100755
index 0000000..6a66140
Binary files /dev/null and b/.config/awesome/lain/widgets/yawn/icons/FreezingDrizzle.png differ
diff --git a/.config/awesome/lain/widgets/yawn/icons/FreezingRain.png b/.config/awesome/lain/widgets/yawn/icons/FreezingRain.png
new file mode 100755
index 0000000..c924fac
Binary files /dev/null and b/.config/awesome/lain/widgets/yawn/icons/FreezingRain.png differ
diff --git a/.config/awesome/lain/widgets/yawn/icons/Hail.png b/.config/awesome/lain/widgets/yawn/icons/Hail.png
new file mode 100755
index 0000000..009039f
Binary files /dev/null and b/.config/awesome/lain/widgets/yawn/icons/Hail.png differ
diff --git a/.config/awesome/lain/widgets/yawn/icons/Haze.png b/.config/awesome/lain/widgets/yawn/icons/Haze.png
new file mode 120000
index 0000000..0874a83
--- /dev/null
+++ b/.config/awesome/lain/widgets/yawn/icons/Haze.png
@@ -0,0 +1 @@
+Hail.png
\ No newline at end of file
diff --git a/.config/awesome/lain/widgets/yawn/icons/HeavyRain.png b/.config/awesome/lain/widgets/yawn/icons/HeavyRain.png
new file mode 120000
index 0000000..ace2a94
--- /dev/null
+++ b/.config/awesome/lain/widgets/yawn/icons/HeavyRain.png
@@ -0,0 +1 @@
+Showers.png
\ No newline at end of file
diff --git a/.config/awesome/lain/widgets/yawn/icons/HeavySnow.png b/.config/awesome/lain/widgets/yawn/icons/HeavySnow.png
new file mode 100755
index 0000000..ddcb8f3
Binary files /dev/null and b/.config/awesome/lain/widgets/yawn/icons/HeavySnow.png differ
diff --git a/.config/awesome/lain/widgets/yawn/icons/LightRain.png b/.config/awesome/lain/widgets/yawn/icons/LightRain.png
new file mode 120000
index 0000000..df34463
--- /dev/null
+++ b/.config/awesome/lain/widgets/yawn/icons/LightRain.png
@@ -0,0 +1 @@
+Rain.png
\ No newline at end of file
diff --git a/.config/awesome/lain/widgets/yawn/icons/LightSnow.png b/.config/awesome/lain/widgets/yawn/icons/LightSnow.png
new file mode 120000
index 0000000..aa8b28e
--- /dev/null
+++ b/.config/awesome/lain/widgets/yawn/icons/LightSnow.png
@@ -0,0 +1 @@
+LightSnowShowers.png
\ No newline at end of file
diff --git a/.config/awesome/lain/widgets/yawn/icons/LightSnowShowers.png b/.config/awesome/lain/widgets/yawn/icons/LightSnowShowers.png
new file mode 100755
index 0000000..d797ee9
Binary files /dev/null and b/.config/awesome/lain/widgets/yawn/icons/LightSnowShowers.png differ
diff --git a/.config/awesome/lain/widgets/yawn/icons/Mist.png b/.config/awesome/lain/widgets/yawn/icons/Mist.png
new file mode 120000
index 0000000..b615645
--- /dev/null
+++ b/.config/awesome/lain/widgets/yawn/icons/Mist.png
@@ -0,0 +1 @@
+Foggy.png
\ No newline at end of file
diff --git a/.config/awesome/lain/widgets/yawn/icons/MixedRainAndHail.png b/.config/awesome/lain/widgets/yawn/icons/MixedRainAndHail.png
new file mode 100755
index 0000000..758b01e
Binary files /dev/null and b/.config/awesome/lain/widgets/yawn/icons/MixedRainAndHail.png differ
diff --git a/.config/awesome/lain/widgets/yawn/icons/MixedRainAndSleet.png b/.config/awesome/lain/widgets/yawn/icons/MixedRainAndSleet.png
new file mode 100755
index 0000000..7f0d252
Binary files /dev/null and b/.config/awesome/lain/widgets/yawn/icons/MixedRainAndSleet.png differ
diff --git a/.config/awesome/lain/widgets/yawn/icons/MixedRainAndSnow.png b/.config/awesome/lain/widgets/yawn/icons/MixedRainAndSnow.png
new file mode 100755
index 0000000..0a07b7b
Binary files /dev/null and b/.config/awesome/lain/widgets/yawn/icons/MixedRainAndSnow.png differ
diff --git a/.config/awesome/lain/widgets/yawn/icons/NightClear.png b/.config/awesome/lain/widgets/yawn/icons/NightClear.png
new file mode 100755
index 0000000..84ea140
Binary files /dev/null and b/.config/awesome/lain/widgets/yawn/icons/NightClear.png differ
diff --git a/.config/awesome/lain/widgets/yawn/icons/NightFair.png b/.config/awesome/lain/widgets/yawn/icons/NightFair.png
new file mode 120000
index 0000000..23df45a
--- /dev/null
+++ b/.config/awesome/lain/widgets/yawn/icons/NightFair.png
@@ -0,0 +1 @@
+NightClear.png
\ No newline at end of file
diff --git a/.config/awesome/lain/widgets/yawn/icons/NightMostlyCloudy.png b/.config/awesome/lain/widgets/yawn/icons/NightMostlyCloudy.png
new file mode 100755
index 0000000..d8b3673
Binary files /dev/null and b/.config/awesome/lain/widgets/yawn/icons/NightMostlyCloudy.png differ
diff --git a/.config/awesome/lain/widgets/yawn/icons/NightPartlyCloudy.png b/.config/awesome/lain/widgets/yawn/icons/NightPartlyCloudy.png
new file mode 100755
index 0000000..9e4404d
Binary files /dev/null and b/.config/awesome/lain/widgets/yawn/icons/NightPartlyCloudy.png differ
diff --git a/.config/awesome/lain/widgets/yawn/icons/README.md b/.config/awesome/lain/widgets/yawn/icons/README.md
new file mode 100644
index 0000000..e4dc111
--- /dev/null
+++ b/.config/awesome/lain/widgets/yawn/icons/README.md
@@ -0,0 +1,6 @@
+Yawn icons
+==========
+
+These are [Plain Weather Icons](http://merlinthered.deviantart.com/art/plain-weather-icons-157162192), created by [MerlinTheRed](http://merlinthered.deviantart.com/).
+
+<a href="http://creativecommons.org/licenses/by-nc-sa/2.5/"><img src="http://i.creativecommons.org/l/by-nc-sa/2.5/80x15.png" align="right"></a>
diff --git a/.config/awesome/lain/widgets/yawn/icons/Rain.png b/.config/awesome/lain/widgets/yawn/icons/Rain.png
new file mode 100755
index 0000000..d00552a
Binary files /dev/null and b/.config/awesome/lain/widgets/yawn/icons/Rain.png differ
diff --git a/.config/awesome/lain/widgets/yawn/icons/RainThunder.png b/.config/awesome/lain/widgets/yawn/icons/RainThunder.png
new file mode 100755
index 0000000..d30e120
Binary files /dev/null and b/.config/awesome/lain/widgets/yawn/icons/RainThunder.png differ
diff --git a/.config/awesome/lain/widgets/yawn/icons/Showers.png b/.config/awesome/lain/widgets/yawn/icons/Showers.png
new file mode 100755
index 0000000..3cc6665
Binary files /dev/null and b/.config/awesome/lain/widgets/yawn/icons/Showers.png differ
diff --git a/.config/awesome/lain/widgets/yawn/icons/Sleet.png b/.config/awesome/lain/widgets/yawn/icons/Sleet.png
new file mode 120000
index 0000000..f8f9693
--- /dev/null
+++ b/.config/awesome/lain/widgets/yawn/icons/Sleet.png
@@ -0,0 +1 @@
+SnowShowers.png
\ No newline at end of file
diff --git a/.config/awesome/lain/widgets/yawn/icons/Snow.png b/.config/awesome/lain/widgets/yawn/icons/Snow.png
new file mode 120000
index 0000000..f8f9693
--- /dev/null
+++ b/.config/awesome/lain/widgets/yawn/icons/Snow.png
@@ -0,0 +1 @@
+SnowShowers.png
\ No newline at end of file
diff --git a/.config/awesome/lain/widgets/yawn/icons/SnowFlurries.png b/.config/awesome/lain/widgets/yawn/icons/SnowFlurries.png
new file mode 120000
index 0000000..2e090cd
--- /dev/null
+++ b/.config/awesome/lain/widgets/yawn/icons/SnowFlurries.png
@@ -0,0 +1 @@
+BlowingSnow.png
\ No newline at end of file
diff --git a/.config/awesome/lain/widgets/yawn/icons/SnowShowers.png b/.config/awesome/lain/widgets/yawn/icons/SnowShowers.png
new file mode 100755
index 0000000..30534a2
Binary files /dev/null and b/.config/awesome/lain/widgets/yawn/icons/SnowShowers.png differ
diff --git a/.config/awesome/lain/widgets/yawn/icons/Sunny.png b/.config/awesome/lain/widgets/yawn/icons/Sunny.png
new file mode 100755
index 0000000..cf08c5c
Binary files /dev/null and b/.config/awesome/lain/widgets/yawn/icons/Sunny.png differ
diff --git a/.config/awesome/lain/widgets/yawn/icons/ThunderintheVicinity.png b/.config/awesome/lain/widgets/yawn/icons/ThunderintheVicinity.png
new file mode 120000
index 0000000..1fb3b9c
--- /dev/null
+++ b/.config/awesome/lain/widgets/yawn/icons/ThunderintheVicinity.png
@@ -0,0 +1 @@
+Cloudy.png
\ No newline at end of file
diff --git a/.config/awesome/lain/widgets/yawn/icons/Wind.png b/.config/awesome/lain/widgets/yawn/icons/Wind.png
new file mode 100755
index 0000000..5dc1356
Binary files /dev/null and b/.config/awesome/lain/widgets/yawn/icons/Wind.png differ
diff --git a/.config/awesome/lain/widgets/yawn/icons/na.png b/.config/awesome/lain/widgets/yawn/icons/na.png
new file mode 100755
index 0000000..62a5350
Binary files /dev/null and b/.config/awesome/lain/widgets/yawn/icons/na.png differ
diff --git a/.config/awesome/lain/widgets/yawn/init.lua b/.config/awesome/lain/widgets/yawn/init.lua
new file mode 100644
index 0000000..3f08cd5
--- /dev/null
+++ b/.config/awesome/lain/widgets/yawn/init.lua
@@ -0,0 +1,200 @@
+
+--[[
+                                                  
+     Licensed under GNU General Public License v2 
+      * (c) 2013, Luke Bonham                     
+                                                  
+--]]
+
+local newtimer     = require("lain.helpers").newtimer
+
+local naughty      = require("naughty")
+local wibox        = require("wibox")
+
+local debug        = { getinfo = debug.getinfo }
+local io           = io
+local os           = { date    = os.date,
+                       getenv  = os.getenv }
+local string       = { find    = string.find,
+                       match   = string.match,
+                       gsub    = string.gsub,
+                       sub     = string.sub }
+local tonumber     = tonumber
+
+local setmetatable = setmetatable
+
+-- YAhoo! Weather Notification
+-- lain.widgets.yawn
+local yawn =
+{
+    icon   = wibox.widget.imagebox(),
+    widget = wibox.widget.textbox('')
+}
+
+local project_path        = debug.getinfo(1, 'S').source:match[[^@(.*/).*$]]
+local localizations_path  = project_path .. 'localizations/'
+local icon_path           = project_path .. 'icons/'
+local api_url             = 'http://weather.yahooapis.com/forecastrss'
+local units_set           = '?u=c&w=' -- Default is Celsius
+local language            = string.match(os.getenv("LANG"), "(%S*$*)[.]")
+local weather_data        = nil
+local notification        = nil
+local city_id             = nil
+local sky                 = nil
+local settings            = function() end
+
+yawn_notification_preset = {}
+
+local function fetch_weather()
+    local url = api_url .. units_set .. city_id
+    local f = io.popen("curl --connect-timeout 1 -fsm 3 '" .. url .. "'" )
+    local text = f:read("*all")
+    f:close()
+
+    -- In case of no connection or invalid city ID
+    -- widgets won't display
+    if text == "" or text:match("City not found")
+    then
+        yawn.icon:set_image(icon_path .. "na.png")
+        if text == "" then
+            weather_data = "Service not available at the moment."
+            yawn.widget:set_text(" N/A ")
+        else
+            weather_data = "City not found!\n" ..
+                           "Are you sure " .. city_id ..
+                           " is your Yahoo city ID?"
+            yawn.widget:set_text(" ? ")
+        end
+        return
+    end
+
+    -- Processing raw data
+    weather_data = text:gsub("<.->", "")
+    weather_data = weather_data:match("Current Conditions:.-Full") or ""
+
+    -- may still happens in case of bad connectivity
+    if weather_data == "" then
+        yawn.icon:set_image(icon_path .. "na.png")
+        yawn.widget:set_text(" ? ")
+        return
+    end
+
+    weather_data = weather_data:gsub("Current Conditions:.-\n", "Now: ")
+    weather_data = weather_data:gsub("Forecast:.-\n", "")
+    weather_data = weather_data:gsub("\nFull", "")
+    weather_data = weather_data:gsub("[\n]$", "")
+    weather_data = weather_data:gsub(" [-] " , ": ")
+    weather_data = weather_data:gsub("[.]", ",")
+    weather_data = weather_data:gsub("High: ", "")
+    weather_data = weather_data:gsub(" Low: ", " - ")
+
+    -- Getting info for text widget
+    local now      = weather_data:sub(weather_data:find("Now:")+5,
+                     weather_data:find("\n")-1)
+    forecast       = now:sub(1, now:find(",")-1)
+    units          = now:sub(now:find(",")+2, -2)
+
+    -- Day/Night icon change
+    local hour = tonumber(os.date("%H"))
+    sky = icon_path
+
+    if forecast == "Clear"         or
+       forecast == "Fair"          or
+       forecast == "Partly Cloudy" or
+       forecast == "Mostly Cloudy"
+       then
+           if hour >= 6 and hour <= 18
+           then
+               sky = sky .. "Day"
+           else
+               sky = sky .. "Night"
+           end
+    end
+
+    sky = sky  .. forecast:gsub(" ", ""):gsub("/", "") .. ".png"
+
+    -- In case there's no defined icon for current forecast
+    if io.open(sky) == nil then
+        sky = icon_path .. "na.png"
+    end
+
+    -- Localization
+    local f = io.open(localizations_path .. language, "r")
+    if language:find("en_") == nil and f ~= nil
+    then
+        f:close()
+        for line in io.lines(localizations_path .. language)
+        do
+            word = string.sub(line, 1, line:find("|")-1)
+            translation = string.sub(line, line:find("|")+1)
+            weather_data = string.gsub(weather_data, word, translation)
+        end
+    end
+
+    -- Finally setting infos
+    yawn.icon:set_image(sky)
+    widget = yawn.widget
+
+    forecast = weather_data:match(": %S.-,"):gsub(": ", ""):gsub(",", "")
+    units = units:gsub(" ", "")
+
+    settings()
+end
+
+function yawn.hide()
+    if notification ~= nil then
+        naughty.destroy(notification)
+        notification = nil
+    end
+end
+
+function yawn.show(t_out)
+    if yawn.widget._layout.text:match("?")
+    then
+        fetch_weather(settings)
+    end
+
+    yawn.hide()
+
+    notification = naughty.notify({
+        preset = yawn_notification_preset,
+        text = weather_data,
+        icon = sky,
+        timeout = t_out
+    })
+end
+
+function yawn.register(id, args)
+    local args     = args or {}
+    local timeout  = args.timeout or 600
+    settings       = args.settings or function() end
+
+    if args.u == "f" then units_set = '?u=f&w=' end
+
+    city_id = id
+
+    newtimer("yawn", timeout, fetch_weather)
+
+    yawn.icon:connect_signal("mouse::enter", function()
+        yawn.show(0)
+    end)
+    yawn.icon:connect_signal("mouse::leave", function()
+        yawn.hide()
+    end)
+
+    return yawn
+end
+
+function yawn.attach(widget, id, args)
+    yawn.register(id, args)
+
+    widget:connect_signal("mouse::enter", function()
+        yawn.show(0)
+    end)
+
+    widget:connect_signal("mouse::leave", function()
+        yawn.hide()
+    end)
+end
+
+return setmetatable(yawn, { __call = function(_, ...) return yawn.register(...) end })
diff --git a/.config/awesome/lain/widgets/yawn/localizations/it_IT b/.config/awesome/lain/widgets/yawn/localizations/it_IT
new file mode 100644
index 0000000..70b0eef
--- /dev/null
+++ b/.config/awesome/lain/widgets/yawn/localizations/it_IT
@@ -0,0 +1,60 @@
+Now:|Ora:
+Sun:|Dom:
+Mon:|Lun:
+Tue:|Mar:
+Wed:|Mer:
+Thu:|Gio:
+Fri:|Ven:
+Sat:|Sab:
+Mostly Sunny|Abbastanza Soleggiato
+Sunny|Soleggiato
+Sun|Soleggiato
+Rain/Thunder|Temporali
+Isolated Thunderstorms|Temporali Isolati
+Scattered Thunderstorms|Temporali Sparsi
+Thundershowers|Rovesci Temporaleschi
+Thunderstorms|Temporali
+Thunder in the Vicinity|Tuoni in prossimità
+Thunder|Temporale
+AM|In Mattinata
+PM|Nel Pomeriggio
+Early|In Mattinata
+Late|In Serata
+Few|Sporadiche
+Severe|Forti
+Clear|Sereno
+Fair|Sereno
+Partly|Parzialmente
+Mostly|Molto
+Cloudy|Nuvoloso
+Clouds|Nuvoloso
+Scattered Showers|Temporali Sparsi
+Light Snow Showers|Nevicate Leggere
+Snow Showers|Nevicate
+aeavy Snow|Forti Nevicate
+Scattered Snow Showers|Nevicate Sparse
+Mixed Rain And Snow|Pioggia E Neve
+Mixed Rain And Sleet|Pioggia E Nevischio
+Mixed Snow And Sleet|Neve E Nevischio
+Mixed Rain And Hail|Pioggia E Grandine
+Snow Flurries|Folate Di Neve
+Blowing Snow|Neve Battente
+Blowing Rain|Pioggia Battente
+Heavy Rain|Forti Piogge
+Freezing Rain|Pioggia Congelantesi
+Showers|Piogge
+Light Rain|Pioggia Leggera
+Heavy|Forti
+Rain|Piovoso
+Windy|Ventoso
+Wind|Ventoso
+Snow|Neve
+Sleet|Nevischio
+Light Drizzle|Pioggia Leggera
+Drizzle|Pioggia Leggera
+Freezing Drizzle|Pioggerella Congelantesi
+Hail|Grandine
+Fog|Nebbia
+Foggy|Nebbioso
+Haze|Nebbia
+Light|Leggere
diff --git a/.config/awesome/lain/widgets/yawn/localizations/localization_template b/.config/awesome/lain/widgets/yawn/localizations/localization_template
new file mode 100644
index 0000000..453807e
--- /dev/null
+++ b/.config/awesome/lain/widgets/yawn/localizations/localization_template
@@ -0,0 +1,60 @@
+Now:|
+Sun:|
+Mon:|
+Tue:|
+Wed:|
+Thu:|
+Fri:|
+Sat:|
+Mostly Sunny|
+Sunny|
+Sun|
+Rain/Thunder|
+Isolated Thunderstorms|
+Scattered Thunderstorms|
+Thundershowers|
+Thunderstorms|
+Thunder in the Vicinity|
+Thunder|
+AM|
+PM|
+Early|
+Late|
+Few|
+Severe|
+Clear|
+Fair|
+Partly|
+Mostly|
+Cloudy|
+Clouds|
+Scattered Showers|
+Light Snow Showers|
+Snow Showers|
+Heavy Snow|
+Scattered Snow Showers|
+Mixed Rain And Snow|
+Mixed Rain And Sleet|
+Mixed Snow And Sleet|
+Mixed Rain And Hail|
+Snow Flurries|
+Blowing Snow|
+Blowing Rain|
+Heavy Rain|
+Freezing Rain|
+Showers|
+Light Rain|
+Heavy|
+Rain|
+Windy|
+Wind|
+Snow|
+Sleet|
+Freezing Drizzle|
+Light Drizzle|
+Drizzle|
+Hail|
+Fog|
+Foggy|
+Haze|
+Light|
-- 
cgit v1.2.1